server: fix confusing wording for incoming tcp connections
[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 * 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 "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 on tcp/%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(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(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 service->type == CONNECTION_STDINOUT) {
470 /* if connection uses a pipe then
471 * shutdown openocd on error */
472 shutdown_openocd = 1;
473 }
474 remove_connection(service, c);
475 LOG_INFO("dropped '%s' connection",
476 service->name);
477 c = next;
478 continue;
479 }
480 }
481 c = c->next;
482 }
483 }
484 }
485
486 #ifdef _WIN32
487 MSG msg;
488 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
489 if (msg.message == WM_QUIT)
490 shutdown_openocd = 1;
491 }
492 #endif
493 }
494
495 return ERROR_OK;
496 }
497
498 #ifdef _WIN32
499 BOOL WINAPI ControlHandler(DWORD dwCtrlType)
500 {
501 shutdown_openocd = 1;
502 return TRUE;
503 }
504
505 void sig_handler(int sig)
506 {
507 shutdown_openocd = 1;
508 }
509 #endif
510
511 int server_preinit(void)
512 {
513 /* this currently only calls WSAStartup on native win32 systems
514 * before any socket operations are performed.
515 * This is an issue if you call init in your config script */
516
517 #ifdef _WIN32
518 WORD wVersionRequested;
519 WSADATA wsaData;
520
521 wVersionRequested = MAKEWORD(2, 2);
522
523 if (WSAStartup(wVersionRequested, &wsaData) != 0) {
524 LOG_ERROR("Failed to Open Winsock");
525 exit(-1);
526 }
527
528 /* register ctrl-c handler */
529 SetConsoleCtrlHandler(ControlHandler, TRUE);
530
531 signal(SIGINT, sig_handler);
532 signal(SIGTERM, sig_handler);
533 signal(SIGBREAK, sig_handler);
534 signal(SIGABRT, sig_handler);
535 #endif
536
537 return ERROR_OK;
538 }
539
540 int server_init(struct command_context *cmd_ctx)
541 {
542 int ret = tcl_init();
543 if (ERROR_OK != ret)
544 return ret;
545
546 return telnet_init("Open On-Chip Debugger");
547 }
548
549 int server_quit(void)
550 {
551 remove_services();
552
553 #ifdef _WIN32
554 WSACleanup();
555 SetConsoleCtrlHandler(ControlHandler, FALSE);
556 #endif
557
558 return ERROR_OK;
559 }
560
561 int connection_write(struct connection *connection, const void *data, int len)
562 {
563 if (len == 0) {
564 /* successful no-op. Sockets and pipes behave differently here... */
565 return 0;
566 }
567 if (connection->service->type == CONNECTION_TCP)
568 return write_socket(connection->fd_out, data, len);
569 else
570 return write(connection->fd_out, data, len);
571 }
572
573 int connection_read(struct connection *connection, void *data, int len)
574 {
575 if (connection->service->type == CONNECTION_TCP)
576 return read_socket(connection->fd, data, len);
577 else
578 return read(connection->fd, data, len);
579 }
580
581 /* tell the server we want to shut down */
582 COMMAND_HANDLER(handle_shutdown_command)
583 {
584 LOG_USER("shutdown command invoked");
585
586 shutdown_openocd = 1;
587
588 return ERROR_OK;
589 }
590
591 static const struct command_registration server_command_handlers[] = {
592 {
593 .name = "shutdown",
594 .handler = &handle_shutdown_command,
595 .mode = COMMAND_ANY,
596 .usage = "",
597 .help = "shut the server down",
598 },
599 COMMAND_REGISTRATION_DONE
600 };
601
602 int server_register_commands(struct command_context *cmd_ctx)
603 {
604 int retval = telnet_register_commands(cmd_ctx);
605 if (ERROR_OK != retval)
606 return retval;
607
608 retval = tcl_register_commands(cmd_ctx);
609 if (ERROR_OK != retval)
610 return retval;
611
612 return register_commands(cmd_ctx, NULL, server_command_handlers);
613 }
614
615 COMMAND_HELPER(server_port_command, unsigned short *out)
616 {
617 switch (CMD_ARGC) {
618 case 0:
619 command_print(CMD_CTX, "%d", *out);
620 break;
621 case 1:
622 {
623 uint16_t port;
624 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
625 *out = port;
626 break;
627 }
628 default:
629 return ERROR_COMMAND_SYNTAX_ERROR;
630 }
631 return ERROR_OK;
632 }
633
634 COMMAND_HELPER(server_pipe_command, char **out)
635 {
636 switch (CMD_ARGC) {
637 case 0:
638 command_print(CMD_CTX, "%s", *out);
639 break;
640 case 1:
641 {
642 if (CMD_CTX->mode == COMMAND_EXEC) {
643 LOG_WARNING("unable to change server port after init");
644 return ERROR_COMMAND_ARGUMENT_INVALID;
645 }
646 free(*out);
647 *out = strdup(CMD_ARGV[0]);
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)