1 /* Serial port emulation using sockets.
2 Copyright (C) 1998 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 2, or (at your option)
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 along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 /* FIXME: will obviously need to evolve.
20 - connectionless sockets might be more appropriate. */
43 #include <sys/types.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
48 #include <sys/socket.h>
51 #include <netinet/tcp.h>
54 #include "sim-assert.h"
55 #include "sim-options.h"
57 #include "dv-sockser.h"
59 /* Get definitions for both O_NONBLOCK and O_NDELAY. */
63 #define O_NDELAY FNDELAY
64 #else /* ! defined (FNDELAY) */
66 #endif /* ! defined (FNDELAY) */
67 #endif /* ! defined (O_NDELAY) */
71 #define O_NONBLOCK FNBLOCK
72 #else /* ! defined (FNBLOCK) */
74 #endif /* ! defined (FNBLOCK) */
75 #endif /* ! defined (O_NONBLOCK) */
77 #define MIN(a,b) ((a) < (b) ? (a) : (b))
79 /* Compromise between eating cpu and properly busy-waiting.
80 One could have an option to set this but for now that seems
82 #define DEFAULT_TIMEOUT 1000 /* microseconds */
84 /* FIXME: These should allocated at run time and kept with other simulator
85 state (duh...). Later. */
86 const char * sockser_addr = NULL;
87 /* Timeout in microseconds during status flag computation.
88 Setting this to zero achieves proper busy wait semantics but eats cpu. */
89 static unsigned int sockser_timeout = DEFAULT_TIMEOUT;
90 static int sockser_listen_fd = -1;
91 static int sockser_fd = -1;
93 /* FIXME: use tree properties when they're ready. */
96 OPTION_ADDR = OPTION_START
99 static DECLARE_OPTION_HANDLER (sockser_option_handler);
101 static const OPTION sockser_options[] =
103 { { "sockser-addr", required_argument, NULL, OPTION_ADDR },
104 '\0', "SOCKET ADDRESS", "Set serial emulation socket address",
105 sockser_option_handler },
106 { { NULL, no_argument, NULL, 0 }, '\0', NULL, NULL, NULL }
110 sockser_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
111 char *arg, int is_command)
124 dv_sockser_init (SIM_DESC sd)
126 struct hostent *hostent;
127 struct sockaddr_in sockaddr;
129 const char *port_str;
132 if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT
133 || sockser_addr == NULL)
136 if (*sockser_addr == '/')
138 /* support for these can come later */
139 sim_io_eprintf (sd, "sockser init: unix domain sockets not supported: `%s'\n",
144 port_str = strchr (sockser_addr, ':');
147 sim_io_eprintf (sd, "sockser init: missing port number: `%s'\n",
151 tmp = MIN (port_str - sockser_addr, (int) sizeof hostname - 1);
152 strncpy (hostname, sockser_addr, tmp);
153 hostname[tmp] = '\000';
154 port = atoi (port_str + 1);
156 hostent = gethostbyname (hostname);
159 sim_io_eprintf (sd, "sockser init: unknown host: %s\n",
164 sockser_listen_fd = socket (PF_INET, SOCK_STREAM, 0);
165 if (sockser_listen_fd < 0)
167 sim_io_eprintf (sd, "sockser init: unable to get socket: %s\n",
172 sockaddr.sin_family = PF_INET;
173 sockaddr.sin_port = htons(port);
174 memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
175 sizeof (struct in_addr));
178 if (setsockopt (sockser_listen_fd, SOL_SOCKET, SO_REUSEADDR, (void*)& tmp, sizeof(tmp)) < 0)
180 sim_io_eprintf (sd, "sockser init: unable to set SO_REUSEADDR: %s\n",
183 if (bind (sockser_listen_fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
185 sim_io_eprintf (sd, "sockser init: unable to bind socket address: %s\n",
187 close (sockser_listen_fd);
188 sockser_listen_fd = -1;
191 if (listen (sockser_listen_fd, 1) < 0)
193 sim_io_eprintf (sd, "sockser init: unable to set up listener: %s\n",
195 close (sockser_listen_fd);
196 sockser_listen_fd = -1;
200 /* Handle writes to missing client -> SIGPIPE.
201 ??? Need a central signal management module. */
203 RETSIGTYPE (*orig) ();
204 orig = signal (SIGPIPE, SIG_IGN);
205 /* If a handler is already set up, don't mess with it. */
206 if (orig != SIG_DFL && orig != SIG_IGN)
207 signal (SIGPIPE, orig);
214 dv_sockser_uninstall (SIM_DESC sd)
216 if (sockser_listen_fd != -1)
218 close (sockser_listen_fd);
219 sockser_listen_fd = -1;
221 if (sockser_fd != -1)
229 dv_sockser_install (SIM_DESC sd)
231 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
232 if (sim_add_option_table (sd, NULL, sockser_options) != SIM_RC_OK)
234 sim_module_add_init_fn (sd, dv_sockser_init);
235 sim_module_add_uninstall_fn (sd, dv_sockser_uninstall);
240 connected_p (SIM_DESC sd)
245 struct sockaddr sockaddr;
248 if (sockser_listen_fd == -1)
253 /* FIXME: has client gone away? */
257 /* Not connected. Connect with a client if there is one. */
260 FD_SET (sockser_listen_fd, &readfds);
262 /* ??? One can certainly argue this should be done differently,
263 but for now this is sufficient. */
265 tv.tv_usec = sockser_timeout;
267 numfds = select (sockser_listen_fd + 1, &readfds, 0, 0, &tv);
271 addrlen = sizeof (sockaddr);
272 sockser_fd = accept (sockser_listen_fd, &sockaddr, &addrlen);
276 /* Set non-blocking i/o. */
277 flags = fcntl (sockser_fd, F_GETFL);
278 flags |= O_NONBLOCK | O_NDELAY;
279 if (fcntl (sockser_fd, F_SETFL, flags) == -1)
281 sim_io_eprintf (sd, "unable to set nonblocking i/o");
290 dv_sockser_status (SIM_DESC sd)
292 int numrfds,numwfds,status;
294 fd_set readfds,writefds;
296 /* status to return if the socket isn't set up, or select fails */
297 status = DV_SOCKSER_INPUT_EMPTY | DV_SOCKSER_OUTPUT_EMPTY;
299 if (! connected_p (sd))
304 FD_SET (sockser_fd, &readfds);
305 FD_SET (sockser_fd, &writefds);
307 /* ??? One can certainly argue this should be done differently,
308 but for now this is sufficient. The read is done separately
309 from the write to enforce the delay which we heuristically set to
310 once every SOCKSER_TIMEOUT_FREQ tries.
311 No, this isn't great for SMP situations, blah blah blah. */
315 #define SOCKSER_TIMEOUT_FREQ 42
316 if (++n == SOCKSER_TIMEOUT_FREQ)
321 tv.tv_usec = sockser_timeout;
322 numrfds = select (sockser_fd + 1, &readfds, 0, 0, &tv);
325 numwfds = select (sockser_fd + 1, 0, &writefds, 0, &tv);
327 else /* do both selects at once */
331 numrfds = numwfds = select (sockser_fd + 1, &readfds, &writefds, 0, &tv);
336 if (numrfds <= 0 || ! FD_ISSET (sockser_fd, &readfds))
337 status |= DV_SOCKSER_INPUT_EMPTY;
338 if (numwfds <= 0 || FD_ISSET (sockser_fd, &writefds))
339 status |= DV_SOCKSER_OUTPUT_EMPTY;
344 dv_sockser_write (SIM_DESC sd, unsigned char c)
348 if (! connected_p (sd))
350 n = write (sockser_fd, &c, 1);
366 dv_sockser_read (SIM_DESC sd)
371 if (! connected_p (sd))
373 n = read (sockser_fd, &c, 1);
374 /* ??? We're assuming semantics that may not be correct for all hosts.
375 In particular (from cvssrc/src/server.c), this assumes that we are using
376 BSD or POSIX nonblocking I/O. System V nonblocking I/O returns zero if
377 there is nothing to read. */