First sketch of stream API
[people/xl0/gpxe.git] / src / net / stream.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 /**
20  * @file
21  *
22  * Stream API
23  */
24
25 #include <stdint.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <gpxe/stream.h>
29
30 /**
31  * Connection established
32  *
33  * @v conn              Stream connection
34  */
35 void stream_connected ( struct stream_connection *conn ) {
36         struct stream_application *app = conn->app;
37
38         DBGC ( app, "Stream %p connected\n", app );
39
40         /* Check connection actually exists */
41         if ( ! app ) {
42                 DBGC ( conn, "Stream connection %p has no application\n",
43                        conn );
44                 return;
45         }
46
47         /* Hand off to application */
48         app->op->connected ( app );
49 }
50
51 /**
52  * Connection closed
53  *
54  * @v conn              Stream connection
55  * @v rc                Error code, if any
56  */
57 void stream_closed ( struct stream_connection *conn, int rc ) {
58         struct stream_application *app = conn->app;
59
60         DBGC ( app, "Stream %p closed (%s)\n", app, strerror ( rc ) );
61
62         /* Check connection actually exists */
63         if ( ! app ) {
64                 DBGC ( conn, "Stream connection %p has no application\n",
65                        conn );
66                 return;
67         }
68
69         /* Hand off to application */
70         app->op->closed ( app, rc );
71 }
72
73 /**
74  * Transmit data
75  *
76  * @v conn              Stream connection
77  * @v data              Temporary data buffer
78  * @v len               Length of temporary data buffer
79  */
80 void stream_senddata ( struct stream_connection *conn,
81                        void *data, size_t len ) {
82         struct stream_application *app = conn->app;
83
84         DBGC2 ( app, "Stream %p sending data\n", app );
85
86         /* Check connection actually exists */
87         if ( ! app ) {
88                 DBGC ( conn, "Stream connection %p has no application\n",
89                        conn );
90                 return;
91         }
92
93         /* Hand off to application */
94         app->op->senddata ( app, data, len );
95 }
96
97 /**
98  * Transmitted data acknowledged
99  *
100  * @v conn              Stream connection
101  * @v len               Length of acknowledged data
102  *
103  * @c len must not exceed the outstanding amount of unacknowledged
104  * data.
105  */
106 void stream_acked ( struct stream_connection *conn, size_t len ) {
107         struct stream_application *app = conn->app;
108
109         DBGC2 ( app, "Stream %p had %zd bytes acknowledged\n", app, len );
110
111         /* Check connection actually exists */
112         if ( ! app ) {
113                 DBGC ( conn, "Stream connection %p has no application\n",
114                        conn );
115                 return;
116         }
117
118         /* Hand off to application */
119         app->op->acked ( app, len );
120 }
121
122 /**
123  * Receive new data
124  *
125  * @v conn              Stream connection
126  * @v data              Data
127  * @v len               Length of data
128  */
129 void stream_newdata ( struct stream_connection *conn, 
130                       void *data, size_t len ) {
131         struct stream_application *app = conn->app;
132
133         DBGC2 ( app, "Stream %p received %zd bytes\n", app, len );
134
135         /* Check connection actually exists */
136         if ( ! app ) {
137                 DBGC ( conn, "Stream connection %p has no application\n",
138                        conn );
139                 return;
140         }
141
142         /* Hand off to application */
143         app->op->newdata ( app, data, len );
144 }
145
146 /**
147  * Bind to local address
148  *
149  * @v app               Stream application
150  * @v local             Local address
151  * @ret rc              Return status code
152  */
153 int stream_bind ( struct stream_application *app, struct sockaddr *local ) {
154         struct stream_connection *conn = app->conn;
155         int rc;
156
157         DBGC2 ( app, "Stream %p binding\n", app );
158
159         /* Check connection actually exists */
160         if ( ! conn ) {
161                 DBGC ( app, "Stream %p has no connection\n", app );
162                 return -ENOTCONN;
163         }
164
165         /* Hand off to connection */
166         if ( ( rc = conn->op->bind ( conn, local ) ) != 0 ) {
167                 DBGC ( app, "Stream %p failed to bind: %s\n",
168                        app, strerror ( rc ) );
169                 return rc;
170         }
171
172         return 0;
173 }
174
175 /**
176  * Connect to remote address
177  *
178  * @v app               Stream application
179  * @v peer              Remote address
180  * @ret rc              Return status code
181  */
182 int stream_connect ( struct stream_application *app, struct sockaddr *peer ) {
183         struct stream_connection *conn = app->conn;
184         int rc;
185
186         DBGC2 ( app, "Stream %p connecting\n", app );
187
188         /* Check connection actually exists */
189         if ( ! conn ) {
190                 DBGC ( app, "Stream %p has no connection\n", app );
191                 return -ENOTCONN;
192         }
193
194         /* Hand off to connection */
195         if ( ( rc = conn->op->connect ( conn, peer ) ) != 0 ) {
196                 DBGC ( app, "Stream %p failed to connect: %s\n",
197                        app, strerror ( rc ) );
198                 return rc;
199         }
200
201         return 0;
202 }
203
204 /**
205  * Close connection
206  *
207  * @v app               Stream application
208  */
209 void stream_close ( struct stream_application *app ) {
210         struct stream_connection *conn = app->conn;
211
212         DBGC2 ( app, "Stream %p closing\n", app );
213
214         /* Check connection actually exists */
215         if ( ! conn ) {
216                 DBGC ( app, "Stream %p has no connection\n", app );
217                 return;
218         }
219
220         /* Hand off to connection */
221         conn->op->close ( conn );
222 }
223
224 /**
225  * Send data via connection
226  *
227  * @v app               Stream application
228  * @v data              Data to send
229  * @v len               Length of data
230  * @ret rc              Return status code
231  *
232  * This method should be called only in the context of an
233  * application's senddata() method.
234  */
235 int stream_send ( struct stream_application *app, void *data, size_t len ) {
236         struct stream_connection *conn = app->conn;
237         int rc;
238
239         DBGC2 ( app, "Stream %p sending %zd bytes\n", app, len );
240
241         /* Check connection actually exists */
242         if ( ! conn ) {
243                 DBGC ( app, "Stream %p has no connection\n", app );
244                 return -ENOTCONN;
245         }
246
247         /* Hand off to connection */
248         if ( ( rc = conn->op->send ( conn, data, len ) ) != 0 ) {
249                 DBGC ( app, "Stream %p failed to send %zd bytes: %s\n",
250                        app, len, strerror ( rc ) );
251                 return rc;
252         }
253
254         return 0;
255 }
256
257 /**
258  * Notify connection that data is available to send
259  *
260  * @v app               Stream application
261  * @ret rc              Return status code
262  */
263 int stream_kick ( struct stream_application *app ) {
264                 struct stream_connection *conn = app->conn;
265         int rc;
266
267         DBGC2 ( app, "Stream %p kicking connection\n", app );
268
269         /* Check connection actually exists */
270         if ( ! conn ) {
271                 DBGC ( app, "Stream %p has no connection\n", app );
272                 return -ENOTCONN;
273         }
274
275         /* Hand off to connection */
276         if ( ( rc = conn->op->kick ( conn ) ) != 0 ) {
277                 DBGC ( app, "Stream %p failed to kick connection: %s\n",
278                        app, strerror ( rc ) );
279                 return rc;
280         }
281
282         return 0;
283 }