Beginning of TCP implementation

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18478 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Andrew Galante 2006-08-11 00:26:36 +00:00
parent 55475b6493
commit 6bfaab8ab3
2 changed files with 333 additions and 39 deletions

View File

@ -0,0 +1,203 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrew Galante, haiku.galante@gmail.com
*/
typedef struct {
in_addr_t source;
in_addr_t destination;
uint16 source_port;
uint16 destination_port;
} tcp_connection_key;
class TCPConnection : public net_protocol {
public:
TCPConnection(net_socket *socket);
~TCPConnection();
status_t Open();
status_t Close();
status_t Free();
status_t Connect(const struct sockaddr *address);
status_t Accept(struct net_socket **_acceptedSocket);
status_t Bind(struct sockaddr *address);
status_t Unbind(struct sockaddr *address);
status_t Listen(int count);
status_t Shutdown(int direction);
status_t SendData(net_buffer *buffer);
status_t SendRoutedData(net_route *route, net_buffer *buffer);
status_t SendAvailable();
status_t ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer);
status_t ReadAvailable();
static int Compare(void *_packet, const void *_key);
static uint32 Hash(void *_packet, const void *_key, uint32 range);
static int32 HashOffset() { return offsetof(TCPConnection, fHashLink); }
private:
TCPConnection *fHashLink;
tcp_state fState;
benaphore fLock;
public:
tcp_connection_key fKey;
};
TCPConnection::TCPConnection(net_socket *socket)
:
fState(CLOSED)
{
benaphore_init(&fLock, "TCPConnection");
}
TCPConnection::~TCPConnection()
{
benaphore_destroy(&fLock);
}
status_t
TCPConnection::Open()
{
return B_OK;
}
status_t
TCPConnection::Close()
{
return B_OK;
}
status_t
TCPConnection::Free()
{
return B_OK;
}
status_t
TCPConnection::Connect(const struct sockaddr *address)
{
return B_OK;
}
status_t
TCPConnection::Accept(struct net_socket **_acceptedSocket)
{
return B_OK;
}
status_t
TCPConnection::Bind(sockaddr *address)
{
if (address->sa_family != AF_INET)
return EAFNOSUPPORT;
BenaphoreLocker lock(&fLock);
// let IP check whether there is an interface that supports the given address:
status_t status = next->module->bind(next, address);
if (status < B_OK)
return status;
//TODO: clean this up
/* fKey.source = ((struct sockaddr_in *)address)->sin_addr;
fKey.source_port = sAddressModule->get_port(address);
fKey.destination = INADDR_ANY;
fKey.destination_port = 0;*/
return B_OK;
}
status_t
TCPConnection::Unbind(struct sockaddr *address)
{
return B_OK;
}
status_t
TCPConnection::Listen(int count)
{
return B_OK;
}
status_t
TCPConnection::Shutdown(int direction)
{
return B_OK;
}
status_t
TCPConnection::SendData(net_buffer *buffer)
{
return B_ERROR;
}
status_t
TCPConnection::SendRoutedData(net_route *route, net_buffer *buffer)
{
return B_ERROR;
}
status_t
TCPConnection::SendAvailable()
{
return B_ERROR;
}
status_t
TCPConnection::ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer)
{
return B_ERROR;
}
status_t
TCPConnection::ReadAvailable()
{
return B_ERROR;
}
int
TCPConnection::Compare(void *_packet, const void *_key)
{
const tcp_connection_key *key = (tcp_connection_key *)_key;
tcp_connection_key *packetKey = &((TCPConnection *)_packet)->fKey;
if (key->source == packetKey->source
&& key->destination == packetKey->destination
&& key->source_port == packetKey->source_port
&& key->destination_port == packetKey->destination_port)
return 0;
return 1;
}
uint32
TCPConnection::Hash(void *_packet, const void *_key, uint32 range)
{
const tcp_connection_key *key = (tcp_connection_key *)_key;
if (_packet != NULL)
key = &((TCPConnection *)_packet)->fKey;
return ((uint32)key->source_port << 16 ^ (uint32)key->destination_port
^ key->source ^ key->destination) % range;
}

View File

@ -7,6 +7,8 @@
*/
#include <net_buffer.h>
#include <net_datalink.h>
#include <net_protocol.h>
#include <net_stack.h>
@ -14,22 +16,51 @@
#include <util/list.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <util/khash.h>
#include <NetBufferUtilities.h>
#include <NetUtilities.h>
#define TRACE_TCP
#ifdef TRACE_TCP
# define TRACE(x) dprintf x
# define TRACE_BLOCK(x) dump_block x
#else
# define TRACE(x)
# define TRACE_BLOCK(x)
#endif
#define MAX_HASH_TCP 64
static net_domain *sDomain;
static net_address_module_info *sAddressModule;
//static net_buffer_module_info *sBufferModule;
static net_datalink_module_info *sDatalinkModule;
static net_stack_module_info *sStackModule;
static hash_table *sTCPHash;
static benaphore sTCPLock;
#include "tcp.h"
struct tcp_protocol : net_protocol {
};
#include "TCPConnection.h"
net_protocol *
tcp_init_protocol(net_socket *socket)
{
tcp_protocol *protocol = new (std::nothrow) tcp_protocol;
socket->protocol = IPPROTO_TCP;
TCPConnection *protocol = new (std::nothrow) TCPConnection(socket);
if (protocol == NULL)
return NULL;
TRACE(("Created new TCPConnection %p\n", protocol));
return protocol;
}
@ -37,7 +68,7 @@ tcp_init_protocol(net_socket *socket)
status_t
tcp_uninit_protocol(net_protocol *protocol)
{
delete protocol;
delete (TCPConnection *)protocol;
return B_OK;
}
@ -45,35 +76,35 @@ tcp_uninit_protocol(net_protocol *protocol)
status_t
tcp_open(net_protocol *protocol)
{
return B_OK;
return ((TCPConnection *)protocol)->Open();
}
status_t
tcp_close(net_protocol *protocol)
{
return B_OK;
return ((TCPConnection *)protocol)->Close();
}
status_t
tcp_free(net_protocol *protocol)
{
return B_OK;
return ((TCPConnection *)protocol)->Free();
}
status_t
tcp_connect(net_protocol *protocol, const struct sockaddr *address)
{
return B_ERROR;
return ((TCPConnection *)protocol)->Connect(address);
}
status_t
tcp_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
{
return B_ERROR;
return ((TCPConnection *)protocol)->Accept(_acceptedSocket);
}
@ -89,28 +120,31 @@ tcp_control(net_protocol *protocol, int level, int option, void *value,
status_t
tcp_bind(net_protocol *protocol, struct sockaddr *address)
{
return B_ERROR;
TRACE(("tcp_bind(%p) on address %s\n", protocol,
AddressString(sDomain, address, true).Data()));
TCPConnection *connection = (TCPConnection *)protocol;
return connection->Bind(address);
}
status_t
tcp_unbind(net_protocol *protocol, struct sockaddr *address)
{
return B_ERROR;
return ((TCPConnection *)protocol)->Unbind(address);
}
status_t
tcp_listen(net_protocol *protocol, int count)
{
return B_ERROR;
return ((TCPConnection *)protocol)->Listen(count);
}
status_t
tcp_shutdown(net_protocol *protocol, int direction)
{
return B_ERROR;
return ((TCPConnection *)protocol)->Shutdown(direction);
}
@ -132,7 +166,7 @@ tcp_send_routed_data(net_protocol *protocol, struct net_route *route,
ssize_t
tcp_send_avail(net_protocol *protocol)
{
return B_ERROR;
return ((TCPConnection *)protocol)->SendAvailable();
}
@ -140,14 +174,14 @@ status_t
tcp_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
net_buffer **_buffer)
{
return B_ERROR;
return ((TCPConnection *)protocol)->ReadData(numBytes, flags, _buffer);
}
ssize_t
tcp_read_avail(net_protocol *protocol)
{
return B_ERROR;
return ((TCPConnection *)protocol)->ReadAvailable();
}
@ -189,36 +223,93 @@ tcp_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
// #pragma mark -
static status_t
tcp_init()
{
status_t status;
sDomain = sStackModule->get_domain(AF_INET);
sAddressModule = sDomain->address_module;
status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule);
if (status < B_OK)
return status;
/* status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&sBufferModule);
if (status < B_OK)
goto err1;*/
status = get_module(NET_DATALINK_MODULE_NAME, (module_info **)&sDatalinkModule);
if (status < B_OK)
goto err2;
sTCPHash = hash_init(MAX_HASH_TCP, TCPConnection::HashOffset(),
&TCPConnection::Compare, &TCPConnection::Hash);
if (sTCPHash == NULL)
goto err3;
status = benaphore_init(&sTCPLock, "TCP Hash Lock");
if (status < B_OK)
goto err4;
status = sStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_IP,
"network/protocols/tcp/v1",
"network/protocols/ipv4/v1",
NULL);
if (status < B_OK)
goto err5;
status = sStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_TCP,
"network/protocols/tcp/v1",
"network/protocols/ipv4/v1",
NULL);
if (status < B_OK)
goto err5;
status = sStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_TCP,
"network/protocols/tcp/v1");
if (status < B_OK)
goto err5;
return B_OK;
err5:
benaphore_destroy(&sTCPLock);
err4:
hash_uninit(sTCPHash);
err3:
put_module(NET_DATALINK_MODULE_NAME);
err2:
/* put_module(NET_BUFFER_MODULE_NAME);
err1:*/
put_module(NET_STACK_MODULE_NAME);
TRACE(("init_tcp() fails with %lx (%s)\n", status, strerror(status)));
return status;
}
static status_t
tcp_uninit()
{
benaphore_destroy(&sTCPLock);
hash_uninit(sTCPHash);
put_module(NET_DATALINK_MODULE_NAME);
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
return B_OK;
}
static status_t
tcp_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
{
net_stack_module_info *stack;
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&stack);
if (status < B_OK)
return status;
stack->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_IP,
"network/protocols/tcp/v1",
"network/protocols/ipv4/v1",
NULL);
stack->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_TCP,
"network/protocols/tcp/v1",
"network/protocols/ipv4/v1",
NULL);
stack->register_domain_receiving_protocol(AF_INET, IPPROTO_TCP,
"network/protocols/tcp/v1");
put_module(NET_STACK_MODULE_NAME);
return B_OK;
}
return tcp_init();
case B_MODULE_UNINIT:
return B_OK;
return tcp_uninit();
default:
return B_ERROR;