2 * Server-side socket management
4 * Copyright (C) 1999 Marcus Meissner, Ove Kåven
6 * FIXME: we use read|write access in all cases. Shouldn't we depend that
7 * on the access of the current handle?
16 #include <sys/errno.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/ioctl.h>
35 struct object obj
; /* object header */
36 struct select_user select
; /* select user */
37 unsigned int state
; /* status bits */
38 unsigned int mask
; /* event mask */
39 unsigned int hmask
; /* held (blocked) events */
40 unsigned int pmask
; /* pending events */
41 struct event
*event
; /* event object */
42 int errors
[FD_MAX_EVENTS
]; /* event errors */
45 static void sock_dump( struct object
*obj
, int verbose
);
46 static int sock_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
47 static void sock_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
48 static int sock_signaled( struct object
*obj
, struct thread
*thread
);
49 static int sock_get_fd( struct object
*obj
);
50 static void sock_destroy( struct object
*obj
);
51 static void sock_set_error(void);
53 static const struct object_ops sock_ops
=
68 static int sock_event( struct sock
*sock
)
70 unsigned int mask
= sock
->mask
& sock
->state
& ~sock
->hmask
;
71 int ev
= EXCEPT_EVENT
;
73 if (sock
->state
& WS_FD_CONNECT
)
74 /* connecting, wait for writable */
75 return WRITE_EVENT
| EXCEPT_EVENT
;
76 if (sock
->state
& WS_FD_LISTENING
)
77 /* listening, wait for readable */
78 return ((sock
->hmask
& FD_ACCEPT
) ? 0 : READ_EVENT
) | EXCEPT_EVENT
;
80 if (mask
& FD_READ
) ev
|= READ_EVENT
;
81 if (mask
& FD_WRITE
) ev
|= WRITE_EVENT
;
85 static void sock_reselect( struct sock
*sock
)
87 set_select_events( &sock
->select
, sock_event( sock
) );
90 inline static int sock_error(int s
)
92 unsigned int optval
, optlen
;
94 optlen
= sizeof(optval
);
95 getsockopt(s
, SOL_SOCKET
, SO_ERROR
, (void *) &optval
, &optlen
);
99 static void sock_select_event( int event
, void *private )
101 struct sock
*sock
= (struct sock
*)private;
103 assert( sock
->obj
.ops
== &sock_ops
);
104 if (sock
->state
& WS_FD_CONNECT
)
107 if (event
& WRITE_EVENT
)
109 /* we got connected */
110 sock
->state
|= WS_FD_CONNECTED
|WS_FD_READ
|WS_FD_WRITE
;
111 sock
->state
&= ~WS_FD_CONNECT
;
112 sock
->pmask
|= FD_CONNECT
;
113 sock
->errors
[FD_CONNECT_BIT
] = 0;
115 else if (event
& EXCEPT_EVENT
)
117 /* we didn't get connected? */
118 sock
->state
&= ~WS_FD_CONNECT
;
119 sock
->pmask
|= FD_CONNECT
;
120 sock
->errors
[FD_CONNECT_BIT
] = sock_error( sock
->select
.fd
);
123 if (sock
->state
& WS_FD_LISTENING
)
126 if (event
& READ_EVENT
)
128 /* incoming connection */
129 sock
->pmask
|= FD_ACCEPT
;
130 sock
->errors
[FD_ACCEPT_BIT
] = 0;
131 sock
->hmask
|= FD_ACCEPT
;
133 else if (event
& EXCEPT_EVENT
)
135 /* failed incoming connection? */
136 sock
->pmask
|= FD_ACCEPT
;
137 sock
->errors
[FD_ACCEPT_BIT
] = sock_error( sock
->select
.fd
);
138 sock
->hmask
|= FD_ACCEPT
;
142 /* normal data flow */
143 if (event
& READ_EVENT
)
145 /* make sure there's data here */
147 ioctl(sock
->select
.fd
, FIONREAD
, (char*)&bytes
);
151 sock
->pmask
|= FD_READ
;
152 sock
->hmask
|= FD_READ
;
153 sock
->errors
[FD_READ_BIT
] = 0;
157 /* 0 bytes readable == socket closed cleanly */
158 sock
->state
&= ~(WS_FD_CONNECTED
|WS_FD_READ
|WS_FD_WRITE
);
159 sock
->pmask
|= FD_CLOSE
;
160 sock
->errors
[FD_CLOSE_BIT
] = 0;
163 if (event
& WRITE_EVENT
)
165 sock
->pmask
|= FD_WRITE
;
166 sock
->hmask
|= FD_WRITE
;
167 sock
->errors
[FD_WRITE_BIT
] = 0;
169 if (event
& EXCEPT_EVENT
)
171 sock
->errors
[FD_CLOSE_BIT
] = sock_error( sock
->select
.fd
);
172 if (sock
->errors
[FD_CLOSE_BIT
])
174 /* we got an error, socket closing? */
175 sock
->state
&= ~(WS_FD_CONNECTED
|WS_FD_READ
|WS_FD_WRITE
);
176 sock
->pmask
|= FD_CLOSE
;
180 /* no error, OOB data? */
181 sock
->pmask
|= FD_OOB
;
182 sock
->hmask
|= FD_OOB
;
187 sock_reselect( sock
);
188 /* wake up anyone waiting for whatever just happened */
189 emask
= sock
->pmask
& sock
->mask
;
190 if (emask
&& sock
->event
)
191 set_event(sock
->event
);
193 /* if anyone is stupid enough to wait on the socket object itself,
194 * maybe we should wake them up too, just in case? */
195 wake_up( &sock
->obj
, 0 );
198 static void sock_dump( struct object
*obj
, int verbose
)
200 struct sock
*sock
= (struct sock
*)obj
;
201 assert( obj
->ops
== &sock_ops
);
202 printf( "Socket fd=%d\n", sock
->select
.fd
);
205 static int sock_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
207 /* struct sock *sock = (struct sock *)obj; */
208 assert( obj
->ops
== &sock_ops
);
210 add_queue( obj
, entry
);
214 static void sock_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
216 /* struct sock *sock = (struct sock *)grab_object(obj); */
217 assert( obj
->ops
== &sock_ops
);
219 remove_queue( obj
, entry
);
220 release_object( obj
);
223 static int sock_signaled( struct object
*obj
, struct thread
*thread
)
225 struct sock
*sock
= (struct sock
*)obj
;
226 assert( obj
->ops
== &sock_ops
);
228 return check_select_events( &sock
->select
, sock_event( sock
) );
231 static int sock_get_fd( struct object
*obj
)
233 struct sock
*sock
= (struct sock
*)obj
;
235 assert( obj
->ops
== &sock_ops
);
236 fd
= dup( sock
->select
.fd
);
242 static void sock_destroy( struct object
*obj
)
244 struct sock
*sock
= (struct sock
*)obj
;
245 assert( obj
->ops
== &sock_ops
);
247 unregister_select_user( &sock
->select
);
248 /* FIXME: special socket shutdown stuff? */
249 close( sock
->select
.fd
);
252 /* if the service thread was waiting for the event object,
253 * we should now signal it, to let the service thread
254 * object detect that it is now orphaned... */
255 set_event( sock
->event
);
256 /* we're through with it */
257 release_object( sock
->event
);
262 /* create a new and unconnected socket */
263 static struct object
*create_socket( int family
, int type
, int protocol
)
267 if (!(sock
= alloc_object( &sock_ops
)))
269 sock
->select
.fd
= socket(family
,type
,protocol
);
270 sock
->select
.func
= sock_select_event
;
271 sock
->select
.private = sock
;
272 sock
->state
= (type
!=SOCK_STREAM
) ? WS_FD_READ
|WS_FD_WRITE
: 0;
277 fprintf(stderr
,"socket(%d,%d,%d)=%d\n",family
,type
,protocol
,sock
->select
.fd
);
278 fcntl(sock
->select
.fd
, F_SETFL
, O_NONBLOCK
); /* make socket nonblocking */
279 register_select_user( &sock
->select
);
284 /* accept a socket (creates a new fd) */
285 static struct object
*accept_socket( int handle
)
287 struct sock
*acceptsock
;
290 struct sockaddr saddr
;
293 sock
=(struct sock
*)get_handle_obj(current
->process
,handle
,
294 GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
,&sock_ops
);
297 /* Try to accept(2). We can't be safe that this an already connected socket
298 * or that accept() is allowed on it. In those cases we will get -1/errno
301 slen
= sizeof(saddr
);
302 acceptfd
= accept(sock
->select
.fd
,&saddr
,&slen
);
305 release_object( sock
);
308 if (!(acceptsock
= alloc_object( &sock_ops
)))
310 release_object( sock
);
314 acceptsock
->select
.fd
= acceptfd
;
315 acceptsock
->select
.func
= sock_select_event
;
316 acceptsock
->select
.private = sock
;
317 acceptsock
->state
= WS_FD_CONNECTED
|WS_FD_READ
|WS_FD_WRITE
;
318 acceptsock
->mask
= sock
->mask
;
319 acceptsock
->hmask
= 0;
320 acceptsock
->pmask
= 0;
321 acceptsock
->event
= (struct event
*)grab_object( sock
->event
);
322 register_select_user( &acceptsock
->select
);
324 sock
->pmask
&= ~FD_ACCEPT
;
325 sock
->hmask
&= ~FD_ACCEPT
;
326 release_object( sock
);
327 return &acceptsock
->obj
;
330 /* set the last error depending on errno */
331 static void sock_set_error(void)
335 case EINTR
: set_error(WSAEINTR
);break;
336 case EBADF
: set_error(WSAEBADF
);break;
338 case EACCES
: set_error(WSAEACCES
);break;
339 case EFAULT
: set_error(WSAEFAULT
);break;
340 case EINVAL
: set_error(WSAEINVAL
);break;
341 case EMFILE
: set_error(WSAEMFILE
);break;
342 case EWOULDBLOCK
: set_error(WSAEWOULDBLOCK
);break;
343 case EINPROGRESS
: set_error(WSAEINPROGRESS
);break;
344 case EALREADY
: set_error(WSAEALREADY
);break;
345 case ENOTSOCK
: set_error(WSAENOTSOCK
);break;
346 case EDESTADDRREQ
: set_error(WSAEDESTADDRREQ
);break;
347 case EMSGSIZE
: set_error(WSAEMSGSIZE
);break;
348 case EPROTOTYPE
: set_error(WSAEPROTOTYPE
);break;
349 case ENOPROTOOPT
: set_error(WSAENOPROTOOPT
);break;
350 case EPROTONOSUPPORT
: set_error(WSAEPROTONOSUPPORT
);break;
351 case ESOCKTNOSUPPORT
: set_error(WSAESOCKTNOSUPPORT
);break;
352 case EOPNOTSUPP
: set_error(WSAEOPNOTSUPP
);break;
353 case EPFNOSUPPORT
: set_error(WSAEPFNOSUPPORT
);break;
354 case EAFNOSUPPORT
: set_error(WSAEAFNOSUPPORT
);break;
355 case EADDRINUSE
: set_error(WSAEADDRINUSE
);break;
356 case EADDRNOTAVAIL
: set_error(WSAEADDRNOTAVAIL
);break;
357 case ENETDOWN
: set_error(WSAENETDOWN
);break;
358 case ENETUNREACH
: set_error(WSAENETUNREACH
);break;
359 case ENETRESET
: set_error(WSAENETRESET
);break;
360 case ECONNABORTED
: set_error(WSAECONNABORTED
);break;
362 case ECONNRESET
: set_error(WSAECONNRESET
);break;
363 case ENOBUFS
: set_error(WSAENOBUFS
);break;
364 case EISCONN
: set_error(WSAEISCONN
);break;
365 case ENOTCONN
: set_error(WSAENOTCONN
);break;
366 case ESHUTDOWN
: set_error(WSAESHUTDOWN
);break;
367 case ETOOMANYREFS
: set_error(WSAETOOMANYREFS
);break;
368 case ETIMEDOUT
: set_error(WSAETIMEDOUT
);break;
369 case ECONNREFUSED
: set_error(WSAECONNREFUSED
);break;
370 case ELOOP
: set_error(WSAELOOP
);break;
371 case ENAMETOOLONG
: set_error(WSAENAMETOOLONG
);break;
372 case EHOSTDOWN
: set_error(WSAEHOSTDOWN
);break;
373 case EHOSTUNREACH
: set_error(WSAEHOSTUNREACH
);break;
374 case ENOTEMPTY
: set_error(WSAENOTEMPTY
);break;
376 case EPROCLIM
: set_error(WSAEPROCLIM
);break;
379 case EUSERS
: set_error(WSAEUSERS
);break;
382 case EDQUOT
: set_error(WSAEDQUOT
);break;
385 case ESTALE
: set_error(WSAESTALE
);break;
388 case EREMOTE
: set_error(WSAEREMOTE
);break;
390 default: perror("sock_set_error"); set_error( ERROR_UNKNOWN
); break;
394 /* create a socket */
395 DECL_HANDLER(create_socket
)
400 if ((obj
= create_socket( req
->family
, req
->type
, req
->protocol
)) != NULL
)
402 s
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
403 release_object( obj
);
408 /* accept a socket */
409 DECL_HANDLER(accept_socket
)
414 if ((obj
= accept_socket( req
->lhandle
)) != NULL
)
416 s
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
417 release_object( obj
);
422 /* set socket event parameters */
423 DECL_HANDLER(set_socket_event
)
426 struct event
*oevent
;
428 sock
=(struct sock
*)get_handle_obj(current
->process
,req
->handle
,GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
,&sock_ops
);
431 oevent
= sock
->event
;
432 sock
->mask
= req
->mask
;
433 sock
->event
= get_event_obj( current
->process
, req
->event
, GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
);
434 sock_reselect( sock
);
436 sock
->state
|= WS_FD_NONBLOCKING
;
439 if (oevent
!= sock
->event
)
440 /* if the service thread was waiting for the old event object,
441 * we should now signal it, to let the service thread
442 * object detect that it is now orphaned... */
444 /* we're through with it */
445 release_object( oevent
);
447 release_object( &sock
->obj
);
450 /* get socket event parameters */
451 DECL_HANDLER(get_socket_event
)
455 sock
=(struct sock
*)get_handle_obj(current
->process
,req
->handle
,GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
,&sock_ops
);
461 set_error(WSAENOTSOCK
);
464 req
->mask
= sock
->mask
;
465 req
->pmask
= sock
->pmask
;
466 req
->state
= sock
->state
;
467 memcpy(req
->errors
, sock
->errors
, sizeof(sock
->errors
));
473 struct event
*sevent
= get_event_obj(current
->process
, req
->s_event
, GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
);
474 if (sevent
== sock
->event
)
476 release_object( sevent
);
481 sock_reselect( sock
);
483 else set_error(WSAEINVAL
);
485 release_object( &sock
->obj
);
488 /* re-enable pending socket events */
489 DECL_HANDLER(enable_socket_event
)
493 sock
=(struct sock
*)get_handle_obj(current
->process
,req
->handle
,GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
,&sock_ops
);
496 sock
->pmask
&= ~req
->mask
; /* is this safe? */
497 sock
->hmask
&= ~req
->mask
;
498 sock
->state
|= req
->sstate
;
499 sock
->state
&= ~req
->cstate
;
500 sock_reselect( sock
);
501 release_object( &sock
->obj
);