1/*
2 * Copyright 2010 Andreas Färber <andreas.faerber@web.de>
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6
7/*
8 * NOTE This is a cleanroom TCP implementation with some known issues.
9 * Protection Against Wrapping Sequence (PAWS) needs to be added.
10 * Congestion control needs to be implemented (slow start, recv. window size).
11 * The use of *Packets needs to be re-evaluated in the context of TCP;
12 * probably a singly-linked list of received data chunks is more efficient.
13 * Debug output should be tuned for better aspect oriented tracing.
14 * While Little Endian systems have been considered, this still needs testing.
15 */
16
17
18#include <boot/net/TCP.h>
19
20#include <stdio.h>
21
22#include <KernelExport.h>
23
24#include <boot/net/ChainBuffer.h>
25#include <boot/net/NetStack.h>
26
27#include "real_time_clock.h"
28
29
30//#define TRACE_TCP
31//#define TRACE_TCP_RANDOMNESS
32//#define TRACE_TCP_CHECKSUM
33//#define TRACE_TCP_QUEUE
34
35
36#ifdef TRACE_TCP
37#	define TRACE(x, ...) dprintf(x, ## __VA_ARGS__)
38#else
39#	define TRACE(x, ...) ;
40#endif
41#ifdef TRACE_TCP_RANDOMNESS
42#	define TRACE_PORT(x, ...) dprintf(x, ## __VA_ARGS__)
43#else
44#	define TRACE_PORT(x, ...) ;
45#endif
46#if defined(TRACE_TCP_CHECKSUM)
47#	define TRACE_CHECKSUM(x, ...) dprintf(x, ## __VA_ARGS__)
48#else
49#	define TRACE_CHECKSUM(x, ...) ;
50#endif
51#if defined(TRACE_TCP_QUEUE)
52#	define TRACE_QUEUE(x, ...) dprintf(x, ## __VA_ARGS__)
53#else
54#	define TRACE_QUEUE(x, ...) ;
55#endif
56
57
58static unsigned int
59_rand32(void)
60{
61	static unsigned int next = 0;
62	if (next == 0)
63		next = real_time_clock_usecs() / 1000000;
64
65	next = (next >> 1) ^ (unsigned int)((0 - (next & 1U)) & 0xd0000001U);
66		// characteristic polynomial: x^32 + x^31 + x^29 + x + 1
67	return next;
68}
69
70
71static unsigned short
72_rand14(void)
73{
74	// TODO: Find suitable generator polynomial.
75	return _rand32() & 0x3fff;
76}
77
78
79TCPPacket::TCPPacket()
80	:
81	fData(NULL),
82	fNext(NULL)
83{
84}
85
86
87TCPPacket::~TCPPacket()
88{
89	free(fData);
90}
91
92
93status_t
94TCPPacket::SetTo(const void* data, size_t size, ip_addr_t sourceAddress,
95	uint16 sourcePort, ip_addr_t destinationAddress, uint16 destinationPort,
96	uint32 sequenceNumber, uint32 acknowledgmentNumber, uint8 flags)
97{
98	if (data == NULL && size > 0)
99		return B_BAD_VALUE;
100
101	if (size > 0) {
102		fData = malloc(size);
103		if (fData == NULL)
104			return B_NO_MEMORY;
105		memcpy(fData, data, size);
106	} else
107		fData = NULL;
108
109	fSize = size;
110	fSourceAddress = sourceAddress;
111	fSourcePort = sourcePort;
112	fDestinationAddress = destinationAddress;
113	fDestinationPort = destinationPort;
114	fSequenceNumber = sequenceNumber;
115	fAcknowledgmentNumber = acknowledgmentNumber;
116	fFlags = flags;
117
118	return B_OK;
119}
120
121
122ip_addr_t
123TCPPacket::SourceAddress() const
124{
125	return fSourceAddress;
126}
127
128
129ip_addr_t
130TCPPacket::DestinationAddress() const
131{
132	return fDestinationAddress;
133}
134
135
136uint16
137TCPPacket::SourcePort() const
138{
139	return fSourcePort;
140}
141
142
143uint16
144TCPPacket::DestinationPort() const
145{
146	return fDestinationPort;
147}
148
149
150uint32
151TCPPacket::SequenceNumber() const
152{
153	return fSequenceNumber;
154}
155
156
157uint32
158TCPPacket::AcknowledgmentNumber() const
159{
160	return fAcknowledgmentNumber;
161}
162
163
164bool
165TCPPacket::ProvidesSequenceNumber(uint32 sequenceNumber) const
166{
167	// TODO PAWS
168	return fSequenceNumber <= sequenceNumber
169		&& fSequenceNumber + fSize > sequenceNumber;
170}
171
172
173TCPPacket*
174TCPPacket::Next() const
175{
176	return fNext;
177}
178
179
180void
181TCPPacket::SetNext(TCPPacket* packet)
182{
183	fNext = packet;
184}
185
186
187
188
189TCPSocket::TCPSocket()
190	:
191	fTCPService(NetStack::Default()->GetTCPService()),
192	fAddress(INADDR_ANY),
193	fPort(0),
194	fSequenceNumber(0),
195	fFirstPacket(NULL),
196	fLastPacket(NULL),
197	fFirstSentPacket(NULL),
198	fLastSentPacket(NULL),
199	fState(TCP_SOCKET_STATE_INITIAL),
200	fRemoteState(TCP_SOCKET_STATE_INITIAL)
201{
202}
203
204
205TCPSocket::~TCPSocket()
206{
207	if (fTCPService != NULL && fPort != 0)
208		fTCPService->UnbindSocket(this);
209}
210
211
212uint16
213TCPSocket::WindowSize() const
214{
215	// TODO A large window size leads to read timeouts
216	// due to resends occuring too late.
217#if 0
218	size_t windowSize = 0xffff;
219	for (TCPPacket* packet = fFirstPacket;
220			packet != NULL && windowSize > packet->DataSize();
221			packet = packet->Next())
222		windowSize -= packet->DataSize();
223	return windowSize;
224#else
225	return 4096;
226#endif
227}
228
229
230status_t
231TCPSocket::Connect(ip_addr_t address, uint16 port)
232{
233	fRemoteAddress = address;
234	fRemotePort = port;
235	fSequenceNumber = _rand32();
236	fPort = 0xC000 + (_rand14() & ~0xc000);
237	TRACE_PORT("TCPSocket::Connect(): connecting from port %u\n", fPort);
238	fAcknowledgeNumber = 0;
239	fNextSequence = 0;
240
241	status_t error = fTCPService->BindSocket(this);
242	if (error != B_OK)
243		return error;
244
245	// send SYN
246	TCPPacket* packet = new(nothrow) TCPPacket();
247	if (packet == NULL)
248		return B_NO_MEMORY;
249	error = packet->SetTo(NULL, 0, fAddress, fPort, address, port,
250		fSequenceNumber, fAcknowledgeNumber, TCP_SYN);
251	if (error != B_OK) {
252		delete packet;
253		return error;
254	}
255	error = _Send(packet);
256	if (error != B_OK)
257		return error;
258	fState = TCP_SOCKET_STATE_SYN_SENT;
259	fSequenceNumber++;
260	TRACE("SYN sent\n");
261
262	// receive SYN-ACK
263	error = _WaitForState(TCP_SOCKET_STATE_OPEN, 1000000LL);
264	if (error != B_OK) {
265		TRACE("no SYN-ACK received\n");
266		return error;
267	}
268	TRACE("SYN-ACK received\n");
269
270	return B_OK;
271}
272
273
274status_t
275TCPSocket::Close()
276{
277	// send FIN
278	TCPPacket* packet = new(nothrow) TCPPacket();
279	if (packet == NULL)
280		return B_NO_MEMORY;
281	status_t error = packet->SetTo(NULL, 0, fAddress, fPort, fRemoteAddress,
282		fRemotePort, fSequenceNumber, fAcknowledgeNumber, TCP_FIN | TCP_ACK);
283	if (error != B_OK) {
284		delete packet;
285		return error;
286	}
287	error = _Send(packet);
288	if (error != B_OK)
289		return error;
290	fState = TCP_SOCKET_STATE_FIN_SENT;
291	TRACE("FIN sent\n");
292
293	error = _WaitForState(TCP_SOCKET_STATE_CLOSED, 1000000LL);
294	if (error != B_OK)
295		return error;
296
297	return B_OK;
298}
299
300
301status_t
302TCPSocket::Read(void* buffer, size_t bufferSize, size_t* bytesRead,
303	bigtime_t timeout)
304{
305	TRACE("TCPSocket::Read(): size = %lu\n", bufferSize);
306	if (bytesRead == NULL)
307		return B_BAD_VALUE;
308
309	*bytesRead = 0;
310	TCPPacket* packet = NULL;
311
312	bigtime_t startTime = system_time();
313	do {
314		fTCPService->ProcessIncomingPackets();
315		//_ResendQueue();
316		packet = _PeekPacket();
317		if (packet == NULL && fRemoteState != TCP_SOCKET_STATE_OPEN)
318			return B_ERROR;
319		if (packet == NULL && timeout > 0LL)
320			_Ack();
321	} while (packet == NULL && system_time() - startTime < timeout);
322	if (packet == NULL) {
323#ifdef TRACE_TCP_QUEUE
324		_DumpQueue();
325#endif
326		return (timeout == 0) ? B_WOULD_BLOCK : B_TIMED_OUT;
327	}
328	uint32 packetOffset = fNextSequence - packet->SequenceNumber();
329	size_t readBytes = packet->DataSize() - packetOffset;
330	if (readBytes > bufferSize)
331		readBytes = bufferSize;
332	if (buffer != NULL)
333		memcpy(buffer, (uint8*)packet->Data() + packetOffset, readBytes);
334	*bytesRead = readBytes;
335	if (!packet->ProvidesSequenceNumber(fNextSequence + readBytes)) {
336		_DequeuePacket();
337		delete packet;
338		packet = NULL;
339	}
340	fNextSequence += readBytes;
341
342	if (packet == NULL && *bytesRead < bufferSize) {
343		do {
344			if (buffer != NULL)
345				buffer = (uint8*)buffer + readBytes;
346			bufferSize -= readBytes;
347			fTCPService->ProcessIncomingPackets();
348			packet = _PeekPacket();
349			if (packet == NULL && fRemoteState != TCP_SOCKET_STATE_OPEN)
350				break;
351			readBytes = 0;
352			if (packet == NULL) {
353				_Ack();
354				continue;
355			}
356			readBytes = packet->DataSize();
357			if (readBytes > bufferSize)
358				readBytes = bufferSize;
359			if (buffer != NULL)
360				memcpy(buffer, packet->Data(), readBytes);
361			*bytesRead += readBytes;
362			if (readBytes == packet->DataSize()) {
363				_DequeuePacket();
364				delete packet;
365			}
366			fNextSequence += readBytes;
367		} while (readBytes < bufferSize &&
368			system_time() - startTime < timeout);
369#ifdef TRACE_TCP_QUEUE
370		if (readBytes < bufferSize) {
371			TRACE_QUEUE("TCP: Unable to deliver more data!\n");
372			_DumpQueue();
373		}
374#endif
375	}
376
377	return B_OK;
378}
379
380
381status_t
382TCPSocket::Write(const void* buffer, size_t bufferSize)
383{
384	if (buffer == NULL || bufferSize == 0)
385		return B_BAD_VALUE;
386
387	// TODO: Check for MTU and create multiple packets if necessary.
388
389	TCPPacket* packet = new(nothrow) TCPPacket();
390	if (packet == NULL)
391		return B_NO_MEMORY;
392	status_t error = packet->SetTo(buffer, bufferSize, fAddress, fPort,
393		fRemoteAddress, fRemotePort, fSequenceNumber, fAcknowledgeNumber,
394		TCP_ACK);
395	if (error != B_OK) {
396		delete packet;
397		return error;
398	}
399	return _Send(packet);
400}
401
402
403void
404TCPSocket::Acknowledge(uint32 number)
405{
406	TRACE("TCPSocket::Acknowledge(): %lu\n", number);
407	// dequeue packets
408	for (TCPPacket* packet = fFirstSentPacket; packet != NULL;
409			packet = fFirstSentPacket) {
410		if (packet->SequenceNumber() >= number)
411			return;
412		fFirstSentPacket = packet->Next();
413		delete packet;
414	}
415	fLastSentPacket = NULL;
416}
417
418
419void
420TCPSocket::ProcessPacket(TCPPacket* packet)
421{
422	TRACE("TCPSocket::ProcessPacket()\n");
423
424	if ((packet->Flags() & TCP_FIN) != 0) {
425		fRemoteState = TCP_SOCKET_STATE_FIN_SENT;
426		TRACE("FIN received\n");
427		_Ack();
428	}
429
430	if (fState == TCP_SOCKET_STATE_SYN_SENT) {
431		if ((packet->Flags() & TCP_SYN) != 0
432				&& (packet->Flags() & TCP_ACK) != 0) {
433			fNextSequence = fAcknowledgeNumber = packet->SequenceNumber() + 1;
434			fRemoteState = TCP_SOCKET_STATE_SYN_SENT;
435			delete packet;
436			_Ack();
437			fState = fRemoteState = TCP_SOCKET_STATE_OPEN;
438			return;
439		}
440	} else if (fState == TCP_SOCKET_STATE_OPEN) {
441	} else if (fState == TCP_SOCKET_STATE_FIN_SENT) {
442		if ((packet->Flags() & TCP_ACK) != 0) {
443			TRACE("FIN-ACK received\n");
444			if (fRemoteState == TCP_SOCKET_STATE_FIN_SENT)
445				fState = TCP_SOCKET_STATE_CLOSED;
446		}
447	}
448
449	if (packet->DataSize() == 0) {
450		TRACE("TCPSocket::ProcessPacket(): not queuing due to lack of data\n");
451		delete packet;
452		return;
453	}
454
455	// For now rather protect us against being flooded with packets already
456	// acknowledged. "If it's important, they'll send it again."
457	// TODO PAWS
458	if (packet->SequenceNumber() < fAcknowledgeNumber) {
459		TRACE_QUEUE("TCPSocket::ProcessPacket(): not queuing due to wraparound\n");
460		delete packet;
461		return;
462	}
463
464	if (fLastPacket == NULL) {
465		// no packets enqueued
466		TRACE("TCPSocket::ProcessPacket(): first in queue\n");
467		packet->SetNext(NULL);
468		fFirstPacket = fLastPacket = packet;
469	} else if (fLastPacket->SequenceNumber() < packet->SequenceNumber()) {
470		// enqueue in back
471		TRACE("TCPSocket::ProcessPacket(): enqueue in back\n");
472		packet->SetNext(NULL);
473		fLastPacket->SetNext(packet);
474		fLastPacket = packet;
475	} else if (fFirstPacket->SequenceNumber() > packet->SequenceNumber()) {
476		// enqueue in front
477		TRACE("TCPSocket::ProcessPacket(): enqueue in front\n");
478		TRACE_QUEUE("TCP: Enqueuing %lx - %lx in front! (next is %lx)\n",
479			packet->SequenceNumber(),
480			packet->SequenceNumber() + packet->DataSize() - 1,
481			fNextSequence);
482		packet->SetNext(fFirstPacket);
483		fFirstPacket = packet;
484	} else if (fFirstPacket->SequenceNumber() == packet->SequenceNumber()) {
485		TRACE_QUEUE("%s(): dropping due to identical first packet\n", __func__);
486		delete packet;
487		return;
488	} else {
489		// enqueue in middle
490		TRACE("TCPSocket::ProcessPacket(): enqueue in middle\n");
491		for (TCPPacket* queuedPacket = fFirstPacket; queuedPacket != NULL;
492				queuedPacket = queuedPacket->Next()) {
493			if (queuedPacket->SequenceNumber() == packet->SequenceNumber()) {
494				TRACE_QUEUE("TCPSocket::EnqueuePacket(): TCP packet dropped\n");
495				// we may be waiting for a previous packet
496				delete packet;
497				return;
498			}
499			if (queuedPacket->Next()->SequenceNumber()
500					> packet->SequenceNumber()) {
501				packet->SetNext(queuedPacket->Next());
502				queuedPacket->SetNext(packet);
503				break;
504			}
505		}
506	}
507	while (packet != NULL && packet->SequenceNumber() == fAcknowledgeNumber) {
508		fAcknowledgeNumber = packet->SequenceNumber() + packet->DataSize();
509		packet = packet->Next();
510	}
511}
512
513
514TCPPacket*
515TCPSocket::_PeekPacket()
516{
517	TRACE("TCPSocket::_PeekPacket(): fNextSequence = %lu\n", fNextSequence);
518	for (TCPPacket* packet = fFirstPacket; packet != NULL;
519			packet = packet->Next()) {
520		if (packet->ProvidesSequenceNumber(fNextSequence))
521			return packet;
522	}
523	return NULL;
524}
525
526
527TCPPacket*
528TCPSocket::_DequeuePacket()
529{
530	//TRACE("TCPSocket::DequeuePacket()\n");
531	if (fFirstPacket == NULL)
532		return NULL;
533
534	if (fFirstPacket->ProvidesSequenceNumber(fNextSequence)) {
535		TCPPacket* packet = fFirstPacket;
536		fFirstPacket = packet->Next();
537		if (fFirstPacket == NULL)
538			fLastPacket = NULL;
539		packet->SetNext(NULL);
540		TRACE("TCP: Dequeuing %lx - %lx from front.\n",
541			packet->SequenceNumber(),
542			packet->SequenceNumber() + packet->DataSize() - 1);
543		return packet;
544	}
545
546	for (TCPPacket* packet = fFirstPacket;
547			packet != NULL && packet->Next() != NULL;
548			packet = packet->Next()) {
549		if (packet->Next()->ProvidesSequenceNumber(fNextSequence)) {
550			TCPPacket* nextPacket = packet->Next();
551			packet->SetNext(nextPacket->Next());
552			if (fLastPacket == nextPacket)
553				fLastPacket = packet;
554			TRACE("TCP: Dequeuing %lx - %lx.\n",
555				nextPacket->SequenceNumber(),
556				nextPacket->SequenceNumber() + nextPacket->DataSize() - 1);
557			return nextPacket;
558		}
559	}
560	TRACE_QUEUE("dequeue failed!\n");
561	return NULL;
562}
563
564
565status_t
566TCPSocket::_Send(TCPPacket* packet, bool enqueue)
567{
568	ChainBuffer buffer((void*)packet->Data(), packet->DataSize());
569	status_t error = fTCPService->Send(fPort, fRemoteAddress, fRemotePort,
570		packet->SequenceNumber(), fAcknowledgeNumber, packet->Flags(),
571		WindowSize(), &buffer);
572	if (error != B_OK)
573		return error;
574	if (packet->SequenceNumber() == fSequenceNumber)
575		fSequenceNumber += packet->DataSize();
576
577	if (enqueue)
578		_EnqueueOutgoingPacket(packet);
579
580	return B_OK;
581}
582
583
584status_t
585TCPSocket::_ResendQueue()
586{
587	TRACE("resending queue\n");
588	for (TCPPacket* packet = fFirstSentPacket; packet != NULL;
589			packet = packet->Next()) {
590		ChainBuffer buffer((void*)packet->Data(), packet->DataSize());
591		status_t error = fTCPService->Send(fPort, fRemoteAddress, fRemotePort,
592			packet->SequenceNumber(), fAcknowledgeNumber, packet->Flags(),
593			WindowSize(), &buffer);
594		if (error != B_OK)
595			return error;
596	}
597	return B_OK;
598}
599
600
601void
602TCPSocket::_EnqueueOutgoingPacket(TCPPacket* packet)
603{
604	if (fLastSentPacket != NULL) {
605		fLastSentPacket->SetNext(packet);
606		fLastSentPacket = packet;
607	} else {
608		fFirstSentPacket = fLastSentPacket = packet;
609	}
610}
611
612
613#ifdef TRACE_TCP_QUEUE
614
615inline void
616TCPSocket::_DumpQueue()
617{
618	TRACE_QUEUE("TCP: waiting for %lx (ack'ed %lx)\n", fNextSequence, fAcknowledgeNumber);
619	if (fFirstPacket == NULL)
620		TRACE_QUEUE("TCP: Queue is empty.\n");
621	else {
622		for (TCPPacket* packet = fFirstPacket; packet != NULL;
623				packet = packet->Next()) {
624			TRACE_QUEUE("TCP: Queue: %lx\n", packet->SequenceNumber());
625		}
626	}
627	if (fFirstSentPacket != NULL)
628		TRACE_QUEUE("TCP: Send queue is non-empty.\n");
629	else
630		TRACE_QUEUE("TCP: Send queue is empty.\n");
631}
632
633#endif
634
635
636status_t
637TCPSocket::_Ack()
638{
639	TCPPacket* packet = new(nothrow) TCPPacket();
640	if (packet == NULL)
641		return B_NO_MEMORY;
642	status_t error = packet->SetTo(NULL, 0, fAddress, fPort, fRemoteAddress,
643		fRemotePort, fSequenceNumber, fAcknowledgeNumber, TCP_ACK);
644	if (error != B_OK) {
645		delete packet;
646		return error;
647	}
648	error = _Send(packet, false);
649	delete packet;
650	if (error != B_OK)
651		return error;
652	return B_OK;
653}
654
655
656status_t
657TCPSocket::_WaitForState(TCPSocketState state, bigtime_t timeout)
658{
659	if (fTCPService == NULL)
660		return B_NO_INIT;
661
662	bigtime_t startTime = system_time();
663	do {
664		fTCPService->ProcessIncomingPackets();
665		if (fState == state)
666			return B_OK;
667	} while (system_time() - startTime < timeout);
668	return timeout == 0 ? B_WOULD_BLOCK : B_TIMED_OUT;
669}
670
671
672
673
674TCPService::TCPService(IPService* ipService)
675	:
676	IPSubService(kTCPServiceName),
677	fIPService(ipService)
678{
679}
680
681
682TCPService::~TCPService()
683{
684	if (fIPService != NULL)
685		fIPService->UnregisterIPSubService(this);
686}
687
688
689status_t
690TCPService::Init()
691{
692	if (fIPService == NULL)
693		return B_BAD_VALUE;
694
695	if (!fIPService->RegisterIPSubService(this))
696		return B_NO_MEMORY;
697
698	return B_OK;
699}
700
701
702uint8
703TCPService::IPProtocol() const
704{
705	return IPPROTO_TCP;
706}
707
708
709void
710TCPService::HandleIPPacket(IPService* ipService, ip_addr_t sourceIP,
711	ip_addr_t destinationIP, const void* data, size_t size)
712{
713	TRACE("TCPService::HandleIPPacket(): source = %08lx, "
714		"destination = %08lx, %lu - %lu bytes\n", sourceIP, destinationIP,
715		size, sizeof(tcp_header));
716
717	if (data == NULL || size < sizeof(tcp_header))
718		return;
719
720	const tcp_header* header = (const tcp_header*)data;
721
722	uint16 chksum = _ChecksumData(data, size, sourceIP, destinationIP);
723	if (chksum != 0) {
724		TRACE_CHECKSUM("TCPService::HandleIPPacket(): invalid checksum "
725			"(%04x vs. %04x), padding %lu\n",
726			header->checksum, chksum, size % 2);
727		return;
728	}
729
730	uint16 source = ntohs(header->source);
731	uint16 destination = ntohs(header->destination);
732	uint32 sequenceNumber = ntohl(header->seqNumber);
733	uint32 ackedNumber = ntohl(header->ackNumber);
734	TRACE("\tsource = %u, dest = %u, seq = %lu, ack = %lu, dataOffset = %u, "
735		"flags %s %s %s %s\n", source, destination, sequenceNumber,
736		ackedNumber, header->dataOffset,
737		(header->flags & TCP_ACK) != 0 ? "ACK" : "",
738		(header->flags & TCP_SYN) != 0 ? "SYN" : "",
739		(header->flags & TCP_FIN) != 0 ? "FIN" : "",
740		(header->flags & TCP_RST) != 0 ? "RST" : "");
741	if (header->dataOffset > 5) {
742		uint8* option = (uint8*)data + sizeof(tcp_header);
743		while ((uint32*)option < (uint32*)data + header->dataOffset) {
744			uint8 optionKind = option[0];
745			if (optionKind == 0)
746				break;
747			uint8 optionLength = 1;
748			if (optionKind > 1) {
749				optionLength = option[1];
750				TRACE("\tTCP option kind %u, length %u\n",
751					optionKind, optionLength);
752				if (optionKind == 2)
753					TRACE("\tTCP MSS = %04hu\n", *(uint16_t*)&option[2]);
754			}
755			option += optionLength;
756		}
757	}
758
759	TCPSocket* socket = _FindSocket(destinationIP, destination);
760	if (socket == NULL) {
761		// TODO If SYN, answer with RST?
762		TRACE("TCPService::HandleIPPacket(): no socket\n");
763		return;
764	}
765
766	if ((header->flags & TCP_ACK) != 0) {
767		socket->Acknowledge(ackedNumber);
768	}
769
770	TCPPacket* packet = new(nothrow) TCPPacket();
771	if (packet == NULL)
772		return;
773	status_t error = packet->SetTo((uint32*)data + header->dataOffset,
774		size - header->dataOffset * 4, sourceIP, source, destinationIP,
775		destination, sequenceNumber, ackedNumber, header->flags);
776	if (error == B_OK)
777		socket->ProcessPacket(packet);
778	else
779		delete packet;
780}
781
782
783status_t
784TCPService::Send(uint16 sourcePort, ip_addr_t destinationAddress,
785	uint16 destinationPort, uint32 sequenceNumber,
786	uint32 acknowledgmentNumber, uint8 flags, uint16 windowSize,
787	ChainBuffer* buffer)
788{
789	TRACE("TCPService::Send(): seq = %lu, ack = %lu\n",
790		sequenceNumber, acknowledgmentNumber);
791	if (fIPService == NULL)
792		return B_NO_INIT;
793	if (buffer == NULL)
794		return B_BAD_VALUE;
795
796	tcp_header header;
797	ChainBuffer headerBuffer(&header, sizeof(header), buffer);
798	memset(&header, 0, sizeof(header));
799	header.source = htons(sourcePort);
800	header.destination = htons(destinationPort);
801	header.seqNumber = htonl(sequenceNumber);
802	header.ackNumber = htonl(acknowledgmentNumber);
803	header.dataOffset = 5;
804	header.flags = flags;
805	header.window = htons(windowSize);
806
807	header.checksum = 0;
808	header.checksum = htons(_ChecksumBuffer(&headerBuffer,
809		fIPService->IPAddress(), destinationAddress,
810		headerBuffer.TotalSize()));
811
812	return fIPService->Send(destinationAddress, IPPROTO_TCP, &headerBuffer);
813}
814
815
816void
817TCPService::ProcessIncomingPackets()
818{
819	if (fIPService != NULL)
820		fIPService->ProcessIncomingPackets();
821}
822
823
824status_t
825TCPService::BindSocket(TCPSocket* socket)
826{
827	if (socket == NULL)
828		return B_BAD_VALUE;
829
830	if (_FindSocket(socket->Address(), socket->Port()) != NULL)
831		return EADDRINUSE;
832
833	return fSockets.Add(socket);
834}
835
836
837void
838TCPService::UnbindSocket(TCPSocket* socket)
839{
840	fSockets.Remove(socket);
841}
842
843
844uint16
845TCPService::_ChecksumBuffer(ChainBuffer* buffer, ip_addr_t source,
846	ip_addr_t destination, uint16 length)
847{
848	struct pseudo_header {
849		ip_addr_t	source;
850		ip_addr_t	destination;
851		uint8		pad;
852		uint8		protocol;
853		uint16		length;
854	} __attribute__ ((__packed__));
855	pseudo_header header = {
856		htonl(source),
857		htonl(destination),
858		0,
859		IPPROTO_TCP,
860		htons(length)
861	};
862
863	ChainBuffer headerBuffer(&header, sizeof(header), buffer);
864	uint16 checksum = ip_checksum(&headerBuffer);
865	headerBuffer.DetachNext();
866	return checksum;
867}
868
869
870uint16
871TCPService::_ChecksumData(const void* data, uint16 length, ip_addr_t source,
872	ip_addr_t destination)
873{
874	ChainBuffer buffer((void*)data, length);
875	return _ChecksumBuffer(&buffer, source, destination, length);
876}
877
878
879TCPSocket*
880TCPService::_FindSocket(ip_addr_t address, uint16 port)
881{
882	for (int i = 0; i < fSockets.Count(); i++) {
883		TCPSocket* socket = fSockets.ElementAt(i);
884		// TODO Remove socket->Address() INADDR_ANY check once the socket is
885		// aware of both its IP addresses (local one is INADDR_ANY for now).
886		if ((address == INADDR_ANY || socket->Address() == INADDR_ANY
887					|| socket->Address() == address)
888				&& socket->Port() == port) {
889			return socket;
890		}
891	}
892	return NULL;
893}
894