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