Home | History | Annotate | Download | only in telephony
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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