edf553f7ded8fae922ec8d8e92877ebd364a3d03
[people/andreif/gpxe.git] / src / include / gpxe / xfer.h
1 #ifndef _GPXE_XFER_H
2 #define _GPXE_XFER_H
3
4 /** @file
5  *
6  * Data transfer interfaces
7  *
8  */
9
10 #include <stddef.h>
11 #include <stdarg.h>
12 #include <gpxe/interface.h>
13 #include <gpxe/iobuf.h>
14
15 struct xfer_interface;
16 struct xfer_metadata;
17
18 /** Data transfer interface operations */
19 struct xfer_interface_operations {
20         /** Close interface
21          *
22          * @v xfer              Data transfer interface
23          * @v rc                Reason for close
24          */
25         void ( * close ) ( struct xfer_interface *xfer, int rc );
26         /** Redirect to new location
27          *
28          * @v xfer              Data transfer interface
29          * @v type              New location type
30          * @v args              Remaining arguments depend upon location type
31          * @ret rc              Return status code
32          */
33         int ( * vredirect ) ( struct xfer_interface *xfer, int type,
34                               va_list args );
35         /** Seek to position
36          *
37          * @v xfer              Data transfer interface
38          * @v offset            Offset to new position
39          * @v whence            Basis for new position
40          * @ret rc              Return status code
41          *
42          * @c whence must be one of @c SEEK_SET or @c SEEK_CUR.  A
43          * successful return indicates that the interface is ready to
44          * immediately accept datagrams; return -EAGAIN if this is not
45          * the case.
46          */
47         int ( * seek ) ( struct xfer_interface *xfer, off_t offset,
48                          int whence );
49         /** Allocate I/O buffer
50          *
51          * @v xfer              Data transfer interface
52          * @v len               I/O buffer payload length
53          * @ret iobuf           I/O buffer
54          */
55         struct io_buffer * ( * alloc_iob ) ( struct xfer_interface *xfer,
56                                              size_t len );
57         /** Deliver datagram as I/O buffer with metadata
58          *
59          * @v xfer              Data transfer interface
60          * @v iobuf             Datagram I/O buffer
61          * @v meta              Data transfer metadata, or NULL
62          * @ret rc              Return status code
63          *
64          * A data transfer interface that wishes to support only raw
65          * data delivery should set this method to
66          * xfer_deliver_as_raw().
67          *
68          * Interfaces may not temporarily refuse to accept data by
69          * returning -EAGAIN; such a response may be treated as a
70          * fatal error.
71          */
72         int ( * deliver_iob ) ( struct xfer_interface *xfer,
73                                 struct io_buffer *iobuf,
74                                 struct xfer_metadata *meta );
75         /** Deliver datagram as raw data
76          *
77          * @v xfer              Data transfer interface
78          * @v data              Data buffer
79          * @v len               Length of data buffer
80          * @ret rc              Return status code
81          *
82          * A data transfer interface that wishes to support only I/O
83          * buffer delivery should set this method to
84          * xfer_deliver_as_iob().
85          *
86          * Interfaces may not temporarily refuse to accept data by
87          * returning -EAGAIN; such a response may be treated as a
88          * fatal error.
89          */
90         int ( * deliver_raw ) ( struct xfer_interface *xfer,
91                                 const void *data, size_t len );
92 };
93
94 /** A data transfer interface */
95 struct xfer_interface {
96         /** Generic object communication interface */
97         struct interface intf;
98         /** Operations for received messages */
99         struct xfer_interface_operations *op;
100 };
101
102 /** Data transfer metadata */
103 struct xfer_metadata {
104         /** Source socket address, or NULL */
105         struct sockaddr *src;
106         /** Destination socket address, or NULL */
107         struct sockaddr *dest;
108         /** Network device, or NULL */
109         struct net_device *netdev;
110 };
111
112 /** Basis positions for seek() events */
113 enum seek_whence {
114         SEEK_SET = 0,
115         SEEK_CUR,
116 };
117
118 /**
119  * Describe seek basis
120  *
121  * @v whence            Basis for new position
122  */
123 static inline __attribute__ (( always_inline )) const char *
124 whence_text ( int whence ) {
125         switch ( whence ) {
126         case SEEK_SET:  return "SET";
127         case SEEK_CUR:  return "CUR";
128         default:        return "INVALID";
129         }
130 }
131
132 extern struct xfer_interface null_xfer;
133 extern struct xfer_interface_operations null_xfer_ops;
134
135 extern void xfer_close ( struct xfer_interface *xfer, int rc );
136 extern int xfer_vredirect ( struct xfer_interface *xfer, int type,
137                             va_list args );
138 extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... );
139 extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence );
140 extern int xfer_ready ( struct xfer_interface *xfer );
141 extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer,
142                                            size_t len );
143 extern int xfer_deliver_iob ( struct xfer_interface *xfer,
144                               struct io_buffer *iobuf );
145 extern int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
146                                    struct io_buffer *iobuf,
147                                    struct xfer_metadata *meta );
148 extern int xfer_deliver_raw ( struct xfer_interface *xfer,
149                               const void *data, size_t len );
150 extern int xfer_vprintf ( struct xfer_interface *xfer,
151                           const char *format, va_list args );
152 extern int xfer_printf ( struct xfer_interface *xfer,
153                          const char *format, ... );
154
155 extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc );
156 extern int ignore_xfer_vredirect ( struct xfer_interface *xfer,
157                                    int type, va_list args );
158 extern int ignore_xfer_seek ( struct xfer_interface *xfer, off_t offset,
159                               int whence );
160 extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer,
161                                                    size_t len );
162 extern int xfer_deliver_as_raw ( struct xfer_interface *xfer,
163                                  struct io_buffer *iobuf,
164                                  struct xfer_metadata *meta );
165 extern int xfer_deliver_as_iob ( struct xfer_interface *xfer,
166                                  const void *data, size_t len );
167 extern int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
168                                      const void *data __unused, size_t len );
169
170 /**
171  * Initialise a data transfer interface
172  *
173  * @v xfer              Data transfer interface
174  * @v op                Data transfer interface operations
175  * @v refcnt            Containing object reference counter, or NULL
176  */
177 static inline void xfer_init ( struct xfer_interface *xfer,
178                                struct xfer_interface_operations *op,
179                                struct refcnt *refcnt ) {
180         xfer->intf.dest = &null_xfer.intf;
181         xfer->intf.refcnt = refcnt;
182         xfer->op = op;
183 }
184
185 /**
186  * Get data transfer interface from generic object communication interface
187  *
188  * @v intf              Generic object communication interface
189  * @ret xfer            Data transfer interface
190  */
191 static inline __attribute__ (( always_inline )) struct xfer_interface *
192 intf_to_xfer ( struct interface *intf ) {
193         return container_of ( intf, struct xfer_interface, intf );
194 }
195
196 /**
197  * Get reference to destination data transfer interface
198  *
199  * @v xfer              Data transfer interface
200  * @ret dest            Destination interface
201  */
202 static inline __attribute__ (( always_inline )) struct xfer_interface *
203 xfer_get_dest ( struct xfer_interface *xfer ) {
204         return intf_to_xfer ( intf_get ( xfer->intf.dest ) );
205 }
206
207 /**
208  * Drop reference to data transfer interface
209  *
210  * @v xfer              Data transfer interface
211  */
212 static inline __attribute__ (( always_inline )) void
213 xfer_put ( struct xfer_interface *xfer ) {
214         intf_put ( &xfer->intf );
215 }
216
217 /**
218  * Plug a data transfer interface into a new destination interface
219  *
220  * @v xfer              Data transfer interface
221  * @v dest              New destination interface
222  */
223 static inline __attribute__ (( always_inline )) void
224 xfer_plug ( struct xfer_interface *xfer, struct xfer_interface *dest ) {
225         plug ( &xfer->intf, &dest->intf );
226 }
227
228 /**
229  * Plug two data transfer interfaces together
230  *
231  * @v a                 Data transfer interface A
232  * @v b                 Data transfer interface B
233  */
234 static inline __attribute__ (( always_inline )) void
235 xfer_plug_plug ( struct xfer_interface *a, struct xfer_interface *b ) {
236         plug_plug ( &a->intf, &b->intf );
237 }
238
239 /**
240  * Unplug a data transfer interface
241  *
242  * @v xfer              Data transfer interface
243  */
244 static inline __attribute__ (( always_inline )) void
245 xfer_unplug ( struct xfer_interface *xfer ) {
246         plug ( &xfer->intf, &null_xfer.intf );
247 }
248
249 /**
250  * Stop using a data transfer interface
251  *
252  * @v xfer              Data transfer interface
253  *
254  * After calling this method, no further messages will be received via
255  * the interface.
256  */
257 static inline void xfer_nullify ( struct xfer_interface *xfer ) {
258         xfer->op = &null_xfer_ops;
259 };
260
261 #endif /* _GPXE_XFER_H */