1/* Serial interface for raw TCP connections on Un*x like systems 2 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001 3 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22#include "defs.h" 23#include "serial.h" 24#include "ser-unix.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#include <netinet/in.h> 37#include <arpa/inet.h> 38#include <netdb.h> 39#include <sys/socket.h> 40#include <netinet/tcp.h> 41 42#include <signal.h> 43#include "gdb_string.h" 44 45static int net_open (struct serial *scb, const char *name); 46static void net_close (struct serial *scb); 47void _initialize_ser_tcp (void); 48 49/* seconds to wait for connect */ 50#define TIMEOUT 15 51/* how many times per second to poll deprecated_ui_loop_hook */ 52#define POLL_INTERVAL 2 53 54/* Open a tcp socket */ 55 56static int 57net_open (struct serial *scb, const char *name) 58{ 59 char *port_str, hostname[100]; 60 int n, port, tmp; 61 int use_udp; 62 struct hostent *hostent; 63 struct sockaddr_in sockaddr; 64 65 use_udp = 0; 66 if (strncmp (name, "udp:", 4) == 0) 67 { 68 use_udp = 1; 69 name = name + 4; 70 } 71 else if (strncmp (name, "tcp:", 4) == 0) 72 name = name + 4; 73 74 port_str = strchr (name, ':'); 75 76 if (!port_str) 77 error ("net_open: No colon in host name!"); /* Shouldn't ever happen */ 78 79 tmp = min (port_str - name, (int) sizeof hostname - 1); 80 strncpy (hostname, name, tmp); /* Don't want colon */ 81 hostname[tmp] = '\000'; /* Tie off host name */ 82 port = atoi (port_str + 1); 83 84 /* default hostname is localhost */ 85 if (!hostname[0]) 86 strcpy (hostname, "localhost"); 87 88 hostent = gethostbyname (hostname); 89 if (!hostent) 90 { 91 fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname); 92 errno = ENOENT; 93 return -1; 94 } 95 96 if (use_udp) 97 scb->fd = socket (AF_INET, SOCK_DGRAM, 0); 98 else 99 scb->fd = socket (AF_INET, SOCK_STREAM, 0); 100 101 if (scb->fd < 0) 102 return -1; 103 104 sockaddr.sin_family = AF_INET; 105 sockaddr.sin_port = htons (port); 106 memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, 107 sizeof (struct in_addr)); 108 109 /* set socket nonblocking */ 110 tmp = 1; 111 ioctl (scb->fd, FIONBIO, &tmp); 112 113 /* Use Non-blocking connect. connect() will return 0 if connected already. */ 114 n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); 115 116 if (n < 0 && errno != EINPROGRESS) 117 { 118 net_close (scb); 119 return -1; 120 } 121 122 if (n) 123 { 124 /* looks like we need to wait for the connect */ 125 struct timeval t; 126 fd_set rset, wset; 127 int polls = 0; 128 FD_ZERO (&rset); 129 130 do 131 { 132 /* While we wait for the connect to complete 133 poll the UI so it can update or the user can 134 interrupt. */ 135 if (deprecated_ui_loop_hook) 136 { 137 if (deprecated_ui_loop_hook (0)) 138 { 139 errno = EINTR; 140 net_close (scb); 141 return -1; 142 } 143 } 144 145 FD_SET (scb->fd, &rset); 146 wset = rset; 147 t.tv_sec = 0; 148 t.tv_usec = 1000000 / POLL_INTERVAL; 149 150 n = select (scb->fd + 1, &rset, &wset, NULL, &t); 151 polls++; 152 } 153 while (n == 0 && polls <= TIMEOUT * POLL_INTERVAL); 154 if (n < 0 || polls > TIMEOUT * POLL_INTERVAL) 155 { 156 if (polls > TIMEOUT * POLL_INTERVAL) 157 errno = ETIMEDOUT; 158 net_close (scb); 159 return -1; 160 } 161 } 162 163 /* Got something. Is it an error? */ 164 { 165 int res, err, len; 166 len = sizeof(err); 167 res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, &err, &len); 168 if (res < 0 || err) 169 { 170 if (err) 171 errno = err; 172 net_close (scb); 173 return -1; 174 } 175 } 176 177 /* turn off nonblocking */ 178 tmp = 0; 179 ioctl (scb->fd, FIONBIO, &tmp); 180 181#if (!defined(__BEOS__) && !defined(__HAIKU__)) 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#endif 190 191 /* If we don't do this, then GDB simply exits 192 when the remote side dies. */ 193 signal (SIGPIPE, SIG_IGN); 194 195 return 0; 196} 197 198static void 199net_close (struct serial *scb) 200{ 201 if (scb->fd < 0) 202 return; 203 204 close (scb->fd); 205 scb->fd = -1; 206} 207 208void 209_initialize_ser_tcp (void) 210{ 211 struct serial_ops *ops = XMALLOC (struct serial_ops); 212 memset (ops, 0, sizeof (struct serial_ops)); 213 ops->name = "tcp"; 214 ops->next = 0; 215 ops->open = net_open; 216 ops->close = net_close; 217 ops->readchar = ser_unix_readchar; 218 ops->write = ser_unix_write; 219 ops->flush_output = ser_unix_nop_flush_output; 220 ops->flush_input = ser_unix_flush_input; 221 ops->send_break = ser_unix_nop_send_break; 222 ops->go_raw = ser_unix_nop_raw; 223 ops->get_tty_state = ser_unix_nop_get_tty_state; 224 ops->set_tty_state = ser_unix_nop_set_tty_state; 225 ops->print_tty_state = ser_unix_nop_print_tty_state; 226 ops->noflush_set_tty_state = ser_unix_nop_noflush_set_tty_state; 227 ops->setbaudrate = ser_unix_nop_setbaudrate; 228 ops->setstopbits = ser_unix_nop_setstopbits; 229 ops->drain_output = ser_unix_nop_drain_output; 230 ops->async = ser_unix_async; 231 serial_add_interface (ops); 232} 233