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