The bitbang driver leaves the TCK 0 when in idle
[openocd.git] / src / server / server.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "replacements.h"
25
26 #include "server.h"
27
28 #include "log.h"
29 #include "telnet_server.h"
30 #include "target.h"
31
32 #include <command.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include <fcntl.h>
39 #include <signal.h>
40
41 service_t *services = NULL;
42
43 /* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
44 static int shutdown_openocd = 0;
45 int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
46
47 int add_connection(service_t *service, command_context_t *cmd_ctx)
48 {
49 unsigned int address_size;
50 connection_t *c, **p;
51 int retval;
52
53 c = malloc(sizeof(connection_t));
54 c->fd = -1;
55 memset(&c->sin, 0, sizeof(c->sin));
56 c->cmd_ctx = copy_command_context(cmd_ctx);
57 c->service = service;
58 c->input_pending = 0;
59 c->priv = NULL;
60 c->next = NULL;
61
62 address_size = sizeof(c->sin);
63 c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
64
65
66 INFO("accepting '%s' connection from %i", service->name, c->sin.sin_port);
67 if ((retval = service->new_connection(c)) == ERROR_OK)
68 {
69 }
70 else
71 {
72 close_socket(c->fd);
73 ERROR("attempted '%s' connection rejected", service->name);
74 free(c);
75 return retval;
76 }
77
78 /* add to the end of linked list */
79 for (p = &service->connections; *p; p = &(*p)->next);
80 *p = c;
81
82 service->max_connections--;
83
84 return ERROR_OK;
85 }
86
87 int remove_connection(service_t *service, connection_t *connection)
88 {
89 connection_t **p = &service->connections;
90 connection_t *c;
91
92 /* find connection */
93 while((c = *p))
94 {
95 if (c->fd == connection->fd)
96 {
97 service->connection_closed(c);
98 close_socket(c->fd);
99 command_done(c->cmd_ctx);
100
101 /* delete connection */
102 *p = c->next;
103 free(c);
104
105 service->max_connections++;
106 break;
107 }
108
109 /* redirect p to next list pointer */
110 p = &(*p)->next;
111 }
112
113 return ERROR_OK;
114 }
115
116 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)
117 {
118 service_t *c, **p;
119 int so_reuseaddr_option = 1;
120
121 c = malloc(sizeof(service_t));
122
123 c->name = strdup(name);
124 c->type = type;
125 c->port = port;
126 c->max_connections = max_connections;
127 c->fd = -1;
128 c->connections = NULL;
129 c->new_connection = new_connection_handler;
130 c->input = input_handler;
131 c->connection_closed = connection_closed_handler;
132 c->priv = priv;
133 c->next = NULL;
134
135 if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
136 {
137 ERROR("error creating socket: %s", strerror(errno));
138 exit(-1);
139 }
140
141 setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
142
143 socket_nonblock(c->fd);
144
145 memset(&c->sin, 0, sizeof(c->sin));
146 c->sin.sin_family = AF_INET;
147 c->sin.sin_addr.s_addr = INADDR_ANY;
148 c->sin.sin_port = htons(port);
149
150 if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
151 {
152 ERROR("couldn't bind to socket: %s", strerror(errno));
153 exit(-1);
154 }
155
156 if (listen(c->fd, 1) == -1)
157 {
158 ERROR("couldn't listen on socket: %s", strerror(errno));
159 exit(-1);
160 }
161
162 /* add to the end of linked list */
163 for (p = &services; *p; p = &(*p)->next);
164 *p = c;
165
166 return ERROR_OK;
167 }
168
169 int remove_service(unsigned short port)
170 {
171 service_t **p = &services;
172 service_t *c;
173
174 /* find service */
175 while((c = *p))
176 {
177 if (c->port == port)
178 {
179 if (c->name)
180 free(c->name);
181
182 if (c->priv)
183 free(c->priv);
184
185 /* delete service */
186 *p = c->next;
187 free(c);
188 }
189
190 /* redirect p to next list pointer */
191 p = &(*p)->next;
192 }
193
194 return ERROR_OK;
195 }
196
197 int remove_services()
198 {
199 service_t *c = services;
200
201 /* loop service */
202 while(c)
203 {
204 service_t *next = c->next;
205
206 if (c->name)
207 free(c->name);
208
209 if (c->priv)
210 free(c->priv);
211
212 /* delete service */
213 free(c);
214
215 /* remember the last service for unlinking */
216 c = next;
217 }
218
219 services = NULL;
220
221 return ERROR_OK;
222 }
223
224 int server_loop(command_context_t *command_context)
225 {
226 service_t *service;
227
228 /* used in select() */
229 fd_set read_fds;
230 struct timeval tv;
231 int fd_max;
232
233 /* used in accept() */
234 int retval;
235
236 #ifndef _WIN32
237 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
238 ERROR("couldn't set SIGPIPE to SIG_IGN");
239 #endif
240
241 /* do regular tasks after at most 10ms */
242 tv.tv_sec = 0;
243 tv.tv_usec = 10000;
244
245 while(!shutdown_openocd)
246 {
247 /* monitor sockets for acitvity */
248 fd_max = 0;
249 FD_ZERO(&read_fds);
250
251 /* add service and connection fds to read_fds */
252 for (service = services; service; service = service->next)
253 {
254 if (service->fd != -1)
255 {
256 /* listen for new connections */
257 FD_SET(service->fd, &read_fds);
258
259 if (service->fd > fd_max)
260 fd_max = service->fd;
261 }
262
263 if (service->connections)
264 {
265 connection_t *c;
266
267 for (c = service->connections; c; c = c->next)
268 {
269 /* check for activity on the connection */
270 FD_SET(c->fd, &read_fds);
271 if (c->fd > fd_max)
272 fd_max = c->fd;
273 }
274 }
275 }
276
277 #ifndef _WIN32
278 /* add STDIN to read_fds */
279 FD_SET(fileno(stdin), &read_fds);
280 #endif
281
282 retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
283
284 if (retval == -1)
285 {
286 #ifdef _WIN32
287
288 errno = WSAGetLastError();
289
290 if (errno == WSAEINTR)
291 FD_ZERO(&read_fds);
292 else
293 {
294 ERROR("error during select: %s", strerror(errno));
295 exit(-1);
296 }
297 #else
298
299 if (errno == EINTR)
300 {
301 FD_ZERO(&read_fds);
302 }
303 else
304 {
305 ERROR("error during select: %s", strerror(errno));
306 exit(-1);
307 }
308 #endif
309 }
310
311 target_call_timer_callbacks();
312
313 if (retval == 0)
314 {
315 /* do regular tasks after at most 100ms */
316 tv.tv_sec = 0;
317 tv.tv_usec = 10000;
318 FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */
319 }
320
321 for (service = services; service; service = service->next)
322 {
323 /* handle new connections on listeners */
324 if ((service->fd != -1)
325 && (FD_ISSET(service->fd, &read_fds)))
326 {
327 if (service->max_connections > 0)
328 {
329 add_connection(service, command_context);
330 }
331 else
332 {
333 struct sockaddr_in sin;
334 unsigned int address_size = sizeof(sin);
335 int tmp_fd;
336 tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
337 close_socket(tmp_fd);
338 INFO("rejected '%s' connection, no more connections allowed", service->name);
339 }
340 }
341
342 /* handle activity on connections */
343 if (service->connections)
344 {
345 connection_t *c;
346
347 for (c = service->connections; c;)
348 {
349 if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending)
350 {
351 if (service->input(c) != ERROR_OK)
352 {
353 connection_t *next = c->next;
354 remove_connection(service, c);
355 INFO("dropped '%s' connection", service->name);
356 c = next;
357 continue;
358 }
359 }
360 c = c->next;
361 }
362 }
363 }
364
365 #ifndef _WIN32
366 if (FD_ISSET(fileno(stdin), &read_fds))
367 {
368 if (getc(stdin) == 'x')
369 {
370 shutdown_openocd = 1;
371 }
372 }
373 #else
374 MSG msg;
375 while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
376 {
377 if (msg.message == WM_QUIT)
378 shutdown_openocd = 1;
379 }
380 #endif
381 }
382
383 return ERROR_OK;
384 }
385
386 #ifdef _WIN32
387 BOOL WINAPI ControlHandler(DWORD dwCtrlType)
388 {
389 shutdown_openocd = 1;
390 return TRUE;
391 }
392
393 void sig_handler(int sig) {
394 shutdown_openocd = 1;
395 }
396 #endif
397
398 int server_init()
399 {
400 #ifdef _WIN32
401 WORD wVersionRequested;
402 WSADATA wsaData;
403
404 wVersionRequested = MAKEWORD( 2, 2 );
405
406 if (WSAStartup(wVersionRequested, &wsaData) != 0)
407 {
408 ERROR("Failed to Open Winsock");
409 exit(-1);
410 }
411
412 SetConsoleCtrlHandler( ControlHandler, TRUE );
413
414 signal(SIGINT, sig_handler);
415 signal(SIGTERM, sig_handler);
416 signal(SIGBREAK, sig_handler);
417 signal(SIGABRT, sig_handler);
418 #endif
419
420
421 return ERROR_OK;
422 }
423
424 int server_quit()
425 {
426 remove_services();
427
428 #ifdef _WIN32
429 WSACleanup();
430 SetConsoleCtrlHandler( ControlHandler, FALSE );
431 #endif
432
433 return ERROR_OK;
434 }
435
436 int server_register_commands(command_context_t *context)
437 {
438 register_command(context, NULL, "shutdown", handle_shutdown_command,
439 COMMAND_ANY, "shut the server down");
440
441 return ERROR_OK;
442 }
443
444 /* tell the server we want to shut down */
445 int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
446 {
447 shutdown_openocd = 1;
448
449 return ERROR_COMMAND_CLOSE_CONNECTION;
450 }
451
452

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)