gdb: fix regression in gdb_port command
[fw/openocd] / src / server / server.c
index d2596112151058082132d82a6784114406b917f0..f762704dd3412f6c6761aeca0c14518311093626 100644 (file)
 #endif
 
 #include "server.h"
-#include "target.h"
+#include <target/target.h>
+#include "openocd.h"
+#include "tcl_server.h"
+#include "telnet_server.h"
 
 #include <signal.h>
 
 #endif
 
 
-service_t *services = NULL;
+struct service *services = NULL;
 
 /* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
 static int shutdown_openocd = 0;
-int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 /* set when using pipes rather than tcp */
 int server_use_pipes = 0;
 
-int add_connection(service_t *service, command_context_t *cmd_ctx)
+int add_connection(struct service *service, struct command_context *cmd_ctx)
 {
        socklen_t address_size;
-       connection_t *c, **p;
+       struct connection *c, **p;
        int retval;
        int flag = 1;
 
-       c = malloc(sizeof(connection_t));
+       c = malloc(sizeof(struct connection));
        c->fd = -1;
        memset(&c->sin, 0, sizeof(c->sin));
        c->cmd_ctx = copy_command_context(cmd_ctx);
@@ -110,10 +112,10 @@ int add_connection(service_t *service, command_context_t *cmd_ctx)
        return ERROR_OK;
 }
 
-int remove_connection(service_t *service, connection_t *connection)
+int remove_connection(struct service *service, struct connection *connection)
 {
-       connection_t **p = &service->connections;
-       connection_t *c;
+       struct connection **p = &service->connections;
+       struct connection *c;
 
        /* find connection */
        while ((c = *p))
@@ -142,10 +144,10 @@ 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;
+       struct service *c, **p;
        int so_reuseaddr_option = 1;
 
-       c = malloc(sizeof(service_t));
+       c = malloc(sizeof(struct service));
 
        c->name = strdup(name);
        c->type = type;
@@ -233,8 +235,8 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
 
 int remove_service(unsigned short port)
 {
-       service_t **p = &services;
-       service_t *c;
+       struct service **p = &services;
+       struct service *c;
 
        /* find service */
        while ((c = *p))
@@ -261,12 +263,12 @@ int remove_service(unsigned short port)
 
 int remove_services(void)
 {
-       service_t *c = services;
+       struct service *c = services;
 
        /* loop service */
        while (c)
        {
-               service_t *next = c->next;
+               struct service *next = c->next;
 
                if (c->name)
                        free(c->name);
@@ -286,16 +288,14 @@ int remove_services(void)
        return ERROR_OK;
 }
 
-extern void openocd_sleep_prelude(void);
-extern void openocd_sleep_postlude(void);
-
-int server_loop(command_context_t *command_context)
+int server_loop(struct command_context *command_context)
 {
-       service_t *service;
+       struct service *service;
+
+       bool poll = true;
 
        /* used in select() */
        fd_set read_fds;
-       struct timeval tv;
        int fd_max;
 
        /* used in accept() */
@@ -306,13 +306,9 @@ int server_loop(command_context_t *command_context)
                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;
-
        while (!shutdown_openocd)
        {
-               /* monitor sockets for acitvity */
+               /* monitor sockets for activity */
                fd_max = 0;
                FD_ZERO(&read_fds);
 
@@ -330,7 +326,7 @@ int server_loop(command_context_t *command_context)
 
                        if (service->connections)
                        {
-                               connection_t *c;
+                               struct connection *c;
 
                                for (c = service->connections; c; c = c->next)
                                {
@@ -352,12 +348,24 @@ int server_loop(command_context_t *command_context)
 #endif
 #endif
 
-               openocd_sleep_prelude();
-               kept_alive();
-
-               /* Only while we're sleeping we'll let others run */
-               retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
-               openocd_sleep_postlude();
+               struct timeval tv;
+               tv.tv_sec = 0;
+               if (poll)
+               {
+                       /* we're just polling this iteration, this is faster on embedded
+                        * hosts */
+                       tv.tv_usec = 0;
+                       retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
+               } else
+               {
+                       /* Every 100ms */
+                       tv.tv_usec = 100000;
+                       /* Only while we're sleeping we'll let others run */
+                       openocd_sleep_prelude();
+                       kept_alive();
+                       retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
+                       openocd_sleep_postlude();
+               }
 
                if (retval == -1)
                {
@@ -386,15 +394,20 @@ int server_loop(command_context_t *command_context)
 #endif
                }
 
-               target_call_timer_callbacks();
-               process_jim_events ();
-
                if (retval == 0)
                {
-                       /* do regular tasks after at most 100ms */
-                       tv.tv_sec = 0;
-                       tv.tv_usec = 10000;
+                       /* We only execute these callbacks when there was nothing to do or we timed out */
+                       target_call_timer_callbacks();
+                       process_jim_events(command_context);
+
                        FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case!  */
+
+                       /* We timed out/there was nothing to do, timeout rather than poll next time */
+                       poll = false;
+               } else
+               {
+                       /* There was something to do, next time we'll just poll */
+                       poll = true;
                }
 
                for (service = services; service; service = service->next)
@@ -424,7 +437,7 @@ int server_loop(command_context_t *command_context)
                        /* handle activity on connections */
                        if (service->connections)
                        {
-                               connection_t *c;
+                               struct connection *c;
 
                                for (c = service->connections; c;)
                                {
@@ -432,7 +445,7 @@ int server_loop(command_context_t *command_context)
                                        {
                                                if ((retval = service->input(c)) != ERROR_OK)
                                                {
-                                                       connection_t *next = c->next;
+                                                       struct connection *next = c->next;
                                                        if (service->type == CONNECTION_PIPE)
                                                        {
                                                                /* if connection uses a pipe then shutdown openocd on error */
@@ -488,8 +501,12 @@ void sig_handler(int sig) {
 }
 #endif
 
-int server_init(void)
+int server_preinit(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;
@@ -522,6 +539,15 @@ int server_init(void)
        return ERROR_OK;
 }
 
+int server_init(struct command_context *cmd_ctx)
+{
+       int ret = tcl_init(cmd_ctx);
+       if (ERROR_OK != ret)
+               return ret;
+
+       return telnet_init("Open On-Chip Debugger");
+}
+
 int server_quit(void)
 {
        remove_services();
@@ -534,18 +560,52 @@ int server_quit(void)
        return ERROR_OK;
 }
 
-int server_register_commands(command_context_t *context)
+/* tell the server we want to shut down */
+COMMAND_HANDLER(handle_shutdown_command)
 {
-       register_command(context, NULL, "shutdown", handle_shutdown_command,
-                                        COMMAND_ANY, "shut the server down");
+       shutdown_openocd = 1;
 
-       return ERROR_OK;
+       return ERROR_COMMAND_CLOSE_CONNECTION;
 }
 
-/* tell the server we want to shut down */
-int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static const struct command_registration server_command_handlers[] = {
+       {
+               .name = "shutdown",
+               .handler = &handle_shutdown_command,
+               .mode = COMMAND_ANY,
+               .help = "shut the server down",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+int server_register_commands(struct command_context *cmd_ctx)
 {
-       shutdown_openocd = 1;
+       int retval = telnet_register_commands(cmd_ctx);
+       if (ERROR_OK != retval)
+               return retval;
 
-       return ERROR_COMMAND_CLOSE_CONNECTION;
+       retval = tcl_register_commands(cmd_ctx);
+       if (ERROR_OK != retval)
+               return retval;
+
+       return register_commands(cmd_ctx, NULL, server_command_handlers);
+}
+
+SERVER_PORT_COMMAND()
+{
+       switch (CMD_ARGC) {
+       case 0:
+               command_print(CMD_CTX, "%d", *out);
+               break;
+       case 1:
+       {
+               uint16_t port;
+               COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
+               *out = port;
+               break;
+       }
+       default:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+       return ERROR_OK;
 }