server: remove connection limit from tcl and telnet servers
[fw/openocd] / src / server / server.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2007-2010 Ã˜yvind Harboe                                 *
6  *   oyvind.harboe@zylin.com                                               *
7  *                                                                         *
8  *   Copyright (C) 2008 by Spencer Oliver                                  *
9  *   spen@spen-soft.co.uk                                                  *
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  *   This program is distributed in the hope that it will be useful,       *
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19  *   GNU General Public License for more details.                          *
20  *                                                                         *
21  *   You should have received a copy of the GNU General Public License     *
22  *   along with this program; if not, write to the                         *
23  *   Free Software Foundation, Inc.,                                       *
24  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
25  ***************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "server.h"
32 #include <target/target.h>
33 #include <target/target_request.h>
34 #include <target/openrisc/jsp_server.h>
35 #include "openocd.h"
36 #include "tcl_server.h"
37 #include "telnet_server.h"
38
39 #include <signal.h>
40
41 #ifndef _WIN32
42 #include <netinet/tcp.h>
43 #endif
44
45 static struct service *services;
46
47 /* shutdown_openocd == 1: exit the main event loop, and quit the
48  * debugger; 2: quit with non-zero return code */
49 static int shutdown_openocd;
50
51 /* store received signal to exit application by killing ourselves */
52 static int last_signal;
53
54 /* set the polling period to 100ms */
55 static int polling_period = 100;
56
57 static int add_connection(struct service *service, struct command_context *cmd_ctx)
58 {
59         socklen_t address_size;
60         struct connection *c, **p;
61         int retval;
62         int flag = 1;
63
64         c = malloc(sizeof(struct connection));
65         c->fd = -1;
66         c->fd_out = -1;
67         memset(&c->sin, 0, sizeof(c->sin));
68         c->cmd_ctx = copy_command_context(cmd_ctx);
69         c->service = service;
70         c->input_pending = 0;
71         c->priv = NULL;
72         c->next = NULL;
73
74         if (service->type == CONNECTION_TCP) {
75                 address_size = sizeof(c->sin);
76
77                 c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
78                 c->fd_out = c->fd;
79
80                 /* This increases performance dramatically for e.g. GDB load which
81                  * does not have a sliding window protocol.
82                  *
83                  * Ignore errors from this fn as it probably just means less performance
84                  */
85                 setsockopt(c->fd,       /* socket affected */
86                         IPPROTO_TCP,                    /* set option at TCP level */
87                         TCP_NODELAY,                    /* name of option */
88                         (char *)&flag,                  /* the cast is historical cruft */
89                         sizeof(int));                   /* length of option value */
90
91                 LOG_INFO("accepting '%s' connection on tcp/%s", service->name, service->port);
92                 retval = service->new_connection(c);
93                 if (retval != ERROR_OK) {
94                         close_socket(c->fd);
95                         LOG_ERROR("attempted '%s' connection rejected", service->name);
96                         command_done(c->cmd_ctx);
97                         free(c);
98                         return retval;
99                 }
100         } else if (service->type == CONNECTION_STDINOUT) {
101                 c->fd = service->fd;
102                 c->fd_out = fileno(stdout);
103
104 #ifdef _WIN32
105                 /* we are using stdin/out so ignore ctrl-c under windoze */
106                 SetConsoleCtrlHandler(NULL, TRUE);
107 #endif
108
109                 /* do not check for new connections again on stdin */
110                 service->fd = -1;
111
112                 LOG_INFO("accepting '%s' connection from pipe", service->name);
113                 retval = service->new_connection(c);
114                 if (retval != ERROR_OK) {
115                         LOG_ERROR("attempted '%s' connection rejected", service->name);
116                         command_done(c->cmd_ctx);
117                         free(c);
118                         return retval;
119                 }
120         } else if (service->type == CONNECTION_PIPE) {
121                 c->fd = service->fd;
122                 /* do not check for new connections again on stdin */
123                 service->fd = -1;
124
125                 char *out_file = alloc_printf("%so", service->port);
126                 c->fd_out = open(out_file, O_WRONLY);
127                 free(out_file);
128                 if (c->fd_out == -1) {
129                         LOG_ERROR("could not open %s", service->port);
130                         exit(1);
131                 }
132
133                 LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
134                 retval = service->new_connection(c);
135                 if (retval != ERROR_OK) {
136                         LOG_ERROR("attempted '%s' connection rejected", service->name);
137                         command_done(c->cmd_ctx);
138                         free(c);
139                         return retval;
140                 }
141         }
142
143         /* add to the end of linked list */
144         for (p = &service->connections; *p; p = &(*p)->next)
145                 ;
146         *p = c;
147
148         if (service->max_connections != CONNECTION_LIMIT_UNLIMITED)
149                 service->max_connections--;
150
151         return ERROR_OK;
152 }
153
154 static int remove_connection(struct service *service, struct connection *connection)
155 {
156         struct connection **p = &service->connections;
157         struct connection *c;
158
159         /* find connection */
160         while ((c = *p)) {
161                 if (c->fd == connection->fd) {
162                         service->connection_closed(c);
163                         if (service->type == CONNECTION_TCP)
164                                 close_socket(c->fd);
165                         else if (service->type == CONNECTION_PIPE) {
166                                 /* The service will listen to the pipe again */
167                                 c->service->fd = c->fd;
168                         }
169
170                         command_done(c->cmd_ctx);
171
172                         /* delete connection */
173                         *p = c->next;
174                         free(c);
175
176                         if (service->max_connections != CONNECTION_LIMIT_UNLIMITED)
177                                 service->max_connections++;
178
179                         break;
180                 }
181
182                 /* redirect p to next list pointer */
183                 p = &(*p)->next;
184         }
185
186         return ERROR_OK;
187 }
188
189 /* FIX! make service return error instead of invoking exit() */
190 int add_service(char *name,
191         const char *port,
192         int max_connections,
193         new_connection_handler_t new_connection_handler,
194         input_handler_t input_handler,
195         connection_closed_handler_t connection_closed_handler,
196         void *priv)
197 {
198         struct service *c, **p;
199         int so_reuseaddr_option = 1;
200
201         c = malloc(sizeof(struct service));
202
203         c->name = strdup(name);
204         c->port = strdup(port);
205         c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */
206         c->fd = -1;
207         c->connections = NULL;
208         c->new_connection = new_connection_handler;
209         c->input = input_handler;
210         c->connection_closed = connection_closed_handler;
211         c->priv = priv;
212         c->next = NULL;
213         long portnumber;
214         if (strcmp(c->port, "pipe") == 0)
215                 c->type = CONNECTION_STDINOUT;
216         else {
217                 char *end;
218                 portnumber = strtol(c->port, &end, 0);
219                 if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) {
220                         c->portnumber = portnumber;
221                         c->type = CONNECTION_TCP;
222                 } else
223                         c->type = CONNECTION_PIPE;
224         }
225
226         if (c->type == CONNECTION_TCP) {
227                 c->max_connections = max_connections;
228
229                 c->fd = socket(AF_INET, SOCK_STREAM, 0);
230                 if (c->fd == -1) {
231                         LOG_ERROR("error creating socket: %s", strerror(errno));
232                         exit(-1);
233                 }
234
235                 setsockopt(c->fd,
236                         SOL_SOCKET,
237                         SO_REUSEADDR,
238                         (void *)&so_reuseaddr_option,
239                         sizeof(int));
240
241                 socket_nonblock(c->fd);
242
243                 memset(&c->sin, 0, sizeof(c->sin));
244                 c->sin.sin_family = AF_INET;
245                 c->sin.sin_addr.s_addr = INADDR_ANY;
246                 c->sin.sin_port = htons(c->portnumber);
247
248                 if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) {
249                         LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
250                         exit(-1);
251                 }
252
253 #ifndef _WIN32
254                 int segsize = 65536;
255                 setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG,  &segsize, sizeof(int));
256 #endif
257                 int window_size = 128 * 1024;
258
259                 /* These setsockopt()s must happen before the listen() */
260
261                 setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF,
262                         (char *)&window_size, sizeof(window_size));
263                 setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF,
264                         (char *)&window_size, sizeof(window_size));
265
266                 if (listen(c->fd, 1) == -1) {
267                         LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
268                         exit(-1);
269                 }
270         } else if (c->type == CONNECTION_STDINOUT) {
271                 c->fd = fileno(stdin);
272
273 #ifdef _WIN32
274                 /* for win32 set stdin/stdout to binary mode */
275                 if (_setmode(_fileno(stdout), _O_BINARY) < 0)
276                         LOG_WARNING("cannot change stdout mode to binary");
277                 if (_setmode(_fileno(stdin), _O_BINARY) < 0)
278                         LOG_WARNING("cannot change stdin mode to binary");
279                 if (_setmode(_fileno(stderr), _O_BINARY) < 0)
280                         LOG_WARNING("cannot change stderr mode to binary");
281 #else
282                 socket_nonblock(c->fd);
283 #endif
284         } else if (c->type == CONNECTION_PIPE) {
285 #ifdef _WIN32
286                 /* we currenty do not support named pipes under win32
287                  * so exit openocd for now */
288                 LOG_ERROR("Named pipes currently not supported under this os");
289                 exit(1);
290 #else
291                 /* Pipe we're reading from */
292                 c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
293                 if (c->fd == -1) {
294                         LOG_ERROR("could not open %s", c->port);
295                         exit(1);
296                 }
297 #endif
298         }
299
300         /* add to the end of linked list */
301         for (p = &services; *p; p = &(*p)->next)
302                 ;
303         *p = c;
304
305         return ERROR_OK;
306 }
307
308 static int remove_services(void)
309 {
310         struct service *c = services;
311
312         /* loop service */
313         while (c) {
314                 struct service *next = c->next;
315
316                 if (c->name)
317                         free(c->name);
318
319                 if (c->type == CONNECTION_PIPE) {
320                         if (c->fd != -1)
321                                 close(c->fd);
322                 }
323                 if (c->port)
324                         free(c->port);
325
326                 if (c->priv)
327                         free(c->priv);
328
329                 /* delete service */
330                 free(c);
331
332                 /* remember the last service for unlinking */
333                 c = next;
334         }
335
336         services = NULL;
337
338         return ERROR_OK;
339 }
340
341 int server_loop(struct command_context *command_context)
342 {
343         struct service *service;
344
345         bool poll_ok = true;
346
347         /* used in select() */
348         fd_set read_fds;
349         int fd_max;
350
351         /* used in accept() */
352         int retval;
353
354 #ifndef _WIN32
355         if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
356                 LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
357 #endif
358
359         while (!shutdown_openocd) {
360                 /* monitor sockets for activity */
361                 fd_max = 0;
362                 FD_ZERO(&read_fds);
363
364                 /* add service and connection fds to read_fds */
365                 for (service = services; service; service = service->next) {
366                         if (service->fd != -1) {
367                                 /* listen for new connections */
368                                 FD_SET(service->fd, &read_fds);
369
370                                 if (service->fd > fd_max)
371                                         fd_max = service->fd;
372                         }
373
374                         if (service->connections) {
375                                 struct connection *c;
376
377                                 for (c = service->connections; c; c = c->next) {
378                                         /* check for activity on the connection */
379                                         FD_SET(c->fd, &read_fds);
380                                         if (c->fd > fd_max)
381                                                 fd_max = c->fd;
382                                 }
383                         }
384                 }
385
386                 struct timeval tv;
387                 tv.tv_sec = 0;
388                 if (poll_ok) {
389                         /* we're just polling this iteration, this is faster on embedded
390                          * hosts */
391                         tv.tv_usec = 0;
392                         retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
393                 } else {
394                         /* Every 100ms, can be changed with "poll_period" command */
395                         tv.tv_usec = polling_period * 1000;
396                         /* Only while we're sleeping we'll let others run */
397                         openocd_sleep_prelude();
398                         kept_alive();
399                         retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
400                         openocd_sleep_postlude();
401                 }
402
403                 if (retval == -1) {
404 #ifdef _WIN32
405
406                         errno = WSAGetLastError();
407
408                         if (errno == WSAEINTR)
409                                 FD_ZERO(&read_fds);
410                         else {
411                                 LOG_ERROR("error during select: %s", strerror(errno));
412                                 exit(-1);
413                         }
414 #else
415
416                         if (errno == EINTR)
417                                 FD_ZERO(&read_fds);
418                         else {
419                                 LOG_ERROR("error during select: %s", strerror(errno));
420                                 exit(-1);
421                         }
422 #endif
423                 }
424
425                 if (retval == 0) {
426                         /* We only execute these callbacks when there was nothing to do or we timed
427                          *out */
428                         target_call_timer_callbacks();
429                         process_jim_events(command_context);
430
431                         FD_ZERO(&read_fds);     /* eCos leaves read_fds unchanged in this case!  */
432
433                         /* We timed out/there was nothing to do, timeout rather than poll next time
434                          **/
435                         poll_ok = false;
436                 } else {
437                         /* There was something to do, next time we'll just poll */
438                         poll_ok = true;
439                 }
440
441                 /* This is a simple back-off algorithm where we immediately
442                  * re-poll if we did something this time around.
443                  *
444                  * This greatly improves performance of DCC.
445                  */
446                 poll_ok = poll_ok || target_got_message();
447
448                 for (service = services; service; service = service->next) {
449                         /* handle new connections on listeners */
450                         if ((service->fd != -1)
451                             && (FD_ISSET(service->fd, &read_fds))) {
452                                 if (service->max_connections != 0)
453                                         add_connection(service, command_context);
454                                 else {
455                                         if (service->type == CONNECTION_TCP) {
456                                                 struct sockaddr_in sin;
457                                                 socklen_t address_size = sizeof(sin);
458                                                 int tmp_fd;
459                                                 tmp_fd = accept(service->fd,
460                                                                 (struct sockaddr *)&service->sin,
461                                                                 &address_size);
462                                                 close_socket(tmp_fd);
463                                         }
464                                         LOG_INFO(
465                                                 "rejected '%s' connection, no more connections allowed",
466                                                 service->name);
467                                 }
468                         }
469
470                         /* handle activity on connections */
471                         if (service->connections) {
472                                 struct connection *c;
473
474                                 for (c = service->connections; c; ) {
475                                         if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending) {
476                                                 retval = service->input(c);
477                                                 if (retval != ERROR_OK) {
478                                                         struct connection *next = c->next;
479                                                         if (service->type == CONNECTION_PIPE ||
480                                                                         service->type == CONNECTION_STDINOUT) {
481                                                                 /* if connection uses a pipe then
482                                                                  * shutdown openocd on error */
483                                                                 shutdown_openocd = 1;
484                                                         }
485                                                         remove_connection(service, c);
486                                                         LOG_INFO("dropped '%s' connection",
487                                                                 service->name);
488                                                         c = next;
489                                                         continue;
490                                                 }
491                                         }
492                                         c = c->next;
493                                 }
494                         }
495                 }
496
497 #ifdef _WIN32
498                 MSG msg;
499                 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
500                         if (msg.message == WM_QUIT)
501                                 shutdown_openocd = 1;
502                 }
503 #endif
504         }
505
506         return shutdown_openocd != 2 ? ERROR_OK : ERROR_FAIL;
507 }
508
509 #ifdef _WIN32
510 BOOL WINAPI ControlHandler(DWORD dwCtrlType)
511 {
512         shutdown_openocd = 1;
513         return TRUE;
514 }
515 #endif
516
517 void sig_handler(int sig)
518 {
519         /* store only first signal that hits us */
520         if (!last_signal)
521                 last_signal = sig;
522         shutdown_openocd = 1;
523 }
524
525 int server_preinit(void)
526 {
527         /* this currently only calls WSAStartup on native win32 systems
528          * before any socket operations are performed.
529          * This is an issue if you call init in your config script */
530
531 #ifdef _WIN32
532         WORD wVersionRequested;
533         WSADATA wsaData;
534
535         wVersionRequested = MAKEWORD(2, 2);
536
537         if (WSAStartup(wVersionRequested, &wsaData) != 0) {
538                 LOG_ERROR("Failed to Open Winsock");
539                 exit(-1);
540         }
541
542         /* register ctrl-c handler */
543         SetConsoleCtrlHandler(ControlHandler, TRUE);
544
545         signal(SIGBREAK, sig_handler);
546 #endif
547         signal(SIGINT, sig_handler);
548         signal(SIGTERM, sig_handler);
549         signal(SIGABRT, sig_handler);
550
551         return ERROR_OK;
552 }
553
554 int server_init(struct command_context *cmd_ctx)
555 {
556         int ret = tcl_init();
557         if (ERROR_OK != ret)
558                 return ret;
559
560         return telnet_init("Open On-Chip Debugger");
561 }
562
563 int server_quit(void)
564 {
565         remove_services();
566         target_quit();
567
568 #ifdef _WIN32
569         WSACleanup();
570         SetConsoleCtrlHandler(ControlHandler, FALSE);
571
572         return ERROR_OK;
573 #endif
574
575         /* return signal number so we can kill ourselves */
576         return last_signal;
577 }
578
579 void exit_on_signal(int sig)
580 {
581 #ifndef _WIN32
582         /* bring back default system handler and kill yourself */
583         signal(sig, SIG_DFL);
584         kill(getpid(), sig);
585 #endif
586 }
587
588 int connection_write(struct connection *connection, const void *data, int len)
589 {
590         if (len == 0) {
591                 /* successful no-op. Sockets and pipes behave differently here... */
592                 return 0;
593         }
594         if (connection->service->type == CONNECTION_TCP)
595                 return write_socket(connection->fd_out, data, len);
596         else
597                 return write(connection->fd_out, data, len);
598 }
599
600 int connection_read(struct connection *connection, void *data, int len)
601 {
602         if (connection->service->type == CONNECTION_TCP)
603                 return read_socket(connection->fd, data, len);
604         else
605                 return read(connection->fd, data, len);
606 }
607
608 /* tell the server we want to shut down */
609 COMMAND_HANDLER(handle_shutdown_command)
610 {
611         LOG_USER("shutdown command invoked");
612
613         shutdown_openocd = 1;
614
615         if (CMD_ARGC == 1) {
616                 if (!strcmp(CMD_ARGV[0], "error")) {
617                         shutdown_openocd = 2;
618                         return ERROR_FAIL;
619                 }
620         }
621
622         return ERROR_COMMAND_CLOSE_CONNECTION;
623 }
624
625 COMMAND_HANDLER(handle_poll_period_command)
626 {
627         if (CMD_ARGC == 0)
628                 LOG_WARNING("You need to set a period value");
629         else
630                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], polling_period);
631
632         LOG_INFO("set servers polling period to %ums", polling_period);
633
634         return ERROR_OK;
635 }
636
637 static const struct command_registration server_command_handlers[] = {
638         {
639                 .name = "shutdown",
640                 .handler = &handle_shutdown_command,
641                 .mode = COMMAND_ANY,
642                 .usage = "",
643                 .help = "shut the server down",
644         },
645         {
646                 .name = "poll_period",
647                 .handler = &handle_poll_period_command,
648                 .mode = COMMAND_ANY,
649                 .usage = "",
650                 .help = "set the servers polling period",
651         },
652         COMMAND_REGISTRATION_DONE
653 };
654
655 int server_register_commands(struct command_context *cmd_ctx)
656 {
657         int retval = telnet_register_commands(cmd_ctx);
658         if (ERROR_OK != retval)
659                 return retval;
660
661         retval = tcl_register_commands(cmd_ctx);
662         if (ERROR_OK != retval)
663                 return retval;
664
665         retval = jsp_register_commands(cmd_ctx);
666         if (ERROR_OK != retval)
667                 return retval;
668
669         return register_commands(cmd_ctx, NULL, server_command_handlers);
670 }
671
672 COMMAND_HELPER(server_port_command, unsigned short *out)
673 {
674         switch (CMD_ARGC) {
675                 case 0:
676                         command_print(CMD_CTX, "%d", *out);
677                         break;
678                 case 1:
679                 {
680                         uint16_t port;
681                         COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
682                         *out = port;
683                         break;
684                 }
685                 default:
686                         return ERROR_COMMAND_SYNTAX_ERROR;
687         }
688         return ERROR_OK;
689 }
690
691 COMMAND_HELPER(server_pipe_command, char **out)
692 {
693         switch (CMD_ARGC) {
694                 case 0:
695                         command_print(CMD_CTX, "%s", *out);
696                         break;
697                 case 1:
698                 {
699                         if (CMD_CTX->mode == COMMAND_EXEC) {
700                                 LOG_WARNING("unable to change server port after init");
701                                 return ERROR_COMMAND_ARGUMENT_INVALID;
702                         }
703                         free(*out);
704                         *out = strdup(CMD_ARGV[0]);
705                         break;
706                 }
707                 default:
708                         return ERROR_COMMAND_SYNTAX_ERROR;
709         }
710         return ERROR_OK;
711 }