From ddf3b56d47231ed135ebe1ff751b3f60813bc928 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 30 Jan 2007 12:16:36 +0000 Subject: [PATCH] Definition of a (hopefully) generic stream API --- src/include/gpxe/stream.h | 187 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 src/include/gpxe/stream.h diff --git a/src/include/gpxe/stream.h b/src/include/gpxe/stream.h new file mode 100644 index 00000000..8d1c5f5d --- /dev/null +++ b/src/include/gpxe/stream.h @@ -0,0 +1,187 @@ +#ifndef _GPXE_STREAM_H +#define _GPXE_STREAM_H + +/** @file + * + * Stream API + */ + +#include +#include + +struct stream_application; +struct stream_connection; + +/** Stream applicatin-layer operations */ +struct stream_application_operations { + /** + * Connection established + * + * @v app Stream application + */ + void ( * connected ) ( struct stream_application *app ); + /** + * Connection closed + * + * @v app Stream application + * @v rc Error code, if any + * + * This is called when the connection is closed for any + * reason, including timeouts or aborts. The error code + * contains the negative error number, if the closure is due + * to an error, or zero for a normal close. + * + * When closed() is called, the application no longer has a + * valid stream connection. Note that connected() may not + * have been called before closed(), if the close is due to an + * error during connection setup. + */ + void ( * closed ) ( struct stream_application *app, int rc ); + /** + * Transmit data + * + * @v app Stream application + * @v data Temporary data buffer + * @v len Length of temporary data buffer + * + * The application should transmit whatever it currently wants + * to send using stream_send(). If retransmissions are + * required, senddata() will be called again and the + * application must regenerate the data. The easiest way to + * implement this is to ensure that senddata() never changes + * the application's state. + * + * The application may use the temporary data buffer to + * construct the data to be sent. Note that merely filling + * the buffer will do nothing; the application must call + * stream_send() in order to actually transmit the data. Use + * of the buffer is not compulsory; the application may call + * stream_send() on any block of data. + */ + void ( * senddata ) ( struct stream_application *app, + void *data, size_t len ); + /** + * Transmitted data acknowledged + * + * @v app Stream application + * @v len Length of acknowledged data + * + * @c len is guaranteed to not exceed the outstanding amount + * of unacknowledged data. + */ + void ( * acked ) ( struct stream_application *app, size_t len ); + /** + * Receive new data + * + * @v app Stream application + * @v data Data + * @v len Length of data + */ + void ( * newdata ) ( struct stream_application *app, + void *data, size_t len ); +}; + +/** Stream connection-layer operations */ +struct stream_connection_operations { + /** + * Bind to local address + * + * @v conn Stream connection + * @v local Local address + * @ret rc Return status code + */ + int ( * bind ) ( struct stream_connection *conn, + struct sockaddr *local ); + /** + * Connect to remote address + * + * @v conn Stream connection + * @v peer Remote address + * @ret rc Return status code + * + * This initiates the connection. If the connection succeeds, + * the application's connected() method will be called. If + * the connection fails (e.g. due to a timeout), the + * application's closed() method will be called with an + * appropriate error code. + */ + int ( * connect ) ( struct stream_connection *conn, + struct sockaddr *peer ); + /** + * Close connection + * + * @v conn Stream connection + */ + void ( * close ) ( struct stream_connection *conn ); + /** + * Send data via connection + * + * @v conn Stream connection + * @v data Data to send + * @v len Length of data + * @ret rc Return status code + * + * This method should be called only in the context of an + * application's senddata() method. + */ + int ( * send ) ( struct stream_connection *conn, + void *data, size_t len ); + /** + * Notify connection that data is available to send + * + * @v conn Stream connection + * @ret rc Return status code + * + * This will cause the connection to call the application's + * senddata() method. It should be called when the + * application acquires new data to send as a result of + * something external to the data stream (e.g. when iSCSI is + * asked to issue a new command on an otherwise-idle + * connection). Most applications will not need to call this + * method. + */ + int ( * kick ) ( struct stream_connection *conn ); +}; + +/** A stream application */ +struct stream_application { + /** Stream connection, if any + * + * This will be NULL if the stream does not currently have a + * valid connection. + */ + struct stream_connection *conn; + /** Stream application-layer operations */ + struct stream_application_operations *op; +}; + +/** A stream connection */ +struct stream_connection { + /** Stream application, if any + * + * This will be NULL if the stream does not currently have a + * valid application. + */ + struct stream_application *app; + /** Stream connection-layer operations */ + struct stream_connection_operations *op; +}; + +extern void stream_connected ( struct stream_connection *conn ); +extern void stream_closed ( struct stream_connection *conn, int rc ); +extern void stream_senddata ( struct stream_connection *conn, + void *data, size_t len ); +extern void stream_acked ( struct stream_connection *conn, size_t len ); +extern void stream_newdata ( struct stream_connection *conn, + void *data, size_t len ); + +extern int stream_bind ( struct stream_application *app, + struct sockaddr *local ); +extern int stream_connect ( struct stream_application *app, + struct sockaddr *peer ); +extern void stream_close ( struct stream_application *app ); +extern int stream_send ( struct stream_application *app, + void *data, size_t len ); +extern int stream_kick ( struct stream_application *app ); + +#endif /* _GPXE_STREAM_H */