2 * Server-side pipe management
4 * Copyright (C) 1998 Alexandre Julliard
5 * Copyright (C) 2001 Mike McCormack
8 * improve error handling
19 #include <sys/types.h>
20 #include <sys/socket.h>
46 enum pipe_state state
;
47 struct pipe_user
*other
;
48 struct named_pipe
*pipe
;
49 struct pipe_user
*next
;
50 struct pipe_user
*prev
;
56 struct object obj
; /* object header */
57 unsigned int pipemode
;
58 unsigned int maxinstances
;
62 struct pipe_user
*users
;
65 static void named_pipe_dump( struct object
*obj
, int verbose
);
66 static void named_pipe_destroy( struct object
*obj
);
68 static const struct object_ops named_pipe_ops
=
70 sizeof(struct named_pipe
), /* size */
71 named_pipe_dump
, /* dump */
72 no_add_queue
, /* add_queue */
73 NULL
, /* remove_queue */
76 NULL
, /* get_poll_events */
77 NULL
, /* poll_event */
78 no_get_fd
, /* get_fd */
80 no_get_file_info
, /* get_file_info */
81 named_pipe_destroy
/* destroy */
84 static void pipe_user_dump( struct object
*obj
, int verbose
);
85 static void pipe_user_destroy( struct object
*obj
);
86 static int pipe_user_get_fd( struct object
*obj
);
88 static const struct object_ops pipe_user_ops
=
90 sizeof(struct pipe_user
), /* size */
91 pipe_user_dump
, /* dump */
92 default_poll_add_queue
, /* add_queue */
93 default_poll_remove_queue
, /* remove_queue */
94 default_poll_signaled
, /* signaled */
95 no_satisfied
, /* satisfied */
96 NULL
, /* get_poll_events */
97 default_poll_event
, /* poll_event */
98 pipe_user_get_fd
, /* get_fd */
100 no_get_file_info
, /* get_file_info */
101 pipe_user_destroy
/* destroy */
104 static void named_pipe_dump( struct object
*obj
, int verbose
)
106 struct named_pipe
*pipe
= (struct named_pipe
*)obj
;
107 assert( obj
->ops
== &named_pipe_ops
);
108 fprintf( stderr
, "named pipe %p\n" ,pipe
);
111 static void pipe_user_dump( struct object
*obj
, int verbose
)
113 struct pipe_user
*user
= (struct pipe_user
*)obj
;
114 assert( obj
->ops
== &pipe_user_ops
);
115 fprintf( stderr
, "named pipe user %p (state %d)\n", user
, user
->state
);
118 static void named_pipe_destroy( struct object
*obj
)
120 struct named_pipe
*pipe
= (struct named_pipe
*)obj
;
121 assert( !pipe
->users
);
124 static void pipe_user_destroy( struct object
*obj
)
126 struct pipe_user
*user
= (struct pipe_user
*)obj
;
128 assert( obj
->ops
== &pipe_user_ops
);
132 /* FIXME: signal waiter of failure */
133 release_object(user
->event
);
138 close(user
->other
->obj
.fd
);
139 user
->other
->obj
.fd
= -1;
140 switch(user
->other
->state
)
142 case ps_connected_server
:
143 user
->other
->state
= ps_idle_server
;
145 case ps_connected_client
:
146 user
->other
->state
= ps_disconnected
;
149 fprintf(stderr
,"connected pipe has strange state %d!\n",
152 user
->other
->other
=NULL
;
156 /* remove user from pipe's user list */
157 if (user
->next
) user
->next
->prev
= user
->prev
;
158 if (user
->prev
) user
->prev
->next
= user
->next
;
159 else user
->pipe
->users
= user
->next
;
160 release_object(user
->pipe
);
163 static int pipe_user_get_fd( struct object
*obj
)
165 struct pipe_user
*user
= (struct pipe_user
*)obj
;
166 assert( obj
->ops
== &pipe_user_ops
);
170 static struct named_pipe
*create_named_pipe( const WCHAR
*name
, size_t len
)
172 struct named_pipe
*pipe
;
174 if ((pipe
= create_named_object( &named_pipe_ops
, name
, len
)))
176 if (get_error() != STATUS_OBJECT_NAME_COLLISION
)
178 /* initialize it if it didn't already exist */
185 static struct pipe_user
*get_pipe_user_obj( struct process
*process
, handle_t handle
,
186 unsigned int access
)
188 return (struct pipe_user
*)get_handle_obj( process
, handle
, access
, &pipe_user_ops
);
191 static struct pipe_user
*create_pipe_user( struct named_pipe
*pipe
, int fd
)
193 struct pipe_user
*user
;
195 user
= alloc_object( &pipe_user_ops
, fd
);
200 user
->state
= ps_none
;
201 user
->event
= NULL
; /* thread wait on this pipe */
204 /* add to list of pipe users */
205 if ((user
->next
= pipe
->users
)) user
->next
->prev
= user
;
214 static struct pipe_user
*find_partner(struct named_pipe
*pipe
, enum pipe_state state
)
218 for(x
= pipe
->users
; x
; x
=x
->next
)
227 return (struct pipe_user
*)grab_object( x
);
230 DECL_HANDLER(create_named_pipe
)
232 struct named_pipe
*pipe
;
233 struct pipe_user
*user
;
236 pipe
= create_named_pipe( get_req_data(req
), get_req_data_size(req
) );
240 if (get_error() != STATUS_OBJECT_NAME_COLLISION
)
242 pipe
->insize
= req
->insize
;
243 pipe
->outsize
= req
->outsize
;
244 pipe
->maxinstances
= req
->maxinstances
;
245 pipe
->timeout
= req
->timeout
;
246 pipe
->pipemode
= req
->pipemode
;
249 user
= create_pipe_user (pipe
, -1);
253 user
->state
= ps_idle_server
;
254 req
->handle
= alloc_handle( current
->process
, user
, GENERIC_READ
|GENERIC_WRITE
, 0 );
255 release_object( user
);
258 release_object( pipe
);
261 DECL_HANDLER(open_named_pipe
)
263 struct named_pipe
*pipe
;
266 pipe
= create_named_pipe( get_req_data(req
), get_req_data_size(req
) );
270 if (get_error() == STATUS_OBJECT_NAME_COLLISION
)
272 struct pipe_user
*partner
;
274 if ((partner
= find_partner(pipe
, ps_wait_open
)))
278 if(!socketpair(PF_UNIX
, SOCK_STREAM
, 0, fds
))
280 struct pipe_user
*user
;
282 if( (user
= create_pipe_user (pipe
, fds
[1])) )
284 partner
->obj
.fd
= fds
[0];
285 set_event(partner
->event
);
286 release_object(partner
->event
);
287 partner
->event
= NULL
;
288 partner
->state
= ps_connected_server
;
289 partner
->other
= user
;
290 user
->state
= ps_connected_client
;
291 user
->other
= partner
;
292 req
->handle
= alloc_handle( current
->process
, user
, req
->access
, 0 );
293 release_object(user
);
300 release_object( partner
);
304 set_error(STATUS_PIPE_NOT_AVAILABLE
);
309 set_error(STATUS_NO_SUCH_FILE
);
312 release_object(pipe
);
315 DECL_HANDLER(connect_named_pipe
)
317 struct pipe_user
*user
, *partner
;
320 user
= get_pipe_user_obj(current
->process
, req
->handle
, 0);
324 if( user
->state
!= ps_idle_server
)
326 set_error(STATUS_PORT_ALREADY_SET
);
330 user
->state
= ps_wait_open
;
331 event
= get_event_obj(current
->process
, req
->event
, 0);
335 /* notify all waiters that a pipe just became available */
336 while( (partner
= find_partner(user
->pipe
,ps_wait_connect
)) )
338 set_event(partner
->event
);
339 release_object(partner
->event
);
340 partner
->event
= NULL
;
341 release_object(partner
);
342 release_object(partner
);
346 release_object(user
);
349 DECL_HANDLER(wait_named_pipe
)
352 struct named_pipe
*pipe
;
354 event
= get_event_obj(current
->process
, req
->event
, 0);
358 pipe
= create_named_pipe( get_req_data(req
), get_req_data_size(req
) );
361 /* only wait if the pipe already exists */
362 if(get_error() == STATUS_OBJECT_NAME_COLLISION
)
364 struct pipe_user
*partner
;
366 set_error(STATUS_SUCCESS
);
367 if( (partner
= find_partner(pipe
,ps_wait_open
)) )
370 release_object(partner
);
374 struct pipe_user
*user
;
376 if( (user
= create_pipe_user (pipe
, -1)) )
378 user
->event
= (struct event
*)grab_object( event
);
379 user
->state
= ps_wait_connect
;
380 /* don't release it */
386 set_error(STATUS_PIPE_NOT_AVAILABLE
);
388 release_object(pipe
);
390 release_object(event
);
393 DECL_HANDLER(disconnect_named_pipe
)
395 struct pipe_user
*user
;
397 user
= get_pipe_user_obj(current
->process
, req
->handle
, 0);
400 if( (user
->state
== ps_connected_server
) &&
401 (user
->other
->state
== ps_connected_client
) )
403 close(user
->other
->obj
.fd
);
404 user
->other
->obj
.fd
= -1;
405 user
->other
->state
= ps_disconnected
;
406 user
->other
->other
= NULL
;
410 user
->state
= ps_idle_server
;
413 release_object(user
);
416 DECL_HANDLER(get_named_pipe_info
)
418 struct pipe_user
*user
;
420 user
= get_pipe_user_obj(current
->process
, req
->handle
, 0);
424 req
->flags
= user
->pipe
->pipemode
;
425 req
->maxinstances
= user
->pipe
->maxinstances
;
426 req
->insize
= user
->pipe
->insize
;
427 req
->outsize
= user
->pipe
->outsize
;
429 release_object(user
);