1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2007-2010 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
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. *
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. *
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 ***************************************************************************/
31 #include <target/target.h>
33 #include "tcl_server.h"
34 #include "telnet_server.h"
39 #include <netinet/tcp.h>
43 static struct service
*services
= NULL
;
45 /* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
46 static int shutdown_openocd
= 0;
48 /* set when using pipes rather than tcp */
49 int server_use_pipes
= 0;
51 static int add_connection(struct service
*service
, struct command_context
*cmd_ctx
)
53 socklen_t address_size
;
54 struct connection
*c
, **p
;
58 c
= malloc(sizeof(struct connection
));
61 memset(&c
->sin
, 0, sizeof(c
->sin
));
62 c
->cmd_ctx
= copy_command_context(cmd_ctx
);
68 if (service
->type
== CONNECTION_TCP
)
70 address_size
= sizeof(c
->sin
);
72 c
->fd
= accept(service
->fd
, (struct sockaddr
*)&service
->sin
, &address_size
);
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 */
83 LOG_INFO("accepting '%s' connection from %i", service
->name
, service
->port
);
84 if ((retval
= service
->new_connection(c
)) != ERROR_OK
)
87 LOG_ERROR("attempted '%s' connection rejected", service
->name
);
92 else if (service
->type
== CONNECTION_PIPE
)
95 c
->fd_out
= fileno(stdout
);
97 /* do not check for new connections again on stdin */
100 /* do not check for new connections again on stdin */
103 LOG_INFO("accepting '%s' connection from pipe", service
->name
);
104 if ((retval
= service
->new_connection(c
)) != ERROR_OK
)
106 LOG_ERROR("attempted '%s' connection rejected", service
->name
);
112 /* add to the end of linked list */
113 for (p
= &service
->connections
; *p
; p
= &(*p
)->next
);
116 service
->max_connections
--;
121 static int remove_connection(struct service
*service
, struct connection
*connection
)
123 struct connection
**p
= &service
->connections
;
124 struct connection
*c
;
126 /* find connection */
129 if (c
->fd
== connection
->fd
)
131 service
->connection_closed(c
);
132 if (service
->type
== CONNECTION_TCP
)
134 command_done(c
->cmd_ctx
);
136 /* delete connection */
140 service
->max_connections
++;
144 /* redirect p to next list pointer */
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
)
153 struct service
*c
, **p
;
154 int so_reuseaddr_option
= 1;
156 c
= malloc(sizeof(struct service
));
158 c
->name
= strdup(name
);
161 c
->max_connections
= max_connections
;
163 c
->connections
= NULL
;
164 c
->new_connection
= new_connection_handler
;
165 c
->input
= input_handler
;
166 c
->connection_closed
= connection_closed_handler
;
170 if (type
== CONNECTION_TCP
)
172 if ((c
->fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
174 LOG_ERROR("error creating socket: %s", strerror(errno
));
178 setsockopt(c
->fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
180 socket_nonblock(c
->fd
);
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
);
187 if (bind(c
->fd
, (struct sockaddr
*)&c
->sin
, sizeof(c
->sin
)) == -1)
189 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
195 setsockopt(c
->fd
, IPPROTO_TCP
, TCP_MAXSEG
, &segsize
, sizeof(int));
197 int window_size
= 128 * 1024;
199 /* These setsockopt()s must happen before the listen() */
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
));
206 if (listen(c
->fd
, 1) == -1)
208 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
212 else if (type
== CONNECTION_PIPE
)
214 c
->fd
= fileno(stdin
);
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");
225 socket_nonblock(c
->fd
);
230 LOG_ERROR("unknown connection type: %d", type
);
234 /* add to the end of linked list */
235 for (p
= &services
; *p
; p
= &(*p
)->next
);
241 static int remove_services(void)
243 struct service
*c
= services
;
248 struct service
*next
= c
->next
;
259 /* remember the last service for unlinking */
268 int server_loop(struct command_context
*command_context
)
270 struct service
*service
;
274 /* used in select() */
278 /* used in accept() */
282 if (signal(SIGPIPE
, SIG_IGN
) == SIG_ERR
)
283 LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
286 while (!shutdown_openocd
)
288 /* monitor sockets for activity */
292 /* add service and connection fds to read_fds */
293 for (service
= services
; service
; service
= service
->next
)
295 if (service
->fd
!= -1)
297 /* listen for new connections */
298 FD_SET(service
->fd
, &read_fds
);
300 if (service
->fd
> fd_max
)
301 fd_max
= service
->fd
;
304 if (service
->connections
)
306 struct connection
*c
;
308 for (c
= service
->connections
; c
; c
= c
->next
)
310 /* check for activity on the connection */
311 FD_SET(c
->fd
, &read_fds
);
322 /* we're just polling this iteration, this is faster on embedded
325 retval
= socket_select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
330 /* Only while we're sleeping we'll let others run */
331 openocd_sleep_prelude();
333 retval
= socket_select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
334 openocd_sleep_postlude();
341 errno
= WSAGetLastError();
343 if (errno
== WSAEINTR
)
347 LOG_ERROR("error during select: %s", strerror(errno
));
358 LOG_ERROR("error during select: %s", strerror(errno
));
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
);
370 FD_ZERO(&read_fds
); /* eCos leaves read_fds unchanged in this case! */
372 /* We timed out/there was nothing to do, timeout rather than poll next time */
376 /* There was something to do, next time we'll just poll */
380 for (service
= services
; service
; service
= service
->next
)
382 /* handle new connections on listeners */
383 if ((service
->fd
!= -1)
384 && (FD_ISSET(service
->fd
, &read_fds
)))
386 if (service
->max_connections
> 0)
388 add_connection(service
, command_context
);
392 if (service
->type
== CONNECTION_TCP
)
394 struct sockaddr_in sin
;
395 socklen_t address_size
= sizeof(sin
);
397 tmp_fd
= accept(service
->fd
, (struct sockaddr
*)&service
->sin
, &address_size
);
398 close_socket(tmp_fd
);
400 LOG_INFO("rejected '%s' connection, no more connections allowed", service
->name
);
404 /* handle activity on connections */
405 if (service
->connections
)
407 struct connection
*c
;
409 for (c
= service
->connections
; c
;)
411 if ((FD_ISSET(c
->fd
, &read_fds
)) || c
->input_pending
)
413 if ((retval
= service
->input(c
)) != ERROR_OK
)
415 struct connection
*next
= c
->next
;
416 if (service
->type
== CONNECTION_PIPE
)
418 /* if connection uses a pipe then shutdown openocd on error */
419 shutdown_openocd
= 1;
421 remove_connection(service
, c
);
422 LOG_INFO("dropped '%s' connection - error %d", service
->name
, retval
);
434 while (PeekMessage(&msg
,NULL
,0,0,PM_REMOVE
))
436 if (msg
.message
== WM_QUIT
)
437 shutdown_openocd
= 1;
446 BOOL WINAPI
ControlHandler(DWORD dwCtrlType
)
448 shutdown_openocd
= 1;
452 void sig_handler(int sig
) {
453 shutdown_openocd
= 1;
457 int server_preinit(void)
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 */
464 WORD wVersionRequested
;
467 wVersionRequested
= MAKEWORD(2, 2);
469 if (WSAStartup(wVersionRequested
, &wsaData
) != 0)
471 LOG_ERROR("Failed to Open Winsock");
475 if (server_use_pipes
== 0)
477 /* register ctrl-c handler */
478 SetConsoleCtrlHandler(ControlHandler
, TRUE
);
482 /* we are using pipes so ignore ctrl-c */
483 SetConsoleCtrlHandler(NULL
, TRUE
);
486 signal(SIGINT
, sig_handler
);
487 signal(SIGTERM
, sig_handler
);
488 signal(SIGBREAK
, sig_handler
);
489 signal(SIGABRT
, sig_handler
);
495 int server_init(struct command_context
*cmd_ctx
)
497 int ret
= tcl_init();
501 return telnet_init("Open On-Chip Debugger");
504 int server_quit(void)
510 SetConsoleCtrlHandler(ControlHandler
, FALSE
);
516 /* tell the server we want to shut down */
517 COMMAND_HANDLER(handle_shutdown_command
)
519 LOG_USER("shutdown command invoked");
521 shutdown_openocd
= 1;
526 static const struct command_registration server_command_handlers
[] = {
529 .handler
= &handle_shutdown_command
,
531 .help
= "shut the server down",
533 COMMAND_REGISTRATION_DONE
536 int server_register_commands(struct command_context
*cmd_ctx
)
538 int retval
= telnet_register_commands(cmd_ctx
);
539 if (ERROR_OK
!= retval
)
542 retval
= tcl_register_commands(cmd_ctx
);
543 if (ERROR_OK
!= retval
)
546 return register_commands(cmd_ctx
, NULL
, server_command_handlers
);
549 SERVER_PORT_COMMAND()
553 command_print(CMD_CTX
, "%d", *out
);
558 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
563 return ERROR_INVALID_ARGUMENTS
;
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)