1 /* 2 * Copyright (C) 2007 Michael Brown <mbrown (at) 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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, &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 */ 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