c75fa002855e6a97d2f8f91c430f50ce50a74177
[people/balajirrao/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         /** Check flow control window
36          *
37          * @v xfer              Data transfer interface
38          * @ret len             Length of window
39          *
40          * Flow control is regarded as advisory but not mandatory.
41          * Users who have control over their own rate of data
42          * generation should perform a flow control check before
43          * generating new data.  Users who have no control (such as
44          * NIC drivers or filter layers) are not obliged to check.
45          *
46          * Data transfer interfaces must be prepared to accept
47          * datagrams even if they are advertising a window of zero
48          * bytes.
49          */
50         size_t ( * window ) ( struct xfer_interface *xfer );
51         /** Allocate I/O buffer
52          *
53          * @v xfer              Data transfer interface
54          * @v len               I/O buffer payload length
55          * @ret iobuf           I/O buffer
56          */
57         struct io_buffer * ( * alloc_iob ) ( struct xfer_interface *xfer,
58                                              size_t len );
59         /** Deliver datagram as I/O buffer with metadata
60          *
61          * @v xfer              Data transfer interface
62          * @v iobuf             Datagram I/O buffer
63          * @v meta              Data transfer metadata
64          * @ret rc              Return status code
65          *
66          * A data transfer interface that wishes to support only raw
67          * data delivery should set this method to
68          * xfer_deliver_as_raw().
69          */
70         int ( * deliver_iob ) ( struct xfer_interface *xfer,
71                                 struct io_buffer *iobuf,
72                                 struct xfer_metadata *meta );
73         /** Deliver datagram as raw data
74          *
75          * @v xfer              Data transfer interface
76          * @v data              Data buffer
77          * @v len               Length of data buffer
78          * @ret rc              Return status code
79          *
80          * A data transfer interface that wishes to support only I/O
81          * buffer delivery should set this method to
82          * xfer_deliver_as_iob().
83          */
84         int ( * deliver_raw ) ( struct xfer_interface *xfer,
85                                 const void *data, size_t len );
86 };
87
88 /** A data transfer interface */
89 struct xfer_interface {
90         /** Generic object communication interface */
91         struct interface intf;
92         /** Operations for received messages */
93         struct xfer_interface_operations *op;
94 };
95
96 /** Basis positions for seek() events */
97 enum seek_whence {
98         SEEK_CUR = 0,
99         SEEK_SET,
100 };
101
102 /** Data transfer metadata */
103 struct xfer_metadata {
104         /** Position of data within stream */
105         off_t offset;
106         /** Basis for data position
107          *
108          * Must be one of @c SEEK_CUR or @c SEEK_SET.
109          */
110         int whence;
111         /** Source socket address, or NULL */
112         struct sockaddr *src;
113         /** Destination socket address, or NULL */
114         struct sockaddr *dest;
115         /** Network device, or NULL */
116         struct net_device *netdev;
117 };
118
119 /**
120  * Describe seek basis
121  *
122  * @v whence            Basis for new position
123  */
124 static inline __attribute__ (( always_inline )) const char *
125 whence_text ( int whence ) {
126         switch ( whence ) {
127         case SEEK_CUR:  return "CUR";
128         case SEEK_SET:  return "SET";
129         default:        return "INVALID";
130         }
131 }
132
133 extern struct xfer_interface null_xfer;
134 extern struct xfer_interface_operations null_xfer_ops;
135
136 extern void xfer_close ( struct xfer_interface *xfer, int rc );
137 extern int xfer_vredirect ( struct xfer_interface *xfer, int type,
138                             va_list args );
139 extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... );
140 extern size_t xfer_window ( 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 extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence );
155
156 extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc );
157 extern int ignore_xfer_vredirect ( struct xfer_interface *xfer,
158                                    int type, va_list args );
159 extern size_t unlimited_xfer_window ( struct xfer_interface *xfer );
160 extern size_t no_xfer_window ( struct xfer_interface *xfer );
161 extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer,
162                                                    size_t len );
163 extern int xfer_deliver_as_raw ( struct xfer_interface *xfer,
164                                  struct io_buffer *iobuf,
165                                  struct xfer_metadata *meta );
166 extern int xfer_deliver_as_iob ( struct xfer_interface *xfer,
167                                  const void *data, size_t len );
168 extern int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
169                                      const void *data __unused, size_t len );
170
171 /**
172  * Initialise a data transfer interface
173  *
174  * @v xfer              Data transfer interface
175  * @v op                Data transfer interface operations
176  * @v refcnt            Containing object reference counter, or NULL
177  */
178 static inline void xfer_init ( struct xfer_interface *xfer,
179                                struct xfer_interface_operations *op,
180                                struct refcnt *refcnt ) {
181         xfer->intf.dest = &null_xfer.intf;
182         xfer->intf.refcnt = refcnt;
183         xfer->op = op;
184 }
185
186 /**
187  * Get data transfer interface from generic object communication interface
188  *
189  * @v intf              Generic object communication interface
190  * @ret xfer            Data transfer interface
191  */
192 static inline __attribute__ (( always_inline )) struct xfer_interface *
193 intf_to_xfer ( struct interface *intf ) {
194         return container_of ( intf, struct xfer_interface, intf );
195 }
196
197 /**
198  * Get reference to destination data transfer interface
199  *
200  * @v xfer              Data transfer interface
201  * @ret dest            Destination interface
202  */
203 static inline __attribute__ (( always_inline )) struct xfer_interface *
204 xfer_get_dest ( struct xfer_interface *xfer ) {
205         return intf_to_xfer ( intf_get ( xfer->intf.dest ) );
206 }
207
208 /**
209  * Drop reference to data transfer interface
210  *
211  * @v xfer              Data transfer interface
212  */
213 static inline __attribute__ (( always_inline )) void
214 xfer_put ( struct xfer_interface *xfer ) {
215         intf_put ( &xfer->intf );
216 }
217
218 /**
219  * Plug a data transfer interface into a new destination interface
220  *
221  * @v xfer              Data transfer interface
222  * @v dest              New destination interface
223  */
224 static inline __attribute__ (( always_inline )) void
225 xfer_plug ( struct xfer_interface *xfer, struct xfer_interface *dest ) {
226         plug ( &xfer->intf, &dest->intf );
227 }
228
229 /**
230  * Plug two data transfer interfaces together
231  *
232  * @v a                 Data transfer interface A
233  * @v b                 Data transfer interface B
234  */
235 static inline __attribute__ (( always_inline )) void
236 xfer_plug_plug ( struct xfer_interface *a, struct xfer_interface *b ) {
237         plug_plug ( &a->intf, &b->intf );
238 }
239
240 /**
241  * Unplug a data transfer interface
242  *
243  * @v xfer              Data transfer interface
244  */
245 static inline __attribute__ (( always_inline )) void
246 xfer_unplug ( struct xfer_interface *xfer ) {
247         plug ( &xfer->intf, &null_xfer.intf );
248 }
249
250 /**
251  * Stop using a data transfer interface
252  *
253  * @v xfer              Data transfer interface
254  *
255  * After calling this method, no further messages will be received via
256  * the interface.
257  */
258 static inline void xfer_nullify ( struct xfer_interface *xfer ) {
259         xfer->op = &null_xfer_ops;
260 };
261
262 #endif /* _GPXE_XFER_H */