iPXE
xfer.c
Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <ipxe/iobuf.h>
31 #include <ipxe/xfer.h>
32 #include <ipxe/open.h>
33 
34 /** @file
35  *
36  * Data transfer interfaces
37  *
38  */
39 
40 /**
41  * Dummy transfer metadata
42  *
43  * This gets passed to xfer_interface::deliver() and equivalents when
44  * no metadata is available.
45  */
47 
48 /*****************************************************************************
49  *
50  * Data transfer interface operations
51  *
52  */
53 
54 /**
55  * Send redirection event
56  *
57  * @v intf Data transfer interface
58  * @v type New location type
59  * @v args Remaining arguments depend upon location type
60  * @ret rc Return status code
61  */
62 int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
64  struct interface *dest;
65  xfer_vredirect_TYPE ( void * ) *op =
67  void *object = intf_object ( dest );
68  int rc;
69 
70  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n",
71  INTF_INTF_DBG ( intf, dest ) );
72 
73  if ( op ) {
74  rc = op ( object, type, args );
75  } else {
76  /* Default is to reopen the interface as instructed,
77  * then send xfer_window_changed() messages to both
78  * new child and parent interfaces. Since our
79  * original child interface is likely to be closed and
80  * unplugged as a result of the call to
81  * xfer_vreopen(), we create a temporary interface in
82  * order to be able to send xfer_window_changed() to
83  * the parent.
84  *
85  * If redirection fails, then send intf_close() to the
86  * parent interface.
87  */
88  intf_plug ( &tmp, dest );
89  rc = xfer_vreopen ( dest, type, args );
90  if ( rc == 0 ) {
93  } else {
94  intf_close ( &tmp, rc );
95  }
96  intf_unplug ( &tmp );
97  }
98 
99  if ( rc != 0 ) {
100  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect "
101  "failed: %s\n", INTF_INTF_DBG ( intf, dest ),
102  strerror ( rc ) );
103  }
104 
105  intf_put ( dest );
106  return rc;
107 }
108 
109 /**
110  * Check flow control window
111  *
112  * @v intf Data transfer interface
113  * @ret len Length of window
114  */
115 size_t xfer_window ( struct interface *intf ) {
116  struct interface *dest;
117  xfer_window_TYPE ( void * ) *op =
118  intf_get_dest_op ( intf, xfer_window, &dest );
119  void *object = intf_object ( dest );
120  size_t len;
121 
122  if ( op ) {
123  len = op ( object );
124  } else {
125  /* Default is to provide an unlimited window */
126  len = ~( ( size_t ) 0 );
127  }
128 
129  intf_put ( dest );
130  return len;
131 }
132 
133 /**
134  * Report change of flow control window
135  *
136  * @v intf Data transfer interface
137  *
138  * Note that this method is used to indicate only unsolicited changes
139  * in the flow control window. In particular, this method must not be
140  * called as part of the response to xfer_deliver(), since that could
141  * easily lead to an infinite loop. Callers of xfer_deliver() should
142  * assume that the flow control window will have changed without
143  * generating an xfer_window_changed() message.
144  */
145 void xfer_window_changed ( struct interface *intf ) {
146 
147  intf_poke ( intf, xfer_window_changed );
148 }
149 
150 /**
151  * Allocate I/O buffer
152  *
153  * @v intf Data transfer interface
154  * @v len I/O buffer payload length
155  * @ret iobuf I/O buffer
156  */
157 struct io_buffer * xfer_alloc_iob ( struct interface *intf, size_t len ) {
158  struct interface *dest;
159  xfer_alloc_iob_TYPE ( void * ) *op =
161  void *object = intf_object ( dest );
162  struct io_buffer *iobuf;
163 
164  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob %zd\n",
165  INTF_INTF_DBG ( intf, dest ), len );
166 
167  if ( op ) {
168  iobuf = op ( object, len );
169  } else {
170  /* Default is to allocate an I/O buffer with no
171  * reserved space.
172  */
173  iobuf = alloc_iob ( len );
174  }
175 
176  if ( ! iobuf ) {
177  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " alloc_iob "
178  "failed\n", INTF_INTF_DBG ( intf, dest ) );
179  }
180 
181  intf_put ( dest );
182  return iobuf;
183 }
184 
185 /**
186  * Deliver datagram
187  *
188  * @v intf Data transfer interface
189  * @v iobuf Datagram I/O buffer
190  * @v meta Data transfer metadata
191  * @ret rc Return status code
192  */
193 int xfer_deliver ( struct interface *intf,
194  struct io_buffer *iobuf,
195  struct xfer_metadata *meta ) {
196  struct interface *dest;
197  xfer_deliver_TYPE ( void * ) *op =
198  intf_get_dest_op ( intf, xfer_deliver, &dest );
199  void *object = intf_object ( dest );
200  int rc;
201 
202  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " deliver %zd\n",
203  INTF_INTF_DBG ( intf, dest ), iob_len ( iobuf ) );
204 
205  if ( op ) {
206  rc = op ( object, iobuf, meta );
207  } else {
208  /* Default is to discard the I/O buffer */
209  free_iob ( iobuf );
210  rc = -EPIPE;
211  }
212 
213  if ( rc != 0 ) {
214  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT
215  " deliver failed: %s\n",
216  INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
217  }
218 
219  intf_put ( dest );
220  return rc;
221 }
222 
223 /*****************************************************************************
224  *
225  * Data transfer interface helper functions
226  *
227  */
228 
229 /**
230  * Send redirection event
231  *
232  * @v intf Data transfer interface
233  * @v type New location type
234  * @v ... Remaining arguments depend upon location type
235  * @ret rc Return status code
236  */
237 int xfer_redirect ( struct interface *intf, int type, ... ) {
238  va_list args;
239  int rc;
240 
241  va_start ( args, type );
242  rc = xfer_vredirect ( intf, type, args );
243  va_end ( args );
244  return rc;
245 }
246 
247 /**
248  * Deliver datagram as I/O buffer without metadata
249  *
250  * @v intf Data transfer interface
251  * @v iobuf Datagram I/O buffer
252  * @ret rc Return status code
253  */
254 int xfer_deliver_iob ( struct interface *intf, struct io_buffer *iobuf ) {
255  return xfer_deliver ( intf, iobuf, &dummy_metadata );
256 }
257 
258 /**
259  * Deliver datagram as raw data
260  *
261  * @v intf Data transfer interface
262  * @v data Data
263  * @v len Length of data
264  * @v meta Data transfer metadata
265  * @ret rc Return status code
266  */
267 int xfer_deliver_raw_meta ( struct interface *intf, const void *data,
268  size_t len, struct xfer_metadata *meta ) {
269  struct io_buffer *iobuf;
270 
271  iobuf = xfer_alloc_iob ( intf, len );
272  if ( ! iobuf )
273  return -ENOMEM;
274 
275  memcpy ( iob_put ( iobuf, len ), data, len );
276  return xfer_deliver ( intf, iobuf, meta );
277 }
278 
279 /**
280  * Deliver datagram as raw data without metadata
281  *
282  * @v intf Data transfer interface
283  * @v data Data
284  * @v len Length of data
285  * @ret rc Return status code
286  */
287 int xfer_deliver_raw ( struct interface *intf, const void *data, size_t len ) {
288  return xfer_deliver_raw_meta ( intf, data, len, &dummy_metadata );
289 }
290 
291 /**
292  * Deliver formatted string
293  *
294  * @v intf Data transfer interface
295  * @v format Format string
296  * @v args Arguments corresponding to the format string
297  * @ret rc Return status code
298  */
299 int xfer_vprintf ( struct interface *intf, const char *format,
300  va_list args ) {
301  va_list args_tmp;
302  char *buf;
303  int len;
304  int rc;
305 
306  /* Create temporary string */
307  va_copy ( args_tmp, args );
308  len = vasprintf ( &buf, format, args );
309  va_end ( args_tmp );
310  if ( len < 0 ) {
311  rc = len;
312  goto err_asprintf;
313  }
314 
315  /* Transmit string */
316  if ( ( rc = xfer_deliver_raw ( intf, buf, len ) ) != 0 )
317  goto err_deliver;
318 
319  err_deliver:
320  free ( buf );
321  err_asprintf:
322  return rc;
323 }
324 
325 /**
326  * Deliver formatted string
327  *
328  * @v intf Data transfer interface
329  * @v format Format string
330  * @v ... Arguments corresponding to the format string
331  * @ret rc Return status code
332  */
333 int xfer_printf ( struct interface *intf, const char *format, ... ) {
334  va_list args;
335  int rc;
336 
337  va_start ( args, format );
338  rc = xfer_vprintf ( intf, format, args );
339  va_end ( args );
340  return rc;
341 }
342 
343 /**
344  * Seek to position
345  *
346  * @v intf Data transfer interface
347  * @v offset Offset to new position
348  * @ret rc Return status code
349  */
350 int xfer_seek ( struct interface *intf, off_t offset ) {
351  struct io_buffer *iobuf;
352  struct xfer_metadata meta = {
353  .flags = XFER_FL_ABS_OFFSET,
354  .offset = offset,
355  };
356 
357  DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " seek to %ld\n",
358  INTF_DBG ( intf ), offset );
359 
360  /* Allocate and send a zero-length data buffer */
361  iobuf = xfer_alloc_iob ( intf, 0 );
362  if ( ! iobuf )
363  return -ENOMEM;
364 
365  return xfer_deliver ( intf, iobuf, &meta );
366 }
367 
368 /**
369  * Check that data is delivered strictly in order
370  *
371  * @v meta Data transfer metadata
372  * @v pos Current position
373  * @v len Length of data
374  * @ret rc Return status code
375  */
376 int xfer_check_order ( struct xfer_metadata *meta, size_t *pos, size_t len ) {
377  size_t new_pos;
378 
379  /* Allow out-of-order zero-length packets (as used by xfer_seek()) */
380  if ( len == 0 )
381  return 0;
382 
383  /* Calculate position of this delivery */
384  new_pos = *pos;
385  if ( meta->flags & XFER_FL_ABS_OFFSET )
386  new_pos = 0;
387  new_pos += meta->offset;
388 
389  /* Fail if delivery position is not equal to current position */
390  if ( new_pos != *pos )
391  return -EPROTO;
392 
393  /* Update current position */
394  *pos += len;
395 
396  return 0;
397 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:145
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:244
#define INTF_INTF_FMT
printf() format string for INTF_INTF_DBG()
Definition: interface.h:240
#define iob_put(iobuf, len)
Definition: iobuf.h:116
#define va_end(ap)
Definition: stdarg.h:9
Data transfer metadata.
Definition: xfer.h:22
#define INTF_DBG(intf)
printf() arguments for representing an object interface
Definition: interface.h:237
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition: xfer.c:254
struct interface_descriptor null_intf_desc
Null interface descriptor.
Definition: interface.c:61
int xfer_deliver_raw_meta(struct interface *intf, const void *data, size_t len, struct xfer_metadata *meta)
Deliver datagram as raw data.
Definition: xfer.c:267
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:47
Error codes.
__SIZE_TYPE__ size_t
Definition: stdint.h:6
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#define INTF_INTF_DBG(intf, dest)
printf() arguments for representing an object interface pair
Definition: interface.h:249
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:187
uint8_t type
Type.
Definition: ena.h:16
#define EPIPE
Broken pipe.
Definition: errno.h:619
#define INTF_COL(intf)
Find debugging colourisation for an object interface.
Definition: interface.h:226
#define DBGC(...)
Definition: compiler.h:505
int xfer_vredirect(struct interface *intf, int type, va_list args)
Send redirection event.
Definition: xfer.c:62
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:157
int xfer_check_order(struct xfer_metadata *meta, size_t *pos, size_t len)
Check that data is delivered strictly in order.
Definition: xfer.c:376
#define va_copy(dest, src)
Definition: stdarg.h:10
#define xfer_vredirect_TYPE(object_type)
Definition: xfer.h:69
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:115
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:154
int xfer_deliver_raw(struct interface *intf, const void *data, size_t len)
Deliver datagram as raw data without metadata.
Definition: xfer.c:287
#define xfer_deliver_TYPE(object_type)
Definition: xfer.h:88
Data transfer interfaces.
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
An object interface.
Definition: interface.h:109
int vasprintf(char **strp, const char *fmt, va_list args)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:17
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
static void * dest
Definition: strings.h:176
#define EPROTO
Protocol error.
Definition: errno.h:624
void intf_unplug(struct interface *intf)
Unplug an object interface.
Definition: interface.c:112
int xfer_seek(struct interface *intf, off_t offset)
Seek to position.
Definition: xfer.c:350
int meta(WINDOW *, bool)
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
uint8_t * tmp
Definition: entropy.h:156
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:193
Data transfer interface opening.
#define xfer_window_TYPE(object_type)
Definition: xfer.h:73
int xfer_vprintf(struct interface *intf, const char *format, va_list args)
Deliver formatted string.
Definition: xfer.c:299
int xfer_vreopen(struct interface *intf, int type, va_list args)
Reopen location.
Definition: open.c:225
int xfer_printf(struct interface *intf, const char *format,...)
Deliver formatted string.
Definition: xfer.c:333
signed long off_t
Definition: stdint.h:8
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
uint32_t len
Length.
Definition: ena.h:14
__builtin_va_list va_list
Definition: stdarg.h:6
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:144
#define intf_get_dest_op_no_passthru(intf, type, dest)
Get object interface destination and operation method (without pass-through)
Definition: interface.h:202
#define xfer_alloc_iob_TYPE(object_type)
Definition: xfer.h:82
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define va_start(ap, last)
Definition: stdarg.h:7
int const char * format
Definition: xfer.h:104
void intf_poke(struct interface *intf, void(type)(struct interface *intf))
Poke an object interface.
Definition: interface.c:397
String functions.
static struct xfer_metadata dummy_metadata
Dummy transfer metadata.
Definition: xfer.c:46
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:214
void intf_plug(struct interface *intf, struct interface *dest)
Plug an object interface into a new destination object interface.
Definition: interface.c:83
#define INTF_FMT
printf() format string for INTF_DBG()
Definition: interface.h:229
A persistent I/O buffer.
Definition: iobuf.h:32
int xfer_redirect(struct interface *intf, int type,...)
Send redirection event.
Definition: xfer.c:237