]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/ser-tcp.c
Switch the license of all .c files to GPLv3.
[thirdparty/binutils-gdb.git] / gdb / ser-tcp.c
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
54 typedef int socklen_t;
55 #endif
56
57 void _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
66 int
67 net_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
238 void
239 net_close (struct serial *scb)
240 {
241 if (scb->fd < 0)
242 return;
243
244 close (scb->fd);
245 scb->fd = -1;
246 }
247
248 int
249 net_read_prim (struct serial *scb, size_t count)
250 {
251 return recv (scb->fd, scb->buf, count, 0);
252 }
253
254 int
255 net_write_prim (struct serial *scb, const void *buf, size_t count)
256 {
257 return send (scb->fd, buf, count, 0);
258 }
259
260 void
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 }