• 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 = strtol( number, &end, 10 );
82 
83     if (end == NULL || *end || (int)num != num )
84         return -1;
85 
86     return remote_number_to_port( (int)num );
87 }
88 
89 /** REMOTE CALL OBJECTS
90  **/
91 
92 typedef struct RemoteCallRec {
93     struct RemoteCallRec*   next;
94     struct RemoteCallRec**  pref;
95     RemoteCallType          type;
96     int                     to_port;
97     int                     from_port;
98     SysChannel              channel;
99     RemoteResultFunc        result_func;
100     void*                   result_opaque;
101 
102     char                    quitting;
103 
104     /* the output buffer */
105     char*                   buff;
106     int                     buff_pos;
107     int                     buff_len;
108     int                     buff_size;
109     char                    buff0[32];
110 
111 } RemoteCallRec, *RemoteCall;
112 
113 static void
remote_call_done(RemoteCall call)114 remote_call_done( RemoteCall  call )
115 {
116     call->pref[0] = call->next;
117     call->next    = NULL;
118     call->pref    = &call->next;
119 
120     if (call->buff && call->buff != call->buff0) {
121         free(call->buff);
122         call->buff      = call->buff0;
123         call->buff_size = (int) sizeof(call->buff0);
124     }
125 
126     if ( call->channel ) {
127         sys_channel_close( call->channel );
128         call->channel = NULL;
129     }
130 
131     call->buff_pos = 0;
132     call->buff_len = 0;
133 }
134 
135 
136 static void
remote_call_free(RemoteCall call)137 remote_call_free( RemoteCall  call )
138 {
139     if (call) {
140         remote_call_done( call );
141         free(call);
142     }
143 }
144 
145 
146 static void  remote_call_event( void*  opaque, int  events );  /* forward */
147 
148 static RemoteCall
remote_call_alloc(RemoteCallType type,int to_port,int from_port)149 remote_call_alloc( RemoteCallType  type, int  to_port, int  from_port )
150 {
151     RemoteCall  rcall    = calloc( sizeof(*rcall), 1 );
152     int         from_num = remote_number_from_port(from_port);
153 
154     if (rcall != NULL) {
155         char  *p, *end;
156 
157         rcall->pref      = &rcall->next;
158         rcall->type      = type;
159         rcall->to_port   = to_port;
160         rcall->from_port = from_port;
161         rcall->buff      = rcall->buff0;
162         rcall->buff_size = sizeof(rcall->buff0);
163         rcall->buff_pos  = 0;
164 
165         p   = rcall->buff;
166         end = p + rcall->buff_size;
167 
168         switch (type) {
169             case REMOTE_CALL_DIAL:
170                 p = bufprint(p, end, "gsm call %d\n", from_num );
171                 break;
172 
173             case REMOTE_CALL_BUSY:
174                 p = bufprint(p, end, "gsm busy %d\n", from_num);
175                 break;
176 
177             case REMOTE_CALL_HOLD:
178                 p = bufprint(p, end, "gsm hold %d\n", from_num);
179                 break;
180 
181             case REMOTE_CALL_ACCEPT:
182                 p = bufprint(p, end, "gsm accept %d\n", from_num);
183                 break;
184 
185             case REMOTE_CALL_HANGUP:
186                 p = bufprint(p, end, "gsm cancel %d\n", from_num );
187                 break;
188 
189             default:
190                 ;
191         }
192         if (p >= end) {
193             D("%s: buffer too short\n", __FUNCTION__ );
194             remote_call_free(rcall);
195             return NULL;
196         }
197 
198         rcall->buff_len = p - rcall->buff;
199 
200         rcall->channel = sys_channel_create_tcp_client( "localhost", to_port );
201         if (rcall->channel == NULL) {
202             D("%s: could not create channel to port %d\n", __FUNCTION__, to_port);
203             remote_call_free(rcall);
204             return NULL;
205         }
206 
207         sys_channel_on( rcall->channel, SYS_EVENT_WRITE, remote_call_event, rcall );
208     }
209     return  rcall;
210 }
211 
212 
213 static int
remote_call_set_sms_pdu(RemoteCall call,SmsPDU pdu)214 remote_call_set_sms_pdu( RemoteCall  call,
215                          SmsPDU      pdu )
216 {
217     char  *p, *end;
218     int    msg2len;
219 
220     msg2len = 32 + smspdu_to_hex( pdu, NULL, 0 );
221     if (msg2len > call->buff_size) {
222         char*  old_buff = call->buff == call->buff0 ? NULL : call->buff;
223         char*  new_buff = realloc( old_buff, msg2len );
224         if (new_buff == NULL) {
225             D("%s: not enough memory to alloc %d bytes", __FUNCTION__, msg2len);
226             return -1;
227         }
228         call->buff      = new_buff;
229         call->buff_size = msg2len;
230     }
231 
232     p   = call->buff;
233     end = p + call->buff_size;
234 
235     p  = bufprint(p, end, "sms pdu ");
236     p += smspdu_to_hex( pdu, p, end-p );
237     *p++ = '\n';
238     *p = 0;
239 
240     call->buff_len = p - call->buff;
241     call->buff_pos = 0;
242     return 0;
243 }
244 
245 
246 static void
remote_call_add(RemoteCall call,RemoteCall * plist)247 remote_call_add( RemoteCall   call,
248                  RemoteCall  *plist )
249 {
250     RemoteCall  first = *plist;
251 
252     call->next = first;
253     call->pref = plist;
254 
255     if (first)
256         first->pref = &call->next;
257 }
258 
259 static void
remote_call_event(void * opaque,int events)260 remote_call_event( void*  opaque, int  events )
261 {
262     RemoteCall  call = opaque;
263 
264     S("%s: called for call (%d,%d), events=%02x\n", __FUNCTION__,
265        call->from_port, call->to_port, events);
266 
267     if (events & SYS_EVENT_READ) {
268         /* simply drain the channel */
269         char  temp[32];
270         int  n = sys_channel_read( call->channel, temp, sizeof(temp) );
271         if (n <= 0) {
272             /* remote emulator probably quitted */
273             //S("%s: emulator %d quitted with %d: %s\n", __FUNCTION__, call->to_port, errno, errno_str);
274             remote_call_free( call );
275             return;
276         }
277     }
278 
279     if (events & SYS_EVENT_WRITE) {
280         int  n;
281 
282         if (S_ACTIVE) {
283             int  nn;
284             S("%s: call (%d,%d) sending %d bytes '", __FUNCTION__,
285             call->from_port, call->to_port, call->buff_len - call->buff_pos );
286             for (nn = call->buff_pos; nn < call->buff_len; nn++) {
287                 int  c = call->buff[nn];
288                 if (c < 32) {
289                     if (c == '\n')
290                         S("\\n");
291                     else if (c == '\t')
292                         S("\\t");
293                     else if (c == '\r')
294                         S("\\r");
295                     else
296                         S("\\x%02x", c);
297                 } else
298                     S("%c", c);
299             }
300             S("'\n");
301         }
302 
303         n = sys_channel_write( call->channel,
304                                call->buff + call->buff_pos,
305                                call->buff_len - call->buff_pos );
306         if (n <= 0) {
307             /* remote emulator probably quitted */
308             S("%s: emulator %d quitted unexpectedly with error %d: %s\n",
309                     __FUNCTION__, call->to_port, errno, errno_str);
310             if (call->result_func)
311                 call->result_func( call->result_opaque, 0 );
312             remote_call_free( call );
313             return;
314         }
315         call->buff_pos += n;
316 
317         if (call->buff_pos >= call->buff_len) {
318             /* cool, we sent everything */
319             S("%s: finished sending data to %d\n", __FUNCTION__, call->to_port);
320             if (!call->quitting) {
321                     call->quitting = 1;
322                     sprintf( call->buff, "quit\n" );
323                     call->buff_len = strlen(call->buff);
324                     call->buff_pos = 0;
325             } else {
326                 call->quitting = 0;
327                 if (call->result_func)
328                     call->result_func( call->result_opaque, 1 );
329 
330                 sys_channel_on( call->channel, SYS_EVENT_READ, remote_call_event, call );
331             }
332         }
333     }
334 }
335 
336 static RemoteCall  _the_remote_calls;
337 
338 #if 0
339 static int
340 remote_from_number( const char*  from )
341 {
342     char*  end;
343     long   num = strtol( from, &end, 10 );
344 
345     if (end == NULL || *end)
346         return -1;
347 
348     if ((unsigned)(num - REMOTE_NUMBER_BASE) >= REMOTE_NUMBER_MAX)
349         return -1;
350 
351     return (int) num;
352 }
353 #endif
354 
355 static RemoteCall
remote_call_generic(RemoteCallType type,const char * to_number,int from_port)356 remote_call_generic( RemoteCallType  type, const char*  to_number, int  from_port )
357 {
358     int         to_port = remote_number_string_to_port(to_number);
359     RemoteCall  call;
360 
361     if ( remote_number_from_port(from_port) < 0 ) {
362         D("%s: from_port value %d is not valid", __FUNCTION__, from_port);
363         return NULL;
364     }
365     if ( to_port < 0 ) {
366         D("%s: phone number '%s' is not decimal or remote", __FUNCTION__, to_number);
367         return NULL;
368     }
369     if (to_port == from_port) {
370         D("%s: trying to call self\n", __FUNCTION__);
371         return NULL;
372     }
373     call = remote_call_alloc( type, to_port, from_port );
374     if (call == NULL) {
375         return NULL;
376     }
377     remote_call_add( call, &_the_remote_calls );
378     D("%s: adding new call from port %d to port %d\n", __FUNCTION__, from_port, to_port);
379     return call;
380 }
381 
382 
383 int
remote_call_dial(const char * number,int from,RemoteResultFunc result_func,void * result_opaque)384 remote_call_dial( const char*       number,
385                   int               from,
386                   RemoteResultFunc  result_func,
387                   void*             result_opaque )
388 {
389     RemoteCall   call = remote_call_generic( REMOTE_CALL_DIAL, number, from );
390 
391     if (call != NULL) {
392         call->result_func   = result_func;
393         call->result_opaque = result_opaque;
394     }
395     return call ? 0 : -1;
396 }
397 
398 
399 void
remote_call_other(const char * to_number,int from_port,RemoteCallType type)400 remote_call_other( const char*  to_number, int  from_port, RemoteCallType  type )
401 {
402     remote_call_generic( type, to_number, from_port );
403 }
404 
405 /* call this function to send a SMS to a remote emulator */
406 int
remote_call_sms(const char * number,int from,SmsPDU pdu)407 remote_call_sms( const char*   number,
408                  int           from,
409                  SmsPDU        pdu )
410 {
411     RemoteCall   call = remote_call_generic( REMOTE_CALL_SMS, number, from );
412 
413     if (call == NULL)
414         return -1;
415 
416     if (call != NULL) {
417         if ( remote_call_set_sms_pdu( call, pdu ) < 0 ) {
418             remote_call_free(call);
419             return -1;
420         }
421     }
422     return call ? 0 : -1;
423 }
424 
425 
426 void
remote_call_cancel(const char * to_number,int from_port)427 remote_call_cancel( const char*  to_number, int  from_port )
428 {
429     remote_call_generic( REMOTE_CALL_HANGUP, to_number, from_port );
430 }
431