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

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)