Add insert_filter() function
[people/xl0/gpxe.git] / src / net / filter.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  * Filter streams
23  */
24
25 #include <stddef.h>
26 #include <errno.h>
27 #include <gpxe/stream.h>
28 #include <gpxe/filter.h>
29
30 /**
31  * Connection established
32  *
33  * @v app               Stream application
34  */
35 void filter_connected ( struct stream_application *app ) {
36         struct filter_stream *filter = 
37                 container_of ( app, struct filter_stream, downstream );
38
39         stream_connected ( &filter->upstream );
40 }
41
42 /**
43  * Connection closed
44  *
45  * @v app               Stream application
46  * @v rc                Error code, if any
47  */
48 void filter_closed ( struct stream_application *app, int rc ) {
49         struct filter_stream *filter = 
50                 container_of ( app, struct filter_stream, downstream );
51
52         stream_closed ( &filter->upstream, rc );
53 }
54
55 /**
56  * Transmit data
57  *
58  * @v app               Stream application
59  * @v buf               Temporary data buffer
60  * @v len               Length of temporary data buffer
61  */
62 void filter_senddata ( struct stream_application *app,
63                        void *data, size_t len ) {
64         struct filter_stream *filter = 
65                 container_of ( app, struct filter_stream, downstream );
66
67         stream_senddata ( &filter->upstream, data, len );
68 }
69
70 /**
71  * Transmitted data acknowledged
72  *
73  * @v app               Stream application
74  * @v len               Length of acknowledged data
75  */
76 void filter_acked ( struct stream_application *app, size_t len ) {
77         struct filter_stream *filter = 
78                 container_of ( app, struct filter_stream, downstream );
79
80         stream_acked ( &filter->upstream, len );
81 }
82
83 /**
84  * Receive new data
85  *
86  * @v app               Stream application
87  * @v data              Data
88  * @v len               Length of data
89  */
90 void filter_newdata ( struct stream_application *app,
91                       void *data, size_t len ) {
92         struct filter_stream *filter = 
93                 container_of ( app, struct filter_stream, downstream );
94
95         stream_newdata ( &filter->upstream, data, len );
96 }
97
98 /**
99  * Bind to local address
100  *
101  * @v conn              Stream connection
102  * @v local             Local address
103  * @ret rc              Return status code
104  */
105 int filter_bind ( struct stream_connection *conn, struct sockaddr *local ) {
106         struct filter_stream *filter = 
107                 container_of ( conn, struct filter_stream, upstream );
108
109         return stream_bind ( &filter->downstream, local );
110 }
111
112 /**
113  * Connect to remote address
114  *
115  * @v conn              Stream connection
116  * @v peer              Remote address
117  * @ret rc              Return status code
118  */
119 int filter_connect ( struct stream_connection *conn, struct sockaddr *peer ) {
120         struct filter_stream *filter = 
121                 container_of ( conn, struct filter_stream, upstream );
122
123         return stream_connect ( &filter->downstream, peer );
124 }
125
126 /**
127  * Close connection
128  *
129  * @v conn              Stream connection
130  */
131 void filter_close ( struct stream_connection *conn ) {
132         struct filter_stream *filter = 
133                 container_of ( conn, struct filter_stream, upstream );
134
135         stream_close ( &filter->downstream );
136 }
137
138 /**
139  * Send data via connection
140  *
141  * @v conn              Stream connection
142  * @v data              Data to send
143  * @v len               Length of data
144  * @ret rc              Return status code
145  */
146 int filter_send ( struct stream_connection *conn, void *data, size_t len ) {
147         struct filter_stream *filter = 
148                 container_of ( conn, struct filter_stream, upstream );
149
150         return stream_send ( &filter->downstream, data, len );
151 }
152
153 /**
154  * Notify connection that data is available to send
155  *
156  * @v conn              Stream connection
157  * @ret rc              Return status code
158  */
159 int filter_kick ( struct stream_connection *conn ) {
160         struct filter_stream *filter = 
161                 container_of ( conn, struct filter_stream, upstream );
162
163         return stream_kick ( &filter->downstream );
164 }
165
166 /**
167  * Insert filter into stream
168  *
169  * @v app               Stream application
170  * @v filter            Filter stream
171  * @ret rc              Return status code
172  */
173 int insert_filter ( struct stream_application *app,
174                     struct filter_stream *filter ) {
175         struct stream_connection *conn = app->conn;
176
177         if ( ! app->conn ) {
178                 DBGC ( filter, "Filter %p cannot insert onto closed stream\n",
179                        filter );
180                 return -ENOTCONN;
181         }
182
183         app->conn = &filter->upstream;
184         conn->app = &filter->downstream;
185
186         return 0;
187 }