Initialize
[sdk/emulator/qemu.git] / sdb.c
1 /* Copyright (C) 2006-2010 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
13
14 #ifdef _WIN32
15 #include <windows.h>
16 #include <winsock2.h>
17 #include <ws2tcpip.h>
18 #else /* !_WIN32 */
19 #include <sys/ioctl.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <netdb.h>
24 #endif /* !_WIN32 */
25
26 #include "net/slirp.h"
27 #include "qemu_socket.h"
28 #include "sdb.h"
29 #include "nbd.h"
30 #include "tizen/src/debug_ch.h"
31
32 //DEFAULT_DEBUG_CHANNEL(qemu);
33 MULTI_DEBUG_CHANNEL(qemu, sdb);
34
35 /* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
36  * easily in QEMU since we use SIGALRM to implement periodic timers
37  */
38
39 #ifdef _WIN32
40 #  define  QSOCKET_CALL(_ret,_cmd)   \
41         do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
42 #else
43 #  define  QSOCKET_CALL(_ret,_cmd)   \
44         do { \
45                 errno = 0; \
46                 do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \
47         } while (0);
48 #endif
49
50 #ifdef _WIN32
51
52 #include <errno.h>
53
54 static int  winsock_error;
55
56 #define  WINSOCK_ERRORS_LIST \
57         EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
58 EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
59 EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
60 EE(WSAEINTR,EINTR,"interrupted function call") \
61 EE(WSAEALREADY,EALREADY,"operation already in progress") \
62 EE(WSAEBADF,EBADF,"bad file descriptor") \
63 EE(WSAEACCES,EACCES,"permission denied") \
64 EE(WSAEFAULT,EFAULT,"bad address") \
65 EE(WSAEINVAL,EINVAL,"invalid argument") \
66 EE(WSAEMFILE,EMFILE,"too many opened files") \
67 EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
68 EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
69 EE(WSAEALREADY,EAGAIN,"operation already in progress") \
70 EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
71 EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
72 EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
73 EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
74 EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
75 EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
76 EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
77 EE(WSAENETDOWN,ENETDOWN,"network is down") \
78 EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
79 EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
80 EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
81 EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
82 EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
83 EE(WSAEISCONN,EISCONN,"socket is already connected") \
84 EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
85 EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
86 EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
87 EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
88 EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
89 EE(WSAELOOP,ELOOP,"cannot translate name") \
90 EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
91 EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
92 EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
93
94 typedef struct {
95         int          winsock;
96         int          unix;
97         const char*  string;
98 } WinsockError;
99
100 static const WinsockError  _winsock_errors[] = {
101 #define  EE(w,u,s)   { w, u, s },
102         WINSOCK_ERRORS_LIST
103 #undef   EE
104         { -1, -1, NULL }
105 };
106
107 /* this function reads the latest winsock error code and updates
108  * errno to a matching value. It also returns the new value of
109  * errno.
110  */
111 static int _fix_errno( void )
112 {
113         const WinsockError*  werr = _winsock_errors;
114         int                  unix = EINVAL;  /* generic error code */
115
116         winsock_error = WSAGetLastError();
117
118         for ( ; werr->string != NULL; werr++ ) {
119                 if (werr->winsock == winsock_error) {
120                         unix = werr->unix;
121                         break;
122                 }
123         }
124         errno = unix;
125         return -1;
126 }
127
128 #else
129 static int _fix_errno( void )
130 {
131         return -1;
132 }
133
134 #endif
135
136 #define  SOCKET_CALL(cmd)  \
137         int  ret; \
138 QSOCKET_CALL(ret, (cmd)); \
139 if (ret < 0) \
140 return _fix_errno(); \
141 return ret; \
142
143 int socket_send(int  fd, const void*  buf, int  buflen)
144 {
145         SOCKET_CALL(send(fd, buf, buflen, 0))
146 }
147
148 #ifdef _WIN32
149
150         static void
151 socket_close_handler( void*  _fd )
152 {
153         int   fd = (int)_fd;
154         int   ret;
155         char  buff[64];
156
157         /* we want to drain the read side of the socket before closing it */
158         do {
159                 ret = recv( fd, buff, sizeof(buff), 0 );
160         } while (ret < 0 && WSAGetLastError() == WSAEINTR);
161
162         if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
163                 return;
164
165         qemu_set_fd_handler( fd, NULL, NULL, NULL );
166         closesocket( fd );
167 }
168
169         void
170 socket_close( int  fd )
171 {
172         int  old_errno = errno;
173
174         shutdown( fd, SD_BOTH );
175         /* we want to drain the socket before closing it */
176         qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
177
178         errno = old_errno;
179 }
180
181 #else /* !_WIN32 */
182
183 #include <unistd.h>
184
185         void
186 socket_close( int  fd )
187 {
188         int  old_errno = errno;
189
190         shutdown( fd, SHUT_RDWR );
191         close( fd );
192
193         errno = old_errno;
194 }
195
196 #endif /* !_WIN32 */
197
198 int inet_strtoip(const char*  str, uint32_t  *ip)
199 {
200         int  comp[4];
201
202         if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
203                 return -1;
204
205         if ((unsigned)comp[0] >= 256 ||
206                         (unsigned)comp[1] >= 256 ||
207                         (unsigned)comp[2] >= 256 ||
208                         (unsigned)comp[3] >= 256)
209                 return -1;
210
211         *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
212                         (comp[2] << 8)  |  comp[3]);
213         return 0;
214 }
215
216 static int check_port_bind_listen(u_int port)
217 {
218         struct sockaddr_in addr;
219         int s, opt = 1;
220         int ret = -1;
221         socklen_t addrlen = sizeof(addr);
222         memset(&addr, 0, addrlen);
223
224         addr.sin_family = AF_INET;
225         addr.sin_addr.s_addr = INADDR_ANY;
226         addr.sin_port = htons(port);
227
228         if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
229                         (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
230                         (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
231                         (listen(s,1) < 0)) {
232
233                 /* fail */
234                 ret = -1;
235                 ERR( "port(%d) listen  fail \n", port);
236         }else{
237                 /*fsucess*/
238                 ret = 1;
239                 INFO( "port(%d) listen  ok \n", port);
240         }
241
242 #ifdef _WIN32
243         closesocket(s);
244 #else
245         close(s);
246 #endif
247
248         return ret;
249 }
250
251 int get_sdb_base_port(void)
252 {
253         int   tries     = 10;
254         int   success   = 0;
255         u_int port = 26100;
256
257         if(tizen_base_port == 0){
258
259                 for ( ; tries > 0; tries--, port += 10 ) {
260                         if(check_port_bind_listen(port+1) < 0 )
261                                 continue;
262
263                         success = 1;
264                         break;
265                 }
266
267                 if (!success) {
268                         ERR( "it seems too many emulator instances are running on this machine. Aborting\n" );
269                         exit(1);
270                 }
271
272                 tizen_base_port = port;
273                 INFO( "sdb port is %d \n", tizen_base_port);
274         }
275
276         return tizen_base_port;
277 }
278
279 void sdb_setup(void)
280 {
281         int   tries     = 10;
282         const char *base_port = "26100";
283         int   success   = 0;
284         int   s;
285         int   port;
286         uint32_t  guest_ip;
287         const char *p;
288         char buf[64] = {0,};
289
290         inet_strtoip("10.0.2.16", &guest_ip);
291
292         port = strtol(base_port, (char **)&p, 0);
293
294         for ( ; tries > 0; tries--, port += 10 ) {
295                 // redir form [tcp:26100:10.0.2.16:26101]
296                 sprintf(buf, "tcp:%d:10.0.2.16:26101", port+1);
297                 if(net_slirp_redir((char*)buf) < 0)
298                         continue;
299
300                 //              fprintf(stdout,"SDBD established on port %d\n", port+1);
301                 success = 1;
302                 break;
303         }
304
305         INFO("redirect [%s] success\n", buf);
306         if (!success) {
307                 ERR( "it seems too many emulator instances are running on this machine. Aborting\n" );
308                 exit(1);
309         }
310
311         if( tizen_base_port != port ){
312                 ERR( "sdb port is miss match. Aborting\n" );
313                 exit(1);
314         }
315
316         /* Save base port. */
317         tizen_base_port = port;
318         INFO( "Port(%d/tcp) listen for SDB \n", tizen_base_port + 1);
319
320         /* for sensort */
321         sprintf(buf, "tcp:%d:10.0.2.16:3577", get_sdb_base_port() + SDB_TCP_EMULD_INDEX );
322         if(net_slirp_redir((char*)buf) < 0){
323                 ERR( "redirect [%s] fail \n", buf);
324         }else{
325                 INFO("redirect [%s] success\n", buf);
326         }
327
328         /* send a simple message to the SDB host server to tell it we just started.
329          * it should be listening on port 26099. if we can't reach it, don't bother
330          */
331         do
332         {
333                 char tmp[32] = {0};
334
335                 s = tcp_socket_outgoing("127.0.0.1", SDB_HOST_PORT);
336                 if (s < 0) {
337                         INFO("can't create socket to talk to the SDB server \n");
338                         INFO("This emulator will be scaned by the SDB server \n");
339                         break;
340                 }
341
342                 /* length is hex: 0x13 = 19 */
343                 sprintf(tmp,"0013host:emulator:%d",port+1);
344                 socket_send(s, tmp, 30);
345
346         }
347         while (0);
348
349         if (s >= 0)
350                 socket_close(s);
351 }