• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 FILE_LICENCE ( GPL2_OR_LATER );
20 
21 #include <string.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include <gpxe/xfer.h>
25 
26 /** @file
27  *
28  * Data transfer interfaces
29  *
30  */
31 
32 /**
33  * Dummy transfer metadata
34  *
35  * This gets passed to xfer_interface::deliver_iob() and equivalents
36  * when no metadata is available.
37  */
38 static struct xfer_metadata dummy_metadata;
39 
40 /**
41  * Close data transfer interface
42  *
43  * @v xfer		Data transfer interface
44  * @v rc		Reason for close
45  */
xfer_close(struct xfer_interface * xfer,int rc)46 void xfer_close ( struct xfer_interface *xfer, int rc ) {
47 	struct xfer_interface *dest = xfer_get_dest ( xfer );
48 	struct xfer_interface_operations *op = xfer->op;
49 
50 	DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
51 
52 	xfer_unplug ( xfer );
53 	xfer_nullify ( xfer );
54 	dest->op->close ( dest, rc );
55 	xfer->op = op;
56 	xfer_put ( dest );
57 }
58 
59 /**
60  * Send redirection event
61  *
62  * @v xfer		Data transfer interface
63  * @v type		New location type
64  * @v args		Remaining arguments depend upon location type
65  * @ret rc		Return status code
66  */
xfer_vredirect(struct xfer_interface * xfer,int type,va_list args)67 int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
68 	struct xfer_interface *dest = xfer_get_dest ( xfer );
69 	int rc;
70 
71 	DBGC ( xfer, "XFER %p->%p redirect\n", xfer, dest );
72 
73 	rc = dest->op->vredirect ( dest, type, args );
74 
75 	if ( rc != 0 ) {
76 		DBGC ( xfer, "XFER %p<-%p redirect: %s\n", xfer, dest,
77 		       strerror ( rc ) );
78 	}
79 	xfer_put ( dest );
80 	return rc;
81 }
82 
83 /**
84  * Send redirection event
85  *
86  * @v xfer		Data transfer interface
87  * @v type		New location type
88  * @v ...		Remaining arguments depend upon location type
89  * @ret rc		Return status code
90  */
xfer_redirect(struct xfer_interface * xfer,int type,...)91 int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
92 	va_list args;
93 	int rc;
94 
95 	va_start ( args, type );
96 	rc = xfer_vredirect ( xfer, type, args );
97 	va_end ( args );
98 	return rc;
99 }
100 
101 /**
102  * Check flow control window
103  *
104  * @v xfer		Data transfer interface
105  * @ret len		Length of window
106  */
xfer_window(struct xfer_interface * xfer)107 size_t xfer_window ( struct xfer_interface *xfer ) {
108 	struct xfer_interface *dest = xfer_get_dest ( xfer );
109 	size_t len;
110 
111 	len = dest->op->window ( dest );
112 
113 	xfer_put ( dest );
114 	return len;
115 }
116 
117 /**
118  * Allocate I/O buffer
119  *
120  * @v xfer		Data transfer interface
121  * @v len		I/O buffer payload length
122  * @ret iobuf		I/O buffer
123  */
xfer_alloc_iob(struct xfer_interface * xfer,size_t len)124 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
125 	struct xfer_interface *dest = xfer_get_dest ( xfer );
126 	struct io_buffer *iobuf;
127 
128 	DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len );
129 
130 	iobuf = dest->op->alloc_iob ( dest, len );
131 
132 	if ( ! iobuf ) {
133 		DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest );
134 	}
135 	xfer_put ( dest );
136 	return iobuf;
137 }
138 
139 /**
140  * Deliver datagram as I/O buffer with metadata
141  *
142  * @v xfer		Data transfer interface
143  * @v iobuf		Datagram I/O buffer
144  * @v meta		Data transfer metadata
145  * @ret rc		Return status code
146  */
xfer_deliver_iob_meta(struct xfer_interface * xfer,struct io_buffer * iobuf,struct xfer_metadata * meta)147 int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
148 			    struct io_buffer *iobuf,
149 			    struct xfer_metadata *meta ) {
150 	struct xfer_interface *dest = xfer_get_dest ( xfer );
151 	int rc;
152 
153 	DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest,
154 	       iob_len ( iobuf ) );
155 
156 	rc = dest->op->deliver_iob ( dest, iobuf, meta );
157 
158 	if ( rc != 0 ) {
159 		DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest,
160 		       strerror ( rc ) );
161 	}
162 	xfer_put ( dest );
163 	return rc;
164 }
165 
166 /**
167  * Deliver datagram as I/O buffer with metadata
168  *
169  * @v xfer		Data transfer interface
170  * @v iobuf		Datagram I/O buffer
171  * @ret rc		Return status code
172  */
xfer_deliver_iob(struct xfer_interface * xfer,struct io_buffer * iobuf)173 int xfer_deliver_iob ( struct xfer_interface *xfer,
174 		       struct io_buffer *iobuf ) {
175 	return xfer_deliver_iob_meta ( xfer, iobuf, &dummy_metadata );
176 }
177 
178 /**
179  * Deliver datagram as raw data
180  *
181  * @v xfer		Data transfer interface
182  * @v iobuf		Datagram I/O buffer
183  * @ret rc		Return status code
184  */
xfer_deliver_raw(struct xfer_interface * xfer,const void * data,size_t len)185 int xfer_deliver_raw ( struct xfer_interface *xfer,
186 		       const void *data, size_t len ) {
187 	struct xfer_interface *dest = xfer_get_dest ( xfer );
188 	int rc;
189 
190 	DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest,
191 	       data, len );
192 
193 	rc = dest->op->deliver_raw ( dest, data, len );
194 
195 	if ( rc != 0 ) {
196 		DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest,
197 		       strerror ( rc ) );
198 	}
199 	xfer_put ( dest );
200 	return rc;
201 }
202 
203 /**
204  * Deliver formatted string
205  *
206  * @v xfer		Data transfer interface
207  * @v format		Format string
208  * @v args		Arguments corresponding to the format string
209  * @ret rc		Return status code
210  */
xfer_vprintf(struct xfer_interface * xfer,const char * format,va_list args)211 int xfer_vprintf ( struct xfer_interface *xfer, const char *format,
212 		   va_list args ) {
213 	size_t len;
214 	va_list args_tmp;
215 
216 	va_copy ( args_tmp, args );
217 	len = vsnprintf ( NULL, 0, format, args );
218 	{
219 		char buf[len + 1];
220 		vsnprintf ( buf, sizeof ( buf ), format, args_tmp );
221 		va_end ( args_tmp );
222 		return xfer_deliver_raw ( xfer, buf, len );
223 	}
224 }
225 
226 /**
227  * Deliver formatted string
228  *
229  * @v xfer		Data transfer interface
230  * @v format		Format string
231  * @v ...		Arguments corresponding to the format string
232  * @ret rc		Return status code
233  */
xfer_printf(struct xfer_interface * xfer,const char * format,...)234 int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) {
235 	va_list args;
236 	int rc;
237 
238 	va_start ( args, format );
239 	rc = xfer_vprintf ( xfer, format, args );
240 	va_end ( args );
241 	return rc;
242 }
243 
244 /**
245  * Seek to position
246  *
247  * @v xfer		Data transfer interface
248  * @v offset		Offset to new position
249  * @v whence		Basis for new position
250  * @ret rc		Return status code
251  */
xfer_seek(struct xfer_interface * xfer,off_t offset,int whence)252 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
253 	struct io_buffer *iobuf;
254 	struct xfer_metadata meta = {
255 		.offset = offset,
256 		.whence = whence,
257 	};
258 
259 	DBGC ( xfer, "XFER %p seek %s+%ld\n", xfer,
260 	       whence_text ( whence ), offset );
261 
262 	/* Allocate and send a zero-length data buffer */
263 	iobuf = xfer_alloc_iob ( xfer, 0 );
264 	if ( ! iobuf )
265 		return -ENOMEM;
266 	return xfer_deliver_iob_meta ( xfer, iobuf, &meta );
267 }
268 
269 /****************************************************************************
270  *
271  * Helper methods
272  *
273  * These functions are designed to be used as methods in the
274  * xfer_interface_operations table.
275  *
276  */
277 
278 /**
279  * Ignore close() event
280  *
281  * @v xfer		Data transfer interface
282  * @v rc		Reason for close
283  */
ignore_xfer_close(struct xfer_interface * xfer __unused,int rc __unused)284 void ignore_xfer_close ( struct xfer_interface *xfer __unused,
285 			 int rc __unused ) {
286 	/* Nothing to do */
287 }
288 
289 /**
290  * Ignore vredirect() event
291  *
292  * @v xfer		Data transfer interface
293  * @v type		New location type
294  * @v args		Remaining arguments depend upon location type
295  * @ret rc		Return status code
296  */
ignore_xfer_vredirect(struct xfer_interface * xfer __unused,int type __unused,va_list args __unused)297 int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
298 			    int type __unused, va_list args __unused ) {
299 	return 0;
300 }
301 
302 /**
303  * Unlimited flow control window
304  *
305  * @v xfer		Data transfer interface
306  * @ret len		Length of window
307  *
308  * This handler indicates that the interface is always ready to accept
309  * data.
310  */
unlimited_xfer_window(struct xfer_interface * xfer __unused)311 size_t unlimited_xfer_window ( struct xfer_interface *xfer __unused ) {
312 	return ~( ( size_t ) 0 );
313 }
314 
315 /**
316  * No flow control window
317  *
318  * @v xfer		Data transfer interface
319  * @ret len		Length of window
320  *
321  * This handler indicates that the interface is never ready to accept
322  * data.
323  */
no_xfer_window(struct xfer_interface * xfer __unused)324 size_t no_xfer_window ( struct xfer_interface *xfer __unused ) {
325 	return 0;
326 }
327 
328 /**
329  * Allocate I/O buffer
330  *
331  * @v xfer		Data transfer interface
332  * @v len		I/O buffer payload length
333  * @ret iobuf		I/O buffer
334  */
335 struct io_buffer *
default_xfer_alloc_iob(struct xfer_interface * xfer __unused,size_t len)336 default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
337 	return alloc_iob ( len );
338 }
339 
340 /**
341  * Deliver datagram as raw data
342  *
343  * @v xfer		Data transfer interface
344  * @v iobuf		Datagram I/O buffer
345  * @v meta		Data transfer metadata
346  * @ret rc		Return status code
347  *
348  * This function is intended to be used as the deliver() method for
349  * data transfer interfaces that prefer to handle raw data.
350  */
xfer_deliver_as_raw(struct xfer_interface * xfer,struct io_buffer * iobuf,struct xfer_metadata * meta __unused)351 int xfer_deliver_as_raw ( struct xfer_interface *xfer,
352 			  struct io_buffer *iobuf,
353 			  struct xfer_metadata *meta __unused ) {
354 	int rc;
355 
356 	rc = xfer->op->deliver_raw ( xfer, iobuf->data, iob_len ( iobuf ) );
357 	free_iob ( iobuf );
358 	return rc;
359 }
360 
361 /**
362  * Deliver datagram as I/O buffer
363  *
364  * @v xfer		Data transfer interface
365  * @v data		Data buffer
366  * @v len		Length of data buffer
367  * @ret rc		Return status code
368  *
369  * This function is intended to be used as the deliver_raw() method
370  * for data transfer interfaces that prefer to handle I/O buffers.
371  */
xfer_deliver_as_iob(struct xfer_interface * xfer,const void * data,size_t len)372 int xfer_deliver_as_iob ( struct xfer_interface *xfer,
373 			  const void *data, size_t len ) {
374 	struct io_buffer *iobuf;
375 
376 	iobuf = xfer->op->alloc_iob ( xfer, len );
377 	if ( ! iobuf )
378 		return -ENOMEM;
379 
380 	memcpy ( iob_put ( iobuf, len ), data, len );
381 	return xfer->op->deliver_iob ( xfer, iobuf, &dummy_metadata );
382 }
383 
384 /**
385  * Ignore datagram as raw data event
386  *
387  * @v xfer		Data transfer interface
388  * @v data		Data buffer
389  * @v len		Length of data buffer
390  * @ret rc		Return status code
391  */
ignore_xfer_deliver_raw(struct xfer_interface * xfer,const void * data __unused,size_t len)392 int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
393 			      const void *data __unused, size_t len ) {
394 	DBGC ( xfer, "XFER %p %zd bytes delivered %s\n", xfer, len,
395 	       ( ( xfer == &null_xfer ) ?
396 		 "before connection" : "after termination" ) );
397 	return 0;
398 }
399 
400 /** Null data transfer interface operations */
401 struct xfer_interface_operations null_xfer_ops = {
402 	.close		= ignore_xfer_close,
403 	.vredirect	= ignore_xfer_vredirect,
404 	.window		= unlimited_xfer_window,
405 	.alloc_iob	= default_xfer_alloc_iob,
406 	.deliver_iob	= xfer_deliver_as_raw,
407 	.deliver_raw	= ignore_xfer_deliver_raw,
408 };
409 
410 /**
411  * Null data transfer interface
412  *
413  * This is the interface to which data transfer interfaces are
414  * connected when unplugged.  It will never generate messages, and
415  * will silently absorb all received messages.
416  */
417 struct xfer_interface null_xfer = XFER_INIT ( &null_xfer_ops );
418