summaryrefslogtreecommitdiffstats
path: root/src/include/gpxe/stream.h
blob: 545bfae79f75fdab0c029e1b77f05535cc3d6eca (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#ifndef _GPXE_STREAM_H
#define _GPXE_STREAM_H

/** @file
 *
 * Stream API
 */

#include <stdint.h>
#include <gpxe/socket.h>

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,
			 const 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_associate ( struct stream_application *app,
			       struct stream_connection *conn );

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,
			 const void *data, size_t len );
extern int stream_kick ( struct stream_application *app );

#endif /* _GPXE_STREAM_H */