xref: /haiku/src/add-ons/kernel/network/protocols/tcp/tcp.cpp (revision 25160e50935c4647beb1f0f07839698c389fdf79)
1 /*
2  * Copyright 2006, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include <net_buffer.h>
11 #include <net_datalink.h>
12 #include <net_protocol.h>
13 #include <net_stack.h>
14 
15 #include <KernelExport.h>
16 #include <util/list.h>
17 
18 #include <netinet/in.h>
19 #include <netinet/ip.h>
20 #include <new>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include <lock.h>
25 #include <util/AutoLock.h>
26 #include <util/khash.h>
27 
28 #include <NetBufferUtilities.h>
29 #include <NetUtilities.h>
30 
31 #define TRACE_TCP
32 #ifdef TRACE_TCP
33 #	define TRACE(x) dprintf x
34 #	define TRACE_BLOCK(x) dump_block x
35 #else
36 #	define TRACE(x)
37 #	define TRACE_BLOCK(x)
38 #endif
39 
40 
41 #define MAX_HASH_TCP	64
42 
43 static net_domain *sDomain;
44 static net_address_module_info *sAddressModule;
45 net_buffer_module_info *sBufferModule;
46 static net_datalink_module_info *sDatalinkModule;
47 static net_stack_module_info *sStackModule;
48 static hash_table *sTCPHash;
49 static benaphore sTCPLock;
50 
51 #include "tcp.h"
52 #include "TCPConnection.h"
53 
54 
55 net_protocol *
56 tcp_init_protocol(net_socket *socket)
57 {
58 	socket->protocol = IPPROTO_TCP;
59 	TCPConnection *protocol = new (std::nothrow) TCPConnection(socket);
60 	if (protocol == NULL)
61 		return NULL;
62 
63 	TRACE(("Created new TCPConnection %p\n", protocol));
64 	return protocol;
65 }
66 
67 
68 status_t
69 tcp_uninit_protocol(net_protocol *protocol)
70 {
71 	delete (TCPConnection *)protocol;
72 	return B_OK;
73 }
74 
75 
76 status_t
77 tcp_open(net_protocol *protocol)
78 {
79 	return ((TCPConnection *)protocol)->Open();
80 }
81 
82 
83 status_t
84 tcp_close(net_protocol *protocol)
85 {
86 	return ((TCPConnection *)protocol)->Close();
87 }
88 
89 
90 status_t
91 tcp_free(net_protocol *protocol)
92 {
93 	return ((TCPConnection *)protocol)->Free();
94 }
95 
96 
97 status_t
98 tcp_connect(net_protocol *protocol, const struct sockaddr *address)
99 {
100 	return ((TCPConnection *)protocol)->Connect(address);
101 }
102 
103 
104 status_t
105 tcp_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
106 {
107 	return ((TCPConnection *)protocol)->Accept(_acceptedSocket);
108 }
109 
110 
111 status_t
112 tcp_control(net_protocol *protocol, int level, int option, void *value,
113 	size_t *_length)
114 {
115 	return protocol->next->module->control(protocol->next, level, option,
116 		value, _length);
117 }
118 
119 
120 status_t
121 tcp_bind(net_protocol *protocol, struct sockaddr *address)
122 {
123 	TRACE(("tcp_bind(%p) on address %s\n", protocol,
124 		AddressString(sDomain, address, true).Data()));
125 	TCPConnection *connection = (TCPConnection *)protocol;
126 	return connection->Bind(address);
127 }
128 
129 
130 status_t
131 tcp_unbind(net_protocol *protocol, struct sockaddr *address)
132 {
133 	return ((TCPConnection *)protocol)->Unbind(address);
134 }
135 
136 
137 status_t
138 tcp_listen(net_protocol *protocol, int count)
139 {
140 	return ((TCPConnection *)protocol)->Listen(count);
141 }
142 
143 
144 status_t
145 tcp_shutdown(net_protocol *protocol, int direction)
146 {
147 	return ((TCPConnection *)protocol)->Shutdown(direction);
148 }
149 
150 
151 status_t
152 tcp_send_data(net_protocol *protocol, net_buffer *buffer)
153 {
154 	return protocol->next->module->send_data(protocol->next, buffer);
155 }
156 
157 
158 status_t
159 tcp_send_routed_data(net_protocol *protocol, struct net_route *route,
160 	net_buffer *buffer)
161 {
162 	return protocol->next->module->send_routed_data(protocol->next, route, buffer);
163 }
164 
165 
166 ssize_t
167 tcp_send_avail(net_protocol *protocol)
168 {
169 	return ((TCPConnection *)protocol)->SendAvailable();
170 }
171 
172 
173 status_t
174 tcp_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
175 	net_buffer **_buffer)
176 {
177 	return ((TCPConnection *)protocol)->ReadData(numBytes, flags, _buffer);
178 }
179 
180 
181 ssize_t
182 tcp_read_avail(net_protocol *protocol)
183 {
184 	return ((TCPConnection *)protocol)->ReadAvailable();
185 }
186 
187 
188 struct net_domain *
189 tcp_get_domain(net_protocol *protocol)
190 {
191 	return protocol->next->module->get_domain(protocol->next);
192 }
193 
194 
195 size_t
196 tcp_get_mtu(net_protocol *protocol, const struct sockaddr *address)
197 {
198 	return protocol->next->module->get_mtu(protocol->next, address);
199 }
200 
201 
202 status_t
203 tcp_receive_data(net_buffer *buffer)
204 {
205 	return B_ERROR;
206 }
207 
208 
209 status_t
210 tcp_error(uint32 code, net_buffer *data)
211 {
212 	return B_ERROR;
213 }
214 
215 
216 status_t
217 tcp_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
218 	void *errorData)
219 {
220 	return B_ERROR;
221 }
222 
223 
224 //	#pragma mark -
225 
226 
227 static status_t
228 tcp_init()
229 {
230 	status_t status;
231 
232 #if 0
233 	sDomain = sStackModule->get_domain(AF_INET);
234 	sAddressModule = sDomain->address_module;
235 #endif
236 
237 	status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule);
238 	if (status < B_OK)
239 		return status;
240 	status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&sBufferModule);
241 	if (status < B_OK)
242 		goto err1;
243 	status = get_module(NET_DATALINK_MODULE_NAME, (module_info **)&sDatalinkModule);
244 	if (status < B_OK)
245 		goto err2;
246 
247 	sTCPHash = hash_init(MAX_HASH_TCP, TCPConnection::HashOffset(),
248 		&TCPConnection::Compare, &TCPConnection::Hash);
249 	if (sTCPHash == NULL)
250 		goto err3;
251 
252 	status = benaphore_init(&sTCPLock, "TCP Hash Lock");
253 	if (status < B_OK)
254 		goto err4;
255 
256 	status = sStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_IP,
257 		"network/protocols/tcp/v1",
258 		"network/protocols/ipv4/v1",
259 		NULL);
260 	if (status < B_OK)
261 		goto err5;
262 
263 	status = sStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_TCP,
264 		"network/protocols/tcp/v1",
265 		"network/protocols/ipv4/v1",
266 		NULL);
267 	if (status < B_OK)
268 		goto err5;
269 
270 	status = sStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_TCP,
271 		"network/protocols/tcp/v1");
272 	if (status < B_OK)
273 		goto err5;
274 
275 	return B_OK;
276 
277 err5:
278 	benaphore_destroy(&sTCPLock);
279 err4:
280 	hash_uninit(sTCPHash);
281 err3:
282 	put_module(NET_DATALINK_MODULE_NAME);
283 err2:
284 	put_module(NET_BUFFER_MODULE_NAME);
285 err1:
286 	put_module(NET_STACK_MODULE_NAME);
287 
288 	TRACE(("init_tcp() fails with %lx (%s)\n", status, strerror(status)));
289 	return status;
290 }
291 
292 
293 static status_t
294 tcp_uninit()
295 {
296 	benaphore_destroy(&sTCPLock);
297 	hash_uninit(sTCPHash);
298 	put_module(NET_DATALINK_MODULE_NAME);
299 	put_module(NET_BUFFER_MODULE_NAME);
300 	put_module(NET_STACK_MODULE_NAME);
301 
302 	return B_OK;
303 }
304 
305 
306 static status_t
307 tcp_std_ops(int32 op, ...)
308 {
309 	switch (op) {
310 		case B_MODULE_INIT:
311 			return tcp_init();
312 
313 		case B_MODULE_UNINIT:
314 			return tcp_uninit();
315 
316 		default:
317 			return B_ERROR;
318 	}
319 }
320 
321 
322 net_protocol_module_info sTCPModule = {
323 	{
324 		"network/protocols/tcp/v1",
325 		0,
326 		tcp_std_ops
327 	},
328 	tcp_init_protocol,
329 	tcp_uninit_protocol,
330 	tcp_open,
331 	tcp_close,
332 	tcp_free,
333 	tcp_connect,
334 	tcp_accept,
335 	tcp_control,
336 	tcp_bind,
337 	tcp_unbind,
338 	tcp_listen,
339 	tcp_shutdown,
340 	tcp_send_data,
341 	tcp_send_routed_data,
342 	tcp_send_avail,
343 	tcp_read_data,
344 	tcp_read_avail,
345 	tcp_get_domain,
346 	tcp_get_mtu,
347 	tcp_receive_data,
348 	tcp_error,
349 	tcp_error_reply,
350 };
351 
352 module_info *modules[] = {
353 	(module_info *)&sTCPModule,
354 	NULL
355 };
356