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