X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=3f579bfc641a79bf02477d03389b34360d7674ad;hb=05752557dd0dcab76250ab12377d59435b74204d;hp=06a2f39de88f8ab983d14c616655c1f1a28bf62b;hpb=c584686fd1d1dc7d2059e619de90f35516598134;p=openocd.git diff --git a/src/server/server.c b/src/server/server.c index 06a2f39de8..3f579bfc64 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -27,6 +27,7 @@ #endif #include "server.h" +#include #include #include #include @@ -46,9 +47,13 @@ static struct service *services; -/* shutdown_openocd == 1: exit the main event loop, and quit the - * debugger; 2: quit with non-zero return code */ -static int shutdown_openocd; +enum shutdown_reason { + CONTINUE_MAIN_LOOP, /* stay in main event loop */ + SHUTDOWN_REQUESTED, /* set by shutdown command; exit the event loop and quit the debugger */ + SHUTDOWN_WITH_ERROR_CODE, /* set by shutdown command; quit with non-zero return code */ + SHUTDOWN_WITH_SIGNAL_CODE /* set by sig_handler; exec shutdown then exit with signal as return code */ +}; +static enum shutdown_reason shutdown_openocd = CONTINUE_MAIN_LOOP; /* store received signal to exit application by killing ourselves */ static int last_signal; @@ -72,7 +77,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c memset(&c->sin, 0, sizeof(c->sin)); c->cmd_ctx = copy_command_context(cmd_ctx); c->service = service; - c->input_pending = 0; + c->input_pending = false; c->priv = NULL; c->next = NULL; @@ -258,11 +263,11 @@ int add_service(char *name, memset(&c->sin, 0, sizeof(c->sin)); c->sin.sin_family = AF_INET; - if (bindto_name == NULL) + if (!bindto_name) c->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else { hp = gethostbyname(bindto_name); - if (hp == NULL) { + if (!hp) { LOG_ERROR("couldn't resolve bindto address: %s", bindto_name); close_socket(c->fd); free_service(c); @@ -321,7 +326,7 @@ int add_service(char *name, #endif } else if (c->type == CONNECTION_PIPE) { #ifdef _WIN32 - /* we currenty do not support named pipes under win32 + /* we currently do not support named pipes under win32 * so exit openocd for now */ LOG_ERROR("Named pipes currently not supported under this os"); free_service(c); @@ -360,6 +365,35 @@ static void remove_connections(struct service *service) } } +int remove_service(const char *name, const char *port) +{ + struct service *tmp; + struct service *prev; + + prev = services; + + for (tmp = services; tmp; prev = tmp, tmp = tmp->next) { + if (!strcmp(tmp->name, name) && !strcmp(tmp->port, port)) { + remove_connections(tmp); + + if (tmp == services) + services = tmp->next; + else + prev->next = tmp->next; + + if (tmp->type != CONNECTION_STDINOUT) + close_socket(tmp->fd); + + free(tmp->priv); + free_service(tmp); + + return ERROR_OK; + } + } + + return ERROR_OK; +} + static int remove_services(void) { struct service *c = services; @@ -370,19 +404,14 @@ static int remove_services(void) remove_connections(c); - if (c->name) - free(c->name); + free(c->name); if (c->type == CONNECTION_PIPE) { if (c->fd != -1) close(c->fd); } - if (c->port) - free(c->port); - - if (c->priv) - free(c->priv); - + free(c->port); + free(c->priv); /* delete service */ free(c); @@ -408,12 +437,14 @@ int server_loop(struct command_context *command_context) /* used in accept() */ int retval; + int64_t next_event = timeval_ms() + polling_period; + #ifndef _WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) LOG_ERROR("couldn't set SIGPIPE to SIG_IGN"); #endif - while (!shutdown_openocd) { + while (shutdown_openocd == CONTINUE_MAIN_LOOP) { /* monitor sockets for activity */ fd_max = 0; FD_ZERO(&read_fds); @@ -449,7 +480,12 @@ int server_loop(struct command_context *command_context) retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv); } else { /* Every 100ms, can be changed with "poll_period" command */ - tv.tv_usec = polling_period * 1000; + int timeout_ms = next_event - timeval_ms(); + if (timeout_ms < 0) + timeout_ms = 0; + else if (timeout_ms > polling_period) + timeout_ms = polling_period; + tv.tv_usec = timeout_ms * 1000; /* Only while we're sleeping we'll let others run */ openocd_sleep_prelude(); kept_alive(); @@ -482,7 +518,8 @@ int server_loop(struct command_context *command_context) if (retval == 0) { /* We only execute these callbacks when there was nothing to do or we timed *out */ - target_call_timer_callbacks(); + target_call_timer_callbacks_now(); + next_event = target_timer_next_event(); process_jim_events(command_context); FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */ @@ -529,7 +566,7 @@ int server_loop(struct command_context *command_context) struct connection *c; for (c = service->connections; c; ) { - if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending) { + if ((c->fd >= 0 && FD_ISSET(c->fd, &read_fds)) || c->input_pending) { retval = service->input(c); if (retval != ERROR_OK) { struct connection *next = c->next; @@ -537,7 +574,7 @@ int server_loop(struct command_context *command_context) service->type == CONNECTION_STDINOUT) { /* if connection uses a pipe then * shutdown openocd on error */ - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_REQUESTED; } remove_connection(service, c); LOG_INFO("dropped '%s' connection", @@ -555,20 +592,24 @@ int server_loop(struct command_context *command_context) MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE; } #endif } - return shutdown_openocd != 2 ? ERROR_OK : ERROR_FAIL; + /* when quit for signal or CTRL-C, run (eventually user implemented) "shutdown" */ + if (shutdown_openocd == SHUTDOWN_WITH_SIGNAL_CODE) + command_run_line(command_context, "shutdown"); + + return shutdown_openocd == SHUTDOWN_WITH_ERROR_CODE ? ERROR_FAIL : ERROR_OK; } -void sig_handler(int sig) +static void sig_handler(int sig) { /* store only first signal that hits us */ - if (!shutdown_openocd) { + if (shutdown_openocd == CONTINUE_MAIN_LOOP) { + shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE; last_signal = sig; - shutdown_openocd = 1; LOG_DEBUG("Terminating on Signal %d", sig); } else LOG_DEBUG("Ignored extra Signal %d", sig); @@ -576,9 +617,9 @@ void sig_handler(int sig) #ifdef _WIN32 -BOOL WINAPI ControlHandler(DWORD dwCtrlType) +BOOL WINAPI control_handler(DWORD ctrl_type) { - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE; return TRUE; } #else @@ -594,25 +635,39 @@ static void sigkey_handler(int sig) #endif -int server_preinit(void) +int server_host_os_entry(void) { /* this currently only calls WSAStartup on native win32 systems * before any socket operations are performed. * This is an issue if you call init in your config script */ #ifdef _WIN32 - WORD wVersionRequested; - WSADATA wsaData; + WORD version_requested; + WSADATA wsadata; - wVersionRequested = MAKEWORD(2, 2); + version_requested = MAKEWORD(2, 2); - if (WSAStartup(wVersionRequested, &wsaData) != 0) { + if (WSAStartup(version_requested, &wsadata) != 0) { LOG_ERROR("Failed to Open Winsock"); return ERROR_FAIL; } +#endif + return ERROR_OK; +} +int server_host_os_close(void) +{ +#ifdef _WIN32 + WSACleanup(); +#endif + return ERROR_OK; +} + +int server_preinit(void) +{ +#ifdef _WIN32 /* register ctrl-c handler */ - SetConsoleCtrlHandler(ControlHandler, TRUE); + SetConsoleCtrlHandler(control_handler, TRUE); signal(SIGBREAK, sig_handler); signal(SIGINT, sig_handler); @@ -651,8 +706,7 @@ int server_quit(void) target_quit(); #ifdef _WIN32 - WSACleanup(); - SetConsoleCtrlHandler(ControlHandler, FALSE); + SetConsoleCtrlHandler(control_handler, FALSE); return ERROR_OK; #endif @@ -666,6 +720,8 @@ void server_free(void) tcl_service_free(); telnet_service_free(); jsp_service_free(); + + free(bindto_name); } void exit_on_signal(int sig) @@ -702,11 +758,11 @@ COMMAND_HANDLER(handle_shutdown_command) { LOG_USER("shutdown command invoked"); - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_REQUESTED; if (CMD_ARGC == 1) { if (!strcmp(CMD_ARGV[0], "error")) { - shutdown_openocd = 2; + shutdown_openocd = SHUTDOWN_WITH_ERROR_CODE; return ERROR_FAIL; } } @@ -730,7 +786,7 @@ COMMAND_HANDLER(handle_bindto_command) { switch (CMD_ARGC) { case 0: - command_print(CMD_CTX, "bindto name: %s", bindto_name); + command_print(CMD, "bindto name: %s", bindto_name); break; case 1: free(bindto_name); @@ -760,7 +816,7 @@ static const struct command_registration server_command_handlers[] = { { .name = "bindto", .handler = &handle_bindto_command, - .mode = COMMAND_ANY, + .mode = COMMAND_CONFIG, .usage = "[name]", .help = "Specify address by name on which to listen for " "incoming TCP/IP connections", @@ -771,15 +827,15 @@ static const struct command_registration server_command_handlers[] = { int server_register_commands(struct command_context *cmd_ctx) { int retval = telnet_register_commands(cmd_ctx); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; retval = tcl_register_commands(cmd_ctx); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; retval = jsp_register_commands(cmd_ctx); - if (ERROR_OK != retval) + if (retval != ERROR_OK) return retval; return register_commands(cmd_ctx, NULL, server_command_handlers); @@ -789,7 +845,7 @@ COMMAND_HELPER(server_port_command, unsigned short *out) { switch (CMD_ARGC) { case 0: - command_print(CMD_CTX, "%d", *out); + command_print(CMD, "%d", *out); break; case 1: { @@ -808,7 +864,7 @@ COMMAND_HELPER(server_pipe_command, char **out) { switch (CMD_ARGC) { case 0: - command_print(CMD_CTX, "%s", *out); + command_print(CMD, "%s", *out); break; case 1: {