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
;
51 struct thread
*thread
;
58 struct object obj
; /* object header */
59 unsigned int pipemode
;
60 unsigned int maxinstances
;
64 struct pipe_user
*users
;
67 static void named_pipe_dump( struct object
*obj
, int verbose
);
68 static void named_pipe_destroy( struct object
*obj
);
70 static const struct object_ops named_pipe_ops
=
72 sizeof(struct named_pipe
), /* size */
73 named_pipe_dump
, /* dump */
74 no_add_queue
, /* add_queue */
75 NULL
, /* remove_queue */
78 NULL
, /* get_poll_events */
79 NULL
, /* poll_event */
80 no_get_fd
, /* get_fd */
82 no_get_file_info
, /* get_file_info */
83 NULL
, /* queue_async */
84 named_pipe_destroy
/* destroy */
87 static void pipe_user_dump( struct object
*obj
, int verbose
);
88 static void pipe_user_destroy( struct object
*obj
);
89 static int pipe_user_get_fd( struct object
*obj
);
90 static int pipe_user_get_info( struct object
*obj
, struct get_file_info_reply
*reply
, int *flags
);
92 static const struct object_ops pipe_user_ops
=
94 sizeof(struct pipe_user
), /* size */
95 pipe_user_dump
, /* dump */
96 default_poll_add_queue
, /* add_queue */
97 default_poll_remove_queue
, /* remove_queue */
98 default_poll_signaled
, /* signaled */
99 no_satisfied
, /* satisfied */
100 NULL
, /* get_poll_events */
101 default_poll_event
, /* poll_event */
102 pipe_user_get_fd
, /* get_fd */
103 no_flush
, /* flush */
104 pipe_user_get_info
, /* get_file_info */
105 NULL
, /* queue_async */
106 pipe_user_destroy
/* destroy */
109 static void named_pipe_dump( struct object
*obj
, int verbose
)
111 struct named_pipe
*pipe
= (struct named_pipe
*)obj
;
112 assert( obj
->ops
== &named_pipe_ops
);
113 fprintf( stderr
, "named pipe %p\n" ,pipe
);
116 static void pipe_user_dump( struct object
*obj
, int verbose
)
118 struct pipe_user
*user
= (struct pipe_user
*)obj
;
119 assert( obj
->ops
== &pipe_user_ops
);
120 fprintf( stderr
, "named pipe user %p (state %d)\n", user
, user
->state
);
123 static void named_pipe_destroy( struct object
*obj
)
125 struct named_pipe
*pipe
= (struct named_pipe
*)obj
;
126 assert( !pipe
->users
);
129 static void notify_waiter( struct pipe_user
*user
, unsigned int status
)
131 if(user
->thread
&& user
->func
&& user
->overlapped
)
133 /* queue a system APC, to notify a waiting thread */
134 thread_queue_apc(user
->thread
,NULL
,user
->func
,
135 APC_ASYNC
,1,2,user
->overlapped
,status
);
137 if (user
->thread
) release_object(user
->thread
);
140 user
->overlapped
=NULL
;
143 static void pipe_user_destroy( struct object
*obj
)
145 struct pipe_user
*user
= (struct pipe_user
*)obj
;
147 assert( obj
->ops
== &pipe_user_ops
);
150 notify_waiter(user
,STATUS_HANDLES_CLOSED
);
154 close(user
->other
->obj
.fd
);
155 user
->other
->obj
.fd
= -1;
156 switch(user
->other
->state
)
158 case ps_connected_server
:
159 user
->other
->state
= ps_idle_server
;
161 case ps_connected_client
:
162 user
->other
->state
= ps_disconnected
;
165 fprintf(stderr
,"connected pipe has strange state %d!\n",
168 user
->other
->other
=NULL
;
172 /* remove user from pipe's user list */
173 if (user
->next
) user
->next
->prev
= user
->prev
;
174 if (user
->prev
) user
->prev
->next
= user
->next
;
175 else user
->pipe
->users
= user
->next
;
176 if (user
->thread
) release_object(user
->thread
);
177 release_object(user
->pipe
);
180 static int pipe_user_get_fd( struct object
*obj
)
182 struct pipe_user
*user
= (struct pipe_user
*)obj
;
183 assert( obj
->ops
== &pipe_user_ops
);
187 static int pipe_user_get_info( struct object
*obj
, struct get_file_info_reply
*reply
, int *flags
)
191 reply
->type
= FILE_TYPE_PIPE
;
193 reply
->access_time
= 0;
194 reply
->write_time
= 0;
195 reply
->size_high
= 0;
198 reply
->index_high
= 0;
199 reply
->index_low
= 0;
203 return FD_TYPE_DEFAULT
;
206 static struct named_pipe
*create_named_pipe( const WCHAR
*name
, size_t len
)
208 struct named_pipe
*pipe
;
210 if ((pipe
= create_named_object( &named_pipe_ops
, name
, len
)))
212 if (get_error() != STATUS_OBJECT_NAME_COLLISION
)
214 /* initialize it if it didn't already exist */
221 static struct pipe_user
*get_pipe_user_obj( struct process
*process
, handle_t handle
,
222 unsigned int access
)
224 return (struct pipe_user
*)get_handle_obj( process
, handle
, access
, &pipe_user_ops
);
227 static struct pipe_user
*create_pipe_user( struct named_pipe
*pipe
, int fd
)
229 struct pipe_user
*user
;
231 user
= alloc_object( &pipe_user_ops
, fd
);
236 user
->state
= ps_none
;
240 user
->overlapped
= NULL
;
242 /* add to list of pipe users */
243 if ((user
->next
= pipe
->users
)) user
->next
->prev
= user
;
252 static struct pipe_user
*find_partner(struct named_pipe
*pipe
, enum pipe_state state
)
256 for(x
= pipe
->users
; x
; x
=x
->next
)
265 return (struct pipe_user
*)grab_object( x
);
268 DECL_HANDLER(create_named_pipe
)
270 struct named_pipe
*pipe
;
271 struct pipe_user
*user
;
274 pipe
= create_named_pipe( get_req_data(), get_req_data_size() );
278 if (get_error() != STATUS_OBJECT_NAME_COLLISION
)
280 pipe
->insize
= req
->insize
;
281 pipe
->outsize
= req
->outsize
;
282 pipe
->maxinstances
= req
->maxinstances
;
283 pipe
->timeout
= req
->timeout
;
284 pipe
->pipemode
= req
->pipemode
;
287 user
= create_pipe_user (pipe
, -1);
291 user
->state
= ps_idle_server
;
292 reply
->handle
= alloc_handle( current
->process
, user
, GENERIC_READ
|GENERIC_WRITE
, 0 );
293 release_object( user
);
296 release_object( pipe
);
299 DECL_HANDLER(open_named_pipe
)
301 struct named_pipe
*pipe
;
304 pipe
= create_named_pipe( get_req_data(), get_req_data_size() );
308 if (get_error() == STATUS_OBJECT_NAME_COLLISION
)
310 struct pipe_user
*partner
;
312 if ((partner
= find_partner(pipe
, ps_wait_open
)))
316 if(!socketpair(PF_UNIX
, SOCK_STREAM
, 0, fds
))
318 struct pipe_user
*user
;
320 if( (user
= create_pipe_user (pipe
, fds
[1])) )
322 partner
->obj
.fd
= fds
[0];
323 notify_waiter(partner
,STATUS_SUCCESS
);
324 partner
->state
= ps_connected_server
;
325 partner
->other
= user
;
326 user
->state
= ps_connected_client
;
327 user
->other
= partner
;
328 reply
->handle
= alloc_handle( current
->process
, user
, req
->access
, 0 );
329 release_object(user
);
336 release_object( partner
);
340 set_error(STATUS_PIPE_NOT_AVAILABLE
);
345 set_error(STATUS_NO_SUCH_FILE
);
348 release_object(pipe
);
351 DECL_HANDLER(connect_named_pipe
)
353 struct pipe_user
*user
, *partner
;
355 user
= get_pipe_user_obj(current
->process
, req
->handle
, 0);
359 if( user
->state
!= ps_idle_server
)
361 set_error(STATUS_PORT_ALREADY_SET
);
365 user
->state
= ps_wait_open
;
366 user
->thread
= (struct thread
*)grab_object(current
);
367 user
->func
= req
->func
;
368 user
->overlapped
= req
->overlapped
;
370 /* notify all waiters that a pipe just became available */
371 while( (partner
= find_partner(user
->pipe
,ps_wait_connect
)) )
373 notify_waiter(partner
,STATUS_SUCCESS
);
374 release_object(partner
);
375 release_object(partner
);
379 release_object(user
);
382 DECL_HANDLER(wait_named_pipe
)
384 struct named_pipe
*pipe
;
386 pipe
= create_named_pipe( get_req_data(), get_req_data_size() );
389 /* only wait if the pipe already exists */
390 if(get_error() == STATUS_OBJECT_NAME_COLLISION
)
392 struct pipe_user
*partner
;
394 set_error(STATUS_SUCCESS
);
395 if( (partner
= find_partner(pipe
,ps_wait_open
)) )
397 /* this should use notify_waiter,
398 but no pipe_user object exists now... */
399 thread_queue_apc(current
,NULL
,req
->func
,
400 APC_ASYNC
,1,2,req
->overlapped
,STATUS_SUCCESS
);
401 release_object(partner
);
405 struct pipe_user
*user
;
407 if( (user
= create_pipe_user (pipe
, -1)) )
409 user
->state
= ps_wait_connect
;
410 user
->thread
= (struct thread
*)grab_object(current
);
411 user
->func
= req
->func
;
412 user
->overlapped
= req
->overlapped
;
413 /* don't release it */
419 set_error(STATUS_PIPE_NOT_AVAILABLE
);
421 release_object(pipe
);
425 DECL_HANDLER(disconnect_named_pipe
)
427 struct pipe_user
*user
;
429 user
= get_pipe_user_obj(current
->process
, req
->handle
, 0);
432 if( (user
->state
== ps_connected_server
) &&
433 (user
->other
->state
== ps_connected_client
) )
435 close(user
->other
->obj
.fd
);
436 user
->other
->obj
.fd
= -1;
437 user
->other
->state
= ps_disconnected
;
438 user
->other
->other
= NULL
;
442 user
->state
= ps_idle_server
;
445 release_object(user
);
448 DECL_HANDLER(get_named_pipe_info
)
450 struct pipe_user
*user
;
452 user
= get_pipe_user_obj(current
->process
, req
->handle
, 0);
456 reply
->flags
= user
->pipe
->pipemode
;
457 reply
->maxinstances
= user
->pipe
->maxinstances
;
458 reply
->insize
= user
->pipe
->insize
;
459 reply
->outsize
= user
->pipe
->outsize
;
461 release_object(user
);