1 /*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2005 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25 #ifndef SU_PORT_H
26 /** Defined when <su_port.h> has been included. */
27 #define SU_PORT_H
28
29 /**@internal @file su_port.h
30 *
31 * @brief Internal OS-independent syncronization interface.
32 *
33 * This looks like the "reactor" pattern.
34 *
35 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
36 *
37 * @date Created: Fri May 12 14:13:34 2000 ppessi
38 */
39
40 #ifndef SU_MSG_ARG_T
41 #define SU_MSG_ARG_T union { char anoymous[4]; }
42 #endif
43
44 #ifndef SU_WAIT_H
45 #include "sofia-sip/su_wait.h"
46 #endif
47
48 #ifndef SU_MODULE_DEBUG_H
49 #include "su_module_debug.h"
50 #endif
51
52 #ifndef SU_ALLOC_H
53 #include <sofia-sip/su_alloc.h>
54 #endif
55
56 #include <assert.h>
57
58 #define SU_WAIT_MIN (16)
59
60 SOFIA_BEGIN_DECLS
61
62 /** @internal Message */
63 struct su_msg_s {
64 size_t sum_size;
65 su_msg_t *sum_next;
66 su_task_r sum_to;
67 su_task_r sum_from;
68 su_msg_f sum_func;
69 su_msg_f sum_report;
70 su_msg_deinit_function *sum_deinit;
71 su_msg_arg_t sum_data[1]; /* minimum size, may be extended */
72 };
73
74 struct _GSource;
75
76 /** @internal Root structure */
77 struct su_root_s {
78 int sur_size;
79 su_root_magic_t *sur_magic;
80 su_root_deinit_f sur_deinit;
81 su_task_r sur_task;
82 su_task_r sur_parent;
83 unsigned sur_threading : 1;
84 unsigned sur_deiniting : 1;
85 };
86
87 #define SU_ROOT_MAGIC(r) ((r) ? (r)->sur_magic : NULL)
88
89 enum su_port_thread_op {
90 su_port_thread_op_is_obtained,
91 su_port_thread_op_release,
92 su_port_thread_op_obtain
93 };
94
95 /** @internal Virtual function table for port */
96 typedef struct su_port_vtable {
97 unsigned su_vtable_size;
98 void (*su_port_lock)(su_port_t *port, char const *who);
99 void (*su_port_unlock)(su_port_t *port, char const *who);
100 void (*su_port_incref)(su_port_t *port, char const *who);
101 void (*su_port_decref)(su_port_t *port, int block, char const *who);
102 struct _GSource *(*su_port_gsource)(su_port_t *port);
103 int (*su_port_send)(su_port_t *self, su_msg_r rmsg);
104 int (*su_port_register)(su_port_t *self,
105 su_root_t *root,
106 su_wait_t *wait,
107 su_wakeup_f callback,
108 su_wakeup_arg_t *arg,
109 int priority);
110 int (*su_port_unregister)(su_port_t *port,
111 su_root_t *root,
112 su_wait_t *wait,
113 su_wakeup_f callback,
114 su_wakeup_arg_t *arg);
115 int (*su_port_deregister)(su_port_t *self, int i);
116 int (*su_port_unregister_all)(su_port_t *self,
117 su_root_t *root);
118 int (*su_port_eventmask)(su_port_t *self, int index, int socket, int events);
119 void (*su_port_run)(su_port_t *self);
120 void (*su_port_break)(su_port_t *self);
121 su_duration_t (*su_port_step)(su_port_t *self, su_duration_t tout);
122
123 /* Reused slot */
124 int (*su_port_thread)(su_port_t *port, enum su_port_thread_op op);
125
126 int (*su_port_add_prepoll)(su_port_t *port,
127 su_root_t *root,
128 su_prepoll_f *,
129 su_prepoll_magic_t *);
130
131 int (*su_port_remove_prepoll)(su_port_t *port,
132 su_root_t *root);
133
134 su_timer_queue_t *(*su_port_timers)(su_port_t *port);
135
136 int (*su_port_multishot)(su_port_t *port, int multishot);
137
138 /* Extension from >= 1.12.4 */
139 int (*su_port_wait_events)(su_port_t *port, su_duration_t timeout);
140 int (*su_port_getmsgs)(su_port_t *port);
141 /* Extension from >= 1.12.5 */
142 int (*su_port_getmsgs_from)(su_port_t *port, su_port_t *cloneport);
143 char const *(*su_port_name)(su_port_t const *port);
144 int (*su_port_start_shared)(su_root_t *root,
145 su_clone_r return_clone,
146 su_root_magic_t *magic,
147 su_root_init_f init,
148 su_root_deinit_f deinit);
149 void (*su_port_wait)(su_clone_r rclone);
150 int (*su_port_execute)(su_task_r const task,
151 int (*function)(void *), void *arg,
152 int *return_value);
153
154 /* >= 1.12.11 */
155 su_timer_queue_t *(*su_port_deferrable)(su_port_t *port);
156 int (*su_port_max_defer)(su_port_t *port,
157 su_duration_t *return_duration,
158 su_duration_t *set_duration);
159 int (*su_port_wakeup)(su_port_t *port);
160 int (*su_port_is_running)(su_port_t const *port);
161 } su_port_vtable_t;
162
163 SOFIAPUBFUN su_port_t *su_port_create(void)
164 __attribute__((__malloc__));
165
166 /* Extension from >= 1.12.5 */
167
168 SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg);
169 SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_queue_t const *timers,
170 su_time_t now);
171 SOFIAPUBFUN su_root_t *su_root_create_with_port(su_root_magic_t *magic,
172 su_port_t *port)
173 __attribute__((__malloc__));
174
175 /* Extension from >= 1.12.6 */
176
177 SOFIAPUBFUN char const *su_port_name(su_port_t const *port);
178
179 SOFIAPUBFUN int su_timer_reset_all(su_timer_queue_t *, su_task_r );
180
181 /* ---------------------------------------------------------------------- */
182
183 /* React to multiple events per one poll() to make sure
184 * that high-priority events can never completely mask other events.
185 * Enabled by default on all platforms except WIN32 */
186 #if !defined(WIN32)
187 #define SU_ENABLE_MULTISHOT_POLL 1
188 #else
189 #define SU_ENABLE_MULTISHOT_POLL 0
190 #endif
191
192 /* ---------------------------------------------------------------------- */
193 /* Virtual functions */
194
195 typedef struct su_virtual_port_s {
196 su_home_t sup_home[1];
197 su_port_vtable_t const *sup_vtable;
198 } su_virtual_port_t;
199
200 su_inline
su_port_home(su_port_t const * self)201 su_home_t *su_port_home(su_port_t const *self)
202 {
203 return (su_home_t *)self;
204 }
205
206 su_inline
su_port_lock(su_port_t * self,char const * who)207 void su_port_lock(su_port_t *self, char const *who)
208 {
209 su_virtual_port_t *base = (su_virtual_port_t *)self;
210 base->sup_vtable->su_port_lock(self, who);
211 }
212
213 su_inline
su_port_unlock(su_port_t * self,char const * who)214 void su_port_unlock(su_port_t *self, char const *who)
215 {
216 su_virtual_port_t *base = (su_virtual_port_t *)self;
217 base->sup_vtable->su_port_unlock(self, who);
218 }
219
220 su_inline
su_port_incref(su_port_t * self,char const * who)221 void su_port_incref(su_port_t *self, char const *who)
222 {
223 su_virtual_port_t *base = (su_virtual_port_t *)self;
224 base->sup_vtable->su_port_incref(self, who);
225 }
226
227 su_inline
su_port_decref(su_port_t * self,char const * who)228 void su_port_decref(su_port_t *self, char const *who)
229 {
230 su_virtual_port_t *base = (su_virtual_port_t *)self;
231 base->sup_vtable->su_port_decref(self, 0, who);
232 }
233
234 su_inline
su_port_zapref(su_port_t * self,char const * who)235 void su_port_zapref(su_port_t *self, char const *who)
236 {
237 su_virtual_port_t *base = (su_virtual_port_t *)self;
238 base->sup_vtable->su_port_decref(self, 1, who);
239 }
240
241 su_inline
su_port_gsource(su_port_t * self)242 struct _GSource *su_port_gsource(su_port_t *self)
243 {
244 su_virtual_port_t *base = (su_virtual_port_t *)self;
245 return base->sup_vtable->su_port_gsource(self);
246 }
247
248 su_inline
su_port_send(su_port_t * self,su_msg_r rmsg)249 int su_port_send(su_port_t *self, su_msg_r rmsg)
250 {
251 su_virtual_port_t *base = (su_virtual_port_t *)self;
252 return base->sup_vtable->su_port_send(self, rmsg);
253 }
254
255 su_inline
su_port_wakeup(su_port_t * self)256 int su_port_wakeup(su_port_t *self)
257 {
258 su_virtual_port_t *base = (su_virtual_port_t *)self;
259 return base->sup_vtable->su_port_wakeup(self);
260 }
261
262 su_inline
su_port_register(su_port_t * self,su_root_t * root,su_wait_t * wait,su_wakeup_f callback,su_wakeup_arg_t * arg,int priority)263 int su_port_register(su_port_t *self,
264 su_root_t *root,
265 su_wait_t *wait,
266 su_wakeup_f callback,
267 su_wakeup_arg_t *arg,
268 int priority)
269 {
270 su_virtual_port_t *base = (su_virtual_port_t *)self;
271 return base->sup_vtable->
272 su_port_register(self, root, wait, callback, arg, priority);
273 }
274
275 su_inline
su_port_unregister(su_port_t * self,su_root_t * root,su_wait_t * wait,su_wakeup_f callback,su_wakeup_arg_t * arg)276 int su_port_unregister(su_port_t *self,
277 su_root_t *root,
278 su_wait_t *wait,
279 su_wakeup_f callback,
280 su_wakeup_arg_t *arg)
281 {
282 su_virtual_port_t *base = (su_virtual_port_t *)self;
283 return base->sup_vtable->
284 su_port_unregister(self, root, wait, callback, arg);
285 }
286
287 su_inline
su_port_deregister(su_port_t * self,int i)288 int su_port_deregister(su_port_t *self, int i)
289 {
290 su_virtual_port_t *base = (su_virtual_port_t *)self;
291 return base->sup_vtable->
292 su_port_deregister(self, i);
293 }
294
295 su_inline
su_port_unregister_all(su_port_t * self,su_root_t * root)296 int su_port_unregister_all(su_port_t *self,
297 su_root_t *root)
298 {
299 su_virtual_port_t *base = (su_virtual_port_t *)self;
300 return base->sup_vtable->
301 su_port_unregister_all(self, root);
302 }
303
304 su_inline
su_port_eventmask(su_port_t * self,int index,int socket,int events)305 int su_port_eventmask(su_port_t *self, int index, int socket, int events)
306 {
307 su_virtual_port_t *base = (su_virtual_port_t *)self;
308 return base->sup_vtable->
309 su_port_eventmask(self, index, socket, events);
310 }
311
312 su_inline
su_port_wait_events(su_port_t * self,su_duration_t timeout)313 int su_port_wait_events(su_port_t *self, su_duration_t timeout)
314 {
315 su_virtual_port_t *base = (su_virtual_port_t *)self;
316 if (base->sup_vtable->su_port_wait_events == NULL)
317 return errno = ENOSYS, -1;
318 return base->sup_vtable->
319 su_port_wait_events(self, timeout);
320 }
321
322 su_inline
su_port_run(su_port_t * self)323 void su_port_run(su_port_t *self)
324 {
325 su_virtual_port_t *base = (su_virtual_port_t *)self;
326 base->sup_vtable->su_port_run(self);
327 }
328
329 su_inline
su_port_break(su_port_t * self)330 void su_port_break(su_port_t *self)
331 {
332 su_virtual_port_t *base = (su_virtual_port_t *)self;
333 base->sup_vtable->su_port_break(self);
334 }
335
336 su_inline
su_port_step(su_port_t * self,su_duration_t tout)337 su_duration_t su_port_step(su_port_t *self, su_duration_t tout)
338 {
339 su_virtual_port_t *base = (su_virtual_port_t *)self;
340 return base->sup_vtable->su_port_step(self, tout);
341 }
342
343
344 su_inline
su_port_own_thread(su_port_t const * self)345 int su_port_own_thread(su_port_t const *self)
346 {
347 su_virtual_port_t const *base = (su_virtual_port_t *)self;
348 return base->sup_vtable->
349 su_port_thread((su_port_t *)self, su_port_thread_op_is_obtained) == 2;
350 }
351
su_port_has_thread(su_port_t * self)352 su_inline int su_port_has_thread(su_port_t *self)
353 {
354 su_virtual_port_t *base = (su_virtual_port_t *)self;
355 return base->sup_vtable->su_port_thread(self, su_port_thread_op_is_obtained);
356 }
357
su_port_release(su_port_t * self)358 su_inline int su_port_release(su_port_t *self)
359 {
360 su_virtual_port_t *base = (su_virtual_port_t *)self;
361 return base->sup_vtable->su_port_thread(self, su_port_thread_op_release);
362 }
363
su_port_obtain(su_port_t * self)364 su_inline int su_port_obtain(su_port_t *self)
365 {
366 su_virtual_port_t *base = (su_virtual_port_t *)self;
367 return base->sup_vtable->su_port_thread(self, su_port_thread_op_obtain);
368 }
369
370 su_inline
su_port_add_prepoll(su_port_t * self,su_root_t * root,su_prepoll_f * prepoll,su_prepoll_magic_t * magic)371 int su_port_add_prepoll(su_port_t *self,
372 su_root_t *root,
373 su_prepoll_f *prepoll,
374 su_prepoll_magic_t *magic)
375 {
376 su_virtual_port_t *base = (su_virtual_port_t *)self;
377 return base->sup_vtable->su_port_add_prepoll(self, root, prepoll, magic);
378 }
379
380 su_inline
su_port_remove_prepoll(su_port_t * self,su_root_t * root)381 int su_port_remove_prepoll(su_port_t *self,
382 su_root_t *root)
383 {
384 su_virtual_port_t *base = (su_virtual_port_t *)self;
385 return base->sup_vtable->su_port_remove_prepoll(self, root);
386 }
387
388 su_inline
su_port_timers(su_port_t * self)389 su_timer_queue_t *su_port_timers(su_port_t *self)
390 {
391 su_virtual_port_t *base = (su_virtual_port_t *)self;
392 return base->sup_vtable->su_port_timers(self);
393 }
394
395 su_inline
su_port_multishot(su_port_t * self,int multishot)396 int su_port_multishot(su_port_t *self, int multishot)
397 {
398 su_virtual_port_t *base = (su_virtual_port_t *)self;
399 return base->sup_vtable->su_port_multishot(self, multishot);
400 }
401
402 su_inline
su_port_getmsgs(su_port_t * self)403 int su_port_getmsgs(su_port_t *self)
404 {
405 su_virtual_port_t *base = (su_virtual_port_t *)self;
406 return base->sup_vtable->su_port_getmsgs(self);
407 }
408
409 su_inline
su_port_getmsgs_from(su_port_t * self,su_port_t * cloneport)410 int su_port_getmsgs_from(su_port_t *self, su_port_t *cloneport)
411 {
412 su_virtual_port_t *base = (su_virtual_port_t *)self;
413 return base->sup_vtable->su_port_getmsgs_from(self, cloneport);
414 }
415
416 /** Extension from >= 1.12.11 */
417
418 su_inline
su_port_deferrable(su_port_t * self)419 su_timer_queue_t *su_port_deferrable(su_port_t *self)
420 {
421 su_virtual_port_t *base = (su_virtual_port_t *)self;
422
423 if (base == NULL) {
424 errno = EFAULT;
425 return NULL;
426 }
427
428 return base->sup_vtable->su_port_deferrable(self);
429 }
430
431 su_inline
su_port_max_defer(su_port_t * self,su_duration_t * return_duration,su_duration_t * set_duration)432 int su_port_max_defer(su_port_t *self,
433 su_duration_t *return_duration,
434 su_duration_t *set_duration)
435 {
436 su_virtual_port_t *base = (su_virtual_port_t *)self;
437
438 if (base == NULL)
439 return (errno = EFAULT), -1;
440
441 return base->sup_vtable->su_port_max_defer(self,
442 return_duration,
443 set_duration);
444 }
445
446 su_inline
su_port_is_running(su_port_t const * self)447 int su_port_is_running(su_port_t const *self)
448 {
449 su_virtual_port_t *base = (su_virtual_port_t *)self;
450 return base && base->sup_vtable->su_port_is_running(self);
451 }
452
453 SOFIAPUBFUN void su_port_wait(su_clone_r rclone);
454
455 SOFIAPUBFUN int su_port_execute(su_task_r const task,
456 int (*function)(void *), void *arg,
457 int *return_value);
458
459 /* ---------------------------------------------------------------------- */
460
461 /**@internal Base port object.
462 *
463 * Port is a per-thread reactor. Multiple root objects executed by a single
464 * thread share the su_port_t object.
465 */
466 typedef struct su_base_port_s {
467 su_home_t sup_home[1];
468 su_port_vtable_t const *sup_vtable;
469
470 /* Implementation may vary stuff below, too. */
471
472 /* Pre-poll callback */
473 su_prepoll_f *sup_prepoll;
474 su_prepoll_magic_t *sup_pp_magic;
475 su_root_t *sup_pp_root;
476
477 /* Message list - this is protected by su_port_lock()/su_port_unlock() */
478 su_msg_t *sup_head, **sup_tail;
479
480 /* Timer list */
481 su_timer_queue_t sup_timers, sup_deferrable;
482
483 su_duration_t sup_max_defer; /**< Maximum time to defer */
484
485 unsigned sup_running; /**< In su_root_run() loop? */
486 } su_base_port_t;
487
488 /* Base methods */
489
490 SOFIAPUBFUN int su_base_port_init(su_port_t *, su_port_vtable_t const *);
491 SOFIAPUBFUN void su_base_port_deinit(su_port_t *self);
492
493 SOFIAPUBFUN void su_base_port_lock(su_port_t *self, char const *who);
494 SOFIAPUBFUN void su_base_port_unlock(su_port_t *self, char const *who);
495
496 SOFIAPUBFUN int su_base_port_thread(su_port_t const *self,
497 enum su_port_thread_op op);
498
499 SOFIAPUBFUN void su_base_port_incref(su_port_t *self, char const *who);
500 SOFIAPUBFUN int su_base_port_decref(su_port_t *self,
501 int blocking,
502 char const *who);
503
504 SOFIAPUBFUN struct _GSource *su_base_port_gsource(su_port_t *self);
505
506 SOFIAPUBFUN su_socket_t su_base_port_mbox(su_port_t *self);
507 SOFIAPUBFUN int su_base_port_send(su_port_t *self, su_msg_r rmsg);
508 SOFIAPUBFUN int su_base_port_getmsgs(su_port_t *self);
509 SOFIAPUBFUN int su_base_port_getmsgs_from(su_port_t *self,
510 su_port_t *from);
511
512 SOFIAPUBFUN void su_base_port_run(su_port_t *self);
513 SOFIAPUBFUN void su_base_port_break(su_port_t *self);
514 SOFIAPUBFUN su_duration_t su_base_port_step(su_port_t *self,
515 su_duration_t tout);
516
517 SOFIAPUBFUN int su_base_port_add_prepoll(su_port_t *self,
518 su_root_t *root,
519 su_prepoll_f *,
520 su_prepoll_magic_t *);
521
522 SOFIAPUBFUN int su_base_port_remove_prepoll(su_port_t *self, su_root_t *root);
523
524 SOFIAPUBFUN su_timer_queue_t *su_base_port_timers(su_port_t *self);
525
526 SOFIAPUBFUN int su_base_port_multishot(su_port_t *self, int multishot);
527
528 SOFIAPUBFUN int su_base_port_start_shared(su_root_t *parent,
529 su_clone_r return_clone,
530 su_root_magic_t *magic,
531 su_root_init_f init,
532 su_root_deinit_f deinit);
533 SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
534
535 SOFIAPUBFUN su_timer_queue_t *su_base_port_deferrable(su_port_t *self);
536
537 SOFIAPUBFUN int su_base_port_max_defer(su_port_t *self,
538 su_duration_t *return_duration,
539 su_duration_t *set_duration);
540
541 SOFIAPUBFUN int su_base_port_is_running(su_port_t const *self);
542
543 /* ---------------------------------------------------------------------- */
544
545 #if SU_HAVE_PTHREADS
546
547 #include <pthread.h>
548
549 /** @internal Pthread port object */
550 typedef struct su_pthread_port_s {
551 su_base_port_t sup_base[1];
552 struct su_pthread_port_waiting_parent
553 *sup_waiting_parent;
554 pthread_t sup_tid;
555 pthread_mutex_t sup_obtained[1];
556
557 #if 0 /* Pausing and resuming are not used */
558 pthread_mutex_t sup_runlock[1];
559 pthread_cond_t sup_resume[1];
560 short sup_paused; /**< True if thread is paused */
561 #endif
562 short sup_thread; /**< True if thread is active */
563 } su_pthread_port_t;
564
565 /* Pthread methods */
566
567 SOFIAPUBFUN int su_pthread_port_init(su_port_t *, su_port_vtable_t const *);
568 SOFIAPUBFUN void su_pthread_port_deinit(su_port_t *self);
569
570 SOFIAPUBFUN void su_pthread_port_lock(su_port_t *self, char const *who);
571 SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who);
572
573 SOFIAPUBFUN int su_pthread_port_thread(su_port_t *self,
574 enum su_port_thread_op op);
575
576 #if 0 /* not yet */
577 SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg);
578
579 SOFIAPUBFUN su_port_t *su_pthread_port_create(void);
580 SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent,
581 su_clone_r return_clone,
582 su_root_magic_t *magic,
583 su_root_init_f init,
584 su_root_deinit_f deinit);
585 #endif
586
587 SOFIAPUBFUN int su_pthreaded_port_start(su_port_create_f *create,
588 su_root_t *parent,
589 su_clone_r return_clone,
590 su_root_magic_t *magic,
591 su_root_init_f init,
592 su_root_deinit_f deinit);
593
594 SOFIAPUBFUN void su_pthread_port_wait(su_clone_r rclone);
595 SOFIAPUBFUN int su_pthread_port_execute(su_task_r const task,
596 int (*function)(void *), void *arg,
597 int *return_value);
598
599 #if 0
600 SOFIAPUBFUN int su_pthread_port_pause(su_port_t *self);
601 SOFIAPUBFUN int su_pthread_port_resume(su_port_t *self);
602 #endif
603
604 #else
605
606 typedef su_base_port_t su_pthread_port_t;
607
608 #define su_pthread_port_init su_base_port_init
609 #define su_pthread_port_deinit su_base_port_deinit
610 #define su_pthread_port_lock su_base_port_lock
611 #define su_pthread_port_unlock su_base_port_unlock
612 #define su_pthread_port_thread su_base_port_thread
613 #define su_pthread_port_wait su_base_port_wait
614 #define su_pthread_port_execute su_base_port_execute
615
616 #endif
617
618 /* ====================================================================== */
619 /* Mailbox port using sockets */
620
621 #define SU_MBOX_SIZE 2
622
623 typedef struct su_socket_port_s {
624 su_pthread_port_t sup_base[1];
625 int sup_mbox_index;
626 su_socket_t sup_mbox[SU_MBOX_SIZE];
627 } su_socket_port_t;
628
629 SOFIAPUBFUN int su_socket_port_init(su_socket_port_t *,
630 su_port_vtable_t const *);
631 SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self);
632 SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg);
633 SOFIAPUBFUN int su_socket_port_wakeup(su_port_t *self);
634
635 SOFIA_END_DECLS
636
637 #endif /* SU_PORT_H */
638