[Title] implement port redirection for sdb // Summary
authormunkyu.im <munkyu.im@samsung.com>
Tue, 27 Sep 2011 11:31:09 +0000 (20:31 +0900)
committermunkyu.im <munkyu.im@samsung.com>
Tue, 27 Sep 2011 11:31:09 +0000 (20:31 +0900)
[Type]      Feature
[Module]    // Module Name - (Main / Sub)
[Priority]  Critical
[CQ#]       // CQ Issue Number
[Redmine#]  // Redmine Isuue Number
[Problem]   // Problem Description
[Cause]     // Cause Description
[Solution]  // Solution Description
[TestCase]  // Executed the test-target

vl.c
vl.h

diff --git a/vl.c b/vl.c
index d9a2a99..2d57eda 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -28,7 +28,6 @@
 #include <errno.h>
 #include <sys/time.h>
 #include <zlib.h>
-
 /* Needed early for CONFIG_BSD etc. */
 #include "config-host.h"
 
@@ -47,6 +46,7 @@
 #include <dirent.h>
 #include <netdb.h>
 #include <sys/select.h>
+
 #ifdef CONFIG_SIMPLE_TRACE
 #include "trace.h"
 #endif
@@ -84,6 +84,8 @@
 #endif
 #endif
 
+
+
 #if defined(__OpenBSD__)
 #include <util.h>
 #endif
@@ -94,6 +96,9 @@
 
 #ifdef _WIN32
 #include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
 #endif
 
 #ifdef CONFIG_SDL
@@ -166,7 +171,7 @@ int main(int argc, char **argv)
 #include "arch_init.h"
 #include "vl.h"
 #include "ui/qemu-spice.h"
-
+#include "nbd.h"
 //#define DEBUG_NET
 //#define DEBUG_SLIRP
 
@@ -174,6 +179,169 @@ int main(int argc, char **argv)
 
 #define MAX_VIRTIO_CONSOLES 1
 
+/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
+ * easily in QEMU since we use SIGALRM to implement periodic timers
+ */
+
+#ifdef _WIN32
+#  define  QSOCKET_CALL(_ret,_cmd)   \
+           do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
+#else
+#  define  QSOCKET_CALL(_ret,_cmd)   \
+           do { \
+                       errno = 0; \
+                       do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \
+               } while (0);
+#endif
+
+#ifdef _WIN32
+
+#include <errno.h>
+
+static int  winsock_error;
+
+#define  WINSOCK_ERRORS_LIST \
+    EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
+    EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
+    EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
+    EE(WSAEINTR,EINTR,"interrupted function call") \
+    EE(WSAEALREADY,EALREADY,"operation already in progress") \
+    EE(WSAEBADF,EBADF,"bad file descriptor") \
+    EE(WSAEACCES,EACCES,"permission denied") \
+    EE(WSAEFAULT,EFAULT,"bad address") \
+    EE(WSAEINVAL,EINVAL,"invalid argument") \
+    EE(WSAEMFILE,EMFILE,"too many opened files") \
+    EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
+    EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
+    EE(WSAEALREADY,EAGAIN,"operation already in progress") \
+    EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
+    EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
+    EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
+    EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
+    EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
+    EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
+    EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
+    EE(WSAENETDOWN,ENETDOWN,"network is down") \
+    EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
+    EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
+    EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
+    EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
+    EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
+    EE(WSAEISCONN,EISCONN,"socket is already connected") \
+    EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
+    EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
+    EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
+    EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
+    EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
+    EE(WSAELOOP,ELOOP,"cannot translate name") \
+    EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
+    EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
+    EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
+
+typedef struct {
+    int          winsock;
+    int          unix;
+    const char*  string;
+} WinsockError;
+
+static const WinsockError  _winsock_errors[] = {
+#define  EE(w,u,s)   { w, u, s },
+    WINSOCK_ERRORS_LIST
+#undef   EE
+    { -1, -1, NULL }
+};
+
+/* this function reads the latest winsock error code and updates
+ * errno to a matching value. It also returns the new value of
+ * errno.
+ */
+static int _fix_errno( void )
+{
+    const WinsockError*  werr = _winsock_errors;
+    int                  unix = EINVAL;  /* generic error code */
+
+    winsock_error = WSAGetLastError();
+
+    for ( ; werr->string != NULL; werr++ ) {
+        if (werr->winsock == winsock_error) {
+            unix = werr->unix;
+            break;
+        }
+    }
+    errno = unix;
+    return -1;
+}
+
+#else
+static int _fix_errno( void )
+{
+    return -1;
+}
+
+#endif
+
+#define  SOCKET_CALL(cmd)  \
+       int  ret; \
+       QSOCKET_CALL(ret, (cmd)); \
+       if (ret < 0) \
+               return _fix_errno(); \
+       return ret; \
+
+int socket_send(int  fd, const void*  buf, int  buflen)
+{
+       SOCKET_CALL(send(fd, buf, buflen, 0))
+}
+
+#ifdef _WIN32
+
+static void
+socket_close_handler( void*  _fd )
+{
+    int   fd = (int)_fd;
+    int   ret;
+    char  buff[64];
+
+    /* we want to drain the read side of the socket before closing it */
+    do {
+        ret = recv( fd, buff, sizeof(buff), 0 );
+    } while (ret < 0 && WSAGetLastError() == WSAEINTR);
+
+    if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
+        return;
+
+    qemu_set_fd_handler( fd, NULL, NULL, NULL );
+    closesocket( fd );
+}
+
+void
+socket_close( int  fd )
+{
+    int  old_errno = errno;
+
+    shutdown( fd, SD_BOTH );
+    /* we want to drain the socket before closing it */
+    qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
+
+    errno = old_errno;
+}
+
+#else /* !_WIN32 */
+
+#include <unistd.h>
+
+void
+socket_close( int  fd )
+{
+    int  old_errno = errno;
+
+    shutdown( fd, SHUT_RDWR );
+    close( fd );
+
+    errno = old_errno;
+}
+
+#endif /* !_WIN32 */
+
 static const char *data_dir;
 const char *bios_name = NULL;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
@@ -230,6 +398,7 @@ int ctrl_grab = 0;
 unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 int boot_menu;
+int SLP_base_port;
 
 typedef struct FWBootEntry FWBootEntry;
 
@@ -3146,6 +3315,8 @@ int qemu_main(int argc, char **argv, char **envp)
      * when bus is created by qdev.c */
     qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
     qemu_run_machine_init_done_notifiers();
+       
+       sdb_setup();
 
     qemu_system_reset();
     if (loadvm) {
@@ -3170,6 +3341,83 @@ int qemu_main(int argc, char **argv, char **envp)
     main_loop();
     quit_timers();
     net_cleanup();
-
     return 0;
 }
+
+int inet_strtoip(const char*  str, uint32_t  *ip)
+{
+       int  comp[4];
+
+       if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
+               return -1;
+
+       if ((unsigned)comp[0] >= 256 ||
+                       (unsigned)comp[1] >= 256 ||
+                       (unsigned)comp[2] >= 256 ||
+                       (unsigned)comp[3] >= 256)
+               return -1;
+
+       *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
+                       (comp[2] << 8)  |  comp[3]);
+       return 0;
+}
+
+void sdb_setup(void)
+{
+    int   tries     = 10;
+    const char *base_port = "26100";
+    int   sdb_host_port = 26099; // sdb's default
+    int   success   = 0;
+    int   s;
+       int   port;
+    uint32_t  guest_ip;
+       const char *p;
+       char buf[30] = {0,};
+
+       inet_strtoip("10.0.2.16", &guest_ip);
+
+       port = strtol(base_port, (char **)&p, 0);
+
+       for ( ; tries > 0; tries--, port += 10 ) {
+               // redir form [tcp:26100:10.0.2.16:26101]
+               sprintf(buf, "tcp:%d:10.0.2.16:26101", port+1);
+               if(net_slirp_redir((char*)buf) < 0)
+                       continue;
+
+               printf("SDB listening on port from %d to %d\n", port, port+9);
+               success = 1;
+               break;
+       }
+       if (!success) {
+               fprintf(stderr, "it seems too many emulator instances are running on this machine. Aborting\n" );
+               exit(1);
+    }
+       setenv( "SDB_PORT", (char*)buf, 1);
+       fflush(stdout);
+
+    /* Save base port. */
+    SLP_base_port = port;
+
+   /* send a simple message to the SDB host server to tell it we just started.
+    * it should be listening on port 26099. if we can't reach it, don't bother
+    */
+    do
+    {
+        char tmp[32];
+        
+               if (s < 0) {
+            fprintf(stderr, "can't create socket to talk to the SDB server");
+            break;
+        }
+               
+        sprintf(tmp,"0013host:emulator:%d",port+1);
+        socket_send(s, tmp, 30);
+               printf("sent '%s' to SDB server\n", tmp);
+               fflush(stdout);
+
+    }
+    while (0);
+
+    if (s >= 0)
+       socket_close(s);
+}
diff --git a/vl.h b/vl.h
index f65c771..1ec8d12 100644 (file)
--- a/vl.h
+++ b/vl.h
@@ -1,3 +1,98 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <errno.h>
 
 int qemu_main(int argc, char **argv, char **envp);
 
+/* added for SDB(Samsung Development Bridge) */
+
+#ifdef _WIN32
+#  ifndef EINTR
+#    define EINTR        10004
+#  endif
+#  ifndef EAGAIN
+#    define EAGAIN       10035
+#  endif
+#  ifndef EWOULDBLOCK
+#    define EWOULDBLOCK  EAGAIN
+#  endif
+#  ifndef EINPROGRESS
+#    define EINPROGRESS  10036
+#  endif
+#  ifndef EALREADY
+#    define EALREADY     10037
+#  endif
+#  ifndef EDESTADDRREQ
+#    define EDESTADDRREQ 10039
+#  endif
+#  ifndef EMSGSIZE
+#    define EMSGSIZE     10040
+#  endif
+#  ifndef EPROTOTYPE
+#    define EPROTOTYPE   10041
+#  endif
+#  ifndef ENOPROTOOPT
+#    define ENOPROTOOPT  10042
+#  endif
+#  ifndef EAFNOSUPPORT
+#    define EAFNOSUPPORT 10047
+#  endif
+#  ifndef EADDRINUSE
+#    define EADDRINUSE   10048
+#  endif
+#  ifndef EADDRNOTAVAIL
+#    define EADDRNOTAVAIL 10049
+#  endif
+#  ifndef ENETDOWN
+#    define ENETDOWN     10050
+#  endif
+#  ifndef ENETUNREACH
+#    define ENETUNREACH  10051
+#  endif
+#  ifndef ENETRESET
+#    define ENETRESET    10052
+#  endif
+#  ifndef ECONNABORTED
+#    define ECONNABORTED 10053
+#  endif
+#  ifndef ECONNRESET
+#    define ECONNRESET   10054
+#  endif
+#  ifndef ENOBUFS
+#    define ENOBUFS      10055
+#  endif
+#  ifndef EISCONN
+#    define EISCONN      10056
+#  endif
+#  ifndef ENOTCONN
+#    define ENOTCONN     10057
+#  endif
+#  ifndef ESHUTDOWN
+#    define ESHUTDOWN     10058
+#  endif
+#  ifndef ETOOMANYREFS
+#    define ETOOMANYREFS  10059
+#  endif
+#  ifndef ETIMEDOUT
+#    define ETIMEDOUT     10060
+#  endif
+#  ifndef ECONNREFUSED
+#    define ECONNREFUSED  10061
+#  endif
+#  ifndef ELOOP
+#    define ELOOP         10062
+#  endif
+#  ifndef EHOSTDOWN
+#    define EHOSTDOWN     10064
+#  endif
+#  ifndef EHOSTUNREACH
+#    define EHOSTUNREACH  10065
+#  endif
+#endif /* _WIN32 */
+
+void sdb_setup(void);
+int inet_strtoip(const char*  str, uint32_t  *ip);
+int socket_send(int fd, const void*  buf, int  buflen);
+void socket_close(int fd);
+
+