Переглянути джерело

Data-transfer interface should now be functionally complete.

tags/v0.9.3
Michael Brown 17 роки тому
джерело
коміт
5471bfbbbe
4 змінених файлів з 243 додано та 73 видалено
  1. 22
    9
      src/core/downloader.c
  2. 68
    0
      src/core/hw.c
  3. 92
    32
      src/core/xfer.c
  4. 61
    32
      src/include/gpxe/xfer.h

+ 22
- 9
src/core/downloader.c Переглянути файл

@@ -115,7 +115,7 @@ static void downloader_job_start ( struct job_interface *job ) {
115 115
 		container_of ( job, struct downloader, job );
116 116
 
117 117
 	/* Start data transfer */
118
-	xfer_start ( &downloader->xfer );
118
+	xfer_request_all ( &downloader->xfer );
119 119
 }
120 120
 
121 121
 /**
@@ -152,17 +152,30 @@ static struct job_interface_operations downloader_job_operations = {
152 152
  * @v pos		New position
153 153
  * @ret rc		Return status code
154 154
  */
155
-static int downloader_xfer_seek ( struct xfer_interface *xfer, size_t pos ) {
155
+static int downloader_xfer_seek ( struct xfer_interface *xfer, off_t offset,
156
+				  int whence ) {
156 157
 	struct downloader *downloader =
157 158
 		container_of ( xfer, struct downloader, xfer );
159
+	off_t new_pos;
158 160
 	int rc;
159 161
 
162
+	/* Calculate new buffer position */
163
+	switch ( whence ) {
164
+	case SEEK_SET:
165
+		new_pos = offset;
166
+		break;
167
+	case SEEK_CUR:
168
+		new_pos = ( downloader->pos + offset );
169
+		break;
170
+	default:
171
+		assert ( 0 );
172
+		return -EINVAL;
173
+	}
174
+
160 175
 	/* Ensure that we have enough buffer space for this buffer position */
161
-	if ( ( rc = downloader_ensure_size ( downloader, pos ) ) != 0 )
176
+	if ( ( rc = downloader_ensure_size ( downloader, new_pos ) ) != 0 )
162 177
 		return rc;
163
-
164
-	/* Update current buffer position */
165
-	downloader->pos = pos;
178
+	downloader->pos = new_pos;
166 179
 
167 180
 	return 0;
168 181
 }
@@ -216,11 +229,11 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) {
216 229
 
217 230
 /** Downloader data transfer interface operations */
218 231
 static struct xfer_interface_operations downloader_xfer_operations = {
219
-	.start		= ignore_xfer_start,
220 232
 	.close		= downloader_xfer_close,
221
-	.vredirect	= default_xfer_vredirect,
233
+	.vredirect	= vopen,
234
+	.request	= ignore_xfer_request,
222 235
 	.seek		= downloader_xfer_seek,
223
-	.deliver	= xfer_deliver_as_raw,
236
+	.deliver_iob	= xfer_deliver_as_raw,
224 237
 	.deliver_raw	= downloader_xfer_deliver_raw,
225 238
 };
226 239
 

+ 68
- 0
src/core/hw.c Переглянути файл

@@ -0,0 +1,68 @@
1
+#include <stddef.h>
2
+#include <stdlib.h>
3
+#include <string.h>
4
+#include <errno.h>
5
+#include <gpxe/refcnt.h>
6
+#include <gpxe/xfer.h>
7
+#include <gpxe/open.h>
8
+
9
+/** @file
10
+ *
11
+ * "Hello World" data source
12
+ *
13
+ */
14
+
15
+struct hw {
16
+	struct refcnt refcnt;
17
+	struct xfer_interface xfer;
18
+};
19
+
20
+static const char hw_msg[] = "Hello world!\n";
21
+
22
+static void hw_finished ( struct hw *hw, int rc ) {
23
+	xfer_nullify ( &hw->xfer );
24
+	xfer_close ( &hw->xfer, rc );
25
+	ref_put ( &hw->refcnt );
26
+}
27
+
28
+static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
29
+	struct hw *hw = container_of ( xfer, struct hw, xfer );
30
+
31
+	hw_finished ( hw, rc );
32
+}
33
+
34
+static int hw_xfer_request ( struct xfer_interface *xfer, off_t start __unused,
35
+			     int whence __unused, size_t len __unused ) {
36
+	struct hw *hw = container_of ( xfer, struct hw, xfer );
37
+
38
+	xfer_deliver_raw ( xfer, hw_msg, sizeof ( hw_msg ) );
39
+	hw_finished ( hw, 0 );
40
+	return 0;
41
+}
42
+
43
+static struct xfer_interface_operations hw_xfer_operations = {
44
+	.close		= hw_xfer_close,
45
+	.vredirect	= ignore_xfer_vredirect,
46
+	.request	= hw_xfer_request,
47
+	.seek		= ignore_xfer_seek,
48
+	.deliver_iob	= xfer_deliver_as_raw,
49
+	.deliver_raw	= ignore_xfer_deliver_raw,
50
+};
51
+
52
+static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) {
53
+	struct hw *hw;
54
+
55
+	hw = malloc ( sizeof ( *hw ) );
56
+	if ( ! hw )
57
+		return -ENOMEM;
58
+	memset ( hw, 0, sizeof ( *hw ) );
59
+	xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt );
60
+
61
+	xfer_plug_plug ( &hw->xfer, xfer );
62
+	return 0;
63
+}
64
+
65
+struct uri_opener hw_uri_opener __uri_opener = {
66
+	.scheme = "hw",
67
+	.open = hw_open,
68
+};

+ 92
- 32
src/core/xfer.c Переглянути файл

@@ -39,19 +39,6 @@ void xfer_close ( struct xfer_interface *xfer, int rc ) {
39 39
 	xfer_unplug ( xfer );
40 40
 }
41 41
 
42
-/**
43
- * Seek to position
44
- *
45
- * @v xfer		Data transfer interface
46
- * @v pos		New position
47
- * @ret rc		Return status code
48
- */
49
-int xfer_seek ( struct xfer_interface *xfer, size_t pos ) {
50
-	struct xfer_interface *dest = xfer_dest ( xfer );
51
-
52
-	return dest->op->seek ( dest, pos );
53
-}
54
-
55 42
 /**
56 43
  * Send redirection event
57 44
  *
@@ -84,6 +71,59 @@ int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
84 71
 	return rc;
85 72
 }
86 73
 
74
+/**
75
+ * Request data
76
+ *
77
+ * @v xfer		Data transfer interface
78
+ * @v offset		Offset to new position
79
+ * @v whence		Basis for new position
80
+ * @v len		Length of requested data
81
+ * @ret rc		Return status code
82
+ */
83
+int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
84
+		   size_t len ) {
85
+	struct xfer_interface *dest = xfer_dest ( xfer );
86
+
87
+	return dest->op->request ( dest, offset, whence, len );
88
+}
89
+
90
+/**
91
+ * Request all data
92
+ *
93
+ * @v xfer		Data transfer interface
94
+ * @ret rc		Return status code
95
+ */
96
+int xfer_request_all ( struct xfer_interface *xfer ) {
97
+	return xfer_request ( xfer, 0, SEEK_SET, ~( ( size_t ) 0 ) );
98
+}
99
+
100
+/**
101
+ * Seek to position
102
+ *
103
+ * @v xfer		Data transfer interface
104
+ * @v offset		Offset to new position
105
+ * @v whence		Basis for new position
106
+ * @ret rc		Return status code
107
+ */
108
+int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
109
+	struct xfer_interface *dest = xfer_dest ( xfer );
110
+
111
+	return dest->op->seek ( dest, offset, whence );
112
+}
113
+
114
+/**
115
+ * Allocate I/O buffer
116
+ *
117
+ * @v xfer		Data transfer interface
118
+ * @v len		I/O buffer payload length
119
+ * @ret iobuf		I/O buffer
120
+ */
121
+struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
122
+	struct xfer_interface *dest = xfer_dest ( xfer );
123
+
124
+	return dest->op->alloc_iob ( dest, len );
125
+}
126
+
87 127
 /**
88 128
  * Deliver datagram
89 129
  *
@@ -91,10 +131,10 @@ int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
91 131
  * @v iobuf		Datagram I/O buffer
92 132
  * @ret rc		Return status code
93 133
  */
94
-int xfer_deliver ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
134
+int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
95 135
 	struct xfer_interface *dest = xfer_dest ( xfer );
96 136
 
97
-	return dest->op->deliver ( dest, iobuf );
137
+	return dest->op->deliver_iob ( dest, iobuf );
98 138
 }
99 139
 
100 140
 /**
@@ -120,15 +160,6 @@ int xfer_deliver_raw ( struct xfer_interface *xfer,
120 160
  *
121 161
  */
122 162
 
123
-/**
124
- * Ignore start() event
125
- *
126
- * @v xfer		Data transfer interface
127
- */
128
-void ignore_xfer_start ( struct xfer_interface *xfer __unused ) {
129
-	/* Nothing to do */
130
-}
131
-
132 163
 /**
133 164
  * Ignore close() event
134 165
  *
@@ -153,18 +184,46 @@ int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
153 184
 	return 0;
154 185
 }
155 186
 
187
+/**
188
+ * Ignore request() event
189
+ *
190
+ * @v xfer		Data transfer interface
191
+ * @v offset		Offset to new position
192
+ * @v whence		Basis for new position
193
+ * @v len		Length of requested data
194
+ * @ret rc		Return status code
195
+ */
196
+int ignore_xfer_request ( struct xfer_interface *xfer __unused,
197
+			  off_t offset __unused, int whence __unused, 
198
+			  size_t len __unused ) {
199
+	return 0;
200
+}
201
+
156 202
 /**
157 203
  * Ignore seek() event
158 204
  *
159 205
  * @v xfer		Data transfer interface
160
- * @v pos		New position
206
+ * @v offset		Offset to new position
207
+ * @v whence		Basis for new position
161 208
  * @ret rc		Return status code
162 209
  */
163 210
 int ignore_xfer_seek ( struct xfer_interface *xfer __unused,
164
-		       size_t pos __unused ) {
211
+		       off_t offset __unused, int whence __unused ) {
165 212
 	return 0;
166 213
 }
167 214
 
215
+/**
216
+ * Allocate I/O buffer
217
+ *
218
+ * @v xfer		Data transfer interface
219
+ * @v len		I/O buffer payload length
220
+ * @ret iobuf		I/O buffer
221
+ */
222
+struct io_buffer *
223
+default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
224
+	return alloc_iob ( len );
225
+}
226
+
168 227
 /**
169 228
  * Deliver datagram as raw data
170 229
  *
@@ -195,16 +254,16 @@ int xfer_deliver_as_raw ( struct xfer_interface *xfer,
195 254
  * This function is intended to be used as the deliver_raw() method
196 255
  * for data transfer interfaces that prefer to handle I/O buffers.
197 256
  */
198
-int xfer_deliver_as_iobuf ( struct xfer_interface *xfer,
199
-			    const void *data, size_t len ) {
257
+int xfer_deliver_as_iob ( struct xfer_interface *xfer,
258
+			  const void *data, size_t len ) {
200 259
 	struct io_buffer *iobuf;
201 260
 
202
-	iobuf = alloc_iob ( len );
261
+	iobuf = xfer->op->alloc_iob ( xfer, len );
203 262
 	if ( ! iobuf )
204 263
 		return -ENOMEM;
205 264
 
206 265
 	memcpy ( iob_put ( iobuf, len ), data, len );
207
-	return xfer->op->deliver ( xfer, iobuf );
266
+	return xfer->op->deliver_iob ( xfer, iobuf );
208 267
 }
209 268
 
210 269
 /**
@@ -225,11 +284,12 @@ int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
225 284
 
226 285
 /** Null data transfer interface operations */
227 286
 struct xfer_interface_operations null_xfer_ops = {
228
-	.start		= ignore_xfer_start,
229 287
 	.close		= ignore_xfer_close,
230 288
 	.vredirect	= ignore_xfer_vredirect,
289
+	.request	= ignore_xfer_request,
231 290
 	.seek		= ignore_xfer_seek,
232
-	.deliver	= xfer_deliver_as_raw,
291
+	.alloc_iob	= default_xfer_alloc_iob,
292
+	.deliver_iob	= xfer_deliver_as_raw,
233 293
 	.deliver_raw	= ignore_xfer_deliver_raw,
234 294
 };
235 295
 

+ 61
- 32
src/include/gpxe/xfer.h Переглянути файл

@@ -16,22 +16,6 @@ struct xfer_interface;
16 16
 
17 17
 /** Data transfer interface operations */
18 18
 struct xfer_interface_operations {
19
-
20
-	/* Missing features:
21
-	 *
22
-	 * notification of non-close status - e.g. connected/opened, ...
23
-	 *
24
-	 * prompt for data delivery
25
-	 *
26
-	 * I/O buffer preparation
27
-	 *
28
-	 */
29
-
30
-	/** Start data transfer
31
-	 *
32
-	 * @v xfer		Data transfer interface
33
-	 */
34
-	void ( * start ) ( struct xfer_interface *xfer );
35 19
 	/** Close interface
36 20
 	 *
37 21
 	 * @v xfer		Data transfer interface
@@ -47,14 +31,39 @@ struct xfer_interface_operations {
47 31
 	 */
48 32
 	int ( * vredirect ) ( struct xfer_interface *xfer, int type,
49 33
 			      va_list args );
34
+	/** Request data
35
+	 *
36
+	 * @v xfer		Data transfer interface
37
+	 * @v offset		Offset to new position
38
+	 * @v whence		Basis for new position
39
+	 * @v len		Length of requested data
40
+	 * @ret rc		Return status code
41
+	 */
42
+	int ( * request ) ( struct xfer_interface *xfer, off_t offset,
43
+			    int whence, size_t len );
50 44
 	/** Seek to position
51 45
 	 *
52 46
 	 * @v xfer		Data transfer interface
53
-	 * @v pos		New position
47
+	 * @v offset		Offset to new position
48
+	 * @v whence		Basis for new position
54 49
 	 * @ret rc		Return status code
50
+	 *
51
+	 * @c whence must be one of @c SEEK_SET or @c SEEK_CUR.  A
52
+	 * successful return indicates that the interface is ready to
53
+	 * immediately accept datagrams; return -EAGAIN if this is not
54
+	 * the case.
55 55
 	 */
56
-	int ( * seek ) ( struct xfer_interface *xfer, size_t pos );
57
-	/** Deliver datagram
56
+	int ( * seek ) ( struct xfer_interface *xfer, off_t offset,
57
+			 int whence );
58
+	/** Allocate I/O buffer
59
+	 *
60
+	 * @v xfer		Data transfer interface
61
+	 * @v len		I/O buffer payload length
62
+	 * @ret iobuf		I/O buffer
63
+	 */
64
+	struct io_buffer * ( * alloc_iob ) ( struct xfer_interface *xfer,
65
+					     size_t len );
66
+	/** Deliver datagram as I/O buffer
58 67
 	 *
59 68
 	 * @v xfer		Data transfer interface
60 69
 	 * @v iobuf		Datagram I/O buffer
@@ -63,9 +72,13 @@ struct xfer_interface_operations {
63 72
 	 * A data transfer interface that wishes to support only raw
64 73
 	 * data delivery should set this method to
65 74
 	 * xfer_deliver_as_raw().
75
+	 *
76
+	 * Interfaces may not temporarily refuse to accept data by
77
+	 * returning -EAGAIN; such a response may be treated as a
78
+	 * fatal error.
66 79
 	 */
67
-	int ( * deliver ) ( struct xfer_interface *xfer,
68
-			    struct io_buffer *iobuf );
80
+	int ( * deliver_iob ) ( struct xfer_interface *xfer,
81
+				struct io_buffer *iobuf );
69 82
 	/** Deliver datagram as raw data
70 83
 	 *
71 84
 	 * @v xfer		Data transfer interface
@@ -75,7 +88,11 @@ struct xfer_interface_operations {
75 88
 	 *
76 89
 	 * A data transfer interface that wishes to support only I/O
77 90
 	 * buffer delivery should set this method to
78
-	 * xfer_deliver_as_iobuf().
91
+	 * xfer_deliver_as_iob().
92
+	 *
93
+	 * Interfaces may not temporarily refuse to accept data by
94
+	 * returning -EAGAIN; such a response may be treated as a
95
+	 * fatal error.
79 96
 	 */
80 97
 	int ( * deliver_raw ) ( struct xfer_interface *xfer,
81 98
 				const void *data, size_t len );
@@ -89,31 +106,43 @@ struct xfer_interface {
89 106
 	struct xfer_interface_operations *op;
90 107
 };
91 108
 
109
+/** Basis positions for seek() events */
110
+enum seek_whence {
111
+	SEEK_SET = 0,
112
+	SEEK_CUR,
113
+};
114
+
92 115
 extern struct xfer_interface null_xfer;
93 116
 extern struct xfer_interface_operations null_xfer_ops;
94 117
 
95
-extern void xfer_start ( struct xfer_interface *xfer );
96 118
 extern void xfer_close ( struct xfer_interface *xfer, int rc );
97
-extern int xfer_seek ( struct xfer_interface *xfer, size_t pos );
98 119
 extern int xfer_vredirect ( struct xfer_interface *xfer, int type,
99 120
 			    va_list args );
100 121
 extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... );
101
-extern int xfer_deliver ( struct xfer_interface *xfer,
102
-			  struct io_buffer *iobuf );
122
+extern int xfer_request ( struct xfer_interface *xfer, off_t offset,
123
+			  int whence, size_t len );
124
+extern int xfer_request_all ( struct xfer_interface *xfer );
125
+extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence );
126
+extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer,
127
+					   size_t len );
128
+extern int xfer_deliver_iob ( struct xfer_interface *xfer,
129
+			      struct io_buffer *iobuf );
103 130
 extern int xfer_deliver_raw ( struct xfer_interface *xfer,
104 131
 			      const void *data, size_t len );
105 132
 
106
-extern void ignore_xfer_start ( struct xfer_interface *xfer );
107 133
 extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc );
108 134
 extern int ignore_xfer_vredirect ( struct xfer_interface *xfer,
109 135
 				   int type, va_list args );
110
-extern int default_xfer_vredirect ( struct xfer_interface *xfer,
111
-				    int type, va_list args );
112
-extern int ignore_xfer_seek ( struct xfer_interface *xfer, size_t pos );
136
+extern int ignore_xfer_request ( struct xfer_interface *xfer, off_t offset,
137
+				 int whence, size_t len );
138
+extern int ignore_xfer_seek ( struct xfer_interface *xfer, off_t offset,
139
+			      int whence );
140
+extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer,
141
+						   size_t len );
113 142
 extern int xfer_deliver_as_raw ( struct xfer_interface *xfer,
114 143
 				 struct io_buffer *iobuf );
115
-extern int xfer_deliver_as_iobuf ( struct xfer_interface *xfer,
116
-				   const void *data, size_t len );
144
+extern int xfer_deliver_as_iob ( struct xfer_interface *xfer,
145
+				 const void *data, size_t len );
117 146
 extern int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
118 147
 				     const void *data __unused, size_t len );
119 148
 

Завантаження…
Відмінити
Зберегти