Do not hold self-references. This then avoids the problem of having to
[people/dverkamp/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 <errno.h>
21 #include <gpxe/xfer.h>
22
23 /** @file
24  *
25  * Data transfer interfaces
26  *
27  */
28
29 /**
30  * Close data transfer interface
31  *
32  * @v xfer              Data transfer interface
33  * @v rc                Reason for close
34  */
35 void xfer_close ( struct xfer_interface *xfer, int rc ) {
36         struct xfer_interface *dest = xfer_get_dest ( xfer );
37
38         dest->op->close ( dest, rc );
39         xfer_unplug ( xfer );
40         xfer_put ( dest );
41 }
42
43 /**
44  * Send redirection event
45  *
46  * @v xfer              Data transfer interface
47  * @v type              New location type
48  * @v args              Remaining arguments depend upon location type
49  * @ret rc              Return status code
50  */
51 int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
52         struct xfer_interface *dest = xfer_get_dest ( xfer );
53         int rc;
54
55         rc = dest->op->vredirect ( dest, type, args );
56         xfer_put ( dest );
57         return rc;
58 }
59
60 /**
61  * Send redirection event
62  *
63  * @v xfer              Data transfer interface
64  * @v type              New location type
65  * @v ...               Remaining arguments depend upon location type
66  * @ret rc              Return status code
67  */
68 int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
69         va_list args;
70         int rc;
71
72         va_start ( args, type );
73         rc = xfer_vredirect ( xfer, type, args );
74         va_end ( args );
75         return rc;
76 }
77
78 /**
79  * Request data
80  *
81  * @v xfer              Data transfer interface
82  * @v offset            Offset to new position
83  * @v whence            Basis for new position
84  * @v len               Length of requested data
85  * @ret rc              Return status code
86  */
87 int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
88                    size_t len ) {
89         struct xfer_interface *dest = xfer_get_dest ( xfer );
90         int rc;
91
92         rc = dest->op->request ( dest, offset, whence, len );
93         xfer_put ( dest );
94         return rc;
95 }
96
97 /**
98  * Request all data
99  *
100  * @v xfer              Data transfer interface
101  * @ret rc              Return status code
102  */
103 int xfer_request_all ( struct xfer_interface *xfer ) {
104         return xfer_request ( xfer, 0, SEEK_SET, ~( ( size_t ) 0 ) );
105 }
106
107 /**
108  * Seek to position
109  *
110  * @v xfer              Data transfer interface
111  * @v offset            Offset to new position
112  * @v whence            Basis for new position
113  * @ret rc              Return status code
114  */
115 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
116         struct xfer_interface *dest = xfer_get_dest ( xfer );
117         int rc;
118
119         rc = dest->op->seek ( dest, offset, whence );
120         xfer_put ( dest );
121         return rc;
122 }
123
124 /**
125  * Allocate I/O buffer
126  *
127  * @v xfer              Data transfer interface
128  * @v len               I/O buffer payload length
129  * @ret iobuf           I/O buffer
130  */
131 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
132         struct xfer_interface *dest = xfer_get_dest ( xfer );
133         struct io_buffer *iobuf;
134
135         iobuf = dest->op->alloc_iob ( dest, len );
136         xfer_put ( dest );
137         return iobuf;
138 }
139
140 /**
141  * Deliver datagram
142  *
143  * @v xfer              Data transfer interface
144  * @v iobuf             Datagram I/O buffer
145  * @ret rc              Return status code
146  */
147 int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
148         struct xfer_interface *dest = xfer_get_dest ( xfer );
149         int rc;
150
151         rc = dest->op->deliver_iob ( dest, iobuf );
152         xfer_put ( dest );
153         return rc;
154 }
155
156 /**
157  * Deliver datagram as raw data
158  *
159  * @v xfer              Data transfer interface
160  * @v iobuf             Datagram I/O buffer
161  * @ret rc              Return status code
162  */
163 int xfer_deliver_raw ( struct xfer_interface *xfer,
164                        const void *data, size_t len ) {
165         struct xfer_interface *dest = xfer_get_dest ( xfer );
166         int rc;
167
168         rc = dest->op->deliver_raw ( dest, data, len );
169         xfer_put ( dest );
170         return rc;
171 }
172
173 /****************************************************************************
174  *
175  * Helper methods
176  *
177  * These functions are designed to be used as methods in the
178  * xfer_interface_operations table.
179  *
180  */
181
182 /**
183  * Ignore close() event
184  *
185  * @v xfer              Data transfer interface
186  * @v rc                Reason for close
187  */
188 void ignore_xfer_close ( struct xfer_interface *xfer __unused,
189                          int rc __unused ) {
190         /* Nothing to do */
191 }
192
193 /**
194  * Ignore vredirect() event
195  *
196  * @v xfer              Data transfer interface
197  * @v type              New location type
198  * @v args              Remaining arguments depend upon location type
199  * @ret rc              Return status code
200  */
201 int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
202                             int type __unused, va_list args __unused ) {
203         return 0;
204 }
205
206 /**
207  * Ignore request() event
208  *
209  * @v xfer              Data transfer interface
210  * @v offset            Offset to new position
211  * @v whence            Basis for new position
212  * @v len               Length of requested data
213  * @ret rc              Return status code
214  */
215 int ignore_xfer_request ( struct xfer_interface *xfer __unused,
216                           off_t offset __unused, int whence __unused, 
217                           size_t len __unused ) {
218         return 0;
219 }
220
221 /**
222  * Ignore seek() event
223  *
224  * @v xfer              Data transfer interface
225  * @v offset            Offset to new position
226  * @v whence            Basis for new position
227  * @ret rc              Return status code
228  */
229 int ignore_xfer_seek ( struct xfer_interface *xfer __unused,
230                        off_t offset __unused, int whence __unused ) {
231         return 0;
232 }
233
234 /**
235  * Allocate I/O buffer
236  *
237  * @v xfer              Data transfer interface
238  * @v len               I/O buffer payload length
239  * @ret iobuf           I/O buffer
240  */
241 struct io_buffer *
242 default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
243         return alloc_iob ( len );
244 }
245
246 /**
247  * Deliver datagram as raw data
248  *
249  * @v xfer              Data transfer interface
250  * @v iobuf             Datagram I/O buffer
251  * @ret rc              Return status code
252  *
253  * This function is intended to be used as the deliver() method for
254  * data transfer interfaces that prefer to handle raw data.
255  */
256 int xfer_deliver_as_raw ( struct xfer_interface *xfer,
257                           struct io_buffer *iobuf ) {
258         int rc;
259
260         rc = xfer->op->deliver_raw ( xfer, iobuf->data, iob_len ( iobuf ) );
261         free_iob ( iobuf );
262         return rc;
263 }
264
265 /**
266  * Deliver datagram as I/O buffer
267  *
268  * @v xfer              Data transfer interface
269  * @v data              Data buffer
270  * @v len               Length of data buffer
271  * @ret rc              Return status code
272  *
273  * This function is intended to be used as the deliver_raw() method
274  * for data transfer interfaces that prefer to handle I/O buffers.
275  */
276 int xfer_deliver_as_iob ( struct xfer_interface *xfer,
277                           const void *data, size_t len ) {
278         struct io_buffer *iobuf;
279
280         iobuf = xfer->op->alloc_iob ( xfer, len );
281         if ( ! iobuf )
282                 return -ENOMEM;
283
284         memcpy ( iob_put ( iobuf, len ), data, len );
285         return xfer->op->deliver_iob ( xfer, iobuf );
286 }
287
288 /**
289  * Ignore datagram as raw data event
290  *
291  * @v xfer              Data transfer interface
292  * @v data              Data buffer
293  * @v len               Length of data buffer
294  * @ret rc              Return status code
295  */
296 int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
297                               const void *data __unused, size_t len ) {
298         DBGC ( xfer, "XFER %p %zd bytes delivered %s\n", xfer, len,
299                ( ( xfer == &null_xfer ) ?
300                  "before connection" : "after termination" ) );
301         return 0;
302 }
303
304 /** Null data transfer interface operations */
305 struct xfer_interface_operations null_xfer_ops = {
306         .close          = ignore_xfer_close,
307         .vredirect      = ignore_xfer_vredirect,
308         .request        = ignore_xfer_request,
309         .seek           = ignore_xfer_seek,
310         .alloc_iob      = default_xfer_alloc_iob,
311         .deliver_iob    = xfer_deliver_as_raw,
312         .deliver_raw    = ignore_xfer_deliver_raw,
313 };
314
315 /**
316  * Null data transfer interface
317  *
318  * This is the interface to which data transfer interfaces are
319  * connected when unplugged.  It will never generate messages, and
320  * will silently absorb all received messages.
321  */
322 struct xfer_interface null_xfer = {
323         .intf = {
324                 .dest = &null_xfer.intf,
325                 .refcnt = NULL,
326         },
327         .op = &null_xfer_ops,
328 };