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;
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
remote_call_done(RemoteCall call)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
remote_call_free(RemoteCall call)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
remote_call_alloc(RemoteCallType type,int to_port,int from_port)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
remote_call_set_sms_pdu(RemoteCall call,SmsPDU pdu)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
remote_call_add(RemoteCall call,RemoteCall * plist)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
remote_call_event(void * opaque,int events)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
remote_call_generic(RemoteCallType type,const char * to_number,int from_port)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
remote_call_dial(const char * number,int from,RemoteResultFunc result_func,void * result_opaque)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
remote_call_other(const char * to_number,int from_port,RemoteCallType type)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
remote_call_sms(const char * number,int from,SmsPDU pdu)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
remote_call_cancel(const char * to_number,int from_port)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