• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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