1 /* Serial port emulation using sockets.
2 Copyright (C) 1998-2013 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
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 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* FIXME: will obviously need to evolve.
19 - connectionless sockets might be more appropriate. */
42 #include <sys/types.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
47 #include <sys/socket.h>
50 #include <netinet/tcp.h>
53 #include "sim-assert.h"
54 #include "sim-options.h"
56 #include "dv-sockser.h"
58 #ifndef HAVE_SOCKLEN_T
59 typedef int socklen_t;
62 /* Get definitions for both O_NONBLOCK and O_NDELAY. */
66 #define O_NDELAY FNDELAY
67 #else /* ! defined (FNDELAY) */
69 #endif /* ! defined (FNDELAY) */
70 #endif /* ! defined (O_NDELAY) */
74 #define O_NONBLOCK FNBLOCK
75 #else /* ! defined (FNBLOCK) */
77 #endif /* ! defined (FNBLOCK) */
78 #endif /* ! defined (O_NONBLOCK) */
81 /* Compromise between eating cpu and properly busy-waiting.
82 One could have an option to set this but for now that seems
84 #define DEFAULT_TIMEOUT 1000 /* microseconds */
86 /* FIXME: These should allocated at run time and kept with other simulator
87 state (duh...). Later. */
88 const char * sockser_addr = NULL;
89 /* Timeout in microseconds during status flag computation.
90 Setting this to zero achieves proper busy wait semantics but eats cpu. */
91 static unsigned int sockser_timeout = DEFAULT_TIMEOUT;
92 static int sockser_listen_fd = -1;
93 static int sockser_fd = -1;
95 /* FIXME: use tree properties when they're ready. */
98 OPTION_ADDR = OPTION_START
101 static DECLARE_OPTION_HANDLER (sockser_option_handler);
103 static const OPTION sockser_options[] =
105 { { "sockser-addr", required_argument, NULL, OPTION_ADDR },
106 '\0', "SOCKET ADDRESS", "Set serial emulation socket address",
107 sockser_option_handler, NULL },
108 { { NULL, no_argument, NULL, 0 }, '\0', NULL, NULL, NULL, NULL }
112 sockser_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
113 char *arg, int is_command)
126 dv_sockser_init (SIM_DESC sd)
128 struct hostent *hostent;
129 struct sockaddr_in sockaddr;
131 const char *port_str;
134 if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT
135 || sockser_addr == NULL)
138 if (*sockser_addr == '/')
140 /* support for these can come later */
141 sim_io_eprintf (sd, "sockser init: unix domain sockets not supported: `%s'\n",
146 port_str = strchr (sockser_addr, ':');
149 sim_io_eprintf (sd, "sockser init: missing port number: `%s'\n",
153 tmp = port_str - sockser_addr;
154 if (tmp >= sizeof hostname)
155 tmp = sizeof (hostname) - 1;
156 strncpy (hostname, sockser_addr, tmp);
157 hostname[tmp] = '\000';
158 port = atoi (port_str + 1);
160 hostent = gethostbyname (hostname);
163 sim_io_eprintf (sd, "sockser init: unknown host: %s\n",
168 sockser_listen_fd = socket (PF_INET, SOCK_STREAM, 0);
169 if (sockser_listen_fd == -1)
171 sim_io_eprintf (sd, "sockser init: unable to get socket: %s\n",
176 sockaddr.sin_family = PF_INET;
177 sockaddr.sin_port = htons (port);
178 memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
179 sizeof (struct in_addr));
182 if (setsockopt (sockser_listen_fd, SOL_SOCKET, SO_REUSEADDR, (void*)& tmp, sizeof (tmp)) < 0)
184 sim_io_eprintf (sd, "sockser init: unable to set SO_REUSEADDR: %s\n",
187 if (bind (sockser_listen_fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
189 sim_io_eprintf (sd, "sockser init: unable to bind socket address: %s\n",
191 close (sockser_listen_fd);
192 sockser_listen_fd = -1;
195 if (listen (sockser_listen_fd, 1) < 0)
197 sim_io_eprintf (sd, "sockser init: unable to set up listener: %s\n",
199 close (sockser_listen_fd);
200 sockser_listen_fd = -1;
204 /* Handle writes to missing client -> SIGPIPE.
205 ??? Need a central signal management module. */
207 RETSIGTYPE (*orig) ();
208 orig = signal (SIGPIPE, SIG_IGN);
209 /* If a handler is already set up, don't mess with it. */
210 if (orig != SIG_DFL && orig != SIG_IGN)
211 signal (SIGPIPE, orig);
218 dv_sockser_uninstall (SIM_DESC sd)
220 if (sockser_listen_fd != -1)
222 close (sockser_listen_fd);
223 sockser_listen_fd = -1;
225 if (sockser_fd != -1)
233 dv_sockser_install (SIM_DESC sd)
235 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
236 if (sim_add_option_table (sd, NULL, sockser_options) != SIM_RC_OK)
238 sim_module_add_init_fn (sd, dv_sockser_init);
239 sim_module_add_uninstall_fn (sd, dv_sockser_uninstall);
244 connected_p (SIM_DESC sd)
249 struct sockaddr sockaddr;
252 if (sockser_listen_fd == -1)
257 /* FIXME: has client gone away? */
261 /* Not connected. Connect with a client if there is one. */
264 FD_SET (sockser_listen_fd, &readfds);
266 /* ??? One can certainly argue this should be done differently,
267 but for now this is sufficient. */
269 tv.tv_usec = sockser_timeout;
271 numfds = select (sockser_listen_fd + 1, &readfds, 0, 0, &tv);
275 addrlen = sizeof (sockaddr);
276 sockser_fd = accept (sockser_listen_fd, &sockaddr, &addrlen);
277 if (sockser_fd == -1)
280 /* Set non-blocking i/o. */
281 flags = fcntl (sockser_fd, F_GETFL);
282 flags |= O_NONBLOCK | O_NDELAY;
283 if (fcntl (sockser_fd, F_SETFL, flags) == -1)
285 sim_io_eprintf (sd, "unable to set nonblocking i/o");
294 dv_sockser_status (SIM_DESC sd)
296 int numrfds,numwfds,status;
298 fd_set readfds,writefds;
300 /* status to return if the socket isn't set up, or select fails */
301 status = DV_SOCKSER_INPUT_EMPTY | DV_SOCKSER_OUTPUT_EMPTY |
302 DV_SOCKSER_DISCONNECTED;
304 if (! connected_p (sd))
309 FD_SET (sockser_fd, &readfds);
310 FD_SET (sockser_fd, &writefds);
312 /* ??? One can certainly argue this should be done differently,
313 but for now this is sufficient. The read is done separately
314 from the write to enforce the delay which we heuristically set to
315 once every SOCKSER_TIMEOUT_FREQ tries.
316 No, this isn't great for SMP situations, blah blah blah. */
320 #define SOCKSER_TIMEOUT_FREQ 42
321 if (++n == SOCKSER_TIMEOUT_FREQ)
326 tv.tv_usec = sockser_timeout;
327 numrfds = select (sockser_fd + 1, &readfds, 0, 0, &tv);
330 numwfds = select (sockser_fd + 1, 0, &writefds, 0, &tv);
332 else /* do both selects at once */
336 numrfds = numwfds = select (sockser_fd + 1, &readfds, &writefds, 0, &tv);
341 if (numrfds <= 0 || ! FD_ISSET (sockser_fd, &readfds))
342 status |= DV_SOCKSER_INPUT_EMPTY;
343 if (numwfds <= 0 || FD_ISSET (sockser_fd, &writefds))
344 status |= DV_SOCKSER_OUTPUT_EMPTY;
349 dv_sockser_write_buffer (SIM_DESC sd, const unsigned char *buffer,
354 if (! connected_p (sd))
356 n = write (sockser_fd, buffer, nr_bytes);
372 dv_sockser_write (SIM_DESC sd, unsigned char c)
374 return dv_sockser_write_buffer (sd, &c, 1);
378 dv_sockser_read (SIM_DESC sd)
383 if (! connected_p (sd))
385 n = read (sockser_fd, &c, 1);
386 /* ??? We're assuming semantics that may not be correct for all hosts.
387 In particular (from cvssrc/src/server.c), this assumes that we are using
388 BSD or POSIX nonblocking I/O. System V nonblocking I/O returns zero if
389 there is nothing to read. */