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 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
)
245 enum connection_type type
= CONNECTION_TCP
;
248 strtol(port
, &end
, 0);
251 if ((parse_long(port
, &portnumber
) == ERROR_OK
) && (portnumber
== 0))
253 type
= CONNECTION_PIPE
;
257 LOG_ERROR("Illegal port number %s", port
);
260 return add_service(name
, type
, portnumber
, max_connections
, new_connection_handler
,
261 input_handler
, connection_closed_handler
, priv
);
264 static int remove_services(void)
266 struct service
*c
= services
;
271 struct service
*next
= c
->next
;
276 if (c
->type
== CONNECTION_PIPE
)
288 /* remember the last service for unlinking */
297 int server_loop(struct command_context
*command_context
)
299 struct service
*service
;
303 /* used in select() */
307 /* used in accept() */
311 if (signal(SIGPIPE
, SIG_IGN
) == SIG_ERR
)
312 LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
315 while (!shutdown_openocd
)
317 /* monitor sockets for activity */
321 /* add service and connection fds to read_fds */
322 for (service
= services
; service
; service
= service
->next
)
324 if (service
->fd
!= -1)
326 /* listen for new connections */
327 FD_SET(service
->fd
, &read_fds
);
329 if (service
->fd
> fd_max
)
330 fd_max
= service
->fd
;
333 if (service
->connections
)
335 struct connection
*c
;
337 for (c
= service
->connections
; c
; c
= c
->next
)
339 /* check for activity on the connection */
340 FD_SET(c
->fd
, &read_fds
);
351 /* we're just polling this iteration, this is faster on embedded
354 retval
= socket_select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
359 /* Only while we're sleeping we'll let others run */
360 openocd_sleep_prelude();
362 retval
= socket_select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
363 openocd_sleep_postlude();
370 errno
= WSAGetLastError();
372 if (errno
== WSAEINTR
)
376 LOG_ERROR("error during select: %s", strerror(errno
));
387 LOG_ERROR("error during select: %s", strerror(errno
));
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
);
399 FD_ZERO(&read_fds
); /* eCos leaves read_fds unchanged in this case! */
401 /* We timed out/there was nothing to do, timeout rather than poll next time */
405 /* There was something to do, next time we'll just poll */
409 for (service
= services
; service
; service
= service
->next
)
411 /* handle new connections on listeners */
412 if ((service
->fd
!= -1)
413 && (FD_ISSET(service
->fd
, &read_fds
)))
415 if (service
->max_connections
> 0)
417 add_connection(service
, command_context
);
421 if (service
->type
== CONNECTION_TCP
)
423 struct sockaddr_in sin
;
424 socklen_t address_size
= sizeof(sin
);
426 tmp_fd
= accept(service
->fd
, (struct sockaddr
*)&service
->sin
, &address_size
);
427 close_socket(tmp_fd
);
429 LOG_INFO("rejected '%s' connection, no more connections allowed", service
->name
);
433 /* handle activity on connections */
434 if (service
->connections
)
436 struct connection
*c
;
438 for (c
= service
->connections
; c
;)
440 if ((FD_ISSET(c
->fd
, &read_fds
)) || c
->input_pending
)
442 if ((retval
= service
->input(c
)) != ERROR_OK
)
444 struct connection
*next
= c
->next
;
445 if (service
->type
== CONNECTION_PIPE
)
447 /* if connection uses a pipe then shutdown openocd on error */
448 shutdown_openocd
= 1;
450 remove_connection(service
, c
);
451 LOG_INFO("dropped '%s' connection - error %d", service
->name
, retval
);
463 while (PeekMessage(&msg
,NULL
,0,0,PM_REMOVE
))
465 if (msg
.message
== WM_QUIT
)
466 shutdown_openocd
= 1;
475 BOOL WINAPI
ControlHandler(DWORD dwCtrlType
)
477 shutdown_openocd
= 1;
481 void sig_handler(int sig
) {
482 shutdown_openocd
= 1;
486 int server_preinit(void)
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 */
493 WORD wVersionRequested
;
496 wVersionRequested
= MAKEWORD(2, 2);
498 if (WSAStartup(wVersionRequested
, &wsaData
) != 0)
500 LOG_ERROR("Failed to Open Winsock");
504 if (server_use_pipes
== 0)
506 /* register ctrl-c handler */
507 SetConsoleCtrlHandler(ControlHandler
, TRUE
);
511 /* we are using pipes so ignore ctrl-c */
512 SetConsoleCtrlHandler(NULL
, TRUE
);
515 signal(SIGINT
, sig_handler
);
516 signal(SIGTERM
, sig_handler
);
517 signal(SIGBREAK
, sig_handler
);
518 signal(SIGABRT
, sig_handler
);
524 int server_init(struct command_context
*cmd_ctx
)
526 int ret
= tcl_init();
530 return telnet_init("Open On-Chip Debugger");
533 int server_quit(void)
539 SetConsoleCtrlHandler(ControlHandler
, FALSE
);
545 int connection_write(struct connection
*connection
, const void *data
, int len
)
549 /* successful no-op. Sockets and pipes behave differently here... */
552 if (connection
->service
->type
== CONNECTION_TCP
)
554 return write_socket(connection
->fd_out
, data
, len
);
557 return write(connection
->fd_out
, data
, len
);
561 int connection_read(struct connection
*connection
, void *data
, int len
)
563 if (connection
->service
->type
== CONNECTION_TCP
)
565 return read_socket(connection
->fd
, data
, len
);
568 return read(connection
->fd
, data
, len
);
572 /* tell the server we want to shut down */
573 COMMAND_HANDLER(handle_shutdown_command
)
575 LOG_USER("shutdown command invoked");
577 shutdown_openocd
= 1;
582 static const struct command_registration server_command_handlers
[] = {
585 .handler
= &handle_shutdown_command
,
587 .help
= "shut the server down",
589 COMMAND_REGISTRATION_DONE
592 int server_register_commands(struct command_context
*cmd_ctx
)
594 int retval
= telnet_register_commands(cmd_ctx
);
595 if (ERROR_OK
!= retval
)
598 retval
= tcl_register_commands(cmd_ctx
);
599 if (ERROR_OK
!= retval
)
602 return register_commands(cmd_ctx
, NULL
, server_command_handlers
);
605 SERVER_PORT_COMMAND()
609 command_print(CMD_CTX
, "%d", *out
);
614 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
619 return ERROR_INVALID_ARGUMENTS
;
624 SERVER_PIPE_COMMAND()
628 command_print(CMD_CTX
, "%s", *out
);
632 const char * t
= strdup(CMD_ARGV
[0]);
638 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)