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

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)