1 /* Copyright (C) 2006-2010 The Android Open Source Project
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.
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.
19 #include <sys/ioctl.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
26 #include "net/slirp.h"
27 #include "qemu_socket.h"
30 #include "tizen/src/debug_ch.h"
32 //DEFAULT_DEBUG_CHANNEL(qemu);
33 MULTI_DEBUG_CHANNEL(qemu, sdb);
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
40 # define QSOCKET_CALL(_ret,_cmd) \
41 do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
43 # define QSOCKET_CALL(_ret,_cmd) \
46 do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \
54 static int winsock_error;
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") \
100 static const WinsockError _winsock_errors[] = {
101 #define EE(w,u,s) { w, u, s },
107 /* this function reads the latest winsock error code and updates
108 * errno to a matching value. It also returns the new value of
111 static int _fix_errno( void )
113 const WinsockError* werr = _winsock_errors;
114 int unix = EINVAL; /* generic error code */
116 winsock_error = WSAGetLastError();
118 for ( ; werr->string != NULL; werr++ ) {
119 if (werr->winsock == winsock_error) {
129 static int _fix_errno( void )
136 #define SOCKET_CALL(cmd) \
138 QSOCKET_CALL(ret, (cmd)); \
140 return _fix_errno(); \
143 int socket_send(int fd, const void* buf, int buflen)
145 SOCKET_CALL(send(fd, buf, buflen, 0))
151 socket_close_handler( void* _fd )
157 /* we want to drain the read side of the socket before closing it */
159 ret = recv( fd, buff, sizeof(buff), 0 );
160 } while (ret < 0 && WSAGetLastError() == WSAEINTR);
162 if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
165 qemu_set_fd_handler( fd, NULL, NULL, NULL );
170 socket_close( int fd )
172 int old_errno = errno;
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 );
186 socket_close( int fd )
188 int old_errno = errno;
190 shutdown( fd, SHUT_RDWR );
198 int inet_strtoip(const char* str, uint32_t *ip)
202 if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
205 if ((unsigned)comp[0] >= 256 ||
206 (unsigned)comp[1] >= 256 ||
207 (unsigned)comp[2] >= 256 ||
208 (unsigned)comp[3] >= 256)
211 *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
212 (comp[2] << 8) | comp[3]);
216 static int check_port_bind_listen(u_int port)
218 struct sockaddr_in addr;
221 socklen_t addrlen = sizeof(addr);
222 memset(&addr, 0, addrlen);
224 addr.sin_family = AF_INET;
225 addr.sin_addr.s_addr = INADDR_ANY;
226 addr.sin_port = htons(port);
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) ||
235 ERR( "port(%d) listen fail \n", port);
239 INFO( "port(%d) listen ok \n", port);
251 int get_sdb_base_port(void)
257 if(tizen_base_port == 0){
259 for ( ; tries > 0; tries--, port += 10 ) {
260 if(check_port_bind_listen(port+1) < 0 )
268 ERR( "it seems too many emulator instances are running on this machine. Aborting\n" );
272 tizen_base_port = port;
273 INFO( "sdb port is %d \n", tizen_base_port);
276 return tizen_base_port;
282 const char *base_port = "26100";
290 inet_strtoip("10.0.2.16", &guest_ip);
292 port = strtol(base_port, (char **)&p, 0);
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)
300 // fprintf(stdout,"SDBD established on port %d\n", port+1);
305 INFO("redirect [%s] success\n", buf);
307 ERR( "it seems too many emulator instances are running on this machine. Aborting\n" );
311 if( tizen_base_port != port ){
312 ERR( "sdb port is miss match. Aborting\n" );
316 /* Save base port. */
317 tizen_base_port = port;
318 INFO( "Port(%d/tcp) listen for SDB \n", tizen_base_port + 1);
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);
325 INFO("redirect [%s] success\n", buf);
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
335 s = tcp_socket_outgoing("127.0.0.1", SDB_HOST_PORT);
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");
342 /* length is hex: 0x13 = 19 */
343 sprintf(tmp,"0013host:emulator:%d",port+1);
344 socket_send(s, tmp, 30);