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 "android/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;
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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