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

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)