X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=ce0ee6cd231863a41fbbe973042d608a2860f4a3;hb=60ba4476dfef5fae48b85d54e376a3ca27442113;hp=a034da7928e73cafa9497be592eabe345a36eddb;hpb=8b4e882a1630d63bbc9840fa3f968e36b6ac3702;p=openocd.git diff --git a/src/server/server.c b/src/server/server.c index a034da7928..ce0ee6cd23 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -17,6 +17,12 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "replacements.h" + #include "server.h" #include "log.h" @@ -29,9 +35,11 @@ #include #include #include -#include #include #include +#ifndef _WIN32 +#include +#endif service_t *services = NULL; @@ -42,8 +50,9 @@ int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char * int add_connection(service_t *service, command_context_t *cmd_ctx) { unsigned int address_size; - connection_t *c, *p; + connection_t *c, **p; int retval; + int flag=1; c = malloc(sizeof(connection_t)); c->fd = -1; @@ -55,29 +64,32 @@ int add_connection(service_t *service, command_context_t *cmd_ctx) c->next = NULL; address_size = sizeof(c->sin); + c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size); - + + /* This increases performance dramatically for e.g. GDB load which + * does not have a sliding window protocol. */ + retval=setsockopt(c->fd, /* socket affected */ + IPPROTO_TCP, /* set option at TCP level */ + TCP_NODELAY, /* name of option */ + (char *)&flag, /* the cast is historical cruft */ + sizeof(int)); /* length of option value */ + + LOG_INFO("accepting '%s' connection from %i", service->name, c->sin.sin_port); if ((retval = service->new_connection(c)) == ERROR_OK) { - INFO("accepted '%s' connection from %i", service->name, c->sin.sin_port); } else { - close(c->fd); - INFO("attempted '%s' connection rejected", service->name); + close_socket(c->fd); + LOG_ERROR("attempted '%s' connection rejected", service->name); free(c); + return retval; } - if (service->connections) - { - for (p = service->connections; p && p->next; p = p->next); - if (p) - p->next = c; - } - else - { - service->connections = c; - } + /* add to the end of linked list */ + for (p = &service->connections; *p; p = &(*p)->next); + *p = c; service->max_connections--; @@ -86,33 +98,28 @@ int add_connection(service_t *service, command_context_t *cmd_ctx) int remove_connection(service_t *service, connection_t *connection) { - connection_t *c, *p = NULL; - + connection_t **p = &service->connections; + connection_t *c; + /* find connection */ - for (c = service->connections; c; c = c->next) - { + while((c = *p)) + { if (c->fd == connection->fd) - { - /* unlink connection */ - if (p) - p->next = c->next; - else - service->connections = c->next; - + { service->connection_closed(c); - close(c->fd); - + close_socket(c->fd); command_done(c->cmd_ctx); /* delete connection */ + *p = c->next; free(c); service->max_connections++; break; } - /* remember the last connection for unlinking */ - p = c; + /* redirect p to next list pointer */ + p = &(*p)->next; } return ERROR_OK; @@ -120,9 +127,8 @@ int remove_connection(service_t *service, connection_t *connection) int add_service(char *name, enum connection_type type, unsigned short port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv) { - service_t *c, *p; + service_t *c, **p; int so_reuseaddr_option = 1; - int oldopts; c = malloc(sizeof(service_t)); @@ -140,14 +146,13 @@ int add_service(char *name, enum connection_type type, unsigned short port, int if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - ERROR("error creating socket: %s", strerror(errno)); + LOG_ERROR("error creating socket: %s", strerror(errno)); exit(-1); } - setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr_option, sizeof(int)); + setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int)); - oldopts = fcntl(c->fd, F_GETFL, 0); - fcntl(c->fd, F_SETFL, oldopts | O_NONBLOCK); + socket_nonblock(c->fd); memset(&c->sin, 0, sizeof(c->sin)); c->sin.sin_family = AF_INET; @@ -156,59 +161,94 @@ int add_service(char *name, enum connection_type type, unsigned short port, int if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { - ERROR("couldn't bind to socket: %s", strerror(errno)); + LOG_ERROR("couldn't bind to socket: %s", strerror(errno)); exit(-1); } +#ifndef _WIN32 + int segsize=65536; + setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int)); +#endif + int window_size = 128 * 1024; + + /* These setsockopt()s must happen before the listen() */ + + setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF, + (char *)&window_size, sizeof(window_size)); + setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF, + (char *)&window_size, sizeof(window_size)); + if (listen(c->fd, 1) == -1) { - ERROR("couldn't listen on socket: %s", strerror(errno)); + LOG_ERROR("couldn't listen on socket: %s", strerror(errno)); exit(-1); } - if (services) - { - for (p = services; p && p->next; p = p->next); - if (p) - p->next = c; - } - else - { - services = c; - } + /* add to the end of linked list */ + for (p = &services; *p; p = &(*p)->next); + *p = c; return ERROR_OK; } int remove_service(unsigned short port) { - service_t *c, *p = NULL; - + service_t **p = &services; + service_t *c; + /* find service */ - for (c = services; c; c = c->next) - { + while((c = *p)) + { if (c->port == port) - { - /* unlink service */ - if (p) - p->next = c->next; - else - services = c->next; - + { if (c->name) free(c->name); + if (c->priv) + free(c->priv); + /* delete service */ + *p = c->next; free(c); } - + + /* redirect p to next list pointer */ + p = &(*p)->next; + } + + return ERROR_OK; +} + +int remove_services() +{ + service_t *c = services; + + /* loop service */ + while(c) + { + service_t *next = c->next; + + if (c->name) + free(c->name); + + if (c->priv) + free(c->priv); + + /* delete service */ + free(c); + /* remember the last service for unlinking */ - p = c; + c = next; } + + services = NULL; return ERROR_OK; } +extern void openocd_sleep_prelude(); +extern void openocd_sleep_postlude(); + int server_loop(command_context_t *command_context) { service_t *service; @@ -221,9 +261,11 @@ int server_loop(command_context_t *command_context) /* used in accept() */ int retval; +#ifndef _WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - ERROR("couldn't set SIGPIPE to SIG_IGN"); - + LOG_ERROR("couldn't set SIGPIPE to SIG_IGN"); +#endif + /* do regular tasks after at most 10ms */ tv.tv_sec = 0; tv.tv_usec = 10000; @@ -260,18 +302,44 @@ int server_loop(command_context_t *command_context) } } +#ifndef _WIN32 +#ifndef BUILD_ECOSBOARD /* add STDIN to read_fds */ FD_SET(fileno(stdin), &read_fds); +#endif +#endif + + openocd_sleep_prelude(); + kept_alive(); + // Only while we're sleeping we'll let others run + retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv); + openocd_sleep_postlude(); - if ((retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv)) == -1) + if (retval == -1) { +#ifdef _WIN32 + + errno = WSAGetLastError(); + + if (errno == WSAEINTR) + FD_ZERO(&read_fds); + else + { + LOG_ERROR("error during select: %s", strerror(errno)); + exit(-1); + } +#else + if (errno == EINTR) + { FD_ZERO(&read_fds); + } else { - ERROR("error during select: %s", strerror(errno)); + LOG_ERROR("error during select: %s", strerror(errno)); exit(-1); } +#endif } target_call_timer_callbacks(); @@ -281,13 +349,7 @@ int server_loop(command_context_t *command_context) /* do regular tasks after at most 100ms */ tv.tv_sec = 0; tv.tv_usec = 10000; - -#if 0 - if (shutdown_openocd) - return ERROR_COMMAND_CLOSE_CONNECTION; - - handle_target(); -#endif + FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */ } for (service = services; service; service = service->next) @@ -297,15 +359,17 @@ int server_loop(command_context_t *command_context) && (FD_ISSET(service->fd, &read_fds))) { if (service->max_connections > 0) + { add_connection(service, command_context); + } else { struct sockaddr_in sin; unsigned int address_size = sizeof(sin); int tmp_fd; tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size); - close(tmp_fd); - INFO("rejected '%s' connection, no more connections allowed", service->name); + close_socket(tmp_fd); + LOG_INFO("rejected '%s' connection, no more connections allowed", service->name); } } @@ -322,7 +386,7 @@ int server_loop(command_context_t *command_context) { connection_t *next = c->next; remove_connection(service, c); - INFO("dropped '%s' connection", service->name); + LOG_INFO("dropped '%s' connection", service->name); c = next; continue; } @@ -332,6 +396,8 @@ int server_loop(command_context_t *command_context) } } +#ifndef _WIN32 +#ifndef BUILD_ECOSBOARD if (FD_ISSET(fileno(stdin), &read_fds)) { if (getc(stdin) == 'x') @@ -339,17 +405,70 @@ int server_loop(command_context_t *command_context) shutdown_openocd = 1; } } +#endif +#else + MSG msg; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) + { + if (msg.message == WM_QUIT) + shutdown_openocd = 1; + } +#endif } return ERROR_OK; } +#ifdef _WIN32 +BOOL WINAPI ControlHandler(DWORD dwCtrlType) +{ + shutdown_openocd = 1; + return TRUE; +} + +void sig_handler(int sig) { + shutdown_openocd = 1; +} +#endif + int server_init() { +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD( 2, 2 ); + + if (WSAStartup(wVersionRequested, &wsaData) != 0) + { + LOG_ERROR("Failed to Open Winsock"); + exit(-1); + } + + SetConsoleCtrlHandler( ControlHandler, TRUE ); + + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + signal(SIGBREAK, sig_handler); + signal(SIGABRT, sig_handler); +#endif + return ERROR_OK; } +int server_quit() +{ + remove_services(); + +#ifdef _WIN32 + WSACleanup(); + SetConsoleCtrlHandler( ControlHandler, FALSE ); +#endif + + return ERROR_OK; +} + int server_register_commands(command_context_t *context) { register_command(context, NULL, "shutdown", handle_shutdown_command, @@ -366,3 +485,4 @@ int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char * return ERROR_COMMAND_CLOSE_CONNECTION; } +