119370Spst/* Serial interface for raw TCP connections on Un*x like systems 298944Sobrien Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001 398944Sobrien Free Software Foundation, Inc. 419370Spst 598944Sobrien This file is part of GDB. 619370Spst 798944Sobrien This program is free software; you can redistribute it and/or modify 898944Sobrien it under the terms of the GNU General Public License as published by 998944Sobrien the Free Software Foundation; either version 2 of the License, or 1098944Sobrien (at your option) any later version. 1119370Spst 1298944Sobrien This program is distributed in the hope that it will be useful, 1398944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1498944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598944Sobrien GNU General Public License for more details. 1619370Spst 1798944Sobrien You should have received a copy of the GNU General Public License 1898944Sobrien along with this program; if not, write to the Free Software 1998944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2098944Sobrien Boston, MA 02111-1307, USA. */ 2119370Spst 2219370Spst#include "defs.h" 2319370Spst#include "serial.h" 2498944Sobrien#include "ser-unix.h" 2598944Sobrien 2619370Spst#include <sys/types.h> 2798944Sobrien 2898944Sobrien#ifdef HAVE_SYS_FILIO_H 2998944Sobrien#include <sys/filio.h> /* For FIONBIO. */ 3098944Sobrien#endif 3198944Sobrien#ifdef HAVE_SYS_IOCTL_H 3298944Sobrien#include <sys/ioctl.h> /* For FIONBIO. */ 3398944Sobrien#endif 3498944Sobrien 3519370Spst#include <sys/time.h> 3619370Spst#include <netinet/in.h> 3719370Spst#include <arpa/inet.h> 3819370Spst#include <netdb.h> 3919370Spst#include <sys/socket.h> 4019370Spst#include <netinet/tcp.h> 4146283Sdfr 4298944Sobrien#include <signal.h> 4319370Spst#include "gdb_string.h" 4419370Spst 45130803Smarcelstatic int net_open (struct serial *scb, const char *name); 46130803Smarcelstatic void net_close (struct serial *scb); 4798944Sobrienextern int (*ui_loop_hook) (int); 4898944Sobrienvoid _initialize_ser_tcp (void); 4919370Spst 5098944Sobrien/* seconds to wait for connect */ 5198944Sobrien#define TIMEOUT 15 5298944Sobrien/* how many times per second to poll ui_loop_hook */ 5398944Sobrien#define POLL_INTERVAL 2 5419370Spst 5598944Sobrien/* Open a tcp socket */ 5646283Sdfr 5719370Spststatic int 58130803Smarcelnet_open (struct serial *scb, const char *name) 5919370Spst{ 6098944Sobrien char *port_str, hostname[100]; 6198944Sobrien int n, port, tmp; 62130803Smarcel int use_udp; 6319370Spst struct hostent *hostent; 6419370Spst struct sockaddr_in sockaddr; 6519370Spst 66130803Smarcel use_udp = 0; 67130803Smarcel if (strncmp (name, "udp:", 4) == 0) 68130803Smarcel { 69130803Smarcel use_udp = 1; 70130803Smarcel name = name + 4; 71130803Smarcel } 72130803Smarcel else if (strncmp (name, "tcp:", 4) == 0) 73130803Smarcel name = name + 4; 74130803Smarcel 7519370Spst port_str = strchr (name, ':'); 7619370Spst 7719370Spst if (!port_str) 78130803Smarcel error ("net_open: No colon in host name!"); /* Shouldn't ever happen */ 7919370Spst 8019370Spst tmp = min (port_str - name, (int) sizeof hostname - 1); 8198944Sobrien strncpy (hostname, name, tmp); /* Don't want colon */ 8219370Spst hostname[tmp] = '\000'; /* Tie off host name */ 8319370Spst port = atoi (port_str + 1); 8419370Spst 8598944Sobrien /* default hostname is localhost */ 8698944Sobrien if (!hostname[0]) 8798944Sobrien strcpy (hostname, "localhost"); 8898944Sobrien 8919370Spst hostent = gethostbyname (hostname); 9019370Spst if (!hostent) 9119370Spst { 9219370Spst fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname); 9319370Spst errno = ENOENT; 9419370Spst return -1; 9519370Spst } 9619370Spst 97130803Smarcel if (use_udp) 98130803Smarcel scb->fd = socket (PF_INET, SOCK_DGRAM, 0); 99130803Smarcel else 100130803Smarcel scb->fd = socket (PF_INET, SOCK_STREAM, 0); 101130803Smarcel 10298944Sobrien if (scb->fd < 0) 10319370Spst return -1; 10498944Sobrien 10598944Sobrien sockaddr.sin_family = PF_INET; 10698944Sobrien sockaddr.sin_port = htons (port); 10798944Sobrien memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, 10898944Sobrien sizeof (struct in_addr)); 10919370Spst 11098944Sobrien /* set socket nonblocking */ 11119370Spst tmp = 1; 11298944Sobrien ioctl (scb->fd, FIONBIO, &tmp); 11319370Spst 11498944Sobrien /* Use Non-blocking connect. connect() will return 0 if connected already. */ 11598944Sobrien n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); 11619370Spst 11798944Sobrien if (n < 0 && errno != EINPROGRESS) 11819370Spst { 119130803Smarcel net_close (scb); 12098944Sobrien return -1; 12119370Spst } 12219370Spst 12398944Sobrien if (n) 12419370Spst { 12598944Sobrien /* looks like we need to wait for the connect */ 12698944Sobrien struct timeval t; 12798944Sobrien fd_set rset, wset; 12898944Sobrien int polls = 0; 12998944Sobrien FD_ZERO (&rset); 13019370Spst 13198944Sobrien do 13298944Sobrien { 13398944Sobrien /* While we wait for the connect to complete 13498944Sobrien poll the UI so it can update or the user can 13598944Sobrien interrupt. */ 13698944Sobrien if (ui_loop_hook) 13798944Sobrien { 13898944Sobrien if (ui_loop_hook (0)) 13998944Sobrien { 14098944Sobrien errno = EINTR; 141130803Smarcel net_close (scb); 14298944Sobrien return -1; 14398944Sobrien } 14498944Sobrien } 14598944Sobrien 14698944Sobrien FD_SET (scb->fd, &rset); 14798944Sobrien wset = rset; 14898944Sobrien t.tv_sec = 0; 14998944Sobrien t.tv_usec = 1000000 / POLL_INTERVAL; 15098944Sobrien 15198944Sobrien n = select (scb->fd + 1, &rset, &wset, NULL, &t); 15298944Sobrien polls++; 15398944Sobrien } 15498944Sobrien while (n == 0 && polls <= TIMEOUT * POLL_INTERVAL); 15598944Sobrien if (n < 0 || polls > TIMEOUT * POLL_INTERVAL) 15698944Sobrien { 15798944Sobrien if (polls > TIMEOUT * POLL_INTERVAL) 15898944Sobrien errno = ETIMEDOUT; 159130803Smarcel net_close (scb); 16098944Sobrien return -1; 16198944Sobrien } 16246283Sdfr } 16319370Spst 16498944Sobrien /* Got something. Is it an error? */ 16598944Sobrien { 16698944Sobrien int res, err, len; 16798944Sobrien len = sizeof(err); 16898944Sobrien res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, &err, &len); 16998944Sobrien if (res < 0 || err) 17098944Sobrien { 17198944Sobrien if (err) 17298944Sobrien errno = err; 173130803Smarcel net_close (scb); 17498944Sobrien return -1; 17598944Sobrien } 17698944Sobrien } 177130803Smarcel 17898944Sobrien /* turn off nonblocking */ 17998944Sobrien tmp = 0; 18098944Sobrien ioctl (scb->fd, FIONBIO, &tmp); 18119370Spst 182130803Smarcel if (use_udp == 0) 183130803Smarcel { 184130803Smarcel /* Disable Nagle algorithm. Needed in some cases. */ 185130803Smarcel tmp = 1; 186130803Smarcel setsockopt (scb->fd, IPPROTO_TCP, TCP_NODELAY, 187130803Smarcel (char *)&tmp, sizeof (tmp)); 188130803Smarcel } 189130803Smarcel 19098944Sobrien /* If we don't do this, then GDB simply exits 19198944Sobrien when the remote side dies. */ 19298944Sobrien signal (SIGPIPE, SIG_IGN); 19319370Spst 19419370Spst return 0; 19519370Spst} 19619370Spst 19719370Spststatic void 198130803Smarcelnet_close (struct serial *scb) 19919370Spst{ 20019370Spst if (scb->fd < 0) 20119370Spst return; 20219370Spst 20398944Sobrien close (scb->fd); 20419370Spst scb->fd = -1; 20519370Spst} 20619370Spst 20719370Spstvoid 20898944Sobrien_initialize_ser_tcp (void) 20919370Spst{ 21098944Sobrien struct serial_ops *ops = XMALLOC (struct serial_ops); 211130803Smarcel memset (ops, 0, sizeof (struct serial_ops)); 21298944Sobrien ops->name = "tcp"; 21398944Sobrien ops->next = 0; 214130803Smarcel ops->open = net_open; 215130803Smarcel ops->close = net_close; 21698944Sobrien ops->readchar = ser_unix_readchar; 21798944Sobrien ops->write = ser_unix_write; 21898944Sobrien ops->flush_output = ser_unix_nop_flush_output; 21998944Sobrien ops->flush_input = ser_unix_flush_input; 22098944Sobrien ops->send_break = ser_unix_nop_send_break; 22198944Sobrien ops->go_raw = ser_unix_nop_raw; 22298944Sobrien ops->get_tty_state = ser_unix_nop_get_tty_state; 22398944Sobrien ops->set_tty_state = ser_unix_nop_set_tty_state; 22498944Sobrien ops->print_tty_state = ser_unix_nop_print_tty_state; 22598944Sobrien ops->noflush_set_tty_state = ser_unix_nop_noflush_set_tty_state; 22698944Sobrien ops->setbaudrate = ser_unix_nop_setbaudrate; 22798944Sobrien ops->setstopbits = ser_unix_nop_setstopbits; 22898944Sobrien ops->drain_output = ser_unix_nop_drain_output; 22998944Sobrien ops->async = ser_unix_async; 23098944Sobrien serial_add_interface (ops); 23119370Spst} 232