made TCP handle multiple domains.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20718 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
|
|
||||||
struct connection_key {
|
struct connection_key {
|
||||||
|
net_address_module_info *address_module;
|
||||||
const sockaddr *local;
|
const sockaddr *local;
|
||||||
const sockaddr *peer;
|
const sockaddr *peer;
|
||||||
};
|
};
|
||||||
@@ -42,7 +43,8 @@ static const uint16 kLastReservedPort = 1023;
|
|||||||
static const uint16 kFirstEphemeralPort = 40000;
|
static const uint16 kFirstEphemeralPort = 40000;
|
||||||
|
|
||||||
|
|
||||||
EndpointManager::EndpointManager()
|
EndpointManager::EndpointManager(net_domain *domain)
|
||||||
|
: fDomain(domain)
|
||||||
{
|
{
|
||||||
fConnectionHash = hash_init(kConnectionHashBuckets,
|
fConnectionHash = hash_init(kConnectionHashBuckets,
|
||||||
offsetof(TCPEndpoint, fConnectionHashNext),
|
offsetof(TCPEndpoint, fConnectionHashNext),
|
||||||
@@ -89,6 +91,7 @@ TCPEndpoint *
|
|||||||
EndpointManager::_LookupConnection(sockaddr *local, sockaddr *peer)
|
EndpointManager::_LookupConnection(sockaddr *local, sockaddr *peer)
|
||||||
{
|
{
|
||||||
connection_key key;
|
connection_key key;
|
||||||
|
key.address_module = AddressModule();
|
||||||
key.local = local;
|
key.local = local;
|
||||||
key.peer = peer;
|
key.peer = peer;
|
||||||
|
|
||||||
@@ -109,9 +112,6 @@ EndpointManager::_DumpConnections()
|
|||||||
{
|
{
|
||||||
RecursiveLocker lock(&fLock);
|
RecursiveLocker lock(&fLock);
|
||||||
|
|
||||||
if (gDomain == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct hash_iterator iterator;
|
struct hash_iterator iterator;
|
||||||
hash_open(fConnectionHash, &iterator);
|
hash_open(fConnectionHash, &iterator);
|
||||||
|
|
||||||
@@ -120,8 +120,8 @@ EndpointManager::_DumpConnections()
|
|||||||
TCPEndpoint *endpoint;
|
TCPEndpoint *endpoint;
|
||||||
while ((endpoint = (TCPEndpoint *)hash_next(fConnectionHash, &iterator)) != NULL) {
|
while ((endpoint = (TCPEndpoint *)hash_next(fConnectionHash, &iterator)) != NULL) {
|
||||||
TRACE((" TCPEndpoint %p: local %s, peer %s\n", endpoint,
|
TRACE((" TCPEndpoint %p: local %s, peer %s\n", endpoint,
|
||||||
AddressString(gDomain, (sockaddr *)&endpoint->socket->address, true).Data(),
|
AddressString(Domain(), (sockaddr *)&endpoint->socket->address, true).Data(),
|
||||||
AddressString(gDomain, (sockaddr *)&endpoint->socket->peer, true).Data()));
|
AddressString(Domain(), (sockaddr *)&endpoint->socket->peer, true).Data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_close(fConnectionHash, &iterator, false);
|
hash_close(fConnectionHash, &iterator, false);
|
||||||
@@ -138,13 +138,14 @@ EndpointManager::SetConnection(TCPEndpoint *endpoint,
|
|||||||
sockaddr localBuffer;
|
sockaddr localBuffer;
|
||||||
|
|
||||||
// need to associate this connection with a real address, not INADDR_ANY
|
// need to associate this connection with a real address, not INADDR_ANY
|
||||||
if (gAddressModule->is_empty_address(local, false)) {
|
if (AddressModule()->is_empty_address(local, false)) {
|
||||||
gAddressModule->set_to(&localBuffer, interfaceLocal);
|
AddressModule()->set_to(&localBuffer, interfaceLocal);
|
||||||
gAddressModule->set_port(&localBuffer, gAddressModule->get_port(local));
|
AddressModule()->set_port(&localBuffer, AddressModule()->get_port(local));
|
||||||
local = &localBuffer;
|
local = &localBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_key key;
|
connection_key key;
|
||||||
|
key.address_module = AddressModule();
|
||||||
key.local = local;
|
key.local = local;
|
||||||
key.peer = peer;
|
key.peer = peer;
|
||||||
|
|
||||||
@@ -153,8 +154,8 @@ EndpointManager::SetConnection(TCPEndpoint *endpoint,
|
|||||||
|
|
||||||
_RemoveConnection(endpoint);
|
_RemoveConnection(endpoint);
|
||||||
|
|
||||||
gAddressModule->set_to((sockaddr *)&endpoint->socket->address, local);
|
AddressModule()->set_to((sockaddr *)&endpoint->socket->address, local);
|
||||||
gAddressModule->set_to((sockaddr *)&endpoint->socket->peer, peer);
|
AddressModule()->set_to((sockaddr *)&endpoint->socket->peer, peer);
|
||||||
|
|
||||||
return hash_insert(fConnectionHash, endpoint);
|
return hash_insert(fConnectionHash, endpoint);
|
||||||
}
|
}
|
||||||
@@ -172,7 +173,7 @@ EndpointManager::FindConnection(sockaddr *local, sockaddr *peer)
|
|||||||
// no explicit endpoint exists, check for wildcard endpoints
|
// no explicit endpoint exists, check for wildcard endpoints
|
||||||
|
|
||||||
sockaddr wildcard;
|
sockaddr wildcard;
|
||||||
gAddressModule->set_to_empty_address(&wildcard);
|
AddressModule()->set_to_empty_address(&wildcard);
|
||||||
|
|
||||||
endpoint = _LookupConnection(local, &wildcard);
|
endpoint = _LookupConnection(local, &wildcard);
|
||||||
if (endpoint != NULL) {
|
if (endpoint != NULL) {
|
||||||
@@ -181,8 +182,8 @@ EndpointManager::FindConnection(sockaddr *local, sockaddr *peer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sockaddr localWildcard;
|
sockaddr localWildcard;
|
||||||
gAddressModule->set_to_empty_address(&localWildcard);
|
AddressModule()->set_to_empty_address(&localWildcard);
|
||||||
gAddressModule->set_port(&localWildcard, gAddressModule->get_port(local));
|
AddressModule()->set_port(&localWildcard, AddressModule()->get_port(local));
|
||||||
|
|
||||||
endpoint = _LookupConnection(&localWildcard, &wildcard);
|
endpoint = _LookupConnection(&localWildcard, &wildcard);
|
||||||
if (endpoint != NULL) {
|
if (endpoint != NULL) {
|
||||||
@@ -217,12 +218,12 @@ EndpointManager::Bind(TCPEndpoint *endpoint)
|
|||||||
sockaddr *address = (sockaddr *)&endpoint->socket->address;
|
sockaddr *address = (sockaddr *)&endpoint->socket->address;
|
||||||
|
|
||||||
TRACE(("EndpointManager::Bind(%p, %s)\n", endpoint,
|
TRACE(("EndpointManager::Bind(%p, %s)\n", endpoint,
|
||||||
AddressString(gDomain, address, true).Data()));
|
AddressString(Domain(), address, true).Data()));
|
||||||
|
|
||||||
if (gAddressModule->is_empty_address(address, true))
|
if (AddressModule()->is_empty_address(address, true))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
uint16 port = gAddressModule->get_port(address);
|
uint16 port = AddressModule()->get_port(address);
|
||||||
|
|
||||||
// TODO: check the root group instead?
|
// TODO: check the root group instead?
|
||||||
if (ntohs(port) <= kLastReservedPort && geteuid() != 0)
|
if (ntohs(port) <= kLastReservedPort && geteuid() != 0)
|
||||||
@@ -245,7 +246,7 @@ EndpointManager::Bind(TCPEndpoint *endpoint)
|
|||||||
TCPEndpoint *last = first;
|
TCPEndpoint *last = first;
|
||||||
while (true) {
|
while (true) {
|
||||||
// check if this endpoint binds to a wildcard address
|
// check if this endpoint binds to a wildcard address
|
||||||
if (gAddressModule->is_empty_address((sockaddr *)&last->socket->address, false)) {
|
if (AddressModule()->is_empty_address((sockaddr *)&last->socket->address, false)) {
|
||||||
// you cannot specialize a wildcard endpoint - you have to open the
|
// you cannot specialize a wildcard endpoint - you have to open the
|
||||||
// wildcard endpoint last
|
// wildcard endpoint last
|
||||||
return B_PERMISSION_DENIED;
|
return B_PERMISSION_DENIED;
|
||||||
@@ -293,9 +294,9 @@ EndpointManager::BindToEphemeral(TCPEndpoint *endpoint)
|
|||||||
TCPEndpoint *other = _LookupEndpoint(port);
|
TCPEndpoint *other = _LookupEndpoint(port);
|
||||||
if (other == NULL) {
|
if (other == NULL) {
|
||||||
// found a port
|
// found a port
|
||||||
gAddressModule->set_port((sockaddr *)&endpoint->socket->address, port);
|
AddressModule()->set_port((sockaddr *)&endpoint->socket->address, port);
|
||||||
TRACE((" EndpointManager::BindToEphemeral(%p) -> %s\n", endpoint,
|
TRACE((" EndpointManager::BindToEphemeral(%p) -> %s\n", endpoint,
|
||||||
AddressString(gDomain, (sockaddr *)&endpoint->socket->address, true).Data()));
|
AddressString(Domain(), (sockaddr *)&endpoint->socket->address, true).Data()));
|
||||||
endpoint->fEndpointNextWithSamePort = NULL;
|
endpoint->fEndpointNextWithSamePort = NULL;
|
||||||
hash_insert(fEndpointHash, endpoint);
|
hash_insert(fEndpointHash, endpoint);
|
||||||
hash_insert(fConnectionHash, endpoint);
|
hash_insert(fConnectionHash, endpoint);
|
||||||
@@ -320,7 +321,7 @@ EndpointManager::Unbind(TCPEndpoint *endpoint)
|
|||||||
RecursiveLocker locker(&fLock);
|
RecursiveLocker locker(&fLock);
|
||||||
|
|
||||||
if (!endpoint->fSpawned) {
|
if (!endpoint->fSpawned) {
|
||||||
TCPEndpoint *other = _LookupEndpoint(gAddressModule->get_port(
|
TCPEndpoint *other = _LookupEndpoint(AddressModule()->get_port(
|
||||||
(sockaddr *)&endpoint->socket->address));
|
(sockaddr *)&endpoint->socket->address));
|
||||||
if (other != endpoint) {
|
if (other != endpoint) {
|
||||||
// remove endpoint from the list of endpoints with the same port
|
// remove endpoint from the list of endpoints with the same port
|
||||||
@@ -351,6 +352,45 @@ EndpointManager::Unbind(TCPEndpoint *endpoint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EndpointManager::ReplyWithReset(tcp_segment_header &segment,
|
||||||
|
net_buffer *buffer)
|
||||||
|
{
|
||||||
|
TRACE(("TCP: Sending RST...\n"));
|
||||||
|
|
||||||
|
net_buffer *reply = gBufferModule->create(512);
|
||||||
|
if (reply == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
AddressModule()->set_to((sockaddr *)&reply->source,
|
||||||
|
(sockaddr *)&buffer->destination);
|
||||||
|
AddressModule()->set_to((sockaddr *)&reply->destination,
|
||||||
|
(sockaddr *)&buffer->source);
|
||||||
|
|
||||||
|
tcp_segment_header outSegment;
|
||||||
|
outSegment.flags = TCP_FLAG_RESET;
|
||||||
|
outSegment.sequence = 0;
|
||||||
|
outSegment.acknowledge = 0;
|
||||||
|
outSegment.advertised_window = 0;
|
||||||
|
outSegment.urgent_offset = 0;
|
||||||
|
|
||||||
|
if ((segment.flags & TCP_FLAG_ACKNOWLEDGE) == 0) {
|
||||||
|
outSegment.flags |= TCP_FLAG_ACKNOWLEDGE;
|
||||||
|
outSegment.acknowledge = segment.sequence + buffer->size;
|
||||||
|
} else
|
||||||
|
outSegment.sequence = segment.acknowledge;
|
||||||
|
|
||||||
|
status_t status = add_tcp_header(AddressModule(), outSegment, reply);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = Domain()->module->send_data(NULL, reply);
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
gBufferModule->free(reply);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - hash functions
|
// #pragma mark - hash functions
|
||||||
|
|
||||||
|
|
||||||
@@ -360,9 +400,9 @@ EndpointManager::_ConnectionCompare(void *_endpoint, const void *_key)
|
|||||||
const connection_key *key = (connection_key *)_key;
|
const connection_key *key = (connection_key *)_key;
|
||||||
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
||||||
|
|
||||||
if (gAddressModule->equal_addresses_and_ports(key->local,
|
if (key->address_module->equal_addresses_and_ports(key->local,
|
||||||
(sockaddr *)&endpoint->socket->address)
|
(sockaddr *)&endpoint->socket->address)
|
||||||
&& gAddressModule->equal_addresses_and_ports(key->peer,
|
&& key->address_module->equal_addresses_and_ports(key->peer,
|
||||||
(sockaddr *)&endpoint->socket->peer))
|
(sockaddr *)&endpoint->socket->peer))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -373,20 +413,23 @@ EndpointManager::_ConnectionCompare(void *_endpoint, const void *_key)
|
|||||||
/*static*/ uint32
|
/*static*/ uint32
|
||||||
EndpointManager::_ConnectionHash(void *_endpoint, const void *_key, uint32 range)
|
EndpointManager::_ConnectionHash(void *_endpoint, const void *_key, uint32 range)
|
||||||
{
|
{
|
||||||
|
net_address_module_info *address_module;
|
||||||
const sockaddr *local;
|
const sockaddr *local;
|
||||||
const sockaddr *peer;
|
const sockaddr *peer;
|
||||||
|
|
||||||
if (_endpoint != NULL) {
|
if (_endpoint != NULL) {
|
||||||
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
||||||
|
address_module = endpoint->AddressModule();
|
||||||
local = (sockaddr *)&endpoint->socket->address;
|
local = (sockaddr *)&endpoint->socket->address;
|
||||||
peer = (sockaddr *)&endpoint->socket->peer;
|
peer = (sockaddr *)&endpoint->socket->peer;
|
||||||
} else {
|
} else {
|
||||||
const connection_key *key = (connection_key *)_key;
|
const connection_key *key = (connection_key *)_key;
|
||||||
|
address_module = key->address_module;
|
||||||
local = key->local;
|
local = key->local;
|
||||||
peer = key->peer;
|
peer = key->peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gAddressModule->hash_address_pair(local, peer) % range;
|
return address_module->hash_address_pair(local, peer) % range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -396,8 +439,8 @@ EndpointManager::_EndpointCompare(void *_endpoint, const void *_key)
|
|||||||
const endpoint_key *key = (endpoint_key *)_key;
|
const endpoint_key *key = (endpoint_key *)_key;
|
||||||
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
||||||
|
|
||||||
return gAddressModule->get_port((sockaddr *)&endpoint->socket->address)
|
return endpoint->AddressModule()->get_port(
|
||||||
== key->port ? 0 : 1;
|
(sockaddr *)&endpoint->socket->address) == key->port ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -406,7 +449,8 @@ EndpointManager::_EndpointHash(void *_endpoint, const void *_key, uint32 range)
|
|||||||
{
|
{
|
||||||
if (_endpoint != NULL) {
|
if (_endpoint != NULL) {
|
||||||
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
TCPEndpoint *endpoint = (TCPEndpoint *)_endpoint;
|
||||||
return gAddressModule->get_port((sockaddr *)&endpoint->socket->address) % range;
|
return endpoint->AddressModule()->get_port(
|
||||||
|
(sockaddr *)&endpoint->socket->address) % range;
|
||||||
}
|
}
|
||||||
|
|
||||||
const endpoint_key *key = (endpoint_key *)_key;
|
const endpoint_key *key = (endpoint_key *)_key;
|
||||||
|
|||||||
@@ -8,18 +8,24 @@
|
|||||||
#ifndef ENDPOINT_MANAGER_H
|
#ifndef ENDPOINT_MANAGER_H
|
||||||
#define ENDPOINT_MANAGER_H
|
#define ENDPOINT_MANAGER_H
|
||||||
|
|
||||||
|
#include "tcp.h"
|
||||||
|
|
||||||
|
#include <net_datalink.h>
|
||||||
|
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/khash.h>
|
#include <util/khash.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct net_address_module_info;
|
||||||
|
struct net_domain;
|
||||||
class TCPEndpoint;
|
class TCPEndpoint;
|
||||||
|
|
||||||
class EndpointManager {
|
class EndpointManager : public DoublyLinkedListLinkImpl<EndpointManager> {
|
||||||
public:
|
public:
|
||||||
EndpointManager();
|
EndpointManager(net_domain *domain);
|
||||||
~EndpointManager();
|
~EndpointManager();
|
||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
@@ -34,6 +40,13 @@ class EndpointManager {
|
|||||||
status_t BindToEphemeral(TCPEndpoint *endpoint);
|
status_t BindToEphemeral(TCPEndpoint *endpoint);
|
||||||
status_t Unbind(TCPEndpoint *endpoint);
|
status_t Unbind(TCPEndpoint *endpoint);
|
||||||
|
|
||||||
|
status_t ReplyWithReset(tcp_segment_header &segment,
|
||||||
|
net_buffer *buffer);
|
||||||
|
|
||||||
|
net_domain *Domain() const { return fDomain; }
|
||||||
|
net_address_module_info *AddressModule() const
|
||||||
|
{ return Domain()->address_module; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TCPEndpoint *_LookupConnection(sockaddr *local, sockaddr *peer);
|
TCPEndpoint *_LookupConnection(sockaddr *local, sockaddr *peer);
|
||||||
status_t _RemoveConnection(TCPEndpoint *endpoint);
|
status_t _RemoveConnection(TCPEndpoint *endpoint);
|
||||||
@@ -45,6 +58,8 @@ class EndpointManager {
|
|||||||
static int _EndpointCompare(void *_endpoint, const void *_key);
|
static int _EndpointCompare(void *_endpoint, const void *_key);
|
||||||
static uint32 _EndpointHash(void *_endpoint, const void *_key, uint32 range);
|
static uint32 _EndpointHash(void *_endpoint, const void *_key, uint32 range);
|
||||||
|
|
||||||
|
net_domain *fDomain;
|
||||||
|
|
||||||
hash_table *fConnectionHash;
|
hash_table *fConnectionHash;
|
||||||
hash_table *fEndpointHash;
|
hash_table *fEndpointHash;
|
||||||
recursive_lock fLock;
|
recursive_lock fLock;
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ WaitList::Signal()
|
|||||||
|
|
||||||
TCPEndpoint::TCPEndpoint(net_socket *socket)
|
TCPEndpoint::TCPEndpoint(net_socket *socket)
|
||||||
:
|
:
|
||||||
|
fManager(NULL),
|
||||||
fReceiveList("tcp receive"),
|
fReceiveList("tcp receive"),
|
||||||
fSendList("tcp send"),
|
fSendList("tcp send"),
|
||||||
fOptions(0),
|
fOptions(0),
|
||||||
@@ -205,7 +206,10 @@ TCPEndpoint::~TCPEndpoint()
|
|||||||
gStackModule->cancel_timer(&fDelayedAcknowledgeTimer);
|
gStackModule->cancel_timer(&fDelayedAcknowledgeTimer);
|
||||||
gStackModule->cancel_timer(&fTimeWaitTimer);
|
gStackModule->cancel_timer(&fTimeWaitTimer);
|
||||||
|
|
||||||
gEndpointManager->Unbind(this);
|
if (fManager) {
|
||||||
|
fManager->Unbind(this);
|
||||||
|
return_endpoint_manager(fManager);
|
||||||
|
}
|
||||||
|
|
||||||
recursive_lock_destroy(&fLock);
|
recursive_lock_destroy(&fLock);
|
||||||
}
|
}
|
||||||
@@ -234,7 +238,14 @@ status_t
|
|||||||
TCPEndpoint::Open()
|
TCPEndpoint::Open()
|
||||||
{
|
{
|
||||||
TRACE("Open()");
|
TRACE("Open()");
|
||||||
// nothing to do here...
|
|
||||||
|
if (Domain() == NULL || AddressModule() == NULL)
|
||||||
|
return EAFNOSUPPORT;
|
||||||
|
|
||||||
|
fManager = create_endpoint_manager(Domain());
|
||||||
|
if (fManager == NULL)
|
||||||
|
return EAFNOSUPPORT;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +315,7 @@ status_t
|
|||||||
TCPEndpoint::Connect(const struct sockaddr *address)
|
TCPEndpoint::Connect(const struct sockaddr *address)
|
||||||
{
|
{
|
||||||
TRACE("Connect() on address %s",
|
TRACE("Connect() on address %s",
|
||||||
AddressString(gDomain, address, true).Data());
|
AddressString(Domain(), address, true).Data());
|
||||||
|
|
||||||
RecursiveLocker locker(&fLock);
|
RecursiveLocker locker(&fLock);
|
||||||
|
|
||||||
@@ -319,14 +330,14 @@ TCPEndpoint::Connect(const struct sockaddr *address)
|
|||||||
// get a net_route if there isn't one
|
// get a net_route if there isn't one
|
||||||
// TODO: get a net_route_info instead!
|
// TODO: get a net_route_info instead!
|
||||||
if (fRoute == NULL) {
|
if (fRoute == NULL) {
|
||||||
fRoute = gDatalinkModule->get_route(gDomain, (sockaddr *)address);
|
fRoute = gDatalinkModule->get_route(Domain(), (sockaddr *)address);
|
||||||
TRACE(" Connect(): Using Route %p", fRoute);
|
TRACE(" Connect(): Using Route %p", fRoute);
|
||||||
if (fRoute == NULL)
|
if (fRoute == NULL)
|
||||||
return ENETUNREACH;
|
return ENETUNREACH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure connection does not already exist
|
// make sure connection does not already exist
|
||||||
status_t status = gEndpointManager->SetConnection(this,
|
status_t status = fManager->SetConnection(this,
|
||||||
(sockaddr *)&socket->address, address, fRoute->interface->address);
|
(sockaddr *)&socket->address, address, fRoute->interface->address);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
TRACE(" Connect(): could not add connection: %s!", strerror(status));
|
TRACE(" Connect(): could not add connection: %s!", strerror(status));
|
||||||
@@ -413,7 +424,7 @@ TCPEndpoint::Bind(sockaddr *address)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
TRACE("Bind() on address %s",
|
TRACE("Bind() on address %s",
|
||||||
AddressString(gDomain, address, true).Data());
|
AddressString(Domain(), address, true).Data());
|
||||||
|
|
||||||
RecursiveLocker lock(fLock);
|
RecursiveLocker lock(fLock);
|
||||||
|
|
||||||
@@ -425,13 +436,13 @@ TCPEndpoint::Bind(sockaddr *address)
|
|||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (gAddressModule->get_port(address) == 0)
|
if (AddressModule()->get_port(address) == 0)
|
||||||
status = gEndpointManager->BindToEphemeral(this);
|
status = fManager->BindToEphemeral(this);
|
||||||
else
|
else
|
||||||
status = gEndpointManager->Bind(this);
|
status = fManager->Bind(this);
|
||||||
|
|
||||||
TRACE(" Bind() bound to %s (status %i)",
|
TRACE(" Bind() bound to %s (status %i)",
|
||||||
AddressString(gDomain, (sockaddr *)&socket->address, true).Data(),
|
AddressString(Domain(), (sockaddr *)&socket->address, true).Data(),
|
||||||
(int)status);
|
(int)status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -444,7 +455,7 @@ TCPEndpoint::Unbind(struct sockaddr *address)
|
|||||||
TRACE("Unbind()");
|
TRACE("Unbind()");
|
||||||
|
|
||||||
RecursiveLocker lock(fLock);
|
RecursiveLocker lock(fLock);
|
||||||
return gEndpointManager->Unbind(this);
|
return fManager->Unbind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -646,7 +657,15 @@ TCPEndpoint::ReadAvailable()
|
|||||||
bool
|
bool
|
||||||
TCPEndpoint::IsBound() const
|
TCPEndpoint::IsBound() const
|
||||||
{
|
{
|
||||||
return !gAddressModule->is_empty_address((sockaddr *)&socket->address, true);
|
return !AddressModule()->is_empty_address((sockaddr *)&socket->address, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TCPEndpoint::DeleteSocket()
|
||||||
|
{
|
||||||
|
// the next call will delete `this'.
|
||||||
|
gSocketModule->delete_socket(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -723,9 +742,9 @@ TCPEndpoint::ListenReceive(tcp_segment_header &segment, net_buffer *buffer)
|
|||||||
if (gSocketModule->spawn_pending_socket(socket, &newSocket) < B_OK)
|
if (gSocketModule->spawn_pending_socket(socket, &newSocket) < B_OK)
|
||||||
return DROP;
|
return DROP;
|
||||||
|
|
||||||
gAddressModule->set_to((sockaddr *)&newSocket->address,
|
AddressModule()->set_to((sockaddr *)&newSocket->address,
|
||||||
(sockaddr *)&buffer->destination);
|
(sockaddr *)&buffer->destination);
|
||||||
gAddressModule->set_to((sockaddr *)&newSocket->peer,
|
AddressModule()->set_to((sockaddr *)&newSocket->peer,
|
||||||
(sockaddr *)&buffer->source);
|
(sockaddr *)&buffer->source);
|
||||||
|
|
||||||
TCPEndpoint *endpoint = (TCPEndpoint *)newSocket->first_protocol;
|
TCPEndpoint *endpoint = (TCPEndpoint *)newSocket->first_protocol;
|
||||||
@@ -734,12 +753,12 @@ TCPEndpoint::ListenReceive(tcp_segment_header &segment, net_buffer *buffer)
|
|||||||
|
|
||||||
// TODO: proper error handling!
|
// TODO: proper error handling!
|
||||||
|
|
||||||
endpoint->fRoute = gDatalinkModule->get_route(gDomain,
|
endpoint->fRoute = gDatalinkModule->get_route(Domain(),
|
||||||
(sockaddr *)&newSocket->peer);
|
(sockaddr *)&newSocket->peer);
|
||||||
if (endpoint->fRoute == NULL)
|
if (endpoint->fRoute == NULL)
|
||||||
return DROP;
|
return DROP;
|
||||||
|
|
||||||
if (gEndpointManager->SetConnection(endpoint, (sockaddr *)&buffer->destination,
|
if (fManager->SetConnection(endpoint, (sockaddr *)&buffer->destination,
|
||||||
(sockaddr *)&buffer->source, NULL) < B_OK)
|
(sockaddr *)&buffer->source, NULL) < B_OK)
|
||||||
return DROP;
|
return DROP;
|
||||||
|
|
||||||
@@ -1085,8 +1104,8 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
gAddressModule->set_to((sockaddr *)&buffer->source, (sockaddr *)&socket->address);
|
AddressModule()->set_to((sockaddr *)&buffer->source, (sockaddr *)&socket->address);
|
||||||
gAddressModule->set_to((sockaddr *)&buffer->destination, (sockaddr *)&socket->peer);
|
AddressModule()->set_to((sockaddr *)&buffer->destination, (sockaddr *)&socket->peer);
|
||||||
|
|
||||||
uint32 size = buffer->size;
|
uint32 size = buffer->size;
|
||||||
if (length > 0 && fSendNext + segmentLength == fSendQueue.LastSequence()) {
|
if (length > 0 && fSendNext + segmentLength == fSendQueue.LastSequence()) {
|
||||||
@@ -1108,10 +1127,10 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
|
|
||||||
TRACE("SendQueued() flags %x, buffer %p, size %lu, from address %s to %s",
|
TRACE("SendQueued() flags %x, buffer %p, size %lu, from address %s to %s",
|
||||||
segment.flags, buffer, buffer->size,
|
segment.flags, buffer, buffer->size,
|
||||||
AddressString(gDomain, (sockaddr *)&buffer->source, true).Data(),
|
AddressString(Domain(), (sockaddr *)&buffer->source, true).Data(),
|
||||||
AddressString(gDomain, (sockaddr *)&buffer->destination, true).Data());
|
AddressString(Domain(), (sockaddr *)&buffer->destination, true).Data());
|
||||||
|
|
||||||
status = add_tcp_header(segment, buffer);
|
status = add_tcp_header(AddressModule(), segment, buffer);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
gBufferModule->free(buffer);
|
gBufferModule->free(buffer);
|
||||||
return status;
|
return status;
|
||||||
@@ -1525,6 +1544,6 @@ TCPEndpoint::_TimeWaitTimer(struct net_timer *timer, void *data)
|
|||||||
if (recursive_lock_lock(&endpoint->Lock()) < B_OK)
|
if (recursive_lock_lock(&endpoint->Lock()) < B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gSocketModule->delete_socket(endpoint->socket);
|
endpoint->DeleteSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ class TCPEndpoint : public net_protocol {
|
|||||||
tcp_state State() const { return fState; }
|
tcp_state State() const { return fState; }
|
||||||
bool IsBound() const;
|
bool IsBound() const;
|
||||||
|
|
||||||
|
void DeleteSocket();
|
||||||
|
|
||||||
status_t DelayedAcknowledge();
|
status_t DelayedAcknowledge();
|
||||||
status_t SendAcknowledge();
|
status_t SendAcknowledge();
|
||||||
status_t UpdateTimeWait();
|
status_t UpdateTimeWait();
|
||||||
@@ -72,6 +74,12 @@ class TCPEndpoint : public net_protocol {
|
|||||||
net_buffer *buffer);
|
net_buffer *buffer);
|
||||||
int32 Receive(tcp_segment_header& segment, net_buffer *buffer);
|
int32 Receive(tcp_segment_header& segment, net_buffer *buffer);
|
||||||
|
|
||||||
|
net_domain *Domain() const
|
||||||
|
{ return socket->first_protocol->module->get_domain(
|
||||||
|
socket->first_protocol); }
|
||||||
|
net_address_module_info *AddressModule() const
|
||||||
|
{ return Domain()->address_module; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class EndpointManager;
|
friend class EndpointManager;
|
||||||
|
|
||||||
@@ -93,6 +101,8 @@ class TCPEndpoint : public net_protocol {
|
|||||||
static void _PersistTimer(net_timer *timer, void *data);
|
static void _PersistTimer(net_timer *timer, void *data);
|
||||||
static void _DelayedAcknowledgeTimer(net_timer *timer, void *data);
|
static void _DelayedAcknowledgeTimer(net_timer *timer, void *data);
|
||||||
|
|
||||||
|
EndpointManager *fManager;
|
||||||
|
|
||||||
TCPEndpoint *fConnectionHashNext;
|
TCPEndpoint *fConnectionHashNext;
|
||||||
TCPEndpoint *fEndpointHashNext;
|
TCPEndpoint *fEndpointHashNext;
|
||||||
TCPEndpoint *fEndpointNextWithSamePort;
|
TCPEndpoint *fEndpointNextWithSamePort;
|
||||||
|
|||||||
@@ -42,34 +42,56 @@
|
|||||||
typedef NetBufferField<uint16, offsetof(tcp_header, checksum)> TCPChecksumField;
|
typedef NetBufferField<uint16, offsetof(tcp_header, checksum)> TCPChecksumField;
|
||||||
|
|
||||||
|
|
||||||
net_domain *gDomain;
|
|
||||||
net_address_module_info *gAddressModule;
|
|
||||||
net_buffer_module_info *gBufferModule;
|
net_buffer_module_info *gBufferModule;
|
||||||
net_datalink_module_info *gDatalinkModule;
|
net_datalink_module_info *gDatalinkModule;
|
||||||
net_socket_module_info *gSocketModule;
|
net_socket_module_info *gSocketModule;
|
||||||
net_stack_module_info *gStackModule;
|
net_stack_module_info *gStackModule;
|
||||||
EndpointManager *gEndpointManager;
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
// TODO we need to think of a better way to do this. It would be
|
||||||
set_domain(net_interface *interface = NULL)
|
// nice if we registered a per EndpointManager receiving
|
||||||
|
// protocol cookie, so we don't have to go through the list
|
||||||
|
// for each segment.
|
||||||
|
typedef DoublyLinkedList<EndpointManager> EndpointManagerList;
|
||||||
|
static benaphore sEndpointManagersLock;
|
||||||
|
static EndpointManagerList sEndpointManagers;
|
||||||
|
|
||||||
|
|
||||||
|
static EndpointManager *
|
||||||
|
endpoint_manager_for(net_domain *domain)
|
||||||
{
|
{
|
||||||
if (gDomain == NULL) {
|
EndpointManagerList::Iterator iterator = sEndpointManagers.GetIterator();
|
||||||
// domain and address module are not known yet, we copy them from
|
while (iterator.HasNext()) {
|
||||||
// the buffer's interface (if any):
|
EndpointManager *endpointManager = iterator.Next();
|
||||||
if (interface == NULL || interface->domain == NULL)
|
if (endpointManager->Domain() == domain)
|
||||||
gDomain = gStackModule->get_domain(AF_INET);
|
return endpointManager;
|
||||||
else
|
|
||||||
gDomain = interface->domain;
|
|
||||||
|
|
||||||
if (gDomain == NULL) {
|
|
||||||
// this shouldn't occur, of course, but who knows...
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
gAddressModule = gDomain->address_module;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EndpointManager *
|
||||||
|
create_endpoint_manager(net_domain *domain)
|
||||||
|
{
|
||||||
|
EndpointManager *endpointManager = endpoint_manager_for(domain);
|
||||||
|
if (endpointManager)
|
||||||
|
return endpointManager;
|
||||||
|
|
||||||
|
endpointManager = new (std::nothrow) EndpointManager(domain);
|
||||||
|
if (endpointManager)
|
||||||
|
sEndpointManagers.Add(endpointManager);
|
||||||
|
|
||||||
|
return endpointManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
return_endpoint_manager(EndpointManager *endpointManager)
|
||||||
|
{
|
||||||
|
// TODO when the connection and endpoint count reach zero
|
||||||
|
// we should remove the endpoint manager from the endpoints
|
||||||
|
// list and delete it.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -125,7 +147,8 @@ add_options(tcp_segment_header &segment, uint8 *buffer, size_t bufferSize)
|
|||||||
for \a flags, \a seq \a ack and \a advertisedWindow.
|
for \a flags, \a seq \a ack and \a advertisedWindow.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
add_tcp_header(tcp_segment_header &segment, net_buffer *buffer)
|
add_tcp_header(net_address_module_info *addressModule,
|
||||||
|
tcp_segment_header &segment, net_buffer *buffer)
|
||||||
{
|
{
|
||||||
buffer->protocol = IPPROTO_TCP;
|
buffer->protocol = IPPROTO_TCP;
|
||||||
|
|
||||||
@@ -138,8 +161,8 @@ add_tcp_header(tcp_segment_header &segment, net_buffer *buffer)
|
|||||||
|
|
||||||
tcp_header &header = bufferHeader.Data();
|
tcp_header &header = bufferHeader.Data();
|
||||||
|
|
||||||
header.source_port = gAddressModule->get_port((sockaddr *)&buffer->source);
|
header.source_port = addressModule->get_port((sockaddr *)&buffer->source);
|
||||||
header.destination_port = gAddressModule->get_port((sockaddr *)&buffer->destination);
|
header.destination_port = addressModule->get_port((sockaddr *)&buffer->destination);
|
||||||
header.sequence = htonl(segment.sequence);
|
header.sequence = htonl(segment.sequence);
|
||||||
header.acknowledge = (segment.flags & TCP_FLAG_ACKNOWLEDGE)
|
header.acknowledge = (segment.flags & TCP_FLAG_ACKNOWLEDGE)
|
||||||
? htonl(segment.acknowledge) : 0;
|
? htonl(segment.acknowledge) : 0;
|
||||||
@@ -161,7 +184,7 @@ add_tcp_header(tcp_segment_header &segment, net_buffer *buffer)
|
|||||||
TRACE(("add_tcp_header(): buffer %p, flags 0x%x, seq %lu, ack %lu, win %u\n", buffer,
|
TRACE(("add_tcp_header(): buffer %p, flags 0x%x, seq %lu, ack %lu, win %u\n", buffer,
|
||||||
segment.flags, segment.sequence, segment.acknowledge, segment.advertised_window));
|
segment.flags, segment.sequence, segment.acknowledge, segment.advertised_window));
|
||||||
|
|
||||||
*TCPChecksumField(buffer) = Checksum::PseudoHeader(gAddressModule,
|
*TCPChecksumField(buffer) = Checksum::PseudoHeader(addressModule,
|
||||||
gBufferModule, buffer, IPPROTO_TCP);
|
gBufferModule, buffer, IPPROTO_TCP);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -222,44 +245,6 @@ process_options(tcp_segment_header &segment, net_buffer *buffer, int32 size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
reply_with_reset(tcp_segment_header &segment, net_buffer *buffer)
|
|
||||||
{
|
|
||||||
TRACE(("TCP: Sending RST...\n"));
|
|
||||||
|
|
||||||
net_buffer *reply = gBufferModule->create(512);
|
|
||||||
if (reply == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
gAddressModule->set_to((sockaddr *)&reply->source,
|
|
||||||
(sockaddr *)&buffer->destination);
|
|
||||||
gAddressModule->set_to((sockaddr *)&reply->destination,
|
|
||||||
(sockaddr *)&buffer->source);
|
|
||||||
|
|
||||||
tcp_segment_header outSegment;
|
|
||||||
outSegment.flags = TCP_FLAG_RESET;
|
|
||||||
outSegment.sequence = 0;
|
|
||||||
outSegment.acknowledge = 0;
|
|
||||||
outSegment.advertised_window = 0;
|
|
||||||
outSegment.urgent_offset = 0;
|
|
||||||
|
|
||||||
if ((segment.flags & TCP_FLAG_ACKNOWLEDGE) == 0) {
|
|
||||||
outSegment.flags |= TCP_FLAG_ACKNOWLEDGE;
|
|
||||||
outSegment.acknowledge = segment.sequence + buffer->size;
|
|
||||||
} else
|
|
||||||
outSegment.sequence = segment.acknowledge;
|
|
||||||
|
|
||||||
status_t status = add_tcp_header(outSegment, reply);
|
|
||||||
if (status == B_OK)
|
|
||||||
status = gDomain->module->send_data(NULL, reply);
|
|
||||||
|
|
||||||
if (status != B_OK)
|
|
||||||
gBufferModule->free(reply);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
name_for_state(tcp_state state)
|
name_for_state(tcp_state state)
|
||||||
{
|
{
|
||||||
@@ -350,9 +335,6 @@ tcp_uninit_protocol(net_protocol *protocol)
|
|||||||
status_t
|
status_t
|
||||||
tcp_open(net_protocol *protocol)
|
tcp_open(net_protocol *protocol)
|
||||||
{
|
{
|
||||||
if (gDomain == NULL && set_domain() != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
return ((TCPEndpoint *)protocol)->Open();
|
return ((TCPEndpoint *)protocol)->Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,9 +479,12 @@ tcp_receive_data(net_buffer *buffer)
|
|||||||
{
|
{
|
||||||
TRACE(("TCP: Received buffer %p\n", buffer));
|
TRACE(("TCP: Received buffer %p\n", buffer));
|
||||||
|
|
||||||
if (gDomain == NULL && set_domain(buffer->interface) != B_OK)
|
if (buffer->interface == NULL || buffer->interface->domain == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
|
net_domain *domain = buffer->interface->domain;
|
||||||
|
net_address_module_info *addressModule = domain->address_module;
|
||||||
|
|
||||||
NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
|
NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
|
||||||
if (bufferHeader.Status() < B_OK)
|
if (bufferHeader.Status() < B_OK)
|
||||||
return bufferHeader.Status();
|
return bufferHeader.Status();
|
||||||
@@ -510,16 +495,17 @@ tcp_receive_data(net_buffer *buffer)
|
|||||||
if (headerLength < sizeof(tcp_header))
|
if (headerLength < sizeof(tcp_header))
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
if (Checksum::PseudoHeader(gAddressModule, gBufferModule, buffer,
|
if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer,
|
||||||
IPPROTO_TCP) != 0)
|
IPPROTO_TCP) != 0)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
gAddressModule->set_port((struct sockaddr *)&buffer->source, header.source_port);
|
addressModule->set_port((sockaddr *)&buffer->source, header.source_port);
|
||||||
gAddressModule->set_port((struct sockaddr *)&buffer->destination, header.destination_port);
|
addressModule->set_port((sockaddr *)&buffer->destination,
|
||||||
|
header.destination_port);
|
||||||
|
|
||||||
TRACE((" Looking for: peer %s, local %s\n",
|
TRACE((" Looking for: peer %s, local %s\n",
|
||||||
AddressString(gDomain, (sockaddr *)&buffer->source, true).Data(),
|
AddressString(domain, (sockaddr *)&buffer->source, true).Data(),
|
||||||
AddressString(gDomain, (sockaddr *)&buffer->destination, true).Data()));
|
AddressString(domain, (sockaddr *)&buffer->destination, true).Data()));
|
||||||
//dump_tcp_header(header);
|
//dump_tcp_header(header);
|
||||||
//gBufferModule->dump(buffer);
|
//gBufferModule->dump(buffer);
|
||||||
|
|
||||||
@@ -538,11 +524,17 @@ tcp_receive_data(net_buffer *buffer)
|
|||||||
bufferHeader.Remove(headerLength);
|
bufferHeader.Remove(headerLength);
|
||||||
// we no longer need to keep the header around
|
// we no longer need to keep the header around
|
||||||
|
|
||||||
RecursiveLocker locker(gEndpointManager->Locker());
|
BenaphoreLocker _(sEndpointManagersLock);
|
||||||
|
|
||||||
|
EndpointManager *endpointManager = endpoint_manager_for(domain);
|
||||||
|
if (endpointManager == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
RecursiveLocker locker(endpointManager->Locker());
|
||||||
int32 segmentAction = DROP;
|
int32 segmentAction = DROP;
|
||||||
|
|
||||||
TCPEndpoint *endpoint = gEndpointManager->FindConnection(
|
TCPEndpoint *endpoint = endpointManager->FindConnection(
|
||||||
(struct sockaddr *)&buffer->destination, (struct sockaddr *)&buffer->source);
|
(sockaddr *)&buffer->destination, (sockaddr *)&buffer->source);
|
||||||
if (endpoint != NULL) {
|
if (endpoint != NULL) {
|
||||||
RecursiveLocker locker(endpoint->Lock());
|
RecursiveLocker locker(endpoint->Lock());
|
||||||
TRACE(("Endpoint %p in state %s\n", endpoint, name_for_state(endpoint->State())));
|
TRACE(("Endpoint %p in state %s\n", endpoint, name_for_state(endpoint->State())));
|
||||||
@@ -575,13 +567,13 @@ tcp_receive_data(net_buffer *buffer)
|
|||||||
else if (segmentAction & ACKNOWLEDGE)
|
else if (segmentAction & ACKNOWLEDGE)
|
||||||
endpoint->DelayedAcknowledge();
|
endpoint->DelayedAcknowledge();
|
||||||
else if (segmentAction & DELETE)
|
else if (segmentAction & DELETE)
|
||||||
gSocketModule->delete_socket(endpoint->socket);
|
endpoint->DeleteSocket();
|
||||||
} else if ((segment.flags & TCP_FLAG_RESET) == 0)
|
} else if ((segment.flags & TCP_FLAG_RESET) == 0)
|
||||||
segmentAction = DROP | RESET;
|
segmentAction = DROP | RESET;
|
||||||
|
|
||||||
if (segmentAction & RESET) {
|
if (segmentAction & RESET) {
|
||||||
// send reset
|
// send reset
|
||||||
reply_with_reset(segment, buffer);
|
endpointManager->ReplyWithReset(segment, buffer);
|
||||||
}
|
}
|
||||||
if (segmentAction & DROP)
|
if (segmentAction & DROP)
|
||||||
gBufferModule->free(buffer);
|
gBufferModule->free(buffer);
|
||||||
@@ -611,52 +603,39 @@ tcp_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
|
|||||||
static status_t
|
static status_t
|
||||||
tcp_init()
|
tcp_init()
|
||||||
{
|
{
|
||||||
status_t status;
|
status_t status = benaphore_init(&sEndpointManagersLock,
|
||||||
|
"endpoint managers lock");
|
||||||
|
|
||||||
gDomain = NULL;
|
|
||||||
gAddressModule = NULL;
|
|
||||||
|
|
||||||
gEndpointManager = new (std::nothrow) EndpointManager();
|
|
||||||
if (gEndpointManager == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
status = gEndpointManager->InitCheck();
|
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
return status;
|
||||||
|
|
||||||
status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, 0,
|
status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, 0,
|
||||||
"network/protocols/tcp/v1",
|
"network/protocols/tcp/v1",
|
||||||
"network/protocols/ipv4/v1",
|
"network/protocols/ipv4/v1",
|
||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
return status;
|
||||||
|
|
||||||
status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_TCP,
|
status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, IPPROTO_TCP,
|
||||||
"network/protocols/tcp/v1",
|
"network/protocols/tcp/v1",
|
||||||
"network/protocols/ipv4/v1",
|
"network/protocols/ipv4/v1",
|
||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
return status;
|
||||||
|
|
||||||
status = gStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_TCP,
|
status = gStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_TCP,
|
||||||
"network/protocols/tcp/v1");
|
"network/protocols/tcp/v1");
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
return status;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
err1:
|
|
||||||
delete gEndpointManager;
|
|
||||||
|
|
||||||
TRACE(("init_tcp() fails with %lx (%s)\n", status, strerror(status)));
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
tcp_uninit()
|
tcp_uninit()
|
||||||
{
|
{
|
||||||
delete gEndpointManager;
|
benaphore_destroy(&sEndpointManagersLock);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,17 +157,18 @@ enum tcp_segment_action {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern net_domain *gDomain;
|
|
||||||
extern net_address_module_info *gAddressModule;
|
|
||||||
extern net_buffer_module_info *gBufferModule;
|
extern net_buffer_module_info *gBufferModule;
|
||||||
extern net_datalink_module_info *gDatalinkModule;
|
extern net_datalink_module_info *gDatalinkModule;
|
||||||
extern net_socket_module_info *gSocketModule;
|
extern net_socket_module_info *gSocketModule;
|
||||||
extern net_stack_module_info *gStackModule;
|
extern net_stack_module_info *gStackModule;
|
||||||
extern EndpointManager *gEndpointManager;
|
|
||||||
|
|
||||||
|
|
||||||
status_t add_tcp_header(tcp_segment_header &segment, net_buffer *buffer);
|
status_t add_tcp_header(net_address_module_info *addressModule,
|
||||||
|
tcp_segment_header &segment, net_buffer *buffer);
|
||||||
|
|
||||||
const char *name_for_state(tcp_state state);
|
const char *name_for_state(tcp_state state);
|
||||||
|
|
||||||
|
EndpointManager *create_endpoint_manager(net_domain *domain);
|
||||||
|
void return_endpoint_manager(EndpointManager *);
|
||||||
|
|
||||||
#endif // TCP_H
|
#endif // TCP_H
|
||||||
|
|||||||
Reference in New Issue
Block a user