1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
|
/* Channel I/O
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2004, 2005, 2007
Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.org>
Reworked for libchannel by Carl Fredrik Hammar <hammy.lite@gmail.com>
This file is part of the GNU Hurd.
The GNU Hurd is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2, or (at
your option) any later version.
The GNU Hurd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
#ifndef __CHANNEL_H__
#define __CHANNEL_H__
#include <pthread.h>
#include <mach.h>
#include <hurd/hurd_types.h>
struct channel
{
int flags;
struct channel_hub *hub;
/* These hooks are not touched by libchannel. */
void *class_hook; /* For class' use. */
void *user_hook; /* For user's use. */
};
struct channel_hub
{
/* Should be held when before access to fields of this hub or call to
any function operating on it. */
pthread_pthread_mutex_t lock;
/* The name of this hub. Its meaning is class-specific. May be null
and is freed by channel_free_hub. */
char *name;
int flags;
const struct channel_class *class;
/* A list of sub-hubs. Their usage is type-specific. */
struct channel_hub **children;
size_t num_children;
void *hook; /* For class' use. */
};
struct channel_class
{
/* Name of the class. */
const char *name;
/* Read at most AMOUNT bytes from CHANNEL into BUF and LEN with the
usual return buf semantics. Blocks until data is available or return
0 bytes on EOF. May not be null. See channel_read. */
error_t (*read) (struct channel *channel,
size_t amount, void **buf, size_t *len);
/* Write LEN bytes from BUF to CHANNEL, AMOUNT is set to the amount
actually witten. Should block until data can be written. May not be
null. See channel_write. */
error_t (*write) (struct channel *channel,
void *buf, size_t len, size_t *amount);
/* Write out any pending data held by CHANNEL for buffering purposes.
It should *not* flush data held to implement specific behavior. May
be null. See channel_flush. */
error_t (*flush) (struct channel *channel);
/* Set any backend handled flags in CHANNEL specified in FLAGS. May be
null. See channel_set_flags. */
error_t (*set_flags) (struct channel *channel, int flags);
/* Clear any backend handled flags in CHANNEL specified in FLAGS. May
be null. See channel_clear_flags. */
error_t (*clear_flags) (struct channel *channel, int flags);
/* Open CHANNEL and set FLAGS. May be null. See channel_open. */
error_t (*open) (struct channel *channel, int flags);
/* Free any resources allocated for CHANNEL. May be null. See
channel_close. */
void (*close) (struct channel *channel);
/* This demuxer should be called whenever an unknown RPC is received by
the translator. See channel_control_demuxer. */
int (*control_demuxer) (mach_msg_header_t *in, mach_msg_header_t *out);
/* Create new hub specified by NAME with given FLAGS and return it in
HUB. The interpretation of NAME is class-specific. CLASSES are
provided in order to open any sub-hubs. */
error_t (*create_hub) (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
/* Free any class-specific resources allocated for HUB. May be null.
See channel_free_hub. */
void (*clear_hub) (struct channel_hub *hub);
/* Set any backend handled flags in HUB specified in FLAGS. May be
null. See channel_set_hub_flags. */
error_t (*set_hub_flags) (struct channel_hub *hub, int flags);
/* Clear any backend handled flags in HUB specified in FLAGS. May be
null. See channel_clear_hub_flags. */
error_t (*clear_hub_flags) (struct channel_hub *hub, int flags);
/* Return EINVAL if NAME is an invalid name for a hub. It should accept
0 if it accepts an empty name. May be null. */
error_t (*validate_name) (const char *name,
const struct channel_class *const *classes);
};
/* Flags implemented by generic channel code. */
#define CHANNEL_READONLY 0x1 /* No writing allowed. */
#define CHANNEL_WRITEONLY 0x2 /* No reading allowed. */
#define CHANNEL_NO_FILEIO 0x4 /* Don't consider file io as an option. */
#define CHANNEL_ENFORCED 0x8 /* Don't transfer hubs over IPC. */
#define CHANNEL_GENERIC_FLAGS (CHANNEL_READONLY | CHANNEL_WRITEONLY \
| CHANNEL_NO_FILEIO | CHANNEL_ENFORCED)
/* Flags implemented by each backend. */
#define CHANNEL_HARD_READONLY 0x010 /* Can't be made writable. */
#define CHANNEL_HARD_WRITEONLY 0x020 /* Can't be made readable. */
#define CHANNEL_BACKEND_SPEC_BASE 0x100 /* Here up are backend-specific */
#define CHANNEL_BACKEND_FLAGS (CHANNEL_HARD_READONLY \
| CHANNEL_HARD_WRITEONLY \
| ~(CHANNEL_BACKEND_SPEC_BASE - 1))
/* Allocate a new channel of hub HUB, with FLAGS set, then return it in
CHANNEL. Return ENOMEM if memory for the hub couldn't be allocated. */
error_t channel_alloc (struct channel_hub *hub, int flags,
struct channel **channel);
/* Free CHANNEL and any generic resources allocated for it. */
void channel_free (struct channel *channel);
/* Allocate a new channel, open it, and return it in CHANNEL. Uses
HUB's open method and passes FLAGS to it, unless it's null. */
error_t channel_open (struct channel_hub *hub, int flags,
struct channel **channel);
/* Call CHANNEL's close method, unless it's null, then free it
(regardless.) */
void channel_close (struct channel *channel);
/* Set the flags FLAGS in CHANNEL. Remove any already set flags in FLAGS,
if FLAGS contain any backend flags call set_flags method or if
set_flags is null return EINVAL. Lastly generic flags get set. */
error_t channel_set_flags (struct channel *channel, int flags);
/* Clear the flags FLAGS in CHANNEL. Remove any already cleared flags in
FLAGS, if FLAGS contain any backend flags call clear_flags method or if
clear_flags is null return EINVAL. Lastly generic flags get
cleared. */
error_t channel_clear_flags (struct channel *channel, int flags);
/* Reads at most AMOUNT bytes from CHANNEL into BUF and LEN with the usual
return buf semantics. Block until data is available and return 0 bytes
on EOF. If channel is write-only return EPERM, otherwise forward call
to CHANNEL's read method. */
error_t channel_read (struct channel *channel, size_t amount,
void **buf, size_t *len);
/* Write LEN bytes of BUF to CHANNEL, AMOUNT is set to the amount actually
witten. Block until data can be written. If channel is read-only
return EPERM, otherwise forward call to CHANNEL's write method. */
error_t channel_write (struct channel *channel, void *buf, size_t len,
size_t *amount);
/* Write out any pending data held by CHANNEL in buffers, by forwarding
call to flush method, unless it's null. */
error_t channel_flush (struct channel *channel);
/* This demuxer will get the channel IN is intended for using
channel_begin_using_channel and call channel_end_using_channel, then
call the channel's control_demuxer method. Return true, unless channel
or its method is null or if the method couldn't handle IN. */
int channel_control_demuxer (mach_msg_header_t *in, mach_msg_header_t *out);
/* The following two functions are provided for use in the MiG .defs file
as a type translator, destructor pair. They are to be implemented in
the translator using libchannel. */
/* Find and return the channel associated with PORT or return null if
there is no such channel. This function should be overridden by the
translator using libchannel, as the default implementation will
always return null. */
struct channel *channel_begin_using_channel (mach_port_t port);
/* Reverses any side-effects of using channel_begin_using_channel and
should also be implemented by the translator using libchannel, as
the default implementation does nothing. */
void channel_end_using_channel (struct channel *channel);
/* Allocate a new hub of CLASS, named NAME and with FLAGS set, then return
it in HUB. Return ENOMEM if memory for the hub couldn't be
allocated. */
error_t channel_alloc_hub (const struct channel_class *class,
const char *name, int flags,
struct channel_hub **hub);
/* If not null call method clear_hub to deallocate class-specific bits of
HUB, then (regardless) free any generic resources used by it and
itself. */
void channel_free_hub (struct channel_hub *hub);
/* Set name of HUB to copy of NAME. Return ENOMEM if no memory if
available. */
error_t channel_set_hub_name (struct channel_hub *hub, const char *name);
/* Set the HUB's list of children to a copy of CHILDREN and NUM_CHILDREN,
or if allocation fails return ENOMEM. */
error_t channel_set_children (struct channel_hub *hub,
struct channel_hub *const *children,
size_t num_children);
/* Generate a name for the children of HUB into NAME. It done by
combining the name of each child in a way that the name can be parsed
by channel_create_hub_children. This is done heuristically, and it may
fail and return EGRATUITOUS. If a child does not have a name, return
EINVAL. If memory is exausted, return ENOMEM. */
error_t channel_children_name (const struct channel_hub *hub,
char **name);
/* Set the flags FLAGS in HUB. Remove any already set flags in FLAGS, if
FLAGS then contain backend flags call set_hub_flags method with with
FLAGS or if set_hub_flags is null return EINVAL. Lastly generic flags
get set. */
error_t channel_set_hub_flags (struct channel_hub *hub, int flags);
/* Clear the flags FLAGS in HUB. Remove any already cleared flags in
FLAGS, if FLAGS then contain backend flags call clear_hub_flags method
with with FLAGS or if clear_hub_flags is null return EINVAL. Lastly
generic flags get clear. */
error_t channel_clear_hub_flags (struct channel_hub *hub, int flags);
/* Set FLAGS in all the children of HUB, and if successful, set them in
HUB also. Flags are set using channel_set_hub_flags. Propagate any
error on failure. */
error_t channel_set_child_flags (struct channel_hub *hub, int flags);
/* Clear FLAGS in all the children of HUB, and if successful, clear them
in HUB also. Flags are cleared as if using channel_clear_hub_flags.
Propagate any error on failure. */
error_t channel_clear_child_flags (struct channel_hub *hub, int flags);
/* Return a new hub in HUB, which is a copy of the hub underlying SOURCE.
The class of hub is found in CLASSES or CHANNEL_STD_CLASSES, if CLASSES
is null. FLAGS is set with channel_set_hub_flags. Keeps the SOURCE
reference, which may be closed using channel_close_hub_source. */
error_t channel_fetch_hub (file_t source, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
/* Open the file NAME and return a new hub in HUB, which is either a copy
of the file's underlying hub or a hub using it through file io, unless
CHANNEL_NO_FILEIO flag is given. The class of HUB is found in CLASSES
or CHANNEL_STD_CLASSES, if CLASSES is null. FLAGS is set with
channel_set_hub_flags. Keeps the SOURCE reference, which may be closed
using channel_close_hub_source. */
error_t
channel_create_query_hub (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
/* Create the channel hub indicated by NAME, which should consist of a
channel type name followed by a ':' and any type-specific name,
returning the new hub in HUB. If NAME doesn't contain a `:', then it
will be interpreted as either a class name, if such a class occurs in
CLASSES, or a filename, which is opened by calling
channel_create_query_hub on NAME; a `:' at the end or the beginning of
NAME unambiguously causes the remainder to be treated as a class-name
or a filename, respectively. CLASSES is used to select classes
specified by the type name; if it is 0, CHANNEL_STD_CLASSES is
used. */
error_t channel_create_typed_hub (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
/* Create and return in HUB, the hub specified by NAME, which should
consist of a hub type name followed by a `:' and any type-specific
name. Its class is loaded dynamically and CLASSES is only passed to
the class' create_hub method (which usually use it for creating
sub-hubs.) */
error_t
channel_create_module_hub (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
/* Create and return in HUB a hub that creates channels that does file i/o
with the file specified by NAME. */
error_t channel_create_file_hub (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
error_t
channel_create_broadcast_hub (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
error_t
channel_create_tee_hub (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub **hub);
/* Parse multiple hub names in NAME, creating and returning each in HUBS
and NUM_HUBS. The syntax of name is a single non-alpha-numeric
character followed by each child hub's name, seperated by the same
separator. Each child name is in TYPE:NAME notation as parsed by
channel_create_typed_hub. If all children has the same TYPE: prefix,
then it may be factored out and put before the child list instead. */
error_t
channel_create_hub_children (const char *name, int flags,
const struct channel_class *const *classes,
struct channel_hub ***hubs, size_t *num_hubs);
/* Find and return a class by name in CLASSES if not null, otherwise in
the `channel_std_class' section and already loaded modules. NAME_END
points to the character after the class name in NAME; if null, then
NAME is the null-terminated class name. */
const struct channel_class *
channel_find_class (const char *name, const char *clname_end,
const struct channel_class *const *classes);
/* Load the module that defines the class NAME (upto NAME_END) and return
it in CLASS. Return ENOENT if module isn't available, or any other
error code from dlopen and friends if module couldn't be loaded. */
error_t
channel_module_find_class (const char *name, const char *clname_end,
const struct channel_class **classp);
/* Standard channel classes implemented by channel. */
extern const struct channel_class channel_query_class;
extern const struct channel_class channel_typed_class;
extern const struct channel_class channel_module_class;
extern const struct channel_class channel_file_class;
extern const struct channel_class channel_broadcast_class;
extern const struct channel_class channel_tee_class;
/* The macro CHANNEL_STD_CLASS produces a reference in the
`channel_std_classes' section for channel_NAME_class. */
#define CHANNEL_STD_CLASS(name) \
static const struct channel_class *const channel_std_classes_##name[] \
__attribute_used__ __attribute__ ((section ("channel_std_classes"))) \
= { &channel_##name##_class }
/* These are pointers to the start and end of the channel_std_classes
section of the executable. */
extern const struct channel_class *const __start_channel_std_classes[]
__attribute__ ((weak));
extern const struct channel_class *const __stop_channel_std_classes[]
__attribute__ ((weak));
/* An argument parser that may be used for parsing a simple command line
specification for channels. The accompanying input parameter must be a
pointer to a struct channel_argp_params. */
extern struct argp channel_argp;
/* The structure used to pass args back and forth from CHANNEL_ARGP. */
struct channel_argp_params
{
/* The resulting parsed result. */
struct channel_parsed *result;
/* If --channel-type isn't specified use this; null is equivalent to
`query'. */
const char *default_type;
/* The set of classes used to validate channel-types and argument
syntax. */
const struct channel_class *const *classes;
/* This controls the behavior when no channel arguments are specified.
If zero, the parser fails with the error message ``No channel
specified''. If nonzero, the parser succeeds and sets `result' to
null. */
int channel_optional;
};
/* The result of parsing a channel, which should be enough information to
open it, or return the arguments. */
struct channel_parsed;
/* Free all resources used by PARSED. */
void channel_parsed_free (struct channel_parsed *parsed);
/* Create and return in HUB the channel hub specified in PARSED. */
error_t channel_create_parsed_hub (const struct channel_parsed *parsed,
int flags, struct channel_hub **hub);
/* Add the arguments used to create PARSED to ARGZ & ARGZ_LEN. */
error_t channel_parsed_append_args (const struct channel_parsed *parsed,
char **argz, size_t *argz_len);
/* Make a string describing PARSED, and return it in malloced storage in
NAME. */
error_t channel_parsed_name (const struct channel_parsed *parsed,
char **name);
#endif /* __CHANNEL_H__ */
|