1/* Serial interface for raw TCP connections on Un*x like systems.
2
3   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2005, 2006,
4   2007 Free Software Foundation, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include "defs.h"
22#include "serial.h"
23#include "ser-base.h"
24#include "ser-tcp.h"
25
26#include <sys/types.h>
27
28#ifdef HAVE_SYS_FILIO_H
29#include <sys/filio.h>  /* For FIONBIO. */
30#endif
31#ifdef HAVE_SYS_IOCTL_H
32#include <sys/ioctl.h>  /* For FIONBIO. */
33#endif
34
35#include <sys/time.h>
36
37#ifdef USE_WIN32API
38#include <winsock2.h>
39#define ETIMEDOUT WSAETIMEDOUT
40#define close(fd) closesocket (fd)
41#define ioctl ioctlsocket
42#else
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#include <netdb.h>
46#include <sys/socket.h>
47#include <netinet/tcp.h>
48#endif
49
50#include <signal.h>
51#include "gdb_string.h"
52
53#ifndef HAVE_SOCKLEN_T
54typedef int socklen_t;
55#endif
56
57void _initialize_ser_tcp (void);
58
59/* seconds to wait for connect */
60#define TIMEOUT 15
61/* how many times per second to poll deprecated_ui_loop_hook */
62#define POLL_INTERVAL 2
63
64/* Open a tcp socket */
65
66int
67net_open (struct serial *scb, const char *name)
68{
69  char *port_str, hostname[100];
70  int n, port, tmp;
71  int use_udp;
72  struct hostent *hostent;
73  struct sockaddr_in sockaddr;
74#ifdef USE_WIN32API
75  u_long ioarg;
76#else
77  int ioarg;
78#endif
79
80  use_udp = 0;
81  if (strncmp (name, "udp:", 4) == 0)
82    {
83      use_udp = 1;
84      name = name + 4;
85    }
86  else if (strncmp (name, "tcp:", 4) == 0)
87    name = name + 4;
88
89  port_str = strchr (name, ':');
90
91  if (!port_str)
92    error (_("net_open: No colon in host name!"));	   /* Shouldn't ever happen */
93
94  tmp = min (port_str - name, (int) sizeof hostname - 1);
95  strncpy (hostname, name, tmp);	/* Don't want colon */
96  hostname[tmp] = '\000';	/* Tie off host name */
97  port = atoi (port_str + 1);
98
99  /* default hostname is localhost */
100  if (!hostname[0])
101    strcpy (hostname, "localhost");
102
103  hostent = gethostbyname (hostname);
104  if (!hostent)
105    {
106      fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
107      errno = ENOENT;
108      return -1;
109    }
110
111  if (use_udp)
112    scb->fd = socket (PF_INET, SOCK_DGRAM, 0);
113  else
114    scb->fd = socket (PF_INET, SOCK_STREAM, 0);
115
116  if (scb->fd < 0)
117    return -1;
118
119  sockaddr.sin_family = PF_INET;
120  sockaddr.sin_port = htons (port);
121  memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
122	  sizeof (struct in_addr));
123
124  /* set socket nonblocking */
125  ioarg = 1;
126  ioctl (scb->fd, FIONBIO, &ioarg);
127
128  /* Use Non-blocking connect.  connect() will return 0 if connected already. */
129  n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
130
131  if (n < 0
132#ifdef USE_WIN32API
133      /* Under Windows, calling "connect" with a non-blocking socket
134	 results in WSAEWOULDBLOCK, not WSAEINPROGRESS.  */
135      && WSAGetLastError() != WSAEWOULDBLOCK
136#else
137      && errno != EINPROGRESS
138#endif
139      )
140    {
141#ifdef USE_WIN32API
142      errno = WSAGetLastError();
143#endif
144      net_close (scb);
145      return -1;
146    }
147
148  if (n)
149    {
150      /* looks like we need to wait for the connect */
151      struct timeval t;
152      fd_set rset, wset, eset;
153      int polls = 0;
154      FD_ZERO (&rset);
155
156      do
157	{
158	  /* While we wait for the connect to complete,
159	     poll the UI so it can update or the user can
160	     interrupt.  */
161	  if (deprecated_ui_loop_hook)
162	    {
163	      if (deprecated_ui_loop_hook (0))
164		{
165		  errno = EINTR;
166		  net_close (scb);
167		  return -1;
168		}
169	    }
170
171	  FD_SET (scb->fd, &rset);
172	  wset = rset;
173	  eset = rset;
174	  t.tv_sec = 0;
175	  t.tv_usec = 1000000 / POLL_INTERVAL;
176
177	  /* POSIX systems return connection success or failure by signalling
178	     wset.  Windows systems return success in wset and failure in
179	     eset.
180
181	     We must call select here, rather than gdb_select, because
182	     the serial structure has not yet been initialized - the
183	     MinGW select wrapper will not know that this FD refers
184	     to a socket.  */
185	  n = select (scb->fd + 1, &rset, &wset, &eset, &t);
186	  polls++;
187	}
188      while (n == 0 && polls <= TIMEOUT * POLL_INTERVAL);
189      if (n < 0 || polls > TIMEOUT * POLL_INTERVAL)
190	{
191	  if (polls > TIMEOUT * POLL_INTERVAL)
192	    errno = ETIMEDOUT;
193	  net_close (scb);
194	  return -1;
195	}
196    }
197
198  /* Got something.  Is it an error? */
199  {
200    int res, err;
201    socklen_t len;
202    len = sizeof (err);
203    /* On Windows, the fourth parameter to getsockopt is a "char *";
204       on UNIX systems it is generally "void *".  The cast to "void *"
205       is OK everywhere, since in C "void *" can be implicitly
206       converted to any pointer type.  */
207    res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len);
208    if (res < 0 || err)
209      {
210	if (err)
211	  errno = err;
212	net_close (scb);
213	return -1;
214      }
215  }
216
217  /* turn off nonblocking */
218  ioarg = 0;
219  ioctl (scb->fd, FIONBIO, &ioarg);
220
221  if (use_udp == 0)
222    {
223      /* Disable Nagle algorithm. Needed in some cases. */
224      tmp = 1;
225      setsockopt (scb->fd, IPPROTO_TCP, TCP_NODELAY,
226		  (char *)&tmp, sizeof (tmp));
227    }
228
229#ifdef SIGPIPE
230  /* If we don't do this, then GDB simply exits
231     when the remote side dies.  */
232  signal (SIGPIPE, SIG_IGN);
233#endif
234
235  return 0;
236}
237
238void
239net_close (struct serial *scb)
240{
241  if (scb->fd < 0)
242    return;
243
244  close (scb->fd);
245  scb->fd = -1;
246}
247
248int
249net_read_prim (struct serial *scb, size_t count)
250{
251  return recv (scb->fd, scb->buf, count, 0);
252}
253
254int
255net_write_prim (struct serial *scb, const void *buf, size_t count)
256{
257  return send (scb->fd, buf, count, 0);
258}
259
260void
261_initialize_ser_tcp (void)
262{
263#ifdef USE_WIN32API
264  /* Do nothing; the TCP serial operations will be initialized in
265     ser-mingw.c.  */
266  return;
267#else
268  struct serial_ops *ops;
269  ops = XMALLOC (struct serial_ops);
270  memset (ops, 0, sizeof (struct serial_ops));
271  ops->name = "tcp";
272  ops->next = 0;
273  ops->open = net_open;
274  ops->close = net_close;
275  ops->readchar = ser_base_readchar;
276  ops->write = ser_base_write;
277  ops->flush_output = ser_base_flush_output;
278  ops->flush_input = ser_base_flush_input;
279  ops->send_break = ser_base_send_break;
280  ops->go_raw = ser_base_raw;
281  ops->get_tty_state = ser_base_get_tty_state;
282  ops->set_tty_state = ser_base_set_tty_state;
283  ops->print_tty_state = ser_base_print_tty_state;
284  ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
285  ops->setbaudrate = ser_base_setbaudrate;
286  ops->setstopbits = ser_base_setstopbits;
287  ops->drain_output = ser_base_drain_output;
288  ops->async = ser_base_async;
289  ops->read_prim = net_read_prim;
290  ops->write_prim = net_write_prim;
291  serial_add_interface (ops);
292#endif /* USE_WIN32API */
293}
294