blob: b69eec68986a696dd41383335b9d2a5144a34785 [file] [log] [blame]
Mike McCormackde7c3002001-07-10 19:16:49 +00001/*
2 * Server-side pipe management
3 *
4 * Copyright (C) 1998 Alexandre Julliard
Mike McCormackbf554572001-08-23 23:29:20 +00005 * Copyright (C) 2001 Mike McCormack
6 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00007 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
Mike McCormackbf554572001-08-23 23:29:20 +000021 * TODO:
Mike McCormackef8b9462003-05-15 04:22:45 +000022 * message mode
Mike McCormackde7c3002001-07-10 19:16:49 +000023 */
24
25#include "config.h"
Alexandre Julliard5769d1d2002-04-26 19:05:15 +000026#include "wine/port.h"
Mike McCormackde7c3002001-07-10 19:16:49 +000027
28#include <assert.h>
29#include <fcntl.h>
30#include <string.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000031#include <stdarg.h>
Mike McCormackde7c3002001-07-10 19:16:49 +000032#include <stdio.h>
33#include <stdlib.h>
34#include <sys/time.h>
35#include <sys/types.h>
Steven Edwards037c8a12003-02-11 22:27:13 +000036#ifdef HAVE_SYS_SOCKET_H
Mike McCormackde7c3002001-07-10 19:16:49 +000037#include <sys/socket.h>
Steven Edwards037c8a12003-02-11 22:27:13 +000038#endif
Mike McCormackde7c3002001-07-10 19:16:49 +000039#include <time.h>
40#include <unistd.h>
41
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000042#include "windef.h"
Mike McCormackde7c3002001-07-10 19:16:49 +000043#include "winbase.h"
44
Alexandre Julliard863637b2003-01-30 00:26:44 +000045#include "file.h"
Mike McCormackde7c3002001-07-10 19:16:49 +000046#include "handle.h"
47#include "thread.h"
48#include "request.h"
49
Mike McCormackbf554572001-08-23 23:29:20 +000050enum pipe_state
51{
52 ps_none,
53 ps_idle_server,
54 ps_wait_open,
Mike McCormackbf554572001-08-23 23:29:20 +000055 ps_connected_server,
Mike McCormackef8b9462003-05-15 04:22:45 +000056 ps_wait_disconnect,
57 ps_disconnected_server,
58 ps_wait_connect
59};
60
61struct wait_info
62{
63 struct thread *thread;
64 void *func;
65 void *overlapped;
Mike McCormackbf554572001-08-23 23:29:20 +000066};
67
Mike McCormackde7c3002001-07-10 19:16:49 +000068struct named_pipe;
69
Mike McCormackef8b9462003-05-15 04:22:45 +000070struct pipe_server
Mike McCormackde7c3002001-07-10 19:16:49 +000071{
Mike McCormackef8b9462003-05-15 04:22:45 +000072 struct object obj;
73 struct fd *fd;
74 enum pipe_state state;
75 struct pipe_client *client;
76 struct named_pipe *pipe;
77 struct pipe_server *next;
78 struct pipe_server *prev;
79 struct timeout_user *flush_poll;
80 struct event *event;
81 struct wait_info wait;
82};
83
84struct pipe_client
85{
86 struct object obj;
87 struct fd *fd;
88 struct pipe_server *server;
89 struct wait_info wait;
90};
91
92struct connect_wait
93{
94 struct wait_info wait;
95 struct connect_wait *next;
Mike McCormackde7c3002001-07-10 19:16:49 +000096};
97
98struct named_pipe
99{
100 struct object obj; /* object header */
101 unsigned int pipemode;
102 unsigned int maxinstances;
103 unsigned int outsize;
104 unsigned int insize;
105 unsigned int timeout;
Mike McCormackef8b9462003-05-15 04:22:45 +0000106 unsigned int instances;
107 struct pipe_server *servers;
108 struct connect_wait *connect_waiters;
Mike McCormackde7c3002001-07-10 19:16:49 +0000109};
110
111static void named_pipe_dump( struct object *obj, int verbose );
Mike McCormackef8b9462003-05-15 04:22:45 +0000112static void named_pipe_destroy( struct object *obj );
Mike McCormackde7c3002001-07-10 19:16:49 +0000113
114static const struct object_ops named_pipe_ops =
115{
116 sizeof(struct named_pipe), /* size */
117 named_pipe_dump, /* dump */
118 no_add_queue, /* add_queue */
119 NULL, /* remove_queue */
120 NULL, /* signaled */
121 NULL, /* satisfied */
Mike McCormackde7c3002001-07-10 19:16:49 +0000122 no_get_fd, /* get_fd */
Mike McCormackde7c3002001-07-10 19:16:49 +0000123 named_pipe_destroy /* destroy */
124};
125
Mike McCormackef8b9462003-05-15 04:22:45 +0000126/* common to clients and servers */
127static int pipe_end_get_poll_events( struct fd *fd );
128static int pipe_end_get_info( struct fd *fd,
129 struct get_file_info_reply *reply, int *flags );
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000130
Mike McCormackef8b9462003-05-15 04:22:45 +0000131/* server end functions */
132static void pipe_server_dump( struct object *obj, int verbose );
133static struct fd *pipe_server_get_fd( struct object *obj );
134static void pipe_server_destroy( struct object *obj);
135static int pipe_server_flush( struct fd *fd, struct event **event );
Mike McCormackde7c3002001-07-10 19:16:49 +0000136
Mike McCormackef8b9462003-05-15 04:22:45 +0000137static const struct object_ops pipe_server_ops =
Mike McCormackde7c3002001-07-10 19:16:49 +0000138{
Mike McCormackef8b9462003-05-15 04:22:45 +0000139 sizeof(struct pipe_server), /* size */
140 pipe_server_dump, /* dump */
Alexandre Julliard863637b2003-01-30 00:26:44 +0000141 default_fd_add_queue, /* add_queue */
142 default_fd_remove_queue, /* remove_queue */
143 default_fd_signaled, /* signaled */
Mike McCormackde7c3002001-07-10 19:16:49 +0000144 no_satisfied, /* satisfied */
Mike McCormackef8b9462003-05-15 04:22:45 +0000145 pipe_server_get_fd, /* get_fd */
146 pipe_server_destroy /* destroy */
Alexandre Julliard863637b2003-01-30 00:26:44 +0000147};
148
Mike McCormackef8b9462003-05-15 04:22:45 +0000149static const struct fd_ops pipe_server_fd_ops =
Alexandre Julliard863637b2003-01-30 00:26:44 +0000150{
Mike McCormackef8b9462003-05-15 04:22:45 +0000151 pipe_end_get_poll_events, /* get_poll_events */
Mike McCormackde7c3002001-07-10 19:16:49 +0000152 default_poll_event, /* poll_event */
Mike McCormackef8b9462003-05-15 04:22:45 +0000153 pipe_server_flush, /* flush */
154 pipe_end_get_info, /* get_file_info */
155 no_queue_async /* queue_async */
156};
157
158/* client end functions */
159static void pipe_client_dump( struct object *obj, int verbose );
160static struct fd *pipe_client_get_fd( struct object *obj );
161static void pipe_client_destroy( struct object *obj );
162static int pipe_client_flush( struct fd *fd, struct event **event );
163
164static const struct object_ops pipe_client_ops =
165{
166 sizeof(struct pipe_client), /* size */
167 pipe_client_dump, /* dump */
168 default_fd_add_queue, /* add_queue */
169 default_fd_remove_queue, /* remove_queue */
170 default_fd_signaled, /* signaled */
171 no_satisfied, /* satisfied */
172 pipe_client_get_fd, /* get_fd */
173 pipe_client_destroy /* destroy */
174};
175
176static const struct fd_ops pipe_client_fd_ops =
177{
178 pipe_end_get_poll_events, /* get_poll_events */
179 default_poll_event, /* poll_event */
180 pipe_client_flush, /* flush */
181 pipe_end_get_info, /* get_file_info */
Alexandre Julliard863637b2003-01-30 00:26:44 +0000182 no_queue_async /* queue_async */
Mike McCormackde7c3002001-07-10 19:16:49 +0000183};
184
185static void named_pipe_dump( struct object *obj, int verbose )
186{
Mike McCormackef8b9462003-05-15 04:22:45 +0000187 struct named_pipe *pipe = (struct named_pipe *) obj;
Mike McCormackde7c3002001-07-10 19:16:49 +0000188 assert( obj->ops == &named_pipe_ops );
189 fprintf( stderr, "named pipe %p\n" ,pipe);
190}
191
Mike McCormackef8b9462003-05-15 04:22:45 +0000192static void pipe_server_dump( struct object *obj, int verbose )
Mike McCormackde7c3002001-07-10 19:16:49 +0000193{
Mike McCormackef8b9462003-05-15 04:22:45 +0000194 struct pipe_server *server = (struct pipe_server *) obj;
195 assert( obj->ops == &pipe_server_ops );
196 fprintf( stderr, "named pipe server %p (state %d)\n",
197 server, server->state );
198}
199
200static void pipe_client_dump( struct object *obj, int verbose )
201{
202 struct pipe_client *client = (struct pipe_client *) obj;
203 assert( obj->ops == &pipe_server_ops );
204 fprintf( stderr, "named pipe client %p (server state %d)\n",
205 client, client->server->state );
Mike McCormackde7c3002001-07-10 19:16:49 +0000206}
207
208static void named_pipe_destroy( struct object *obj)
209{
Mike McCormackef8b9462003-05-15 04:22:45 +0000210 struct named_pipe *pipe = (struct named_pipe *) obj;
211 assert( !pipe->servers );
212 assert( !pipe->instances );
Mike McCormackde7c3002001-07-10 19:16:49 +0000213}
214
Mike McCormackef8b9462003-05-15 04:22:45 +0000215static void notify_waiter( struct wait_info *wait, unsigned int status )
Mike McCormack309ed4e2001-11-07 20:14:45 +0000216{
Mike McCormackef8b9462003-05-15 04:22:45 +0000217 if( wait->thread && wait->func && wait->overlapped )
Mike McCormack309ed4e2001-11-07 20:14:45 +0000218 {
219 /* queue a system APC, to notify a waiting thread */
Mike McCormackef8b9462003-05-15 04:22:45 +0000220 thread_queue_apc( wait->thread, NULL, wait->func, APC_ASYNC,
221 1, wait->overlapped, (void *)status, NULL );
Mike McCormack309ed4e2001-11-07 20:14:45 +0000222 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000223 if( wait->thread ) release_object( wait->thread );
224 wait->thread = NULL;
Mike McCormack309ed4e2001-11-07 20:14:45 +0000225}
226
Mike McCormackef8b9462003-05-15 04:22:45 +0000227static void set_waiter( struct wait_info *wait, void *func, void *ov )
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000228{
Mike McCormackef8b9462003-05-15 04:22:45 +0000229 wait->thread = (struct thread *) grab_object( current );
230 wait->func = func;
231 wait->overlapped = ov;
232}
233
234static void notify_connect_waiters( struct named_pipe *pipe )
235{
236 struct connect_wait *cw, **x = &pipe->connect_waiters;
237
238 while( *x )
239 {
240 cw = *x;
241 notify_waiter( &cw->wait, STATUS_SUCCESS );
242 release_object( pipe );
243 *x = cw->next;
244 free( cw );
245 }
246}
247
248static void queue_connect_waiter( struct named_pipe *pipe,
249 void *func, void *overlapped )
250{
251 struct connect_wait *waiter;
252
Francois Gouget95918362003-06-18 19:45:22 +0000253 waiter = mem_alloc( sizeof(*waiter) );
Mike McCormackef8b9462003-05-15 04:22:45 +0000254 if( waiter )
255 {
256 set_waiter( &waiter->wait, func, overlapped );
257 waiter->next = pipe->connect_waiters;
258 pipe->connect_waiters = waiter;
259 grab_object( pipe );
260 }
261}
262
263static struct fd *pipe_client_get_fd( struct object *obj )
264{
265 struct pipe_client *client = (struct pipe_client *) obj;
266 if( client->fd )
267 return (struct fd *) grab_object( client->fd );
Bill Medland3f7c3ff2003-04-17 02:14:04 +0000268 set_error( STATUS_PIPE_DISCONNECTED );
269 return NULL;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000270}
271
Mike McCormackef8b9462003-05-15 04:22:45 +0000272static struct fd *pipe_server_get_fd( struct object *obj )
Mike McCormackde7c3002001-07-10 19:16:49 +0000273{
Mike McCormackef8b9462003-05-15 04:22:45 +0000274 struct pipe_server *server = (struct pipe_server *) obj;
Mike McCormackde7c3002001-07-10 19:16:49 +0000275
Mike McCormackef8b9462003-05-15 04:22:45 +0000276 switch(server->state)
Mike McCormackbf554572001-08-23 23:29:20 +0000277 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000278 case ps_connected_server:
279 case ps_wait_disconnect:
280 assert( server->fd );
281 return (struct fd *) grab_object( server->fd );
Mike McCormackde7c3002001-07-10 19:16:49 +0000282
Mike McCormackef8b9462003-05-15 04:22:45 +0000283 case ps_wait_open:
284 case ps_idle_server:
285 set_error( STATUS_PIPE_LISTENING );
286 break;
287
288 case ps_disconnected_server:
289 case ps_wait_connect:
290 set_error( STATUS_PIPE_DISCONNECTED );
291 break;
292
293 default:
294 assert( 0 );
295 }
296 return NULL;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000297}
298
Mike McCormackef8b9462003-05-15 04:22:45 +0000299
300static void notify_empty( struct pipe_server *server )
301{
302 if( !server->flush_poll )
303 return;
304 assert( server->state == ps_connected_server );
305 assert( server->event );
306 remove_timeout_user( server->flush_poll );
307 server->flush_poll = NULL;
308 set_event( server->event );
309 release_object( server->event );
310 server->event = NULL;
311}
312
313static void do_disconnect( struct pipe_server *server )
314{
315 /* we may only have a server fd, if the client disconnected */
316 if( server->client )
317 {
318 assert( server->client->server == server );
319 assert( server->client->fd );
320 release_object( server->client->fd );
321 server->client->fd = NULL;
322 }
323 assert( server->fd );
324 release_object( server->fd );
325 server->fd = NULL;
326}
327
328static void pipe_server_destroy( struct object *obj)
329{
330 struct pipe_server *server = (struct pipe_server *)obj;
331
332 assert( obj->ops == &pipe_server_ops );
333
334 if( server->fd )
335 {
336 notify_empty( server );
337 do_disconnect( server );
338 }
339
340 if( server->client )
341 {
342 server->client->server = NULL;
343 server->client = NULL;
344 }
345
346 notify_waiter( &server->wait, STATUS_HANDLES_CLOSED );
347
348 assert( server->pipe->instances );
349 server->pipe->instances--;
350
351 /* remove server from pipe's server list */
352 if( server->next ) server->next->prev = server->prev;
353 if( server->prev ) server->prev->next = server->next;
354 else server->pipe->servers = server->next;
355 release_object( server->pipe );
356}
357
358static void pipe_client_destroy( struct object *obj)
359{
360 struct pipe_client *client = (struct pipe_client *)obj;
361 struct pipe_server *server = client->server;
362
363 assert( obj->ops == &pipe_client_ops );
364
365 notify_waiter( &client->wait, STATUS_HANDLES_CLOSED );
366
367 if( server )
368 {
369 notify_empty( server );
370
371 switch( server->state )
372 {
373 case ps_connected_server:
374 /* Don't destroy the server's fd here as we can't
375 do a successful flush without it. */
376 server->state = ps_wait_disconnect;
377 release_object( client->fd );
378 client->fd = NULL;
379 break;
380 case ps_disconnected_server:
381 server->state = ps_wait_connect;
382 break;
383 default:
384 assert( 0 );
385 }
386 assert( server->client );
387 server->client = NULL;
388 client->server = NULL;
389 }
390 assert( !client->fd );
391}
392
393static int pipe_end_get_poll_events( struct fd *fd )
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000394{
395 return POLLIN | POLLOUT; /* FIXME */
Mike McCormackde7c3002001-07-10 19:16:49 +0000396}
397
Mike McCormackef8b9462003-05-15 04:22:45 +0000398static int pipe_data_remaining( struct pipe_server *server )
399{
400 struct pollfd pfd;
401 int fd;
402
403 assert( server->client );
404
405 fd = get_unix_fd( server->client->fd );
406 if( fd < 0 )
407 return 0;
408 pfd.fd = fd;
409 pfd.events = POLLIN;
410 pfd.revents = 0;
411
412 if( 0 > poll( &pfd, 1, 0 ) )
413 return 0;
414
415 return pfd.revents&POLLIN;
416}
417
418static void check_flushed( void *arg )
419{
420 struct pipe_server *server = (struct pipe_server*) arg;
421
422 assert( server->event );
423 if( pipe_data_remaining( server ) )
424 {
425 struct timeval tv;
426
427 gettimeofday( &tv, 0 );
428 add_timeout( &tv, 100 );
429 server->flush_poll = add_timeout_user( &tv, check_flushed, server );
430 }
431 else
432 notify_empty( server );
433}
434
435static int pipe_server_flush( struct fd *fd, struct event **event )
436{
437 struct pipe_server *server = get_fd_user( fd );
438
439 if( !server )
440 return 0;
441
442 if( server->state != ps_connected_server )
443 return 0;
444
445 /* FIXME: if multiple threads flush the same pipe,
446 maybe should create a list of processes to notify */
447 if( server->flush_poll )
448 return 0;
449
450 if( pipe_data_remaining( server ) )
451 {
452 struct timeval tv;
453
454 /* this kind of sux -
455 there's no unix way to be alerted when a pipe becomes empty */
456 server->event = create_event( NULL, 0, 0, 0 );
457 if( !server->event )
458 return 0;
459 gettimeofday( &tv, 0 );
460 add_timeout( &tv, 100 );
461 server->flush_poll = add_timeout_user( &tv, check_flushed, server );
462 *event = server->event;
463 }
464
465 return 0;
466}
467
468static int pipe_client_flush( struct fd *fd, struct event **event )
469{
470 /* FIXME: what do we have to do for this? */
471 return 0;
472}
473
474static int pipe_end_get_info( struct fd *fd,
475 struct get_file_info_reply *reply, int *flags )
Alexandre Julliard646d6212001-10-05 19:45:45 +0000476{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000477 if (reply)
Alexandre Julliard646d6212001-10-05 19:45:45 +0000478 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000479 reply->type = FILE_TYPE_PIPE;
480 reply->attr = 0;
481 reply->access_time = 0;
482 reply->write_time = 0;
483 reply->size_high = 0;
484 reply->size_low = 0;
485 reply->links = 0;
486 reply->index_high = 0;
487 reply->index_low = 0;
488 reply->serial = 0;
Alexandre Julliard646d6212001-10-05 19:45:45 +0000489 }
Martin Wilck88cd32b2002-01-09 20:30:51 +0000490 *flags = 0;
Alexandre Julliard646d6212001-10-05 19:45:45 +0000491 return FD_TYPE_DEFAULT;
492}
493
Mike McCormackde7c3002001-07-10 19:16:49 +0000494static struct named_pipe *create_named_pipe( const WCHAR *name, size_t len )
495{
496 struct named_pipe *pipe;
497
Mike McCormackef8b9462003-05-15 04:22:45 +0000498 pipe = create_named_object( sync_namespace, &named_pipe_ops, name, len );
499 if( pipe )
Mike McCormackde7c3002001-07-10 19:16:49 +0000500 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000501 if( get_error() != STATUS_OBJECT_NAME_COLLISION )
Mike McCormackde7c3002001-07-10 19:16:49 +0000502 {
503 /* initialize it if it didn't already exist */
Mike McCormackef8b9462003-05-15 04:22:45 +0000504 pipe->servers = 0;
505 pipe->instances = 0;
506 pipe->connect_waiters = NULL;
Mike McCormackde7c3002001-07-10 19:16:49 +0000507 }
508 }
509 return pipe;
510}
511
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000512static struct named_pipe *open_named_pipe( const WCHAR *name, size_t len )
513{
514 struct object *obj;
515
516 if ((obj = find_object( sync_namespace, name, len )))
517 {
518 if (obj->ops == &named_pipe_ops) return (struct named_pipe *)obj;
519 release_object( obj );
520 set_error( STATUS_OBJECT_TYPE_MISMATCH );
521 }
522 else set_error( STATUS_OBJECT_NAME_NOT_FOUND );
523
524 return NULL;
525}
526
Mike McCormackef8b9462003-05-15 04:22:45 +0000527static struct pipe_server *get_pipe_server_obj( struct process *process,
528 obj_handle_t handle, unsigned int access )
Mike McCormackde7c3002001-07-10 19:16:49 +0000529{
Mike McCormackef8b9462003-05-15 04:22:45 +0000530 struct object *obj;
531 obj = get_handle_obj( process, handle, access, &pipe_server_ops );
532 return (struct pipe_server *) obj;
Mike McCormackde7c3002001-07-10 19:16:49 +0000533}
534
Mike McCormackef8b9462003-05-15 04:22:45 +0000535static struct pipe_server *create_pipe_server( struct named_pipe *pipe )
Mike McCormackde7c3002001-07-10 19:16:49 +0000536{
Mike McCormackef8b9462003-05-15 04:22:45 +0000537 struct pipe_server *server;
Mike McCormackde7c3002001-07-10 19:16:49 +0000538
Mike McCormackef8b9462003-05-15 04:22:45 +0000539 server = alloc_object( &pipe_server_ops );
540 if( !server )
Mike McCormackde7c3002001-07-10 19:16:49 +0000541 return NULL;
Mike McCormackde7c3002001-07-10 19:16:49 +0000542
Mike McCormackef8b9462003-05-15 04:22:45 +0000543 server->fd = NULL;
544 server->pipe = pipe;
545 server->state = ps_none;
546 server->client = NULL;
547 server->flush_poll = NULL;
548 server->wait.thread = NULL;
Mike McCormackde7c3002001-07-10 19:16:49 +0000549
Mike McCormackef8b9462003-05-15 04:22:45 +0000550 /* add to list of pipe servers */
551 if ((server->next = pipe->servers)) server->next->prev = server;
552 server->prev = NULL;
553 pipe->servers = server;
Mike McCormackde7c3002001-07-10 19:16:49 +0000554
Mike McCormackef8b9462003-05-15 04:22:45 +0000555 grab_object( pipe );
Mike McCormackde7c3002001-07-10 19:16:49 +0000556
Mike McCormackef8b9462003-05-15 04:22:45 +0000557 return server;
Mike McCormackde7c3002001-07-10 19:16:49 +0000558}
559
Mike McCormackef8b9462003-05-15 04:22:45 +0000560static struct pipe_client *create_pipe_client( struct pipe_server *server )
Mike McCormackde7c3002001-07-10 19:16:49 +0000561{
Mike McCormackef8b9462003-05-15 04:22:45 +0000562 struct pipe_client *client;
Mike McCormackde7c3002001-07-10 19:16:49 +0000563
Mike McCormackef8b9462003-05-15 04:22:45 +0000564 client = alloc_object( &pipe_client_ops );
565 if( !client )
Mike McCormackbf554572001-08-23 23:29:20 +0000566 return NULL;
567
Mike McCormackef8b9462003-05-15 04:22:45 +0000568 client->fd = NULL;
569 client->server = server;
570 client->wait.thread = NULL;
571
572 return client;
573}
574
575static struct pipe_server *find_server( struct named_pipe *pipe,
576 enum pipe_state state )
577{
578 struct pipe_server *x;
579
580 for( x = pipe->servers; x; x = x->next )
581 if( x->state == state )
582 break;
583
584 if( !x )
585 return NULL;
586
587 return (struct pipe_server *) grab_object( x );
Mike McCormackde7c3002001-07-10 19:16:49 +0000588}
589
590DECL_HANDLER(create_named_pipe)
591{
592 struct named_pipe *pipe;
Mike McCormackef8b9462003-05-15 04:22:45 +0000593 struct pipe_server *server;
Mike McCormackde7c3002001-07-10 19:16:49 +0000594
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000595 reply->handle = 0;
596 pipe = create_named_pipe( get_req_data(), get_req_data_size() );
Mike McCormackef8b9462003-05-15 04:22:45 +0000597 if( !pipe )
Mike McCormackde7c3002001-07-10 19:16:49 +0000598 return;
599
Mike McCormackef8b9462003-05-15 04:22:45 +0000600 if( get_error() != STATUS_OBJECT_NAME_COLLISION )
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000601 {
602 pipe->insize = req->insize;
603 pipe->outsize = req->outsize;
604 pipe->maxinstances = req->maxinstances;
605 pipe->timeout = req->timeout;
606 pipe->pipemode = req->pipemode;
607 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000608 else
Mike McCormackde7c3002001-07-10 19:16:49 +0000609 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000610 set_error( 0 ); /* clear the name collision */
611 if( pipe->maxinstances <= pipe->instances )
612 {
613 set_error( STATUS_PIPE_BUSY );
614 release_object( pipe );
615 return;
616 }
617 if( ( pipe->maxinstances != req->maxinstances ) ||
618 ( pipe->timeout != req->timeout ) ||
619 ( pipe->pipemode != req->pipemode ) )
620 {
621 set_error( STATUS_ACCESS_DENIED );
622 release_object( pipe );
623 return;
624 }
625 }
626
627 server = create_pipe_server( pipe );
628 if(server)
629 {
630 server->state = ps_idle_server;
631 reply->handle = alloc_handle( current->process, server,
632 GENERIC_READ|GENERIC_WRITE, 0 );
633 server->pipe->instances++;
634 release_object( server );
Mike McCormackde7c3002001-07-10 19:16:49 +0000635 }
636
637 release_object( pipe );
638}
639
640DECL_HANDLER(open_named_pipe)
641{
Mike McCormackef8b9462003-05-15 04:22:45 +0000642 struct pipe_server *server;
643 struct pipe_client *client;
Mike McCormackde7c3002001-07-10 19:16:49 +0000644 struct named_pipe *pipe;
Mike McCormackef8b9462003-05-15 04:22:45 +0000645 int fds[2];
Mike McCormackde7c3002001-07-10 19:16:49 +0000646
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000647 reply->handle = 0;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000648
Mike McCormackef8b9462003-05-15 04:22:45 +0000649 pipe = open_named_pipe( get_req_data(), get_req_data_size() );
650 if ( !pipe )
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000651 {
652 set_error( STATUS_NO_SUCH_FILE );
Mike McCormackde7c3002001-07-10 19:16:49 +0000653 return;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000654 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000655
656 for( server = pipe->servers; server; server = server->next )
657 if( ( server->state==ps_idle_server ) ||
658 ( server->state==ps_wait_open ) )
659 break;
660 release_object( pipe );
661
662 if ( !server )
Mike McCormackde7c3002001-07-10 19:16:49 +0000663 {
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000664 set_error( STATUS_PIPE_NOT_AVAILABLE );
665 return;
666 }
Mike McCormackbf554572001-08-23 23:29:20 +0000667
Mike McCormackef8b9462003-05-15 04:22:45 +0000668 client = create_pipe_client( server );
669 if( client )
670 {
671 if( !socketpair( PF_UNIX, SOCK_STREAM, 0, fds ) )
Mike McCormackde7c3002001-07-10 19:16:49 +0000672 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000673 assert( !client->fd );
674 assert( !server->fd );
675 client->fd = create_anonymous_fd( &pipe_server_fd_ops,
676 fds[1], &client->obj );
677 server->fd = create_anonymous_fd( &pipe_server_fd_ops,
678 fds[0], &server->obj );
679 if (client->fd && server->fd)
Mike McCormackde7c3002001-07-10 19:16:49 +0000680 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000681 if( server->state == ps_wait_open )
682 notify_waiter( &server->wait, STATUS_SUCCESS );
683 assert( !server->wait.thread );
684 server->state = ps_connected_server;
685 server->client = client;
686 client->server = server;
687 reply->handle = alloc_handle( current->process, client,
Alexandre Julliard693bbd72003-06-14 01:31:56 +0000688 req->access, req->inherit );
Mike McCormackde7c3002001-07-10 19:16:49 +0000689 }
Mike McCormackde7c3002001-07-10 19:16:49 +0000690 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000691 else
692 file_set_error();
Mike McCormackde7c3002001-07-10 19:16:49 +0000693
Mike McCormackef8b9462003-05-15 04:22:45 +0000694 release_object( client );
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000695 }
Mike McCormackde7c3002001-07-10 19:16:49 +0000696}
697
698DECL_HANDLER(connect_named_pipe)
699{
Mike McCormackef8b9462003-05-15 04:22:45 +0000700 struct pipe_server *server;
Mike McCormackde7c3002001-07-10 19:16:49 +0000701
Mike McCormackef8b9462003-05-15 04:22:45 +0000702 server = get_pipe_server_obj(current->process, req->handle, 0);
703 if(!server)
Mike McCormackde7c3002001-07-10 19:16:49 +0000704 return;
705
Mike McCormackef8b9462003-05-15 04:22:45 +0000706 switch( server->state )
Mike McCormackde7c3002001-07-10 19:16:49 +0000707 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000708 case ps_idle_server:
709 case ps_wait_connect:
710 assert( !server->fd );
711 server->state = ps_wait_open;
712 set_waiter( &server->wait, req->func, req->overlapped );
713 notify_connect_waiters( server->pipe );
714 break;
715 case ps_connected_server:
716 assert( server->fd );
717 set_error( STATUS_PIPE_CONNECTED );
718 break;
719 case ps_disconnected_server:
720 set_error( STATUS_PIPE_BUSY );
721 break;
722 case ps_wait_disconnect:
723 set_error( STATUS_NO_DATA_DETECTED );
724 break;
725 default:
726 set_error( STATUS_INVALID_HANDLE );
727 break;
Mike McCormackde7c3002001-07-10 19:16:49 +0000728 }
729
Mike McCormackef8b9462003-05-15 04:22:45 +0000730 release_object(server);
Mike McCormackde7c3002001-07-10 19:16:49 +0000731}
Mike McCormackbf554572001-08-23 23:29:20 +0000732
733DECL_HANDLER(wait_named_pipe)
734{
Mike McCormackbf554572001-08-23 23:29:20 +0000735 struct named_pipe *pipe;
Mike McCormackef8b9462003-05-15 04:22:45 +0000736 struct pipe_server *server;
Mike McCormackbf554572001-08-23 23:29:20 +0000737
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000738 if (!(pipe = open_named_pipe( get_req_data(), get_req_data_size() )))
Mike McCormackbf554572001-08-23 23:29:20 +0000739 {
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000740 set_error( STATUS_PIPE_NOT_AVAILABLE );
741 return;
Mike McCormackbf554572001-08-23 23:29:20 +0000742 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000743 server = find_server( pipe, ps_wait_open );
744 if( server )
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000745 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000746 /* there's already a server waiting for a client to connect */
747 struct wait_info wait;
748 set_waiter( &wait, req->func, req->overlapped );
749 notify_waiter( &wait, STATUS_SUCCESS );
750 release_object( server );
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000751 }
752 else
Mike McCormackef8b9462003-05-15 04:22:45 +0000753 queue_connect_waiter( pipe, req->func, req->overlapped );
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000754
Mike McCormackef8b9462003-05-15 04:22:45 +0000755 release_object( pipe );
Mike McCormackbf554572001-08-23 23:29:20 +0000756}
757
758DECL_HANDLER(disconnect_named_pipe)
759{
Mike McCormackef8b9462003-05-15 04:22:45 +0000760 struct pipe_server *server;
Mike McCormackbf554572001-08-23 23:29:20 +0000761
Mike McCormackef8b9462003-05-15 04:22:45 +0000762 reply->fd = -1;
763 server = get_pipe_server_obj( current->process, req->handle, 0 );
764 if( !server )
Mike McCormackbf554572001-08-23 23:29:20 +0000765 return;
Mike McCormackef8b9462003-05-15 04:22:45 +0000766 switch( server->state )
Mike McCormackbf554572001-08-23 23:29:20 +0000767 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000768 case ps_connected_server:
769 assert( server->fd );
770 assert( server->client );
771 assert( server->client->fd );
Mike McCormackbf554572001-08-23 23:29:20 +0000772
Mike McCormackef8b9462003-05-15 04:22:45 +0000773 notify_empty( server );
774 notify_waiter( &server->client->wait, STATUS_PIPE_DISCONNECTED );
775
776 /* Dump the client and server fds, but keep the pointers
777 around - client loses all waiting data */
778 server->state = ps_disconnected_server;
779 do_disconnect( server );
780 reply->fd = flush_cached_fd( current->process, req->handle );
781 break;
782
783 case ps_wait_disconnect:
784 assert( !server->client );
785 assert( server->fd );
786 do_disconnect( server );
787 server->state = ps_wait_connect;
788 reply->fd = flush_cached_fd( current->process, req->handle );
789 break;
790
791 default:
792 set_error( STATUS_PIPE_DISCONNECTED );
Mike McCormackbf554572001-08-23 23:29:20 +0000793 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000794 release_object( server );
Mike McCormackbf554572001-08-23 23:29:20 +0000795}
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000796
797DECL_HANDLER(get_named_pipe_info)
798{
Mike McCormackef8b9462003-05-15 04:22:45 +0000799 struct pipe_server *server;
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000800
Mike McCormackef8b9462003-05-15 04:22:45 +0000801 server = get_pipe_server_obj( current->process, req->handle, 0 );
802 if(!server)
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000803 return;
804
Mike McCormackef8b9462003-05-15 04:22:45 +0000805 reply->flags = server->pipe->pipemode;
806 reply->maxinstances = server->pipe->maxinstances;
807 reply->insize = server->pipe->insize;
808 reply->outsize = server->pipe->outsize;
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000809
Mike McCormackef8b9462003-05-15 04:22:45 +0000810 release_object(server);
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000811}