SDB: support suspend mode 35/12635/2
authorho.namkoong <ho.namkoong@samsung.com>
Wed, 20 Nov 2013 12:58:45 +0000 (21:58 +0900)
committerho.namkoong <ho.namkoong@samsung.com>
Wed, 20 Nov 2013 13:05:45 +0000 (22:05 +0900)
support suspend mode in emulator.
If emulator is in suspend mode, all the connections between sdb and emulator are closed

Change-Id: I633e06906aeb8a84ac0044f3efbbd369b37842d2
Signed-off-by: ho.namkoong <ho.namkoong@samsung.com>
15 files changed:
Makefile
src/command_function.c
src/commandline.c
src/common_modules.h
src/listener.c
src/listener.h
src/sdb.c
src/sdb_constants.c
src/sdb_constants.h
src/sockets.c
src/sockets.h
src/transport.c
src/transport.h
src/transport_local.c
src/transport_usb.c

index 45c645e25e4308796fed9caa17016f3a95080bbc..5e89fbd0f83f48bf9793a94b85685f704b210d63 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -72,6 +72,9 @@ SDB_CFLAGS := -O2 -g -Wall -Wno-unused-parameter
 SDB_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
 SDB_CFLAGS += -Iinclude -Isrc
 SDB_CFLAGS += $(LOCAL_CFLAGS)
+ifeq ($(MAKE_DEBUG),true)
+SDB_CFLAGS += -DMAKE_DEBUG
+endif
 SDB_LFLAGS := $(LOCAL_LFLAGS)
 STATIC_LFLAGS := $(LOCAL_STATIC_LFLAGS)
 
index 0d5f994b81b9a680dee34a9e6dbd39d3b61d576d..b95a3d143fe5d433e733992935dc8df7ac95b9e1 100644 (file)
@@ -316,14 +316,11 @@ int device_con(int argc, char ** argv, void** extargv) {
 }
 
 int get_state_serialno(int argc, char ** argv, void** extargv) {
-    char* serial = (char *)extargv[0];
-    transport_type* ttype = (transport_type*)extargv[1];
-    char *tmp;
-    char full_cmd[PATH_MAX];
 
-    format_host_command(full_cmd, sizeof full_cmd, argv[0], *ttype, serial);
-    D(COMMANDLINE_MSG_FULL_CMD, argv[0], full_cmd);
-    tmp = sdb_query(full_cmd, extargv);
+    char full_cmd[PATH_MAX];
+    format_host_command(full_cmd, sizeof full_cmd, argv[0], *(transport_type *)extargv[1], (char*)extargv[0]);
+    LOG_INFO(COMMANDLINE_MSG_FULL_CMD, argv[0], full_cmd);
+    char* tmp = sdb_query(full_cmd, extargv);
     if(tmp) {
         printf("%s\n", tmp);
         return 0;
index 46b8e1b168d017a3afd90f0b526746c2803b5700..2558b45c367bacdbd4ec55f09992825d0d699c6f 100755 (executable)
@@ -303,6 +303,22 @@ static void create_cmd_list(LIST_NODE** cmd_list) {
             COMMANDLINE_DEVICE_CON_DESC_SIZE, COMMANDLINE_DEVICE_CON_ARG_DESC, device_con, COMMANDLINE_DEVICE_CON_MAX_ARG, COMMANDLINE_DEVICE_CON_MIN_ARG);
     prepend(cmd_list, device_con_cmd);
 #endif
+
+    //hidden command for testing suspended mode
+#ifdef MAKE_DEBUG
+    COMMAND* send_packet_cmd = NULL;
+    create_command(&send_packet_cmd, "send-packet", NULL,
+            0, NULL, get_state_serialno, 0, 0);
+    prepend(cmd_list, send_packet_cmd);
+
+    COMMAND* transport_close_cmd = NULL;
+    create_command(&transport_close_cmd, "transport-close", NULL,
+            0, NULL, get_state_serialno, 0, 0);
+    prepend(cmd_list, transport_close_cmd);
+#endif
+
+
+
     COMMAND* disconnect_cmd = NULL;
     create_command(&disconnect_cmd, COMMANDLINE_DISCONNECT_NAME, COMMANDLINE_DISCONNECT_DESC,
             COMMANDLINE_DISCONNECT_DESC_SIZE, COMMANDLINE_DISCONNECT_ARG_DESC, __disconnect, COMMANDLINE_DISCONNECT_MAX_ARG, COMMANDLINE_DISCONNECT_MIN_ARG);
index 3fa5e020c0465b00cb97df3f13c86518a5f44180..1f2ed05be0f6dbd50bf39ea8627f8e76a5d028be 100644 (file)
@@ -33,6 +33,7 @@
 
 #define MAX_PAYLOAD 4096
 #define CHUNK_SIZE (64*1024)
+#define DEFAULT_SDB_QEMU_PORT 26097
 #define DEFAULT_SDB_PORT 26099
 
 #define A_VERSION 0x0100000
@@ -69,6 +70,7 @@ typedef enum transport_type {
         kTransportUsb,
         kTransportLocal,
         kTransportAny,
+        kTransportConnect,
         kTransportRemoteDevCon
 } transport_type;
 
@@ -85,12 +87,16 @@ struct transport
     void (*kick)(TRANSPORT *t);
 
     int connection_state;
+
+    //for checking emulator suspended mode
+    int suspended;
     transport_type type;
 
     usb_handle *usb;
     int sfd;
 
     char *serial;
+    char host[20];
     int sdb_port;
     char *device_name;
 
@@ -99,6 +105,12 @@ struct transport
     unsigned res;
 };
 
+typedef enum listener_type {
+        serverListener,
+        qemuListener,
+        forwardListener
+} LISTENER_TYPE;
+
 typedef struct listener LISTENER;
 struct listener
 {
@@ -107,9 +119,10 @@ struct listener
     FD_EVENT fde;
     int fd;
 
-    const char *local_name;
-    const char *connect_to;
+    int local_port;
+    int connect_port;
     TRANSPORT *transport;
+    LISTENER_TYPE type;
 };
 
 typedef struct t_packet T_PACKET;
@@ -142,5 +155,6 @@ struct socket {
 
 int readx(int fd, void *ptr, size_t len);
 int writex(int fd, const void *ptr, size_t len);
+int notify_qemu(char* host, int port, char* serial);
 
 #endif /* SDB_TYPES_H_ */
index c6ce208b116f8ccd05400dae45dbd4515e897df9..0ab08b548d19a3068850e4ebf20b6c7787869a12 100644 (file)
 LIST_NODE* listener_list = NULL;
 
 static void listener_event_func(int _fd, unsigned ev, void *_l);
-static LISTENER* find_listener(const char *local_name);
+static LISTENER* find_listener(int local_port);
 
 void  free_listener(void* data)
 {
     LISTENER* listener = data;
     fdevent_remove(&(listener->fde));
-    free((void*)listener->local_name);
-    free((void*)listener->connect_to);
     free(listener);
 }
 
-int install_listener(const char *local_name, const char *connect_to, TRANSPORT* transport)
+int install_listener(int local_port, int connect_port, TRANSPORT* transport, LISTENER_TYPE ltype)
 {
-    D("LN(%s)\n", local_name);
+    D("LN(%d)\n", local_port);
 
-    LISTENER* listener = find_listener(local_name);
+    LISTENER* listener = find_listener(local_port);
 
     if(listener != NULL) {
-        char *cto;
-
-            /* can't repurpose a smartsocket */
-        if(listener->connect_to[0] == '*') {
-            return -1;
-        }
-
-        cto = strdup(connect_to);
-        if(cto == 0) {
+        if(listener->type != forwardListener) {
+            LOG_ERROR("can not repurpose if it is not forward listener");
             return -1;
         }
 
-        //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
-        free((void*) listener->connect_to);
-        listener->connect_to = cto;
-        if (listener->transport != transport) {
-            listener->transport = transport;
-        }
+        listener->type = ltype;
+        listener->connect_port = connect_port;
+        listener->transport = transport;
         return 0;
     }
 
-    if(strncmp("tcp:", local_name, 4)){
-        LOG_FATAL("LN(%s) unknown local portname\n", local_name);
-        return -2;
-    }
-
-    int port = atoi(local_name + 4);
-
     //TODO REMOTE_DEVICE_CONNECT block remote connect until security issue is cleard
 //    int fd = sdb_port_listen(INADDR_ANY, port, SOCK_STREAM);
-    int fd = sdb_port_listen(INADDR_LOOPBACK, port, SOCK_STREAM);
+
+    int fd = -1;
+    if(ltype == qemuListener) {
+        fd = sdb_port_listen(INADDR_ANY, local_port, SOCK_STREAM);
+    }
+    else {
+        fd = sdb_port_listen(INADDR_LOOPBACK, local_port, SOCK_STREAM);
+    }
 
     if(fd < 0) {
-        LOG_ERROR("LN(%s) cannot bind\n", local_name);
+        if(ltype == serverListener) {
+            LOG_FATAL("server LN(%d) cannot bind \n", local_port);
+        }
+        else {
+            LOG_ERROR("LN(%d) cannot bind \n", local_port);
+        }
         return -2;
     }
 
     listener = calloc(1, sizeof(LISTENER));
-    listener->local_name = strdup(local_name);
-    listener->connect_to = strdup(connect_to);
+    listener->type = ltype;
+    listener->local_port = local_port;
+    listener->connect_port = connect_port;
     listener->fd = fd;
     listener->node = prepend(&listener_list, listener);
     listener->transport = transport;
@@ -104,77 +98,75 @@ int install_listener(const char *local_name, const char *connect_to, TRANSPORT*
     return 0;
 }
 
-int remove_listener(const char *local_name, const char *connect_to, TRANSPORT* transport)
+int remove_listener(int local_port, int connect_port, TRANSPORT* transport)
 {
-    D("LN(%s)\n", local_name);
-    LISTENER* listener = find_listener(local_name);
+    LOG_INFO("LN(%d)\n", local_port);
+    LISTENER* listener = find_listener(local_port);
 
     if(listener != NULL &&
-            !strcmp(connect_to, listener->connect_to) &&
+            connect_port == listener->connect_port &&
             listener->transport != NULL &&
             listener->transport == transport) {
         remove_node(&listener_list, listener->node, free_listener);
-        D("LN(%s) removed\n", local_name);
+        LOG_INFO("LN(%d) removed\n", local_port);
         return 0;
     }
 
-    D("LN(%s) could not find\n", local_name);
+    LOG_ERROR("LN(%d) could not find\n", local_port);
     return -1;
 }
 
 static void listener_event_func(int _fd, unsigned ev, void *_l)
 {
     LISTENER *l = _l;
-    D("LN(%s)\n", l->local_name);
+    LOG_INFO("LN(%d)\n", l->local_port);
 
     if(ev & FDE_READ) {
         int fd = sdb_socket_accept(_fd);
 
         if(fd < 0) {
-            D("LN(%s) fail to create\n", l->local_name);
+            LOG_ERROR("LN(%d) fail to create socket\n", l->local_port);
             return;
         }
 
         SDB_SOCKET *s = create_local_socket(fd);
 
-        int ss = 0;
-        if(!strcmp(l->connect_to, "*smartsocket*")) {
-            ss = 1;
+        if(l->type == serverListener) {
+            sdb_socket_setbufsize(fd, CHUNK_SIZE);
+            local_socket_ready(s);
         }
-
-        if(ss) {
+        else  if(l->type == qemuListener) {
             sdb_socket_setbufsize(fd, CHUNK_SIZE);
+            SET_SOCKET_STATUS(s, QEMU_SOCKET);
+            local_socket_ready(s);
         }
-        if(s) {
-
-            if(ss) {
-                local_socket_ready(s);
+        else {
+
+//TODO REMOTE_DEVICE_CONNECT
+#if 0
+            if(l->transport->type == kTransportRemoteDevCon) {
+                if(assign_remote_connect_socket_rid(s)) {
+                    local_socket_close(s);
+                    return;
+                }
             }
-            else {
+#endif
 
-                if(l->transport->type == kTransportRemoteDevCon) {
-                    if(assign_remote_connect_socket_rid(s)) {
-                        local_socket_close(s);
-                        return;
-                    }
-                }
+            s->transport = l->transport;
+            char connect_to[50];
+            snprintf(connect_to, sizeof connect_to, "tcp:%d", l->connect_port);
 
-                s->transport = l->transport;
-                connect_to_remote(s, l->connect_to);
-            }
-            return;
+            connect_to_remote(s, connect_to);
         }
-
-        sdb_close(fd);
     }
 }
 
-static LISTENER* find_listener(const char *local_name) {
+static LISTENER* find_listener(int local_port) {
     LIST_NODE* currentptr = listener_list;
     while(currentptr != NULL) {
         LISTENER* l = currentptr->data;
         currentptr = currentptr->next_ptr;
-        if(!strcmp(local_name, l->local_name)) {
+        if(local_port == l->local_port) {
             return l;
         }
     }
index b2850cc87f36aa0a78bfa53fc3ec0b8e7b1828a8..ee598105f97664bb214ec0f349322f00f377f50b 100644 (file)
@@ -30,8 +30,8 @@
 #include "common_modules.h"
 extern LIST_NODE* listener_list;
 
-int remove_listener(const char *local_name, const char *connect_to, TRANSPORT* transport);
-int install_listener(const char *local_name, const char *connect_to, TRANSPORT* transport);
+int remove_listener(int local_port, int connect_port, TRANSPORT* transport);
+int install_listener(int local_port, int connect_port, TRANSPORT* transport, LISTENER_TYPE ltype);
 void  free_listener(void* data);
 
 #endif /* LISTENER_H_ */
index e17c34f0f270cdca321a928ce87561cc9f82228c..bb7a08e3bcd286b0de5106de0fabaf23ece2fca0 100755 (executable)
--- a/src/sdb.c
+++ b/src/sdb.c
@@ -109,15 +109,6 @@ static void init_map() {
 #endif
 }
 
-/* Constructs a local name of form tcp:port.
- * target_str points to the target string, it's content will be overwritten.
- * target_size is the capacity of the target string.
- * server_port is the port number to use for the local name.
- */
-void build_local_name(char* target_str, size_t target_size, int server_port)
-{
-  snprintf(target_str, target_size, "tcp:%d", server_port);
-}
 
 int sdb_main(int is_daemon, int server_port)
 {
@@ -130,17 +121,19 @@ int sdb_main(int is_daemon, int server_port)
 
     init_wakeup_select_func();
 
-    sdb_usb_init();
-    local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
-
-    char local_name[30];
-    build_local_name(local_name, sizeof(local_name), server_port);
-    if(install_listener(local_name, "*smartsocket*", NULL)) {
+    if(install_listener(server_port, 0, NULL, serverListener)) {
         _exit(1);
     }
     if (is_daemon) {
         start_logging();
     }
+
+    //install listener for getting emulator information from qemu
+    install_listener(DEFAULT_SDB_QEMU_PORT, 0, NULL, qemuListener);
+
+    sdb_usb_init();
+    local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
+
     LOG_INFO("Event loop starting\n");
     FDEVENT_LOOP();
 
index 57a9e633ac0695b6d5c3369d71b6b2cdf83b66ae..0f88bd740b5701232ac794c54920e6315a145c29 100644 (file)
     const char* STATE_NOPERM = "no permissions";
     const char* STATE_LOCKED = "locked";
     const char* STATE_UNKNOWN = "unknown";
+    const char* STATE_SUSPENDED = "suspended";
 
     const char* TRANSPORT_ERR_MORE_THAN_ONE_TARGET = "more than one target";
     const char* TRANSPORT_ERR_MORE_THAN_ONE_EMUL = "more than one emulator";
+    const char* TRANSPORT_ERR_MORE_THAN_ONE_CONNECT = "more than one connected emulator";
     const char* TRANSPORT_ERR_MORE_THAN_ONE_DEV = "more than one device";
     const char* TRANSPORT_ERR_TARGET_OFFLINE = "target offline";
+    const char* TRANSPORT_ERR_TARGET_SUSPENDED = "emulator is in suspended mode";
     const char* TRANSPORT_ERR_TARGET_NOT_FOUND = "target not found";
+
+    const char* FORWARD_ERR_UNKNOWN_LOCAL_PORT = "wrong local port format";
+    const char* FORWARD_ERR_UNKNOWN_REMOTE_PORT = "wrong remote port format";
+    const char* FORWARD_ERR_INSTALL_FAIL = "cannot install listener";
+    const char* FORWARD_ERR_REMOVE_FAIL = "cannot remove listener";
index d0dda5536787e929b638d07b126c54e11ed5a1a1..030a87e071e4c28fdc81a49adcc41bcfedee03fa 100644 (file)
@@ -227,11 +227,18 @@ typedef enum host_type HOST_TYPE;
     extern const char* STATE_NOPERM;
     extern const char* STATE_LOCKED;
     extern const char* STATE_UNKNOWN;
+    extern const char* STATE_SUSPENDED;
 
     extern const char* TRANSPORT_ERR_MORE_THAN_ONE_TARGET;
     extern const char* TRANSPORT_ERR_MORE_THAN_ONE_EMUL;
     extern const char* TRANSPORT_ERR_MORE_THAN_ONE_DEV;
     extern const char* TRANSPORT_ERR_TARGET_OFFLINE;
+    extern const char* TRANSPORT_ERR_TARGET_SUSPENDED;
     extern const char* TRANSPORT_ERR_TARGET_NOT_FOUND;
 
+    extern const char* FORWARD_ERR_UNKNOWN_LOCAL_PORT;
+    extern const char* FORWARD_ERR_UNKNOWN_REMOTE_PORT;
+    extern const char* FORWARD_ERR_INSTALL_FAIL;
+    extern const char* FORWARD_ERR_REMOVE_FAIL;
+
 #endif /* SDB_CONSTANTS_H_*/
index 7d858371bbc22a98e4fbe22b7393fc9b9b6bf648..1ef12c343c5b896c9ff9fd2e87389e347e31c08f 100755 (executable)
@@ -33,6 +33,8 @@
 
 #define  TRACE_TAG  TRACE_SOCKETS
 
+static int qemu_socket_enqueue(SDB_SOCKET *s, PACKET *p);
+static int smart_socket_check(SDB_SOCKET *s, PACKET **p);
 static int smart_socket_enqueue(SDB_SOCKET *s, PACKET *p);
 static int local_enqueue(int fd, PACKET* p, SDB_SOCKET* s, int event_func);
 static int peer_enqueue(SDB_SOCKET* socket, PACKET* p);
@@ -353,6 +355,10 @@ static int peer_enqueue(SDB_SOCKET* socket, PACKET* p) {
         return -1;
     }
 
+    if(HAS_SOCKET_STATUS(socket, QEMU_SOCKET)) {
+        return qemu_socket_enqueue(socket, p);
+    }
+
     //packet can be queued, so do not free it here.
     return smart_socket_enqueue(socket, p);
 }
@@ -400,7 +406,7 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
 {
     SDB_SOCKET *s = _s;
 
-    D("LS(%X) FD(%d)\n", s->local_id, s->fd);
+    LOG_INFO("LS(%X) FD(%d)\n", s->local_id, s->fd);
 
     /* put the FDE_WRITE processing before the FDE_READ
     ** in order to simplify the code.
@@ -523,7 +529,7 @@ void create_remote_connection_socket(SDB_SOCKET* socket) {
     socket->read_packet->len = 0;
 }
 
-void connect_to_remote(SDB_SOCKET *s, const char *destination)
+void connect_to_remote(SDB_SOCKET *s, const chardestination)
 {
     D("LS(%X)\n", s->local_id);
     PACKET *p = get_apacket();
@@ -623,6 +629,7 @@ static int parse_host_service(char* host_str, char** service_ptr, TRANSPORT** t,
 
 static int handle_request_with_t(SDB_SOCKET* socket, char* service, TRANSPORT* t, char* err_str) {
     int forward = 0;
+
     if(!strncmp(service,"forward:",8)) {
         forward = 8;
     }
@@ -652,22 +659,32 @@ static int handle_request_with_t(SDB_SOCKET* socket, char* service, TRANSPORT* t
         }
         *remote++ = 0;
 
+        if(strncmp("tcp:", local, 4)){
+            forward_err = (char*)FORWARD_ERR_UNKNOWN_LOCAL_PORT;
+            goto sendfail;
+        }
+
+        if(strncmp("tcp:", remote, 4)){
+            forward_err = (char*)FORWARD_ERR_UNKNOWN_REMOTE_PORT;
+            goto sendfail;
+        }
+
         if (forward == 8) {
-            if(!install_listener(local, remote, t)) {
+            if(!install_listener(atoi(local + 4), atoi(remote + 4), t, forwardListener)) {
                 writex(socket->fd, "OKAYOKAY", 8);
                 return 0;
             }
             else {
-                LOG_INFO("LS(%X) T(%s) fail to install listener\n", socket->fd, t->serial);
-                forward_err = "cannot install listener";
+                forward_err = (char*)FORWARD_ERR_INSTALL_FAIL;
+                goto sendfail;
             }
         } else {
-            if(!remove_listener(local, remote, t)) {
+            if(!remove_listener(atoi(local + 4), atoi(remote + 4), t)) {
                 writex(socket->fd, "OKAYOKAY", 8);
                 return 0;
             } else {
-                LOG_INFO("LS(%X) T(%s) fail to remove listener\n", socket->fd, t->serial);
-                forward_err = "cannot remove listener";
+                forward_err = (char*)FORWARD_ERR_REMOVE_FAIL;
+                goto sendfail;
             }
         }
 sendfail:
@@ -688,6 +705,23 @@ sendfail:
         sendokmsg(socket->fd, state);
         return 0;
     }
+#ifdef MAKE_DEBUG
+    else if(!strncmp(service, "send-packet", strlen("send-packet"))) {
+        char data[MAX_PAYLOAD] = {'1', };
+        send_cmd(0, 0, 0x00000000, data, t);
+        sendokmsg(socket->fd, "send_packet OK!");
+        return 0;
+    }
+    else if(!strncmp(service, "transport-close", strlen("transport-close"))) {
+        if(!sdb_close(t->sfd)) {
+            sendokmsg(socket->fd, "transport sfd closed!");
+        }
+        else {
+            sendfailmsg(socket->fd, "fail to close sfd!");
+        }
+        return 0;
+    }
+#endif
 
     //TODO REMOTE_DEVICE_CONNECT block this code until security issue is cleared
 #if 0
@@ -761,7 +795,7 @@ static void unregister_all_tcp_transports()
     while(curptr != NULL) {
         TRANSPORT* t = curptr->data;
         curptr = curptr->next_ptr;
-        if (t->type == kTransportLocal && t->sdb_port == 0) {
+        if (t->type == kTransportConnect) {
             //just kick the transport. transport is destroied by transport thread.
             if(!t->kicked) {
                 t->kicked = 1;
@@ -956,73 +990,162 @@ success:
         return 0;
     }
 
-       if(!strcmp(service, "kill")) {
-          LOG_INFO("sdb is being killed\n");
-           sdb_cleanup();
-           sdb_write(socket->fd, "OKAY", 4);
-           exit(0);
-       }
+   if(!strcmp(service, "kill")) {
+       LOG_INFO("sdb is being killed\n");
+       sdb_cleanup();
+       sdb_write(socket->fd, "OKAY", 4);
+       exit(0);
+   }
 
     return -1;
 }
 
-static int smart_socket_enqueue(SDB_SOCKET *s, PACKET *p)
-{
+static int smart_socket_check(SDB_SOCKET *s, PACKET **p) {
     unsigned len;
 
-    D("LS(%X)\n", s->local_id);
-
     if(s->pkt_list == NULL) {
-        prepend(&s->pkt_list, p);
+        prepend(&s->pkt_list, *p);
     }
     else {
         PACKET* socket_packet = s->pkt_list->data;
-        if((socket_packet->len + p->len) > MAX_PAYLOAD) {
-            D("SS(%d): overflow\n", s->local_id);
-            put_apacket(p);
-            goto fail;
+        if((socket_packet->len + (*p)->len) > MAX_PAYLOAD) {
+            LOG_ERROR("LS(%x): overflow\n", s->local_id);
+            put_apacket(*p);
+            return -1;
         }
 
         memcpy(socket_packet->data + socket_packet->len,
-               p->data, p->len);
-        socket_packet->len += p->len;
-        put_apacket(p);
+                (*p)->data, (*p)->len);
+        socket_packet->len += (*p)->len;
+        put_apacket(*p);
 
-        p = socket_packet;
+        *p = socket_packet;
     }
 
         /* don't bother if we can't decode the length */
-    if(p->len < 4) return 0;
+    if((*p)->len < 4) {
+        LOG_INFO("LS(%X): waiting for more bytes for getting the packet length\n", s->local_id);
+        return 1;
+    }
 
-    len = unhex(p->data, 4);
+    len = unhex((*p)->data, 4);
 
     if((len < 1) ||  (len > 1024)) {
-        D("LS(%X): bad size (%d)\n", s->local_id, len);
-        goto fail;
+        LOG_ERROR("LS(%X): bad size (%d)\n", s->local_id, len);
+        return -1;
     }
 
         /* can't do anything until we have the full header */
-    if((len + 4) > p->len) {
-        D("LS(%X): waiting for %d more bytes in smart socket\n", s->local_id, len+4 - p->len);
-        return 0;
+    if((len + 4) > (*p)->len) {
+        LOG_INFO("LS(%X): waiting for %d more bytes in smart socket\n", s->local_id, len+4 - (*p)->len);
+        return 1;
+    }
+
+    (*p)->data[len + 4] = 0;
+    LOG_INFO("LS(%X) %s\n", s->local_id, (*p)->data + 4);
+    return 0;
+}
+
+static int qemu_socket_enqueue(SDB_SOCKET *s, PACKET *p)
+{
+    LOG_INFO("LS(%X) data %s\n", s->local_id, p->data);
+
+    //TODO sync command is not fully implemented.
+    int result = smart_socket_check(s, &p);
+
+    if(result == -1) {
+        goto fail;
+    }
+
+    if(result == 1) {
+        return result;
+    }
+
+    //TODO sync command is not fully implemented.
+    char* host_str = (char *)p->data + 4;
+
+    if(strncmp(host_str, "host:", strlen("host:"))) {
+        LOG_ERROR("unknown qemu protocol '%s'\n", host_str);
+        goto fail;
+    }
+
+    host_str = host_str + 5;
+
+    LOG_INFO("qemu request: '%s'\n", host_str);
+    if(!strncmp(host_str, "sync:", strlen("sync:"))) {
+        host_str += strlen("sync:");
+        char* suspend = strchr(host_str, ':');
+        if(suspend == NULL) {
+            LOG_ERROR("sync: does not contain suspended status!\n");
+            goto fail;
+        }
+        *(suspend++) = '\0';
+
+        TRANSPORT* t = acquire_one_transport(kTransportAny, host_str, NULL);
+
+        if(t == NULL) {
+            LOG_ERROR("sync: error. No Such serial name '%s'\n", host_str);
+            goto fail;
+        }
+
+        if(*suspend == '0') {
+            LOG_INFO("T(%s) exits suspended mode\n", t->serial);
+            if(t->suspended != 0) {
+                t->suspended = 0;
+                update_transports();
+            }
+        }
+        else if(*suspend == '1') {
+            LOG_INFO("T(%s) enters suspended mode\n", t->serial);
+            if(t->suspended != 1) {
+                t->suspended = 1;
+                run_transport_close(t);
+                update_transports();
+            }
+        }
+        else {
+            LOG_ERROR("sync: contains wrong suspended status '%c'!\n", suspend);
+            goto fail;
+        }
     }
 
-    p->data[len + 4] = 0;
-    D("LS(%X) %s\n", s->local_id, p->data + 4);
+    fail:
+        free_list(s->pkt_list, put_apacket);
+        s->pkt_list = NULL;
+        local_socket_close(s);
+        return -1;
+}
+
+static int smart_socket_enqueue(SDB_SOCKET *s, PACKET *p)
+{
+    LOG_INFO("LS(%X)\n", s->local_id);
+    int result = smart_socket_check(s, &p);
+
+    if(result == -1) {
+        goto fail;
+    }
+
+    if(result == 1) {
+        return result;
+    }
 
     char* host_str = (char *)p->data + 4;
     char *service = NULL;
     char* err_str = NULL;
     TRANSPORT* t = NULL;
-
     if(parse_host_service(host_str, &service, &t, &err_str) == 1) {
-        if (t && t->connection_state != CS_OFFLINE) {
+        if (t && t->connection_state != CS_OFFLINE && t->suspended == 0) {
             s->transport = t;
             sdb_write(s->fd, "OKAY", 4);
             D("LS(%X) get transport T(%s)", s->local_id, t->serial);
         } else {
             if(t != NULL) {
-                err_str = (char*)TRANSPORT_ERR_TARGET_OFFLINE;
+                if(t->suspended) {
+                    err_str =(char*)TRANSPORT_ERR_TARGET_SUSPENDED;
+                }
+                else {
+                    err_str = (char*)TRANSPORT_ERR_TARGET_OFFLINE;
+                }
             }
             LOG_ERROR("LS(%X) get no transport", s->local_id);
             sendfailmsg(s->fd, err_str);
@@ -1030,7 +1153,6 @@ static int smart_socket_enqueue(SDB_SOCKET *s, PACKET *p)
         p->len = 0;
         return 0;
     }
-
     if (service) {
         if(handle_request_with_t(s, service, t, err_str) == 0) {
             D( "LS(%X): handled host service with '%s'\n", s->local_id, service );
@@ -1063,7 +1185,6 @@ static int smart_socket_enqueue(SDB_SOCKET *s, PACKET *p)
             goto fail;
         }
     }
-
     if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {
         sendfailmsg(s->fd, "device offline (x)");
         goto fail;
@@ -1074,6 +1195,8 @@ static int smart_socket_enqueue(SDB_SOCKET *s, PACKET *p)
         goto fail;
     }
 
+    //TODO REMOTE_DEVICE_CONNECT
+#if 0
     if(s->transport->type == kTransportRemoteDevCon) {
         if(assign_remote_connect_socket_rid(s)) {
             sendfailmsg(s->fd, "remote connect socket exceeds limit. cannot create remote socket\n");
@@ -1081,8 +1204,10 @@ static int smart_socket_enqueue(SDB_SOCKET *s, PACKET *p)
             return -1;
         }
     }
+#endif
 
     SET_SOCKET_STATUS(s, NOTIFY);
+
     connect_to_remote(s, (char*) (p->data + 4));
     free_list(s->pkt_list, put_apacket);
     s->pkt_list = NULL;
@@ -1093,10 +1218,10 @@ fail:
 
     free_list(s->pkt_list, put_apacket);
     s->pkt_list = NULL;
-    if(!HAS_SOCKET_STATUS(s, REMOTE_CON)) {
-        //do not close socket if it is remote connected socket
+#if 0 //REMOTE_DEVICE_CONNECT
+    if(!HAS_SOCKET_STATUS(s, REMOTE_CON))
+#endif
         local_socket_close(s);
-    }
     return -1;
 }
 
@@ -1147,6 +1272,34 @@ device_tracker_send( SDB_SOCKET* local_socket,
     return local_socket_enqueue( local_socket, p );
 }
 
+int notify_qemu(char* host, int port, char* serial) {
+    int  fd = -1;
+    int  qemu_port = port + 2;
+
+    fd = sdb_host_connect(host, qemu_port, SOCK_DGRAM);
+
+    if (fd < 0) {
+        LOG_ERROR("failed to create socket to localhost(%d)\n", qemu_port);
+        return -1;
+    }
+
+    char request[255];
+    snprintf(request, sizeof request, "5\n%s\n", serial);
+
+    // send to sensord with udp
+
+    LOG_INFO("notify qemu: %s\n", request);
+
+    if (sdb_write(fd, request, strlen(request)) < 0) {
+        LOG_ERROR("could not send sensord request\n");
+        sdb_close(fd);
+        return -1;
+    }
+
+    sdb_close(fd);
+    return 0;
+}
+
 static void connect_emulator(char* host, int port, char* buf, int buf_len) {
     if(port < 0) {
         port = DEFAULT_SDB_LOCAL_TRANSPORT_PORT;
@@ -1170,6 +1323,10 @@ static void connect_emulator(char* host, int port, char* buf, int buf_len) {
         return;
     }
 
-    register_socket_transport(fd, serial, port, 0, NULL);
+    if(notify_qemu(host, port, serial)) {
+        return;
+    }
+    register_socket_transport(fd, serial, host, port, kTransportConnect, NULL);
+
     snprintf(buf, buf_len, "connected to %s", serial);
 }
index 51fe87548c8eaaec2d96b4f9fae5201f51bf5a10..363e617df60bf4df0683a2231806f9be7bf4c400 100644 (file)
@@ -46,7 +46,8 @@ typedef enum {
     NOTIFY = 0,
     DEVICE_TRACKER,
     REMOTE_SOCKET,
-    REMOTE_CON
+    REMOTE_CON,
+    QEMU_SOCKET
 } SOCKET_STATUS;
 
 extern LIST_NODE* local_socket_list;
@@ -56,7 +57,7 @@ int local_socket_enqueue(SDB_SOCKET *s, PACKET *p);
 void local_socket_ready(SDB_SOCKET *s);
 void local_socket_close(SDB_SOCKET *s);
 SDB_SOCKET *create_local_socket(int fd);
-void connect_to_remote(SDB_SOCKET *s, const char *destination);
+void connect_to_remote(SDB_SOCKET *s, const chardestination);
 int assign_remote_connect_socket_rid (SDB_SOCKET* s);
 int device_tracker_send( SDB_SOCKET* local_socket, const char* buffer, int len );
 #endif /* SOCKETS_H_ */
index 309291a0b51039a4990b17e84cbad6e54aa20f6a..8c444ae38a2725e5c0fc9d5b01134833d231d625 100755 (executable)
@@ -35,8 +35,6 @@ static void transport_unref(TRANSPORT *t);
 static void handle_packet(PACKET *p, TRANSPORT *t);
 static void parse_banner(char *banner, TRANSPORT *t);
 static void wakeup_select(T_PACKET* t_packet);
-static void  update_transports(void);
-static void run_transport_close(TRANSPORT* t);
 static void encoding_packet(PACKET* p);
 static int check_header(PACKET *p);
 static int check_data(PACKET *p);
@@ -127,7 +125,7 @@ kick_transport(TRANSPORT*  t)
     }
 }
 
-static void run_transport_close(TRANSPORT* t)
+void run_transport_close(TRANSPORT* t)
 {
     D("T(%s)\n", t->serial);
     LIST_NODE* curptr = listener_list;
@@ -137,7 +135,7 @@ static void run_transport_close(TRANSPORT* t)
         curptr = curptr->next_ptr;
 
         if(l->transport == t) {
-            D("LN(%s) being closed by T(%s)\n", l->local_name, t->serial);
+            D("LN(%d) being closed by T(%s)\n", l->local_port, t->serial);
             remove_node(&listener_list, l->node, free_listener);
         }
     }
@@ -323,7 +321,7 @@ int list_transports_msg(char*  buffer, size_t  bufferlen)
     return len;
 }
 
-static void  update_transports(void)
+void  update_transports(void)
 {
     D("update transports\n");
     char             buffer[1024];
@@ -361,6 +359,7 @@ static void *transport_thread(void *_t)
 {
     TRANSPORT *t = _t;
     PACKET *p;
+read_loop:
 
     D("T(%s), FD(%d)\n", t->serial, t->sfd);
     t->connection_state = CS_WAITCNXN;
@@ -368,7 +367,6 @@ static void *transport_thread(void *_t)
     t->connection_state = CS_OFFLINE;
     // allow the device some time to respond to the connect message
     sdb_sleep_ms(1000);
-
     D("%s: data dump started\n", t->serial);
     while(1) {
         p = get_apacket();
@@ -396,6 +394,32 @@ static void *transport_thread(void *_t)
        LOG_INFO("T(%s) remote read fail. terminate transport\n", t->serial);
        put_apacket(p);
 
+       if(t->suspended == 1) {
+           LOG_INFO("T(%s) connection is closed in suspended mode\n");
+           sdb_close(t->sfd);
+           while(1) {
+
+               t->sfd = sdb_host_connect(t->host, t->sdb_port, SOCK_STREAM);
+
+               if( t->sfd < 0) {
+                   LOG_INFO("T(%s) dies during suspended mode\n");
+                   break;
+               }
+
+            close_on_exec(t->sfd);
+            disable_tcp_nagle(t->sfd);
+
+            if(t->suspended == 0) {
+                LOG_INFO("T(%s) exits suspended mode\n");
+                goto read_loop;
+            }
+            sdb_close(t->sfd);
+            LOG_INFO("T(%s) still in suspended mode, sleep 2 sec\n");
+               sdb_sleep_ms(2000);
+           }
+       }
+
+
     t->connection_state = CS_OFFLINE;
     do {
         if(t->req == t->res) {
@@ -520,7 +544,8 @@ TRANSPORT *acquire_one_transport(transport_type ttype, const char* serial, char*
                 }
                 result = transport_;
             }
-            if (ttype == transport_->type) {
+            else if (ttype == transport_->type ||
+                    (ttype == kTransportLocal && transport_->type == kTransportConnect)) {
                 if (result) {
                     if(ttype == kTransportUsb) {
                         *error_out = (char*)TRANSPORT_ERR_MORE_THAN_ONE_DEV;
@@ -832,6 +857,10 @@ endup:
 const char *connection_state_name(TRANSPORT *t)
 {
     if(t != NULL) {
+        if(t->suspended) {
+            return STATE_SUSPENDED;
+        }
+
         int state = t->connection_state;
 
         if(state == CS_OFFLINE) {
index d7c18af26d93bc9994869886d902dc15a7906184..eaebeb86c69f1e74ddc13ebd39ccd506637de3ca 100755 (executable)
@@ -57,7 +57,7 @@ void send_packet(PACKET *p, TRANSPORT *t);
 const char *connection_state_name(TRANSPORT *t);
 PACKET *get_apacket(void);
 void put_apacket(void *p);
-void register_socket_transport(int s, const char *serial, int port, int local, const char *device_name);
+void register_socket_transport(int s, const char *serial, char* host, int port, transport_type ttype, const char *device_name);
 void register_usb_transport(usb_handle *usb, const char *serial);
 int register_device_con_transport(int s, const char *serial);
 void send_cmd(unsigned arg0, unsigned arg1, unsigned cmd, char* data, TRANSPORT* t);
@@ -68,4 +68,6 @@ int local_connect(int  port, const char *device_name);
 TRANSPORT *acquire_one_transport(transport_type ttype, const char* serial, char **error_out);
 void kick_transport( TRANSPORT*  t );
 void register_transport(TRANSPORT *t);
+void run_transport_close(TRANSPORT* t);
+void  update_transports(void);
 #endif   /* __TRANSPORT_H */
index a58542a6c178f3e4558adb3b4d55e75cc20ebbb5..61ddc2837ebc143f608e2a81a4689415d5f76002 100755 (executable)
@@ -92,7 +92,8 @@ int local_connect(int sdb_port, const char *device_name) {
     }
 #endif
 
-    int fd = sdb_host_connect("127.0.0.1", sdb_port, SOCK_STREAM);
+    char* host = "127.0.0.1";
+    int fd = sdb_host_connect(host, sdb_port, SOCK_STREAM);
 
     if (fd >= 0) {
         D("connected on remote on fd '%d', port '%d'\n", fd, sdb_port);
@@ -101,7 +102,12 @@ int local_connect(int sdb_port, const char *device_name) {
 
 
         snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, sdb_port);
-        register_socket_transport(fd, buf, sdb_port, 1, device_name);
+
+        if(notify_qemu(host, sdb_port, buf)) {
+            return -1;
+        }
+
+        register_socket_transport(fd, buf, host, sdb_port, kTransportLocal, device_name);
 
         // noti to sensord port to enable shell context menu on
         notify_sensord(sdb_port);
@@ -205,22 +211,7 @@ static void remote_close(TRANSPORT *t)
     D("close remote socket. T(%s), device name: '%s'\n", t->serial, t->device_name);
 }
 
-static void init_socket_transport(TRANSPORT *t, int s, int sdb_port)
-{
-    t->kick = remote_kick;
-    t->close = remote_close;
-    t->read_from_remote = remote_read;
-    t->write_to_remote = remote_write;
-    t->sfd = s;
-    t->connection_state = CS_OFFLINE;
-    t->type = kTransportLocal;
-    t->node = NULL;
-    t->req = 0;
-    t->res = 0;
-    t->sdb_port = sdb_port;
-}
-
-void register_socket_transport(int s, const char *serial, int port, int local, const char *device_name)
+void register_socket_transport(int s, const char *serial, char* host, int port, transport_type ttype, const char *device_name)
 {
     if(current_local_transports >= SDB_LOCAL_TRANSPORT_MAX) {
         D("Too many emulators\n");
@@ -236,18 +227,32 @@ void register_socket_transport(int s, const char *serial, int port, int local, c
         serial = buff;
     }
     D("transport: %s init'ing for socket %d, on port %d (%s)\n", serial, s, port, device_name);
-    int _port = port;
-    if(!local) {
-        _port = 0;
-    }
-    init_socket_transport(t, s, _port);
     TRANSPORT* old_t = acquire_one_transport(kTransportAny, serial, NULL);
     if(old_t != NULL) {
         D("old transport '%s' is found. Unregister it\n", old_t->serial);
         kick_transport(old_t);
     }
 
+    t->kick = remote_kick;
+    t->close = remote_close;
+    t->read_from_remote = remote_read;
+    t->write_to_remote = remote_write;
+    t->sfd = s;
+    t->connection_state = CS_OFFLINE;
+    t->node = NULL;
+    t->req = 0;
+    t->res = 0;
+    t->sdb_port = port;
+    t->suspended = 0;
+    t->type = ttype;
     t->remote_cnxn_socket = NULL;
+
+    if(host) {
+        snprintf(t->host, 20, "%s", host);
+    }
+    else {
+        snprintf(t->host, 20, "%s", "127.0.0.1");
+    }
     if(serial) {
         t->serial = strdup(serial);
     }
index 270bddd66fc9fc1e07a4e374dc8768e3bcdc1fb1..b364e871caab8daeaaeddf60ae4aa27382f7fd22 100755 (executable)
@@ -25,7 +25,6 @@
 #include "sdb_usb.h"
 #include "transport.h"
 
-static void init_usb_transport(TRANSPORT *t, usb_handle *h, int state);
 
 static int remote_read(TRANSPORT* t, void* data, int len)
 {
@@ -61,21 +60,6 @@ static void remote_kick(TRANSPORT *t)
     sdb_usb_kick(t->usb);
 }
 
-static void init_usb_transport(TRANSPORT *t, usb_handle *h, int state)
-{
-    D("transport: usb\n");
-    t->close = remote_close;
-    t->kick = remote_kick;
-    t->read_from_remote = remote_read;
-    t->write_to_remote = remote_write;
-    t->connection_state = state;
-    t->type = kTransportUsb;
-    t->usb = h;
-    t->sdb_port = -1;
-    t->req = 0;
-    t->res = 0;
-}
-
 static int get_connected_device_count(transport_type type)
 {
     int cnt = 0;
@@ -102,7 +86,19 @@ void register_usb_transport(usb_handle *usb, const char *serial)
 
     D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
       serial ? serial : "");
-    init_usb_transport(t, usb, CS_OFFLINE);
+
+    t->close = remote_close;
+    t->kick = remote_kick;
+    t->read_from_remote = remote_read;
+    t->write_to_remote = remote_write;
+    t->connection_state = CS_OFFLINE;
+    t->type = kTransportUsb;
+    t->usb = usb;
+    t->sdb_port = -1;
+    t->req = 0;
+    t->res = 0;
+    t->suspended = 0;
+
     if(serial) {
         t->serial = strdup(serial);
     }