• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 #include "remote_call.h"
13 #include "android/utils/bufprint.h"
14 #include "android/utils/debug.h"
15 #include "sysdeps.h"
16 #include "gsm.h"
17 #include "android/android.h"
18 #include "sockets.h"
19 #include <stdlib.h>
20 
21 #define  DEBUG  1
22 
23 #if 1
24 #  define  D_ACTIVE  VERBOSE_CHECK(modem)
25 #else
26 #  define  D_ACTIVE  DEBUG
27 #endif
28 
29 #if 1
30 #  define  S_ACTIVE  VERBOSE_CHECK(socket)
31 #else
32 #  define  S_ACTIVE  DEBUG
33 #endif
34 
35 #if DEBUG
36 #  include <stdio.h>
37 #  define  D(...)   do { if (D_ACTIVE) fprintf( stderr, __VA_ARGS__ ); } while (0)
38 #  define  S(...)   do { if (S_ACTIVE) fprintf( stderr, __VA_ARGS__ ); } while (0)
39 #else
40 #  define  D(...)   ((void)0)
41 #  define  S(...)   ((void)0)
42 #endif
43 
44 /** By convention, remote numbers are the console ports, i.e. 5554, 5556, etc...
45  **/
46 #define  REMOTE_NUMBER_BASE       5554
47 #define  REMOTE_NUMBER_MAX        16
48 #define  REMOTE_NUMBER_MAX_CHARS  4
49 #define  REMOTE_CONSOLE_PORT      5554
50 
51 int
remote_number_from_port(int port)52 remote_number_from_port( int  port )
53 {
54     if (port & 1)  /* must be even */
55         return -1;
56 
57     port = (port - REMOTE_CONSOLE_PORT) >> 1;
58     if ((unsigned)port >= REMOTE_NUMBER_MAX)
59         return -1;
60 
61     return REMOTE_NUMBER_BASE + port*2;
62 }
63 
64 int
remote_number_to_port(int number)65 remote_number_to_port( int  number )
66 {
67     if (number & 1)  /* must be even */
68         return -1;
69 
70     number = (number - REMOTE_NUMBER_BASE) >> 1;
71     if ((unsigned)number >= REMOTE_NUMBER_MAX)
72         return -1;
73 
74     return REMOTE_CONSOLE_PORT + number*2;
75 }
76 
77 int
remote_number_string_to_port(const char * number)78 remote_number_string_to_port( const char*  number )
79 {
80     char*  end;
81     long   num;
82     const char*  temp = number;
83     int    len;
84 
85     len = strlen(number);
86     if (len > 0 && number[len-1] == ';')
87         len--;
88     if (len == 11 && !memcmp(number, PHONE_PREFIX, 7))
89         temp += 7;
90     num = strtol( temp, &end, 10 );
91 
92     if (end == NULL || *end || (int)num != num )
93         return -1;
94 
95     return remote_number_to_port( (int)num );
96 }
97 
98 /** REMOTE CALL OBJECTS
99  **/
100 
101 typedef struct RemoteCallRec {
102     struct RemoteCallRec*   next;
103     struct RemoteCallRec**  pref;
104     RemoteCallType          type;
105     int                     to_port;
106     int                     from_port;
107     SysChannel              channel;
108     RemoteResultFunc        result_func;
109     void*                   result_opaque;
110 
111     char                    quitting;
112 
113     /* the output buffer */
114     char*                   buff;
115     int                     buff_pos;
116     int                     buff_len;
117     int                     buff_size;
118     char                    buff0[32];
119 
120 } RemoteCallRec, *RemoteCall;
121 
122 static void
remote_call_done(RemoteCall call)123 remote_call_done( RemoteCall  call )
124 {
125     call->pref[0] = call->next;
126     call->next    = NULL;
127     call->pref    = &call->next;
128 
129     if (call->buff && call->buff != call->buff0) {
130         free(call->buff);
131         call->buff      = call->buff0;
132         call->buff_size = (int) sizeof(call->buff0);
133     }
134 
135     if ( call->channel ) {
136         sys_channel_close( call->channel );
137         call->channel = NULL;
138     }
139 
140     call->buff_pos = 0;
141     call->buff_len = 0;
142 }
143 
144 
145 static void
remote_call_free(RemoteCall call)146 remote_call_free( RemoteCall  call )
147 {
148     if (call) {
149         remote_call_done( call );
150         free(call);
151     }
152 }
153 
154 
155 static void  remote_call_event( void*  opaque, int  events );  /* forward */
156 
157 static RemoteCall
remote_call_alloc(RemoteCallType type,int to_port,int from_port)158 remote_call_alloc( RemoteCallType  type, int  to_port, int  from_port )
159 {
160     RemoteCall  rcall    = calloc( sizeof(*rcall), 1 );
161     int         from_num = remote_number_from_port(from_port);
162 
163     if (rcall != NULL) {
164         char  *p, *end;
165 
166         rcall->pref      = &rcall->next;
167         rcall->type      = type;
168         rcall->to_port   = to_port;
169         rcall->from_port = from_port;
170         rcall->buff      = rcall->buff0;
171         rcall->buff_size = sizeof(rcall->buff0);
172         rcall->buff_pos  = 0;
173 
174         p   = rcall->buff;
175         end = p + rcall->buff_size;
176 
177         switch (type) {
178             case REMOTE_CALL_DIAL:
179                 p = bufprint(p, end, "gsm call " PHONE_PREFIX "%d\n", from_num );
180                 break;
181 
182             case REMOTE_CALL_BUSY:
183                 p = bufprint(p, end, "gsm busy " PHONE_PREFIX "%d\n", from_num);
184                 break;
185 
186             case REMOTE_CALL_HOLD:
187                 p = bufprint(p, end, "gsm hold " PHONE_PREFIX "%d\n", from_num);
188                 break;
189 
190             case REMOTE_CALL_ACCEPT:
191                 p = bufprint(p, end, "gsm accept " PHONE_PREFIX "%d\n", from_num);
192                 break;
193 
194             case REMOTE_CALL_HANGUP:
195                 p = bufprint(p, end, "gsm cancel " PHONE_PREFIX "%d\n", from_num );
196                 break;
197 
198             default:
199                 ;
200         }
201         if (p >= end) {
202             D("%s: buffer too short\n", __FUNCTION__ );
203             remote_call_free(rcall);
204             return NULL;
205         }
206 
207         rcall->buff_len = p - rcall->buff;
208 
209         rcall->channel = sys_channel_create_tcp_client( "localhost", to_port );
210         if (rcall->channel == NULL) {
211             D("%s: could not create channel to port %d\n", __FUNCTION__, to_port);
212             remote_call_free(rcall);
213             return NULL;
214         }
215 
216         sys_channel_on( rcall->channel, SYS_EVENT_WRITE, remote_call_event, rcall );
217     }
218     return  rcall;
219 }
220 
221 
222 static int
remote_call_set_sms_pdu(RemoteCall call,SmsPDU pdu)223 remote_call_set_sms_pdu( RemoteCall  call,
224                          SmsPDU      pdu )
225 {
226     char  *p, *end;
227     int    msg2len;
228 
229     msg2len = 32 + smspdu_to_hex( pdu, NULL, 0 );
230     if (msg2len > call->buff_size) {
231         char*  old_buff = call->buff == call->buff0 ? NULL : call->buff;
232         char*  new_buff = realloc( old_buff, msg2len );
233         if (new_buff == NULL) {
234             D("%s: not enough memory to alloc %d bytes", __FUNCTION__, msg2len);
235             return -1;
236         }
237         call->buff      = new_buff;
238         call->buff_size = msg2len;
239     }
240 
241     p   = call->buff;
242     end = p + call->buff_size;
243 
244     p  = bufprint(p, end, "sms pdu ");
245     p += smspdu_to_hex( pdu, p, end-p );
246     *p++ = '\n';
247     *p = 0;
248 
249     call->buff_len = p - call->buff;
250     call->buff_pos = 0;
251     return 0;
252 }
253 
254 
255 static void
remote_call_add(RemoteCall call,RemoteCall * plist)256 remote_call_add( RemoteCall   call,
257                  RemoteCall  *plist )
258 {
259     RemoteCall  first = *plist;
260 
261     call->next = first;
262     call->pref = plist;
263 
264     if (first)
265         first->pref = &call->next;
266 }
267 
268 static void
remote_call_event(void * opaque,int events)269 remote_call_event( void*  opaque, int  events )
270 {
271     RemoteCall  call = opaque;
272 
273     S("%s: called for call (%d,%d), events=%02x\n", __FUNCTION__,
274        call->from_port, call->to_port, events);
275 
276     if (events & SYS_EVENT_READ) {
277         /* simply drain the channel */
278         char  temp[32];
279         int  n = sys_channel_read( call->channel, temp, sizeof(temp) );
280         if (n <= 0) {
281             /* remote emulator probably quitted */
282             //S("%s: emulator %d quitted with %d: %s\n", __FUNCTION__, call->to_port, errno, errno_str);
283             remote_call_free( call );
284             return;
285         }
286     }
287 
288     if (events & SYS_EVENT_WRITE) {
289         int  n;
290 
291         if (S_ACTIVE) {
292             int  nn;
293             S("%s: call (%d,%d) sending %d bytes '", __FUNCTION__,
294             call->from_port, call->to_port, call->buff_len - call->buff_pos );
295             for (nn = call->buff_pos; nn < call->buff_len; nn++) {
296                 int  c = call->buff[nn];
297                 if (c < 32) {
298                     if (c == '\n')
299                         S("\\n");
300                     else if (c == '\t')
301                         S("\\t");
302                     else if (c == '\r')
303                         S("\\r");
304                     else
305                         S("\\x%02x", c);
306                 } else
307                     S("%c", c);
308             }
309             S("'\n");
310         }
311 
312         n = sys_channel_write( call->channel,
313                                call->buff + call->buff_pos,
314                                call->buff_len - call->buff_pos );
315         if (n <= 0) {
316             /* remote emulator probably quitted */
317             S("%s: emulator %d quitted unexpectedly with error %d: %s\n",
318                     __FUNCTION__, call->to_port, errno, errno_str);
319             if (call->result_func)
320                 call->result_func( call->result_opaque, 0 );
321             remote_call_free( call );
322             return;
323         }
324         call->buff_pos += n;
325 
326         if (call->buff_pos >= call->buff_len) {
327             /* cool, we sent everything */
328             S("%s: finished sending data to %d\n", __FUNCTION__, call->to_port);
329             if (!call->quitting) {
330                     call->quitting = 1;
331                     sprintf( call->buff, "quit\n" );
332                     call->buff_len = strlen(call->buff);
333                     call->buff_pos = 0;
334             } else {
335                 call->quitting = 0;
336                 if (call->result_func)
337                     call->result_func( call->result_opaque, 1 );
338 
339                 sys_channel_on( call->channel, SYS_EVENT_READ, remote_call_event, call );
340             }
341         }
342     }
343 }
344 
345 static RemoteCall  _the_remote_calls;
346 
347 #if 0
348 static int
349 remote_from_number( const char*  from )
350 {
351     char*  end;
352     long   num = strtol( from, &end, 10 );
353 
354     if (end == NULL || *end)
355         return -1;
356 
357     if ((unsigned)(num - REMOTE_NUMBER_BASE) >= REMOTE_NUMBER_MAX)
358         return -1;
359 
360     return (int) num;
361 }
362 #endif
363 
364 static RemoteCall
remote_call_generic(RemoteCallType type,const char * to_number,int from_port)365 remote_call_generic( RemoteCallType  type, const char*  to_number, int  from_port )
366 {
367     int         to_port = remote_number_string_to_port(to_number);
368     RemoteCall  call;
369 
370     if ( remote_number_from_port(from_port) < 0 ) {
371         D("%s: from_port value %d is not valid", __FUNCTION__, from_port);
372         return NULL;
373     }
374     if ( to_port < 0 ) {
375         D("%s: phone number '%s' is not decimal or remote", __FUNCTION__, to_number);
376         return NULL;
377     }
378     if (to_port == from_port) {
379         D("%s: trying to call self\n", __FUNCTION__);
380         return NULL;
381     }
382     call = remote_call_alloc( type, to_port, from_port );
383     if (call == NULL) {
384         return NULL;
385     }
386     remote_call_add( call, &_the_remote_calls );
387     D("%s: adding new call from port %d to port %d\n", __FUNCTION__, from_port, to_port);
388     return call;
389 }
390 
391 
392 int
remote_call_dial(const char * number,int from,RemoteResultFunc result_func,void * result_opaque)393 remote_call_dial( const char*       number,
394                   int               from,
395                   RemoteResultFunc  result_func,
396                   void*             result_opaque )
397 {
398     RemoteCall   call = remote_call_generic( REMOTE_CALL_DIAL, number, from );
399 
400     if (call != NULL) {
401         call->result_func   = result_func;
402         call->result_opaque = result_opaque;
403     }
404     return call ? 0 : -1;
405 }
406 
407 
408 void
remote_call_other(const char * to_number,int from_port,RemoteCallType type)409 remote_call_other( const char*  to_number, int  from_port, RemoteCallType  type )
410 {
411     remote_call_generic( type, to_number, from_port );
412 }
413 
414 /* call this function to send a SMS to a remote emulator */
415 int
remote_call_sms(const char * number,int from,SmsPDU pdu)416 remote_call_sms( const char*   number,
417                  int           from,
418                  SmsPDU        pdu )
419 {
420     RemoteCall   call = remote_call_generic( REMOTE_CALL_SMS, number, from );
421 
422     if (call == NULL)
423         return -1;
424 
425     if (call != NULL) {
426         if ( remote_call_set_sms_pdu( call, pdu ) < 0 ) {
427             remote_call_free(call);
428             return -1;
429         }
430     }
431     return call ? 0 : -1;
432 }
433 
434 
435 void
remote_call_cancel(const char * to_number,int from_port)436 remote_call_cancel( const char*  to_number, int  from_port )
437 {
438     remote_call_generic( REMOTE_CALL_HANGUP, to_number, from_port );
439 }
440