server: read/write now goes through connection fn's
[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 static int remove_services(void)
242 {
243 struct service *c = services;
244
245 /* loop service */
246 while (c)
247 {
248 struct service *next = c->next;
249
250 if (c->name)
251 free(c->name);
252
253 if (c->priv)
254 free(c->priv);
255
256 /* delete service */
257 free(c);
258
259 /* remember the last service for unlinking */
260 c = next;
261 }
262
263 services = NULL;
264
265 return ERROR_OK;
266 }
267
268 int server_loop(struct command_context *command_context)
269 {
270 struct service *service;
271
272 bool poll_ok = true;
273
274 /* used in select() */
275 fd_set read_fds;
276 int fd_max;
277
278 /* used in accept() */
279 int retval;
280
281 #ifndef _WIN32
282 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
283 LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
284 #endif
285
286 while (!shutdown_openocd)
287 {
288 /* monitor sockets for activity */
289 fd_max = 0;
290 FD_ZERO(&read_fds);
291
292 /* add service and connection fds to read_fds */
293 for (service = services; service; service = service->next)
294 {
295 if (service->fd != -1)
296 {
297 /* listen for new connections */
298 FD_SET(service->fd, &read_fds);
299
300 if (service->fd > fd_max)
301 fd_max = service->fd;
302 }
303
304 if (service->connections)
305 {
306 struct connection *c;
307
308 for (c = service->connections; c; c = c->next)
309 {
310 /* check for activity on the connection */
311 FD_SET(c->fd, &read_fds);
312 if (c->fd > fd_max)
313 fd_max = c->fd;
314 }
315 }
316 }
317
318 struct timeval tv;
319 tv.tv_sec = 0;
320 if (poll_ok)
321 {
322 /* we're just polling this iteration, this is faster on embedded
323 * hosts */
324 tv.tv_usec = 0;
325 retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
326 } else
327 {
328 /* Every 100ms */
329 tv.tv_usec = 100000;
330 /* Only while we're sleeping we'll let others run */
331 openocd_sleep_prelude();
332 kept_alive();
333 retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
334 openocd_sleep_postlude();
335 }
336
337 if (retval == -1)
338 {
339 #ifdef _WIN32
340
341 errno = WSAGetLastError();
342
343 if (errno == WSAEINTR)
344 FD_ZERO(&read_fds);
345 else
346 {
347 LOG_ERROR("error during select: %s", strerror(errno));
348 exit(-1);
349 }
350 #else
351
352 if (errno == EINTR)
353 {
354 FD_ZERO(&read_fds);
355 }
356 else
357 {
358 LOG_ERROR("error during select: %s", strerror(errno));
359 exit(-1);
360 }
361 #endif
362 }
363
364 if (retval == 0)
365 {
366 /* We only execute these callbacks when there was nothing to do or we timed out */
367 target_call_timer_callbacks();
368 process_jim_events(command_context);
369
370 FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */
371
372 /* We timed out/there was nothing to do, timeout rather than poll next time */
373 poll_ok = false;
374 } else
375 {
376 /* There was something to do, next time we'll just poll */
377 poll_ok = true;
378 }
379
380 for (service = services; service; service = service->next)
381 {
382 /* handle new connections on listeners */
383 if ((service->fd != -1)
384 && (FD_ISSET(service->fd, &read_fds)))
385 {
386 if (service->max_connections > 0)
387 {
388 add_connection(service, command_context);
389 }
390 else
391 {
392 if (service->type == CONNECTION_TCP)
393 {
394 struct sockaddr_in sin;
395 socklen_t address_size = sizeof(sin);
396 int tmp_fd;
397 tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
398 close_socket(tmp_fd);
399 }
400 LOG_INFO("rejected '%s' connection, no more connections allowed", service->name);
401 }
402 }
403
404 /* handle activity on connections */
405 if (service->connections)
406 {
407 struct connection *c;
408
409 for (c = service->connections; c;)
410 {
411 if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending)
412 {
413 if ((retval = service->input(c)) != ERROR_OK)
414 {
415 struct connection *next = c->next;
416 if (service->type == CONNECTION_PIPE)
417 {
418 /* if connection uses a pipe then shutdown openocd on error */
419 shutdown_openocd = 1;
420 }
421 remove_connection(service, c);
422 LOG_INFO("dropped '%s' connection - error %d", service->name, retval);
423 c = next;
424 continue;
425 }
426 }
427 c = c->next;
428 }
429 }
430 }
431
432 #ifdef _WIN32
433 MSG msg;
434 while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
435 {
436 if (msg.message == WM_QUIT)
437 shutdown_openocd = 1;
438 }
439 #endif
440 }
441
442 return ERROR_OK;
443 }
444
445 #ifdef _WIN32
446 BOOL WINAPI ControlHandler(DWORD dwCtrlType)
447 {
448 shutdown_openocd = 1;
449 return TRUE;
450 }
451
452 void sig_handler(int sig) {
453 shutdown_openocd = 1;
454 }
455 #endif
456
457 int server_preinit(void)
458 {
459 /* this currently only calls WSAStartup on native win32 systems
460 * before any socket operations are performed.
461 * This is an issue if you call init in your config script */
462
463 #ifdef _WIN32
464 WORD wVersionRequested;
465 WSADATA wsaData;
466
467 wVersionRequested = MAKEWORD(2, 2);
468
469 if (WSAStartup(wVersionRequested, &wsaData) != 0)
470 {
471 LOG_ERROR("Failed to Open Winsock");
472 exit(-1);
473 }
474
475 if (server_use_pipes == 0)
476 {
477 /* register ctrl-c handler */
478 SetConsoleCtrlHandler(ControlHandler, TRUE);
479 }
480 else
481 {
482 /* we are using pipes so ignore ctrl-c */
483 SetConsoleCtrlHandler(NULL, TRUE);
484 }
485
486 signal(SIGINT, sig_handler);
487 signal(SIGTERM, sig_handler);
488 signal(SIGBREAK, sig_handler);
489 signal(SIGABRT, sig_handler);
490 #endif
491
492 return ERROR_OK;
493 }
494
495 int server_init(struct command_context *cmd_ctx)
496 {
497 int ret = tcl_init();
498 if (ERROR_OK != ret)
499 return ret;
500
501 return telnet_init("Open On-Chip Debugger");
502 }
503
504 int server_quit(void)
505 {
506 remove_services();
507
508 #ifdef _WIN32
509 WSACleanup();
510 SetConsoleCtrlHandler(ControlHandler, FALSE);
511 #endif
512
513 return ERROR_OK;
514 }
515
516 int connection_write(struct connection *connection, const void *data, int len)
517 {
518 if (len == 0)
519 {
520 /* successful no-op. Sockets and pipes behave differently here... */
521 return 0;
522 }
523 if (connection->service->type == CONNECTION_TCP)
524 {
525 return write_socket(connection->fd_out, data, len);
526 } else
527 {
528 return write(connection->fd_out, data, len);
529 }
530 }
531
532 int connection_read(struct connection *connection, void *data, int len)
533 {
534 if (connection->service->type == CONNECTION_TCP)
535 {
536 return read_socket(connection->fd, data, len);
537 } else
538 {
539 return read(connection->fd, data, len);
540 }
541 }
542
543 /* tell the server we want to shut down */
544 COMMAND_HANDLER(handle_shutdown_command)
545 {
546 LOG_USER("shutdown command invoked");
547
548 shutdown_openocd = 1;
549
550 return ERROR_OK;
551 }
552
553 static const struct command_registration server_command_handlers[] = {
554 {
555 .name = "shutdown",
556 .handler = &handle_shutdown_command,
557 .mode = COMMAND_ANY,
558 .help = "shut the server down",
559 },
560 COMMAND_REGISTRATION_DONE
561 };
562
563 int server_register_commands(struct command_context *cmd_ctx)
564 {
565 int retval = telnet_register_commands(cmd_ctx);
566 if (ERROR_OK != retval)
567 return retval;
568
569 retval = tcl_register_commands(cmd_ctx);
570 if (ERROR_OK != retval)
571 return retval;
572
573 return register_commands(cmd_ctx, NULL, server_command_handlers);
574 }
575
576 SERVER_PORT_COMMAND()
577 {
578 switch (CMD_ARGC) {
579 case 0:
580 command_print(CMD_CTX, "%d", *out);
581 break;
582 case 1:
583 {
584 uint16_t port;
585 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
586 *out = port;
587 break;
588 }
589 default:
590 return ERROR_INVALID_ARGUMENTS;
591 }
592 return ERROR_OK;
593 }

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)