Changed SILC Stream API implementation static inline functions.
[runtime.git] / lib / silcutil / silcstream.h
1 /*
2
3   silcstream.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2005 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 /****h* silcutil/Stream Interface
21  *
22  * DESCRIPTION
23  *
24  * SILC Stream API is a generic representation of a stream.  A common API
25  * is defined that can be used to read from and write to the stream.  Any
26  * other stream API derived from this API can use this same interface for
27  * reading and writing.
28  *
29  * The SilcStream is an abstraction.  It can represent any stream; socket
30  * stream, file descriptor stream, packet stream, etc.  See examples in
31  * silcsocketstream.h and silcfdstream.h.
32  *
33  * Note that stream implementations usually are not thread-safe.  Always
34  * verify whether a stream implementation is thread-safe by checking their
35  * corresponding documentation.
36  *
37  ***/
38
39 #ifndef SILCSTREAM_H
40 #define SILCSTREAM_H
41
42 /****s* silcutil/SilcStream
43  *
44  * NAME
45  *
46  *    typedef void *SilcStream;
47  *
48  * DESCRIPTION
49  *
50  *    Abstact stream context representing any stream.  All streams are using
51  *    this abstraction so that the stream can be accessed using the standard
52  *    silc_stream_* functions.  All streams are destroyed by calling the
53  *    silc_stream_destroy function.
54  *
55  ***/
56 typedef void *SilcStream;
57
58 /****d* silcutil/SilcStreamStatus
59  *
60  * NAME
61  *
62  *    typedef enum { ... } SilcStreamStatus;
63  *
64  * DESCRIPTION
65  *
66  *    Stream status.  This status is returned into the SilcStreamNotifier
67  *    callback function to indicate the status of the stream at a given
68  *    moment.
69  *
70  * SOURCE
71  */
72 typedef enum {
73   SILC_STREAM_CAN_READ,         /* Data available for reading */
74   SILC_STREAM_CAN_WRITE,        /* Stream ready for writing */
75 } SilcStreamStatus;
76 /***/
77
78 /****f* silcutil/SilcStreamNotifier
79  *
80  * SYNOPSIS
81  *
82  *    typedef void (*SilcStreamNotifier)(SilcStream stream,
83  *                                       SilcStreamStatus status,
84  *                                       void *context);
85  *
86  * DESCRIPTION
87  *
88  *    A callback of this type is called as stream notifier to notify of a
89  *    certain action taken over the stream.  This is called to notify for
90  *    example that data is ready for reading, or writing or that end of
91  *    stream occurred.
92  *
93  ***/
94 typedef void (*SilcStreamNotifier)(SilcStream stream,
95                                    SilcStreamStatus status,
96                                    void *context);
97
98 /****s* silcutil/SilcStreamOps
99  *
100  * NAME
101  *
102  *    typedef struct { ... } SilcStreamOps;
103  *
104  * DESCRIPTION
105  *
106  *    SILC Stream operations structure.  This structure includes callback
107  *    functions to the actual stream implementation.  Any stream that
108  *    use SILC Stream abstraction must fill this structure with the actual
109  *    stream implementation.
110  *
111  *    Each stream implementation MUST set this structure as the first field
112  *    in their stream structure.  As it is that structure that is passed
113  *    to the silc_stream_* routines, the SILC Stream API expects that the
114  *    SilcStream context starts with this structure.
115  *
116  * EXAMPLE
117  *
118  *    typedef struct {
119  *      const SilcStreamOps *ops;
120  *      ... other stuff ...
121  *    } *SilcFooStream;
122  *
123  *    SilcFooStream foo;
124  *    silc_stream_write((SilcStream)foo, data, data_len);
125  *
126  * SOURCE
127  */
128 typedef struct {
129   /* This is called to read data from the stream.  This is called when
130      silc_stream_read function was called. */
131   int (*read)(SilcStream stream, unsigned char *buf, SilcUInt32 buf_len);
132
133   /* This is called when writing data to the stream.  This is called when
134      silc_stream_write function was called. */
135   int (*write)(SilcStream stream, const unsigned char *data,
136                SilcUInt32 data_len);
137
138   /* This is called to close the stream.  This is called when the
139      silc_stream_close function was called. */
140   SilcBool (*close)(SilcStream stream);
141
142   /* This is called to destroy the stream.  This is called when the
143      silc_stream_destroy function was called. */
144   void (*destroy)(SilcStream stream);
145
146   /* This is called to set a notifier callback to the stream and schedule
147      the stream.  Stream should not be scheduled before calling this
148      function.  If stream does not need scheduler then the scheduler can
149      be ignored.  This is called when silc_stream_set_notifier was called.
150      Returns FALSE if the stream could not be scheduled. */
151   SilcBool (*notifier)(SilcStream stream, SilcSchedule schedule,
152                        SilcStreamNotifier callback, void *context);
153
154   /* This is called to return the associated scheduler, if set.  This is
155      called when silc_stream_get_schedule was called. */
156   SilcSchedule (*get_schedule)(SilcStream stream);
157 } SilcStreamOps;
158 /***/
159
160 /* Stream header */
161 typedef struct SilcStreamHeaderObject {
162   SilcStreamOps *ops;
163 } *SilcStreamHeader, SilcStreamHeaderStruct;
164
165 /****f* silcutil/silc_stream_read
166  *
167  * SYNOPSIS
168  *
169  *    int silc_stream_read(SilcStream stream, unsigned char *buf,
170  *                         SilcUInt32 buf_len);
171  *
172  * DESCRIPTION
173  *
174  *    Reads data from the stream indicated by `stream' into the data buffer
175  *    indicated by `buf' which is size of `buf_len'.  This returns the amount
176  *    of data read, zero (0) if end of stream occurred, -1 if data could
177  *    not be read at this moment, or -2 if error occurred.  If -1 is returned
178  *    the notifier callback will later be called with SILC_STREAM_CAN_READ
179  *    status when stream is again ready for reading.
180  *
181  *    If error occurred the error code can be retrieved with silc_errno.
182  *
183  ***/
184 static inline
185 int silc_stream_read(SilcStream stream, unsigned char *buf,
186                      SilcUInt32 buf_len)
187 {
188   SilcStreamHeader h = stream;
189   return h->ops->read(stream, buf, buf_len);
190 }
191
192 /****f* silcutil/silc_stream_write
193  *
194  * SYNOPSIS
195  *
196  *    int silc_stream_write(SilcStream stream, const unsigned char *data,
197  *                          SilcUInt32 data_len);
198  *
199  * DESCRIPTION
200  *
201  *    Writes `data_len' bytes of data to the stream indicated by `stream' from
202  *    data buffer indicated by `data'.  Returns the amount of data written,
203  *    zero (0) if end of stream occurred, -1 if data could not be written
204  *    at this moment, or -2 if error occurred.  If -1 is returned the
205  *    notifier callback will later be called with SILC_STREAM_CAN_WRITE
206  *    status when stream is again ready for writing.
207  *
208  *    If error occurred the error code can be retrieved with silc_errno.
209  *
210  ***/
211 static inline
212 int silc_stream_write(SilcStream stream, const unsigned char *data,
213                       SilcUInt32 data_len)
214 {
215   SilcStreamHeader h = stream;
216   return h->ops->write(stream, data, data_len);
217 }
218
219 /****f* silcutil/silc_stream_close
220  *
221  * SYNOPSIS
222  *
223  *    SilcBool silc_stream_close(SilcStream stream);
224  *
225  * DESCRIPTION
226  *
227  *    Closes the stream indicated by `stream'.  No data can be read or written
228  *    to the stream after calling this function.  Return TRUE if the stream
229  *    could be closed.  If action is taken on closed stream the notifier
230  *    callback may be called with an error status.
231  *
232  ***/
233 static inline
234 SilcBool silc_stream_close(SilcStream stream)
235 {
236   SilcStreamHeader h = stream;
237   return h->ops->close(stream);
238 }
239
240 /****f* silcutil/silc_stream_destroy
241  *
242  * SYNOPSIS
243  *
244  *    void silc_stream_destroy(SilcStream stream);
245  *
246  * DESCRIPTION
247  *
248  *    Destroy the stream indicated by `stream'.  The `stream' will become
249  *    invalid after this function returns.  All streams are destroyed by
250  *    calling this function.  The silc_stream_close should be called
251  *    before calling this function.  However, if it is not called this
252  *    function will call it.
253  *
254  ***/
255 static inline
256 void silc_stream_destroy(SilcStream stream)
257 {
258   SilcStreamHeader h = stream;
259   h->ops->destroy(stream);
260 }
261
262 /****f* silcutil/silc_stream_set_notifier
263  *
264  * SYNOPSIS
265  *
266  *    SilcBool silc_stream_set_notifier(SilcStream stream,
267  *                                      SilcSchedule schedule,
268  *                                      SilcStreamNotifier notifier,
269  *                                      void *context);
270  *
271  * DESCRIPTION
272  *
273  *    Schedule `stream' for stream events.  Set the `notifier' callback to
274  *    be called when some event takes place on the stream.  The event will
275  *    be delievered to the `notifier' callback with the `context'.  It is
276  *    called for example when data is available for reading or writing, or
277  *    if an error occurs.  This can be called at any time for valid stream.
278  *    This call will also set the `stream' into non-blocking mode.
279  *
280  *    If `notifier' is set to NULL no callback will be called for the stream,
281  *    and the stream is not scheduled anymore.
282  *
283  *    This function returns FALSE if the stream could not be scheduled.
284  *    Returns TRUE on success.  The `schedule' must always be non-NULL.
285  *
286  ***/
287 static inline
288 SilcBool silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
289                                   SilcStreamNotifier notifier, void *context)
290 {
291   SilcStreamHeader h = stream;
292   return h->ops->notifier(stream, schedule, notifier, context);
293 }
294
295 /****f* silcutil/silc_stream_get_schedule
296  *
297  * SYNOPSIS
298  *
299  *    SilcSchedule silc_stream_get_schedule(SilcStream stream);
300  *
301  * DESCRIPTION
302  *
303  *    Returns the scheduler that has been associated with the `stream', or
304  *    NULL if one has not been set for the `stream'.
305  *
306  ***/
307 static inline
308 SilcSchedule silc_stream_get_schedule(SilcStream stream)
309 {
310   SilcStreamHeader h = stream;
311   return h->ops->get_schedule(stream);
312 }
313
314 #endif /* SILCSTREAM_H */