OSDN Git Service

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