Merge branch 'master' into mcb-tcp-xfer
[people/holger/gpxe.git] / src / core / xfer.c
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 #include <string.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <gpxe/xfer.h>
23
24 /** @file
25  *
26  * Data transfer interfaces
27  *
28  */
29
30 /**
31  * Close data transfer interface
32  *
33  * @v xfer              Data transfer interface
34  * @v rc                Reason for close
35  */
36 void xfer_close ( struct xfer_interface *xfer, int rc ) {
37         struct xfer_interface *dest = xfer_get_dest ( xfer );
38
39         DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
40
41         dest->op->close ( dest, rc );
42         xfer_unplug ( xfer );
43         xfer_put ( dest );
44 }
45
46 /**
47  * Send redirection event
48  *
49  * @v xfer              Data transfer interface
50  * @v type              New location type
51  * @v args              Remaining arguments depend upon location type
52  * @ret rc              Return status code
53  */
54 int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
55         struct xfer_interface *dest = xfer_get_dest ( xfer );
56         int rc;
57
58         DBGC ( xfer, "XFER %p->%p redirect\n", xfer, dest );
59
60         rc = dest->op->vredirect ( dest, type, args );
61
62         if ( rc != 0 ) {
63                 DBGC ( xfer, "XFER %p<-%p redirect: %s\n", xfer, dest,
64                        strerror ( rc ) );
65         }
66         xfer_put ( dest );
67         return rc;
68 }
69
70 /**
71  * Send redirection event
72  *
73  * @v xfer              Data transfer interface
74  * @v type              New location type
75  * @v ...               Remaining arguments depend upon location type
76  * @ret rc              Return status code
77  */
78 int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
79         va_list args;
80         int rc;
81
82         va_start ( args, type );
83         rc = xfer_vredirect ( xfer, type, args );
84         va_end ( args );
85         return rc;
86 }
87
88 /**
89  * Request data
90  *
91  * @v xfer              Data transfer interface
92  * @v offset            Offset to new position
93  * @v whence            Basis for new position
94  * @v len               Length of requested data
95  * @ret rc              Return status code
96  */
97 int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
98                    size_t len ) {
99         struct xfer_interface *dest = xfer_get_dest ( xfer );
100         int rc;
101
102         DBGC ( xfer, "XFER %p->%p request %s+%ld %zd\n", xfer, dest,
103                whence_text ( whence ), offset, len );
104
105         rc = dest->op->request ( dest, offset, whence, len );
106
107         if ( rc != 0 ) {
108                 DBGC ( xfer, "XFER %p<-%p request: %s\n", xfer, dest,
109                        strerror ( rc ) );
110         }
111         xfer_put ( dest );
112         return rc;
113 }
114
115 /**
116  * Seek to position
117  *
118  * @v xfer              Data transfer interface
119  * @v offset            Offset to new position
120  * @v whence            Basis for new position
121  * @ret rc              Return status code
122  */
123 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
124         struct xfer_interface *dest = xfer_get_dest ( xfer );
125         int rc;
126
127         DBGC ( xfer, "XFER %p->%p seek %s+%ld\n", xfer, dest,
128                whence_text ( whence ), offset );
129
130         rc = dest->op->seek ( dest, offset, whence );
131
132         if ( rc != 0 ) {
133                 DBGC ( xfer, "XFER %p<-%p seek: %s\n", xfer, dest,
134                        strerror ( rc ) );
135         }
136         xfer_put ( dest );
137         return rc;
138 }
139
140 /**
141  * Test to see if interface is ready to accept data
142  *
143  * @v xfer              Data transfer interface
144  * @ret rc              Return status code
145  *
146  * This test is optional; the data transfer interface may wish that it
147  * does not yet wish to accept data, but cannot prevent attempts to
148  * deliver data to it.
149  */
150 int xfer_ready ( struct xfer_interface *xfer ) {
151         return xfer_seek ( xfer, 0, SEEK_CUR );
152 }
153
154 /**
155  * Allocate I/O buffer
156  *
157  * @v xfer              Data transfer interface
158  * @v len               I/O buffer payload length
159  * @ret iobuf           I/O buffer
160  */
161 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
162         struct xfer_interface *dest = xfer_get_dest ( xfer );
163         struct io_buffer *iobuf;
164
165         DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len );
166
167         iobuf = dest->op->alloc_iob ( dest, len );
168
169         if ( ! iobuf ) {
170                 DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest );
171         }
172         xfer_put ( dest );
173         return iobuf;
174 }
175
176 /**
177  * Deliver datagram
178  *
179  * @v xfer              Data transfer interface
180  * @v iobuf             Datagram I/O buffer
181  * @ret rc              Return status code
182  */
183 int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
184         struct xfer_interface *dest = xfer_get_dest ( xfer );
185         int rc;
186
187         DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest,
188                iob_len ( iobuf ) );
189
190         rc = dest->op->deliver_iob ( dest, iobuf );
191
192         if ( rc != 0 ) {
193                 DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest,
194                        strerror ( rc ) );
195         }
196         xfer_put ( dest );
197         return rc;
198 }
199
200 /**
201  * Deliver datagram as raw data
202  *
203  * @v xfer              Data transfer interface
204  * @v iobuf             Datagram I/O buffer
205  * @ret rc              Return status code
206  */
207 int xfer_deliver_raw ( struct xfer_interface *xfer,
208                        const void *data, size_t len ) {
209         struct xfer_interface *dest = xfer_get_dest ( xfer );
210         int rc;
211
212         DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest,
213                data, len );
214
215         rc = dest->op->deliver_raw ( dest, data, len );
216
217         if ( rc != 0 ) {
218                 DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest,
219                        strerror ( rc ) );
220         }
221         xfer_put ( dest );
222         return rc;
223 }
224
225 /**
226  * Deliver formatted string
227  *
228  * @v xfer              Data transfer interface
229  * @v format            Format string
230  * @v args              Arguments corresponding to the format string
231  * @ret rc              Return status code
232  */
233 int xfer_vprintf ( struct xfer_interface *xfer, const char *format,
234                    va_list args ) {
235         size_t len;
236         va_list args_tmp;
237
238         va_copy ( args_tmp, args );
239         len = vsnprintf ( NULL, 0, format, args );
240         {
241                 char buf[len + 1];
242                 vsnprintf ( buf, sizeof ( buf ), format, args_tmp );
243                 va_end ( args_tmp );
244                 return xfer_deliver_raw ( xfer, buf, len );
245         }
246 }
247
248 /**
249  * Deliver formatted string
250  *
251  * @v xfer              Data transfer interface
252  * @v format            Format string
253  * @v ...               Arguments corresponding to the format string
254  * @ret rc              Return status code
255  */
256 int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) {
257         va_list args;
258         int rc;
259
260         va_start ( args, format );
261         rc = xfer_vprintf ( xfer, format, args );
262         va_end ( args );
263         return rc;
264 }
265
266 /****************************************************************************
267  *
268  * Helper methods
269  *
270  * These functions are designed to be used as methods in the
271  * xfer_interface_operations table.
272  *
273  */
274
275 /**
276  * Ignore close() event
277  *
278  * @v xfer              Data transfer interface
279  * @v rc                Reason for close
280  */
281 void ignore_xfer_close ( struct xfer_interface *xfer __unused,
282                          int rc __unused ) {
283         /* Nothing to do */
284 }
285
286 /**
287  * Ignore vredirect() event
288  *
289  * @v xfer              Data transfer interface
290  * @v type              New location type
291  * @v args              Remaining arguments depend upon location type
292  * @ret rc              Return status code
293  */
294 int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
295                             int type __unused, va_list args __unused ) {
296         return 0;
297 }
298
299 /**
300  * Ignore request() event
301  *
302  * @v xfer              Data transfer interface
303  * @v offset            Offset to new position
304  * @v whence            Basis for new position
305  * @v len               Length of requested data
306  * @ret rc              Return status code
307  */
308 int ignore_xfer_request ( struct xfer_interface *xfer __unused,
309                           off_t offset __unused, int whence __unused, 
310                           size_t len __unused ) {
311         return 0;
312 }
313
314 /**
315  * Ignore seek() event
316  *
317  * @v xfer              Data transfer interface
318  * @v offset            Offset to new position
319  * @v whence            Basis for new position
320  * @ret rc              Return status code
321  */
322 int ignore_xfer_seek ( struct xfer_interface *xfer __unused,
323                        off_t offset __unused, int whence __unused ) {
324         return 0;
325 }
326
327 /**
328  * Allocate I/O buffer
329  *
330  * @v xfer              Data transfer interface
331  * @v len               I/O buffer payload length
332  * @ret iobuf           I/O buffer
333  */
334 struct io_buffer *
335 default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
336         return alloc_iob ( len );
337 }
338
339 /**
340  * Deliver datagram as raw data
341  *
342  * @v xfer              Data transfer interface
343  * @v iobuf             Datagram I/O buffer
344  * @ret rc              Return status code
345  *
346  * This function is intended to be used as the deliver() method for
347  * data transfer interfaces that prefer to handle raw data.
348  */
349 int xfer_deliver_as_raw ( struct xfer_interface *xfer,
350                           struct io_buffer *iobuf ) {
351         int rc;
352
353         rc = xfer->op->deliver_raw ( xfer, iobuf->data, iob_len ( iobuf ) );
354         free_iob ( iobuf );
355         return rc;
356 }
357
358 /**
359  * Deliver datagram as I/O buffer
360  *
361  * @v xfer              Data transfer interface
362  * @v data              Data buffer
363  * @v len               Length of data buffer
364  * @ret rc              Return status code
365  *
366  * This function is intended to be used as the deliver_raw() method
367  * for data transfer interfaces that prefer to handle I/O buffers.
368  */
369 int xfer_deliver_as_iob ( struct xfer_interface *xfer,
370                           const void *data, size_t len ) {
371         struct io_buffer *iobuf;
372
373         iobuf = xfer->op->alloc_iob ( xfer, len );
374         if ( ! iobuf )
375                 return -ENOMEM;
376
377         memcpy ( iob_put ( iobuf, len ), data, len );
378         return xfer->op->deliver_iob ( xfer, iobuf );
379 }
380
381 /**
382  * Ignore datagram as raw data event
383  *
384  * @v xfer              Data transfer interface
385  * @v data              Data buffer
386  * @v len               Length of data buffer
387  * @ret rc              Return status code
388  */
389 int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
390                               const void *data __unused, size_t len ) {
391         DBGC ( xfer, "XFER %p %zd bytes delivered %s\n", xfer, len,
392                ( ( xfer == &null_xfer ) ?
393                  "before connection" : "after termination" ) );
394         return 0;
395 }
396
397 /** Null data transfer interface operations */
398 struct xfer_interface_operations null_xfer_ops = {
399         .close          = ignore_xfer_close,
400         .vredirect      = ignore_xfer_vredirect,
401         .request        = ignore_xfer_request,
402         .seek           = ignore_xfer_seek,
403         .alloc_iob      = default_xfer_alloc_iob,
404         .deliver_iob    = xfer_deliver_as_raw,
405         .deliver_raw    = ignore_xfer_deliver_raw,
406 };
407
408 /**
409  * Null data transfer interface
410  *
411  * This is the interface to which data transfer interfaces are
412  * connected when unplugged.  It will never generate messages, and
413  * will silently absorb all received messages.
414  */
415 struct xfer_interface null_xfer = {
416         .intf = {
417                 .dest = &null_xfer.intf,
418                 .refcnt = NULL,
419         },
420         .op = &null_xfer_ops,
421 };