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