From b9624afc01b221260f007b694609db7e39af89c5 Mon Sep 17 00:00:00 2001 From: "ho.namkoong" Date: Wed, 20 Nov 2013 21:58:45 +0900 Subject: SDB: support suspend mode 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 --- Makefile | 3 + src/command_function.c | 11 +-- src/commandline.c | 16 ++++ src/common_modules.h | 18 +++- src/listener.c | 120 +++++++++++------------- src/listener.h | 4 +- src/sdb.c | 23 ++--- src/sdb_constants.c | 8 ++ src/sdb_constants.h | 7 ++ src/sockets.c | 249 ++++++++++++++++++++++++++++++++++++++++--------- src/sockets.h | 5 +- src/transport.c | 43 +++++++-- src/transport.h | 4 +- src/transport_local.c | 51 +++++----- src/transport_usb.c | 30 +++--- 15 files changed, 406 insertions(+), 186 deletions(-) diff --git a/Makefile b/Makefile index 45c645e..5e89fbd 100644 --- 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) diff --git a/src/command_function.c b/src/command_function.c index 0d5f994..b95a3d1 100644 --- a/src/command_function.c +++ b/src/command_function.c @@ -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; diff --git a/src/commandline.c b/src/commandline.c index 46b8e1b..2558b45 100755 --- a/src/commandline.c +++ b/src/commandline.c @@ -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); diff --git a/src/common_modules.h b/src/common_modules.h index 3fa5e02..1f2ed05 100644 --- a/src/common_modules.h +++ b/src/common_modules.h @@ -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_ */ diff --git a/src/listener.c b/src/listener.c index c6ce208..0ab08b5 100644 --- a/src/listener.c +++ b/src/listener.c @@ -37,64 +37,58 @@ 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; } } diff --git a/src/listener.h b/src/listener.h index b2850cc..ee59810 100644 --- a/src/listener.h +++ b/src/listener.h @@ -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_ */ diff --git a/src/sdb.c b/src/sdb.c index e17c34f..bb7a08e 100755 --- 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(); diff --git a/src/sdb_constants.c b/src/sdb_constants.c index 57a9e63..0f88bd7 100644 --- a/src/sdb_constants.c +++ b/src/sdb_constants.c @@ -269,9 +269,17 @@ 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"; diff --git a/src/sdb_constants.h b/src/sdb_constants.h index d0dda55..030a87e 100644 --- a/src/sdb_constants.h +++ b/src/sdb_constants.h @@ -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_*/ diff --git a/src/sockets.c b/src/sockets.c index 7d85837..1ef12c3 100755 --- a/src/sockets.c +++ b/src/sockets.c @@ -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 char* destination) { 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); } diff --git a/src/sockets.h b/src/sockets.h index 51fe875..363e617 100644 --- a/src/sockets.h +++ b/src/sockets.h @@ -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 char* destination); 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_ */ diff --git a/src/transport.c b/src/transport.c index 309291a..8c444ae 100755 --- a/src/transport.c +++ b/src/transport.c @@ -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) { diff --git a/src/transport.h b/src/transport.h index d7c18af..eaebeb8 100755 --- a/src/transport.h +++ b/src/transport.h @@ -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 */ diff --git a/src/transport_local.c b/src/transport_local.c index a58542a..61ddc28 100755 --- a/src/transport_local.c +++ b/src/transport_local.c @@ -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); } diff --git a/src/transport_usb.c b/src/transport_usb.c index 270bddd..b364e87 100755 --- a/src/transport_usb.c +++ b/src/transport_usb.c @@ -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); } -- cgit v1.2.3