Remove xfer_ready() (it has been replaced by xfer_window())
[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  * Seek to position
90  *
91  * @v xfer              Data transfer interface
92  * @v offset            Offset to new position
93  * @v whence            Basis for new position
94  * @ret rc              Return status code
95  */
96 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
97         struct xfer_interface *dest = xfer_get_dest ( xfer );
98         int rc;
99
100         DBGC ( xfer, "XFER %p->%p seek %s+%ld\n", xfer, dest,
101                whence_text ( whence ), offset );
102
103         rc = dest->op->seek ( dest, offset, whence );
104
105         if ( rc != 0 ) {
106                 DBGC ( xfer, "XFER %p<-%p seek: %s\n", xfer, dest,
107                        strerror ( rc ) );
108         }
109         xfer_put ( dest );
110         return rc;
111 }
112
113 /**
114  * Check flow control window
115  *
116  * @v xfer              Data transfer interface
117  * @ret len             Length of window
118  */
119 size_t xfer_window ( struct xfer_interface *xfer ) {
120         struct xfer_interface *dest = xfer_get_dest ( xfer );
121         size_t len;
122
123         len = dest->op->window ( dest );
124
125         xfer_put ( dest );
126         return len;
127 }
128
129 /**
130  * Allocate I/O buffer
131  *
132  * @v xfer              Data transfer interface
133  * @v len               I/O buffer payload length
134  * @ret iobuf           I/O buffer
135  */
136 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
137         struct xfer_interface *dest = xfer_get_dest ( xfer );
138         struct io_buffer *iobuf;
139
140         DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len );
141
142         iobuf = dest->op->alloc_iob ( dest, len );
143
144         if ( ! iobuf ) {
145                 DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest );
146         }
147         xfer_put ( dest );
148         return iobuf;
149 }
150
151 /**
152  * Deliver datagram as I/O buffer with metadata
153  *
154  * @v xfer              Data transfer interface
155  * @v iobuf             Datagram I/O buffer
156  * @v meta              Data transfer metadata, or NULL
157  * @ret rc              Return status code
158  */
159 int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
160                             struct io_buffer *iobuf,
161                             struct xfer_metadata *meta ) {
162         struct xfer_interface *dest = xfer_get_dest ( xfer );
163         int rc;
164
165         DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest,
166                iob_len ( iobuf ) );
167
168         rc = dest->op->deliver_iob ( dest, iobuf, meta );
169
170         if ( rc != 0 ) {
171                 DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest,
172                        strerror ( rc ) );
173         }
174         xfer_put ( dest );
175         return rc;
176 }
177
178 /**
179  * Deliver datagram as I/O buffer with metadata
180  *
181  * @v xfer              Data transfer interface
182  * @v iobuf             Datagram I/O buffer
183  * @ret rc              Return status code
184  */
185 int xfer_deliver_iob ( struct xfer_interface *xfer,
186                        struct io_buffer *iobuf ) {
187         return xfer_deliver_iob_meta ( xfer, iobuf, NULL );
188 }
189
190 /**
191  * Deliver datagram as raw data
192  *
193  * @v xfer              Data transfer interface
194  * @v iobuf             Datagram I/O buffer
195  * @ret rc              Return status code
196  */
197 int xfer_deliver_raw ( struct xfer_interface *xfer,
198                        const void *data, size_t len ) {
199         struct xfer_interface *dest = xfer_get_dest ( xfer );
200         int rc;
201
202         DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest,
203                data, len );
204
205         rc = dest->op->deliver_raw ( dest, data, len );
206
207         if ( rc != 0 ) {
208                 DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest,
209                        strerror ( rc ) );
210         }
211         xfer_put ( dest );
212         return rc;
213 }
214
215 /**
216  * Deliver formatted string
217  *
218  * @v xfer              Data transfer interface
219  * @v format            Format string
220  * @v args              Arguments corresponding to the format string
221  * @ret rc              Return status code
222  */
223 int xfer_vprintf ( struct xfer_interface *xfer, const char *format,
224                    va_list args ) {
225         size_t len;
226         va_list args_tmp;
227
228         va_copy ( args_tmp, args );
229         len = vsnprintf ( NULL, 0, format, args );
230         {
231                 char buf[len + 1];
232                 vsnprintf ( buf, sizeof ( buf ), format, args_tmp );
233                 va_end ( args_tmp );
234                 return xfer_deliver_raw ( xfer, buf, len );
235         }
236 }
237
238 /**
239  * Deliver formatted string
240  *
241  * @v xfer              Data transfer interface
242  * @v format            Format string
243  * @v ...               Arguments corresponding to the format string
244  * @ret rc              Return status code
245  */
246 int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) {
247         va_list args;
248         int rc;
249
250         va_start ( args, format );
251         rc = xfer_vprintf ( xfer, format, args );
252         va_end ( args );
253         return rc;
254 }
255
256 /****************************************************************************
257  *
258  * Helper methods
259  *
260  * These functions are designed to be used as methods in the
261  * xfer_interface_operations table.
262  *
263  */
264
265 /**
266  * Ignore close() event
267  *
268  * @v xfer              Data transfer interface
269  * @v rc                Reason for close
270  */
271 void ignore_xfer_close ( struct xfer_interface *xfer __unused,
272                          int rc __unused ) {
273         /* Nothing to do */
274 }
275
276 /**
277  * Ignore vredirect() event
278  *
279  * @v xfer              Data transfer interface
280  * @v type              New location type
281  * @v args              Remaining arguments depend upon location type
282  * @ret rc              Return status code
283  */
284 int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
285                             int type __unused, va_list args __unused ) {
286         return 0;
287 }
288
289 /**
290  * Ignore seek() event
291  *
292  * @v xfer              Data transfer interface
293  * @v offset            Offset to new position
294  * @v whence            Basis for new position
295  * @ret rc              Return status code
296  */
297 int ignore_xfer_seek ( struct xfer_interface *xfer __unused,
298                        off_t offset __unused, int whence __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  */
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  */
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 *
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  */
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  */
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, NULL );
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  */
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         .seek           = ignore_xfer_seek,
405         .window         = unlimited_xfer_window,
406         .alloc_iob      = default_xfer_alloc_iob,
407         .deliver_iob    = xfer_deliver_as_raw,
408         .deliver_raw    = ignore_xfer_deliver_raw,
409 };
410
411 /**
412  * Null data transfer interface
413  *
414  * This is the interface to which data transfer interfaces are
415  * connected when unplugged.  It will never generate messages, and
416  * will silently absorb all received messages.
417  */
418 struct xfer_interface null_xfer = {
419         .intf = {
420                 .dest = &null_xfer.intf,
421                 .refcnt = NULL,
422         },
423         .op = &null_xfer_ops,
424 };