server: add support for pipes
authorØyvind Harboe <oyvind.harboe@zylin.com>
Mon, 27 Sep 2010 06:50:49 +0000 (08:50 +0200)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Fri, 1 Oct 2010 08:26:08 +0000 (10:26 +0200)
-p/--pipe is now deprecated. Use '-c "gdb_port pipe;log_output openocd.log"'
instead. Warning logged.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
doc/openocd.texi
src/helper/options.c
src/server/gdb_server.c
src/server/server.c
src/server/server.h
src/server/tcl_server.c
src/server/telnet_server.c

index 230e47c9e44cb030d50f907f8bc0d74701928060..77a0ad3b73f7ea19eb7073b7f28f8a1f6d258705 100644 (file)
@@ -574,7 +574,6 @@ bash$ openocd --help
 --debug      | -d       set debug level <0-3>
 --log_output | -l       redirect log output to file <name>
 --command    | -c       run <command>
---pipe       | -p       use pipes when talking to gdb
 @end verbatim
 
 If you don't give any @option{-f} or @option{-c} options,
@@ -7052,11 +7051,12 @@ This would cause GDB to connect to the gdbserver on the local pc using port 3333
 @item
 A pipe connection is typically started as follows:
 @example
-target remote | openocd --pipe
+target remote | openocd -c "gdb_port pipe; log_output openocd.log"
 @end example
 This would cause GDB to run OpenOCD and communicate using pipes (stdin/stdout).
 Using this method has the advantage of GDB starting/stopping OpenOCD for the debug
-session.
+session. log_output sends the log output to a file to ensure that the pipe is
+not saturated when using higher debug level outputs.
 @end enumerate
 
 To list the available OpenOCD commands type @command{monitor help} on the
index 3a95df46d0799923f12af0f3b7c165eaf0c24f4b..df4676d2e322f773826320921800b7a807d9096e 100644 (file)
@@ -2,7 +2,7 @@
  *   Copyright (C) 2004, 2005 by Dominic Rath                              *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
- *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
+ *   Copyright (C) 2007-2010 Øyvind Harboe                                 *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -177,13 +177,9 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
                                        add_config_command(optarg);
                                }
                                break;
-                       case 'p':       /* --pipe | -p */
-#if BUILD_ECOSBOARD == 1
-                               /* pipes unsupported on hosted platforms */
-                               LOG_WARNING("pipes not supported on this platform");
-#else
-                               server_use_pipes = 1;
-#endif
+                       case 'p':
+                               LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; log_output openocd.log\"' instead.");
+                               add_config_command("gdb_port pipe; log_output openocd.log");
                                break;
                }
        }
@@ -198,7 +194,6 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
                LOG_OUTPUT("--debug      | -d\tset debug level <0-3>\n");
                LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
                LOG_OUTPUT("--command    | -c\trun <command>\n");
-               LOG_OUTPUT("--pipe       | -p\tuse pipes for gdb communication\n");
                exit(-1);
        }
 
index 54899589dc622fe5fda07e4c76c4d5d28c07bc56..7026ff21871869e5f2883cb891ee123451ecafa1 100644 (file)
@@ -2387,42 +2387,22 @@ static int gdb_input(struct connection *connection)
        return ERROR_OK;
 }
 
-static int gdb_target_start(struct target *target, uint16_t port)
+static int gdb_target_start(struct target *target, const char *port)
 {
-       bool use_pipes = 0 == port;
        struct gdb_service *gdb_service = malloc(sizeof(struct gdb_service));
        if (NULL == gdb_service)
                return -ENOMEM;
 
        gdb_service->target = target;
 
-       add_service("gdb", use_pipes ? CONNECTION_PIPE : CONNECTION_TCP,
+       return add_service("gdb",
                        port, 1, &gdb_new_connection, &gdb_input,
                        &gdb_connection_closed, gdb_service);
-
-       const char *name = target_name(target);
-       if (use_pipes)
-               LOG_DEBUG("gdb service for target '%s' using pipes", name);
-       else
-               LOG_DEBUG("gdb service for target '%s' on TCP port %u", name, port);
-       return ERROR_OK;
 }
 
 static int gdb_target_add_one(struct target *target)
 {
-       long portnumber_parsed;
-       /* If we can parse the port number
-        * then we increment the port number for the next target.
-        */
-       char *end_parse;
-       portnumber_parsed = strtol(gdb_port_next, &end_parse, 0);
-       if (!*end_parse)
-       {
-               LOG_ERROR("Illegal port number");
-               return ERROR_FAIL;
-       }
-
-       int retval = gdb_target_start(target, portnumber_parsed);
+       int retval = gdb_target_start(target, gdb_port_next);
        if (retval == ERROR_OK)
        {
                long portnumber;
index 435ddbb7d4854234785d7a87c1c421d268b353ef..c7e1e40cceb45c26de26930ddf49520f1fc0d4e4 100644 (file)
@@ -45,9 +45,6 @@ static struct service *services = NULL;
 /* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
 static int shutdown_openocd = 0;
 
-/* set when using pipes rather than tcp */
-int server_use_pipes = 0;
-
 static int add_connection(struct service *service, struct command_context *cmd_ctx)
 {
        socklen_t address_size;
@@ -80,7 +77,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c
                                (char *)&flag,          /* the cast is historical cruft */
                                sizeof(int));           /* length of option value */
 
-               LOG_INFO("accepting '%s' connection from %i", service->name, service->port);
+               LOG_INFO("accepting '%s' connection from %s", service->name, service->port);
                if ((retval = service->new_connection(c)) != ERROR_OK)
                {
                        close_socket(c->fd);
@@ -88,8 +85,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c
                        free(c);
                        return retval;
                }
-       }
-       else if (service->type == CONNECTION_PIPE)
+       } else if (service->type == CONNECTION_STDINOUT)
        {
                c->fd = service->fd;
                c->fd_out = fileno(stdout);
@@ -97,10 +93,29 @@ static int add_connection(struct service *service, struct command_context *cmd_c
                /* do not check for new connections again on stdin */
                service->fd = -1;
 
+               LOG_INFO("accepting '%s' connection from pipe", service->name);
+               if ((retval = service->new_connection(c)) != ERROR_OK)
+               {
+                       LOG_ERROR("attempted '%s' connection rejected", service->name);
+                       free(c);
+                       return retval;
+               }
+       } else if (service->type == CONNECTION_PIPE)
+       {
+               c->fd = service->fd;
                /* do not check for new connections again on stdin */
                service->fd = -1;
 
-               LOG_INFO("accepting '%s' connection from pipe", service->name);
+               char * out_file = alloc_printf("%so", service->port);
+               c->fd_out = open(out_file, O_WRONLY);
+               free(out_file);
+               if (c->fd_out == -1)
+               {
+                       LOG_ERROR("could not open %s", service->port);
+                       exit(1);
+               }
+
+               LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
                if ((retval = service->new_connection(c)) != ERROR_OK)
                {
                        LOG_ERROR("attempted '%s' connection rejected", service->name);
@@ -130,7 +145,14 @@ static int remove_connection(struct service *service, struct connection *connect
                {
                        service->connection_closed(c);
                        if (service->type == CONNECTION_TCP)
+                       {
                                close_socket(c->fd);
+                       } else if (service->type == CONNECTION_PIPE)
+                       {
+                               /* The service will listen to the pipe again */
+                               c->service->fd = c->fd;
+                       }
+
                        command_done(c->cmd_ctx);
 
                        /* delete connection */
@@ -148,7 +170,8 @@ static int remove_connection(struct service *service, struct connection *connect
        return ERROR_OK;
 }
 
-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)
+/* FIX! make service return error instead of invoking exit() */
+int add_service(char *name, const char *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)
 {
        struct service *c, **p;
        int so_reuseaddr_option = 1;
@@ -156,9 +179,8 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
        c = malloc(sizeof(struct service));
 
        c->name = strdup(name);
-       c->type = type;
-       c->port = port;
-       c->max_connections = max_connections;
+       c->port = strdup(port);
+       c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */
        c->fd = -1;
        c->connections = NULL;
        c->new_connection = new_connection_handler;
@@ -166,9 +188,28 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
        c->connection_closed = connection_closed_handler;
        c->priv = priv;
        c->next = NULL;
+       long portnumber;
+       if (strcmp(c->port, "pipe") == 0)
+       {
+               c->type = CONNECTION_STDINOUT;
+       } else
+       {
+               char *end;
+               strtol(c->port, &end, 0);
+               if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK))
+               {
+                       c->portnumber = portnumber;
+                       c->type = CONNECTION_TCP;
+               } else
+               {
+                       c->type = CONNECTION_PIPE;
+               }
+       }
 
-       if (type == CONNECTION_TCP)
+       if (c->type == CONNECTION_TCP)
        {
+               c->max_connections = max_connections;
+
                if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
                {
                        LOG_ERROR("error creating socket: %s", strerror(errno));
@@ -182,7 +223,7 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
                memset(&c->sin, 0, sizeof(c->sin));
                c->sin.sin_family = AF_INET;
                c->sin.sin_addr.s_addr = INADDR_ANY;
-               c->sin.sin_port = htons(port);
+               c->sin.sin_port = htons(c->portnumber);
 
                if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
                {
@@ -209,7 +250,7 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
                        exit(-1);
                }
        }
-       else if (type == CONNECTION_PIPE)
+       else if (c->type == CONNECTION_STDINOUT)
        {
                c->fd = fileno(stdin);
 
@@ -225,10 +266,15 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
                socket_nonblock(c->fd);
 #endif
        }
-       else
+       else if (c->type == CONNECTION_PIPE)
        {
-               LOG_ERROR("unknown connection type: %d", type);
-               exit(1);
+               /* Pipe we're reading from */
+               c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
+               if (c->fd == -1)
+               {
+                       LOG_ERROR("could not open %s", c->port);
+                       exit(1);
+               }
        }
 
        /* add to the end of linked list */
@@ -238,29 +284,6 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
        return ERROR_OK;
 }
 
-int add_service_pipe(char *name, const char *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)
-{
-       enum connection_type type = CONNECTION_TCP;
-       long portnumber;
-       char *end;
-       strtol(port, &end, 0);
-       if (!*end)
-       {
-               if ((parse_long(port, &portnumber) == ERROR_OK) && (portnumber == 0))
-               {
-                       type = CONNECTION_PIPE;
-               }
-       } else
-       {
-               LOG_ERROR("Illegal port number %s", port);
-               return ERROR_FAIL;
-       }
-       return add_service(name, type, portnumber, max_connections, new_connection_handler,
-                       input_handler, connection_closed_handler, priv);
-}
-
 static int remove_services(void)
 {
        struct service *c = services;
@@ -278,6 +301,8 @@ static int remove_services(void)
                        if (c->fd != -1)
                                close(c->fd);
                }
+               if (c->port)
+                       free((void *)c->port);
 
                if (c->priv)
                        free(c->priv);
index 2c9ed4457009d83a75ac63727410085bb318b3f5..face13867fabdadb084114d85a4bbf6fe8fa5340 100644 (file)
@@ -35,7 +35,8 @@
 enum connection_type
 {
        CONNECTION_TCP,
-       CONNECTION_PIPE
+       CONNECTION_PIPE,
+       CONNECTION_STDINOUT
 };
 
 struct connection
@@ -58,7 +59,8 @@ struct service
 {
        char *name;
        enum connection_type type;
-       unsigned short port;
+       const char *port;
+       unsigned short portnumber;
        int fd;
        struct sockaddr_in sin;
        int max_connections;
@@ -70,12 +72,7 @@ struct service
        struct service *next;
 };
 
-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 in_handler, connection_closed_handler_t close_handler,
-               void *priv);
-
-int add_service_pipe(char *name, const char *port,
+int add_service(char *name, const char *port,
                int max_connections, new_connection_handler_t new_connection_handler,
                input_handler_t in_handler, connection_closed_handler_t close_handler,
                void *priv);
@@ -115,8 +112,6 @@ SERVER_PIPE_COMMAND();
 
 SERVER_PORT_COMMAND();
 
-extern int server_use_pipes;
-
 #define ERROR_SERVER_REMOTE_CLOSED     (-400)
 #define ERROR_CONNECTION_REJECTED      (-401)
 
index f82cafefd5492fd1a7943d2fd7127122a2c8a31a..613eb23f9260190b0b7c56434e82a3acbeb24026 100644 (file)
@@ -166,7 +166,7 @@ int tcl_init(void)
                return ERROR_OK;
        }
 
-       return add_service_pipe("tcl", tcl_port, 1,
+       return add_service("tcl", tcl_port, 1,
                        &tcl_new_connection, &tcl_input,
                        &tcl_closed, NULL);
 }
index 420f5d70a05e407c27807caad310fadbeff4a00d..00b4b5d26b2013929aa23fbfbedfb1fdfcd11f95 100644 (file)
@@ -592,9 +592,7 @@ int telnet_init(char *banner)
 
        telnet_service->banner = banner;
 
-       add_service_pipe("telnet", telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);
-
-       return ERROR_OK;
+       return add_service("telnet", telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);
 }
 
 /* daemon configuration command telnet_port */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)