Tizen 2.1 base
[sdk/target/sdbd.git] / src / sdb_client.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <stdarg.h>
23 // tizen specific #include <zipfile/zipfile.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include "sysdeps.h"
28
29 #define  TRACE_TAG  TRACE_SDB
30 #include "sdb_client.h"
31
32 static transport_type __sdb_transport = kTransportAny;
33 static const char* __sdb_serial = NULL;
34
35 static int __sdb_server_port = DEFAULT_SDB_PORT;
36
37 void sdb_set_transport(transport_type type, const char* serial)
38 {
39     __sdb_transport = type;
40     __sdb_serial = serial;
41 }
42
43 void sdb_set_tcp_specifics(int server_port)
44 {
45     __sdb_server_port = server_port;
46 }
47
48 int  sdb_get_emulator_console_port(void)
49 {
50     const char*   serial = __sdb_serial;
51     int           port;
52
53     if (serial == NULL) {
54         /* if no specific device was specified, we need to look at */
55         /* the list of connected devices, and extract an emulator  */
56         /* name from it. two emulators is an error                 */
57         char*  tmp = sdb_query("host:devices");
58         char*  p   = tmp;
59         if(!tmp) {
60             printf("no emulator connected\n");
61             return -1;
62         }
63         while (*p) {
64             char*  q = strchr(p, '\n');
65             if (q != NULL)
66                 *q++ = 0;
67             else
68                 q = p + strlen(p);
69
70             if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
71                 if (serial != NULL) {  /* more than one emulator listed */
72                     free(tmp);
73                     return -2;
74                 }
75                 serial = p;
76             }
77
78             p = q;
79         }
80         free(tmp);
81
82         if (serial == NULL)
83             return -1;  /* no emulator found */
84     }
85     else {
86         if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
87             return -1;  /* not an emulator */
88     }
89
90     serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
91     port    = strtol(serial, NULL, 10);
92     return port;
93 }
94
95 static char __sdb_error[256] = { 0 };
96
97 const char *sdb_error(void)
98 {
99     return __sdb_error;
100 }
101
102 static int switch_socket_transport(int fd)
103 {
104     char service[64];
105     char tmp[5];
106     int len;
107
108     if (__sdb_serial)
109         snprintf(service, sizeof service, "host:transport:%s", __sdb_serial);
110     else {
111         char* transport_type = "???";
112
113          switch (__sdb_transport) {
114             case kTransportUsb:
115                 transport_type = "transport-usb";
116                 break;
117             case kTransportLocal:
118                 transport_type = "transport-local";
119                 break;
120             case kTransportAny:
121                 transport_type = "transport-any";
122                 break;
123             case kTransportHost:
124                 // no switch necessary
125                 return 0;
126                 break;
127         }
128
129         snprintf(service, sizeof service, "host:%s", transport_type);
130     }
131     len = strlen(service);
132     snprintf(tmp, sizeof tmp, "%04x", len);
133
134     if(writex(fd, tmp, 4) || writex(fd, service, len)) {
135         strcpy(__sdb_error, "write failure during connection");
136         sdb_close(fd);
137         return -1;
138     }
139     D("Switch transport in progress\n");
140
141     if(sdb_status(fd)) {
142         sdb_close(fd);
143         D("Switch transport failed\n");
144         return -1;
145     }
146     D("Switch transport success\n");
147     return 0;
148 }
149
150 int sdb_status(int fd)
151 {
152     unsigned char buf[5];
153     unsigned len;
154
155     if(readx(fd, buf, 4)) {
156         strcpy(__sdb_error, "protocol fault (no status)");
157         return -1;
158     }
159
160     if(!memcmp(buf, "OKAY", 4)) {
161         return 0;
162     }
163
164     if(memcmp(buf, "FAIL", 4)) {
165         sprintf(__sdb_error,
166                 "protocol fault (status %02x %02x %02x %02x?!)",
167                 buf[0], buf[1], buf[2], buf[3]);
168         return -1;
169     }
170
171     if(readx(fd, buf, 4)) {
172         strcpy(__sdb_error, "protocol fault (status len)");
173         return -1;
174     }
175     buf[4] = 0;
176     len = strtoul((char*)buf, 0, 16);
177     if(len > 255) len = 255;
178     if(readx(fd, __sdb_error, len)) {
179         strcpy(__sdb_error, "protocol fault (status read)");
180         return -1;
181     }
182     __sdb_error[len] = 0;
183     return -1;
184 }
185
186 int _sdb_connect(const char *service)
187 {
188     char tmp[5];
189     int len;
190     int fd;
191
192     D("_sdb_connect: %s\n", service);
193     len = strlen(service);
194     if((len < 1) || (len > 1024)) {
195         strcpy(__sdb_error, "service name too long");
196         return -1;
197     }
198     snprintf(tmp, sizeof tmp, "%04x", len);
199
200     fd = socket_loopback_client(__sdb_server_port, SOCK_STREAM);
201     if(fd < 0) {
202         strcpy(__sdb_error, "cannot connect to daemon");
203         return -2;
204     }
205
206     if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
207         return -1;
208     }
209
210     if(writex(fd, tmp, 4) || writex(fd, service, len)) {
211         strcpy(__sdb_error, "write failure during connection");
212         sdb_close(fd);
213         return -1;
214     }
215
216     if(sdb_status(fd)) {
217         sdb_close(fd);
218         return -1;
219     }
220
221     D("_sdb_connect: return fd %d\n", fd);
222     return fd;
223 }
224
225 int sdb_connect(const char *service)
226 {
227     // first query the sdb server's version
228     int fd = _sdb_connect("host:version");
229
230     D("sdb_connect: service %s\n", service);
231     if(fd == -2) {
232         fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
233                 __sdb_server_port);
234     start_server:
235         if(launch_server(__sdb_server_port)) {
236             fprintf(stderr,"* failed to start daemon *\n");
237             return -1;
238         } else {
239             fprintf(stdout,"* daemon started successfully *\n");
240         }
241         /* give the server some time to start properly and detect devices */
242         sdb_sleep_ms(3000);
243         // fall through to _sdb_connect
244     } else {
245         // if server was running, check its version to make sure it is not out of date
246         char buf[100];
247         int n;
248         int version = SDB_SERVER_VERSION - 1;
249
250         // if we have a file descriptor, then parse version result
251         if(fd >= 0) {
252             if(readx(fd, buf, 4)) goto error;
253
254             buf[4] = 0;
255             n = strtoul(buf, 0, 16);
256             if(n > (int)sizeof(buf)) goto error;
257             if(readx(fd, buf, n)) goto error;
258             sdb_close(fd);
259
260             if (sscanf(buf, "%04x", &version) != 1) goto error;
261         } else {
262             // if fd is -1, then check for "unknown host service",
263             // which would indicate a version of sdb that does not support the version command
264             if (strcmp(__sdb_error, "unknown host service") != 0)
265                 return fd;
266         }
267
268         if(version != SDB_SERVER_VERSION) {
269             printf("sdb server is out of date.  killing...\n");
270             fd = _sdb_connect("host:kill");
271             sdb_close(fd);
272
273             /* XXX can we better detect its death? */
274             sdb_sleep_ms(2000);
275             goto start_server;
276         }
277     }
278
279     // if the command is start-server, we are done.
280     if (!strcmp(service, "host:start-server"))
281         return 0;
282
283     fd = _sdb_connect(service);
284     if(fd == -2) {
285         fprintf(stderr,"** daemon still not running");
286     }
287     D("sdb_connect: return fd %d\n", fd);
288
289     return fd;
290 error:
291     sdb_close(fd);
292     return -1;
293 }
294
295
296 int sdb_command(const char *service)
297 {
298     int fd = sdb_connect(service);
299     if(fd < 0) {
300         return -1;
301     }
302
303     if(sdb_status(fd)) {
304         sdb_close(fd);
305         return -1;
306     }
307
308     return 0;
309 }
310
311 char *sdb_query(const char *service)
312 {
313     char buf[5];
314     unsigned n;
315     char *tmp;
316
317     D("sdb_query: %s\n", service);
318     int fd = sdb_connect(service);
319     if(fd < 0) {
320         fprintf(stderr,"error: %s\n", __sdb_error);
321         return 0;
322     }
323
324     if(readx(fd, buf, 4)) goto oops;
325
326     buf[4] = 0;
327     n = strtoul(buf, 0, 16);
328     if(n > 1024) goto oops;
329
330     tmp = malloc(n + 1);
331     if(tmp == 0) goto oops;
332
333     if(readx(fd, tmp, n) == 0) {
334         tmp[n] = 0;
335         sdb_close(fd);
336         return tmp;
337     }
338     free(tmp);
339
340 oops:
341     sdb_close(fd);
342     return 0;
343 }