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 51int 52remote_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 64int 65remote_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 77int 78remote_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 101typedef 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 122static void 123remote_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 145static void 146remote_call_free( RemoteCall call ) 147{ 148 if (call) { 149 remote_call_done( call ); 150 free(call); 151 } 152} 153 154 155static void remote_call_event( void* opaque, int events ); /* forward */ 156 157static RemoteCall 158remote_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 222static int 223remote_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 255static void 256remote_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 268static void 269remote_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 345static RemoteCall _the_remote_calls; 346 347#if 0 348static int 349remote_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 364static RemoteCall 365remote_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 392int 393remote_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 408void 409remote_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 */ 415int 416remote_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 435void 436remote_call_cancel( const char* to_number, int from_port ) 437{ 438 remote_call_generic( REMOTE_CALL_HANGUP, to_number, from_port ); 439} 440