]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygserver/transport_sockets.cc
Remove superfluous libgloss/ directory names from recent ChangeLog entries.
[newlib-cygwin.git] / winsup / cygserver / transport_sockets.cc
1 /* transport_sockets.cc
2
3 Copyright 2001, 2002, 2003, 2004 Red Hat Inc.
4
5 Written by Robert Collins <rbtcollins@hotmail.com>
6
7 This file is part of Cygwin.
8
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 details. */
12
13 /* to allow this to link into cygwin and the .dll, a little magic is needed. */
14 #ifdef __OUTSIDE_CYGWIN__
15 #include "woutsup.h"
16 #else
17 #include "winsup.h"
18 #endif
19
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23
24 #include <assert.h>
25 #include <stdio.h>
26 #include <unistd.h>
27
28 #include "cygerrno.h"
29 #include "transport.h"
30 #include "transport_sockets.h"
31
32 #ifdef __INSIDE_CYGWIN__
33 #define SET_ERRNO(err) set_errno (err)
34 #define GET_ERRNO() get_errno ()
35 #else
36 #define SET_ERRNO(err) errno = (err)
37 #define GET_ERRNO() (errno)
38 #endif
39
40 /* to allow this to link into cygwin and the .dll, a little magic is needed. */
41 #ifndef __OUTSIDE_CYGWIN__
42
43 extern "C" int cygwin_accept (int fd, struct sockaddr *, int *len);
44 extern "C" int cygwin_bind (int fd, const struct sockaddr *, int len);
45 extern "C" int cygwin_connect (int fd, const struct sockaddr *, int len);
46 extern "C" int cygwin_listen (int fd, int backlog);
47 extern "C" int cygwin_shutdown (int fd, int how);
48 extern "C" int cygwin_socket (int af, int type, int protocol);
49
50 #else /* __OUTSIDE_CYGWIN__ */
51
52 #define cygwin_accept(A,B,C) ::accept (A,B,C)
53 #define cygwin_bind(A,B,C) ::bind (A,B,C)
54 #define cygwin_connect(A,B,C) ::connect (A,B,C)
55 #define cygwin_listen(A,B) ::listen (A,B)
56 #define cygwin_shutdown(A,B) ::shutdown (A,B)
57 #define cygwin_socket(A,B,C) ::socket (A,B,C)
58
59 #endif /* __OUTSIDE_CYGWIN__ */
60
61 enum
62 {
63 MAX_CONNECT_RETRY = 64
64 };
65
66 transport_layer_sockets::transport_layer_sockets (const int fd)
67 : _fd (fd),
68 _addr_len (0),
69 _is_accepted_endpoint (true),
70 _is_listening_endpoint (false)
71 {
72 assert (_fd != -1);
73
74 memset (&_addr, '\0', sizeof (_addr));
75 }
76
77 transport_layer_sockets::transport_layer_sockets ()
78 : _fd (-1),
79 _addr_len (0),
80 _is_accepted_endpoint (false),
81 _is_listening_endpoint (false)
82 {
83 memset (&_addr, '\0', sizeof (_addr));
84
85 _addr.sun_family = AF_UNIX;
86 strcpy (_addr.sun_path, "/tmp/cygdaemo"); // FIXME: $TMP?
87 _addr_len = SUN_LEN (&_addr);
88 }
89
90 transport_layer_sockets::~transport_layer_sockets ()
91 {
92 close ();
93 }
94
95 #ifndef __INSIDE_CYGWIN__
96
97 int
98 transport_layer_sockets::listen ()
99 {
100 assert (_fd == -1);
101 assert (!_is_accepted_endpoint);
102 assert (!_is_listening_endpoint);
103
104 debug_printf ("listen () [this = %p]", this);
105
106 struct stat sbuf;
107
108 if (stat (_addr.sun_path, &sbuf) == -1)
109 {
110 if (GET_ERRNO () != ENOENT)
111 {
112 system_printf ("cannot access socket file `%s': %s",
113 _addr.sun_path, strerror (GET_ERRNO ()));
114 return -1;
115 }
116 }
117 else if (S_ISSOCK (sbuf.st_mode))
118 {
119 // The socket already exists: is a duplicate cygserver running?
120
121 const int newfd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0);
122
123 if (newfd == -1)
124 {
125 system_printf ("failed to create UNIX domain socket: %s",
126 strerror (GET_ERRNO ()));
127 return -1;
128 }
129
130 if (cygwin_connect (newfd, (struct sockaddr *) &_addr, _addr_len) == 0)
131 {
132 system_printf ("the daemon is already running");
133 (void) cygwin_shutdown (newfd, SHUT_WR);
134 char buf[BUFSIZ];
135 while (::read (newfd, buf, sizeof (buf)) > 0)
136 {}
137 (void) ::close (newfd);
138 return -1;
139 }
140
141 if (unlink (_addr.sun_path) == -1)
142 {
143 system_printf ("failed to remove `%s': %s",
144 _addr.sun_path, strerror (GET_ERRNO ()));
145 (void) ::close (newfd);
146 return -1;
147 }
148 }
149 else
150 {
151 system_printf ("cannot create socket `%s': File already exists",
152 _addr.sun_path);
153 return -1;
154 }
155
156 _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0);
157
158 if (_fd == -1)
159 {
160 system_printf ("failed to create UNIX domain socket: %s",
161 strerror (GET_ERRNO ()));
162 return -1;
163 }
164
165 if (cygwin_bind (_fd, (struct sockaddr *) &_addr, _addr_len) == -1)
166 {
167 const int saved_errno = GET_ERRNO ();
168 close ();
169 SET_ERRNO (saved_errno);
170 system_printf ("failed to bind UNIX domain socket `%s': %s",
171 _addr.sun_path, strerror (GET_ERRNO ()));
172 return -1;
173 }
174
175 _is_listening_endpoint = true; // i.e. this really means "have bound".
176
177 if (cygwin_listen (_fd, SOMAXCONN) == -1)
178 {
179 const int saved_errno = GET_ERRNO ();
180 close ();
181 SET_ERRNO (saved_errno);
182 system_printf ("failed to listen on UNIX domain socket `%s': %s",
183 _addr.sun_path, strerror (GET_ERRNO ()));
184 return -1;
185 }
186
187 debug_printf ("0 = listen () [this = %p, fd = %d]", this, _fd);
188
189 return 0;
190 }
191
192 class transport_layer_sockets *
193 transport_layer_sockets::accept (bool *const recoverable)
194 {
195 assert (_fd != -1);
196 assert (!_is_accepted_endpoint);
197 assert (_is_listening_endpoint);
198
199 debug_printf ("accept () [this = %p, fd = %d]", this, _fd);
200
201 struct sockaddr_un client_addr;
202 socklen_t client_addr_len = sizeof (client_addr);
203
204 const int accept_fd =
205 cygwin_accept (_fd, (struct sockaddr *) &client_addr, &client_addr_len);
206
207 if (accept_fd == -1)
208 {
209 system_printf ("failed to accept connection: %s", strerror (GET_ERRNO ()));
210 switch (GET_ERRNO ())
211 {
212 case ECONNABORTED:
213 case EINTR:
214 case EMFILE:
215 case ENFILE:
216 case ENOBUFS:
217 case ENOMEM:
218 *recoverable = true;
219 break;
220
221 default:
222 *recoverable = false;
223 break;
224 }
225 return NULL;
226 }
227
228 debug_printf ("%d = accept () [this = %p, fd = %d]", accept_fd, this, _fd);
229
230 return new transport_layer_sockets (accept_fd);
231 }
232
233 #endif /* !__INSIDE_CYGWIN__ */
234
235 void
236 transport_layer_sockets::close ()
237 {
238 debug_printf ("close () [this = %p, fd = %d]", this, _fd);
239
240 if (_is_listening_endpoint)
241 (void) unlink (_addr.sun_path);
242
243 if (_fd != -1)
244 {
245 (void) cygwin_shutdown (_fd, SHUT_WR);
246 if (!_is_listening_endpoint)
247 {
248 char buf[BUFSIZ];
249 while (::read (_fd, buf, sizeof (buf)) > 0)
250 {}
251 }
252 (void) ::close (_fd);
253 _fd = -1;
254 }
255
256 _is_listening_endpoint = false;
257 }
258
259 ssize_t
260 transport_layer_sockets::read (void *const buf, const size_t buf_len)
261 {
262 assert (_fd != -1);
263 assert (!_is_listening_endpoint);
264
265 assert (buf);
266 assert (buf_len > 0);
267
268 // verbose: debug_printf ("read (buf = %p, len = %u) [this = %p, fd = %d]",
269 // buf, buf_len, this, _fd);
270
271 char *read_buf = static_cast<char *> (buf);
272 size_t read_buf_len = buf_len;
273 ssize_t res = 0;
274
275 while (read_buf_len != 0
276 && (res = ::read (_fd, read_buf, read_buf_len)) > 0)
277 {
278 read_buf += res;
279 read_buf_len -= res;
280
281 assert (read_buf_len >= 0);
282 }
283
284 if (res != -1)
285 {
286 if (res == 0)
287 SET_ERRNO (EIO); // FIXME?
288
289 res = buf_len - read_buf_len;
290 }
291
292 if (res != static_cast<ssize_t> (buf_len))
293 debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]: %s",
294 res, buf, buf_len, this, _fd,
295 (res == -1 ? strerror (GET_ERRNO ()) : "EOF"));
296 else
297 {
298 // verbose: debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]",
299 // res, buf, buf_len, this, _fd);
300 }
301
302 return res;
303 }
304
305 ssize_t
306 transport_layer_sockets::write (void *const buf, const size_t buf_len)
307 {
308 assert (_fd != -1);
309 assert (!_is_listening_endpoint);
310
311 assert (buf);
312 assert (buf_len > 0);
313
314 // verbose: debug_printf ("write (buf = %p, len = %u) [this = %p, fd = %d]",
315 // buf, buf_len, this, _fd);
316
317 char *write_buf = static_cast<char *> (buf);
318 size_t write_buf_len = buf_len;
319 ssize_t res = 0;
320
321 while (write_buf_len != 0
322 && (res = ::write (_fd, write_buf, write_buf_len)) > 0)
323 {
324 write_buf += res;
325 write_buf_len -= res;
326
327 assert (write_buf_len >= 0);
328 }
329
330 if (res != -1)
331 {
332 if (res == 0)
333 SET_ERRNO (EIO); // FIXME?
334
335 res = buf_len - write_buf_len;
336 }
337
338 if (res != static_cast<ssize_t> (buf_len))
339 debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]: %s",
340 res, buf, buf_len, this, _fd,
341 (res == -1 ? strerror (GET_ERRNO ()) : "EOF"));
342 else
343 {
344 // verbose: debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]",
345 // res, buf, buf_len, this, _fd);
346 }
347
348 return res;
349 }
350
351 int
352 transport_layer_sockets::connect ()
353 {
354 assert (_fd == -1);
355 assert (!_is_accepted_endpoint);
356 assert (!_is_listening_endpoint);
357
358 static bool assume_cygserver = false;
359
360 debug_printf ("connect () [this = %p]", this);
361
362 for (int retries = 0; retries != MAX_CONNECT_RETRY; retries++)
363 {
364 _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0);
365
366 if (_fd == -1)
367 {
368 system_printf ("failed to create UNIX domain socket: %s",
369 strerror (GET_ERRNO ()));
370 return -1;
371 }
372
373 if (cygwin_connect (_fd, (struct sockaddr *) &_addr, _addr_len) == 0)
374 {
375 assume_cygserver = true;
376 debug_printf ("0 = connect () [this = %p, fd = %d]", this, _fd);
377 return 0;
378 }
379
380 if (!assume_cygserver || GET_ERRNO () != ECONNREFUSED)
381 {
382 debug_printf ("failed to connect to server: %s", strerror (GET_ERRNO ()));
383 (void) ::close (_fd);
384 _fd = -1;
385 return -1;
386 }
387
388 (void) ::close (_fd);
389 _fd = -1;
390 Sleep (0); // Give the server a chance.
391 }
392
393 debug_printf ("failed to connect to server: %s", strerror (GET_ERRNO ()));
394 return -1;
395 }
This page took 0.06404 seconds and 5 git commands to generate.