1270310Sse/* Serial interface for raw TCP connections on Un*x like systems
2270310Sse   Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001
343334Syokota   Free Software Foundation, Inc.
443334Syokota
543334Syokota   This file is part of GDB.
643334Syokota
743334Syokota   This program is free software; you can redistribute it and/or modify
843334Syokota   it under the terms of the GNU General Public License as published by
943334Syokota   the Free Software Foundation; either version 2 of the License, or
1043334Syokota   (at your option) any later version.
1143334Syokota
12270310Sse   This program is distributed in the hope that it will be useful,
1343334Syokota   but WITHOUT ANY WARRANTY; without even the implied warranty of
14270310Sse   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15270310Sse   GNU General Public License for more details.
16270310Sse
1743334Syokota   You should have received a copy of the GNU General Public License
18270310Sse   along with this program; if not, write to the Free Software
1943334Syokota   Foundation, Inc., 59 Temple Place - Suite 330,
20270310Sse   Boston, MA 02111-1307, USA.  */
21270310Sse
22270310Sse#include "defs.h"
2343334Syokota#include "serial.h"
2443334Syokota#include "ser-unix.h"
2543334Syokota
2643334Syokota#include <sys/types.h>
2743334Syokota
2843334Syokota#ifdef HAVE_SYS_FILIO_H
2943334Syokota#include <sys/filio.h>  /* For FIONBIO. */
3043334Syokota#endif
3143334Syokota#ifdef HAVE_SYS_IOCTL_H
3243334Syokota#include <sys/ioctl.h>  /* For FIONBIO. */
3343334Syokota#endif
3443334Syokota
35270310Sse#include <sys/time.h>
36270310Sse#include <netinet/in.h>
3743334Syokota#include <arpa/inet.h>
3843334Syokota#include <netdb.h>
3943334Syokota#include <sys/socket.h>
4043334Syokota#include <netinet/tcp.h>
4143334Syokota
4243334Syokota#include <signal.h>
4343334Syokota#include "gdb_string.h"
4443334Syokota
4543334Syokotastatic int net_open (struct serial *scb, const char *name);
46270310Ssestatic void net_close (struct serial *scb);
47270310Sseextern int (*ui_loop_hook) (int);
48270310Ssevoid _initialize_ser_tcp (void);
49270310Sse
50270310Sse/* seconds to wait for connect */
5143334Syokota#define TIMEOUT 15
52270310Sse/* how many times per second to poll ui_loop_hook */
5343334Syokota#define POLL_INTERVAL 2
5443334Syokota
5543334Syokota/* Open a tcp socket */
5643334Syokota
5743334Syokotastatic int
5843334Syokotanet_open (struct serial *scb, const char *name)
59270310Sse{
60166500Sphilip  char *port_str, hostname[100];
61166500Sphilip  int n, port, tmp;
6243334Syokota  int use_udp;
6343334Syokota  struct hostent *hostent;
6443334Syokota  struct sockaddr_in sockaddr;
6543334Syokota
6643334Syokota  use_udp = 0;
6743334Syokota  if (strncmp (name, "udp:", 4) == 0)
6843334Syokota    {
6943334Syokota      use_udp = 1;
7043334Syokota      name = name + 4;
7143334Syokota    }
7243334Syokota  else if (strncmp (name, "tcp:", 4) == 0)
7343334Syokota    name = name + 4;
7443334Syokota
7543334Syokota  port_str = strchr (name, ':');
7643334Syokota
7743334Syokota  if (!port_str)
7843334Syokota    error ("net_open: No colon in host name!");	   /* Shouldn't ever happen */
7943334Syokota
8043334Syokota  tmp = min (port_str - name, (int) sizeof hostname - 1);
8143334Syokota  strncpy (hostname, name, tmp);	/* Don't want colon */
8243334Syokota  hostname[tmp] = '\000';	/* Tie off host name */
8343334Syokota  port = atoi (port_str + 1);
8443334Syokota
8543334Syokota  /* default hostname is localhost */
8643334Syokota  if (!hostname[0])
8743334Syokota    strcpy (hostname, "localhost");
8843334Syokota
8943334Syokota  hostent = gethostbyname (hostname);
9043334Syokota  if (!hostent)
9143334Syokota    {
9243334Syokota      fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
9343334Syokota      errno = ENOENT;
9443334Syokota      return -1;
9543334Syokota    }
9643334Syokota
9743334Syokota  if (use_udp)
9843334Syokota    scb->fd = socket (PF_INET, SOCK_DGRAM, 0);
9943334Syokota  else
10043334Syokota    scb->fd = socket (PF_INET, SOCK_STREAM, 0);
10174119Sache
10243334Syokota  if (scb->fd < 0)
10343334Syokota    return -1;
10443334Syokota
10543334Syokota  sockaddr.sin_family = PF_INET;
10643334Syokota  sockaddr.sin_port = htons (port);
10743334Syokota  memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
10843334Syokota	  sizeof (struct in_addr));
10943334Syokota
11043334Syokota  /* set socket nonblocking */
11174119Sache  tmp = 1;
112270310Sse  ioctl (scb->fd, FIONBIO, &tmp);
11343334Syokota
11443334Syokota  /* Use Non-blocking connect.  connect() will return 0 if connected already. */
11543334Syokota  n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
11643334Syokota
11743334Syokota  if (n < 0 && errno != EINPROGRESS)
118    {
119      net_close (scb);
120      return -1;
121    }
122
123  if (n)
124    {
125      /* looks like we need to wait for the connect */
126      struct timeval t;
127      fd_set rset, wset;
128      int polls = 0;
129      FD_ZERO (&rset);
130
131      do
132	{
133	  /* While we wait for the connect to complete
134	     poll the UI so it can update or the user can
135	     interrupt. */
136	  if (ui_loop_hook)
137	    {
138	      if (ui_loop_hook (0))
139		{
140		  errno = EINTR;
141		  net_close (scb);
142		  return -1;
143		}
144	    }
145
146	  FD_SET (scb->fd, &rset);
147	  wset = rset;
148	  t.tv_sec = 0;
149	  t.tv_usec = 1000000 / POLL_INTERVAL;
150
151	  n = select (scb->fd + 1, &rset, &wset, NULL, &t);
152	  polls++;
153	}
154      while (n == 0 && polls <= TIMEOUT * POLL_INTERVAL);
155      if (n < 0 || polls > TIMEOUT * POLL_INTERVAL)
156	{
157	  if (polls > TIMEOUT * POLL_INTERVAL)
158	    errno = ETIMEDOUT;
159	  net_close (scb);
160	  return -1;
161	}
162    }
163
164  /* Got something.  Is it an error? */
165  {
166    int res, err, len;
167    len = sizeof(err);
168    res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, &err, &len);
169    if (res < 0 || err)
170      {
171	if (err)
172	  errno = err;
173	net_close (scb);
174	return -1;
175      }
176  }
177
178  /* turn off nonblocking */
179  tmp = 0;
180  ioctl (scb->fd, FIONBIO, &tmp);
181
182  if (use_udp == 0)
183    {
184      /* Disable Nagle algorithm. Needed in some cases. */
185      tmp = 1;
186      setsockopt (scb->fd, IPPROTO_TCP, TCP_NODELAY,
187		  (char *)&tmp, sizeof (tmp));
188    }
189
190  /* If we don't do this, then GDB simply exits
191     when the remote side dies.  */
192  signal (SIGPIPE, SIG_IGN);
193
194  return 0;
195}
196
197static void
198net_close (struct serial *scb)
199{
200  if (scb->fd < 0)
201    return;
202
203  close (scb->fd);
204  scb->fd = -1;
205}
206
207void
208_initialize_ser_tcp (void)
209{
210  struct serial_ops *ops = XMALLOC (struct serial_ops);
211  memset (ops, 0, sizeof (struct serial_ops));
212  ops->name = "tcp";
213  ops->next = 0;
214  ops->open = net_open;
215  ops->close = net_close;
216  ops->readchar = ser_unix_readchar;
217  ops->write = ser_unix_write;
218  ops->flush_output = ser_unix_nop_flush_output;
219  ops->flush_input = ser_unix_flush_input;
220  ops->send_break = ser_unix_nop_send_break;
221  ops->go_raw = ser_unix_nop_raw;
222  ops->get_tty_state = ser_unix_nop_get_tty_state;
223  ops->set_tty_state = ser_unix_nop_set_tty_state;
224  ops->print_tty_state = ser_unix_nop_print_tty_state;
225  ops->noflush_set_tty_state = ser_unix_nop_noflush_set_tty_state;
226  ops->setbaudrate = ser_unix_nop_setbaudrate;
227  ops->setstopbits = ser_unix_nop_setstopbits;
228  ops->drain_output = ser_unix_nop_drain_output;
229  ops->async = ser_unix_async;
230  serial_add_interface (ops);
231}
232