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