* Sockets now inherit from WeakReferenceable.
* This fixes the problem when a socket changes something with regards to its parent. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30000 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef NET_SOCKET_H
|
#ifndef NET_SOCKET_H
|
||||||
@@ -38,7 +38,6 @@ typedef struct net_socket {
|
|||||||
} send, receive;
|
} send, receive;
|
||||||
|
|
||||||
status_t error;
|
status_t error;
|
||||||
struct net_socket *parent;
|
|
||||||
} net_socket;
|
} net_socket;
|
||||||
|
|
||||||
struct net_socket_module_info {
|
struct net_socket_module_info {
|
||||||
@@ -47,7 +46,7 @@ struct net_socket_module_info {
|
|||||||
status_t (*open_socket)(int family, int type, int protocol,
|
status_t (*open_socket)(int family, int type, int protocol,
|
||||||
net_socket **_socket);
|
net_socket **_socket);
|
||||||
status_t (*close)(net_socket *socket);
|
status_t (*close)(net_socket *socket);
|
||||||
status_t (*free)(net_socket *socket);
|
void (*free)(net_socket *socket);
|
||||||
|
|
||||||
status_t (*readv)(net_socket *socket, const iovec *vecs,
|
status_t (*readv)(net_socket *socket, const iovec *vecs,
|
||||||
size_t vecCount, size_t *_length);
|
size_t vecCount, size_t *_length);
|
||||||
@@ -72,13 +71,17 @@ struct net_socket_module_info {
|
|||||||
struct net_stat *stat);
|
struct net_stat *stat);
|
||||||
|
|
||||||
// connections
|
// connections
|
||||||
|
void (*acquire_socket)(net_socket *socket);
|
||||||
|
bool (*release_socket)(net_socket *socket);
|
||||||
|
|
||||||
status_t (*spawn_pending_socket)(net_socket *parent,
|
status_t (*spawn_pending_socket)(net_socket *parent,
|
||||||
net_socket **_socket);
|
net_socket **_socket);
|
||||||
void (*delete_socket)(net_socket *socket);
|
|
||||||
status_t (*dequeue_connected)(net_socket *parent, net_socket **_socket);
|
status_t (*dequeue_connected)(net_socket *parent, net_socket **_socket);
|
||||||
ssize_t (*count_connected)(net_socket *parent);
|
ssize_t (*count_connected)(net_socket *parent);
|
||||||
status_t (*set_max_backlog)(net_socket *socket, uint32 backlog);
|
status_t (*set_max_backlog)(net_socket *socket, uint32 backlog);
|
||||||
|
bool (*has_parent)(net_socket *socket);
|
||||||
status_t (*set_connected)(net_socket *socket);
|
status_t (*set_connected)(net_socket *socket);
|
||||||
|
status_t (*set_aborted)(net_socket *socket);
|
||||||
|
|
||||||
// notifications
|
// notifications
|
||||||
status_t (*request_notification)(net_socket *socket, uint8 event,
|
status_t (*request_notification)(net_socket *socket, uint8 event,
|
||||||
|
|||||||
@@ -318,7 +318,9 @@ EndpointManager::FindConnection(sockaddr* local, sockaddr* peer)
|
|||||||
|
|
||||||
TCPEndpoint *endpoint = _LookupConnection(local, peer);
|
TCPEndpoint *endpoint = _LookupConnection(local, peer);
|
||||||
if (endpoint != NULL) {
|
if (endpoint != NULL) {
|
||||||
TRACE(("TCP: Received packet corresponds to explicit endpoint %p\n", endpoint));
|
TRACE(("TCP: Received packet corresponds to explicit endpoint %p\n",
|
||||||
|
endpoint));
|
||||||
|
gSocketModule->acquire_socket(endpoint->socket);
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +331,9 @@ EndpointManager::FindConnection(sockaddr* local, sockaddr* peer)
|
|||||||
|
|
||||||
endpoint = _LookupConnection(local, *wildcard);
|
endpoint = _LookupConnection(local, *wildcard);
|
||||||
if (endpoint != NULL) {
|
if (endpoint != NULL) {
|
||||||
TRACE(("TCP: Received packet corresponds to wildcard endpoint %p\n", endpoint));
|
TRACE(("TCP: Received packet corresponds to wildcard endpoint %p\n",
|
||||||
|
endpoint));
|
||||||
|
gSocketModule->acquire_socket(endpoint->socket);
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +343,9 @@ EndpointManager::FindConnection(sockaddr* local, sockaddr* peer)
|
|||||||
|
|
||||||
endpoint = _LookupConnection(*localWildcard, *wildcard);
|
endpoint = _LookupConnection(*localWildcard, *wildcard);
|
||||||
if (endpoint != NULL) {
|
if (endpoint != NULL) {
|
||||||
TRACE(("TCP: Received packet corresponds to local wildcard endpoint %p\n", endpoint));
|
TRACE(("TCP: Received packet corresponds to local wildcard endpoint "
|
||||||
|
"%p\n", endpoint));
|
||||||
|
gSocketModule->acquire_socket(endpoint->socket);
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,7 +570,7 @@ void
|
|||||||
EndpointManager::Dump() const
|
EndpointManager::Dump() const
|
||||||
{
|
{
|
||||||
kprintf("-------- TCP Domain %p ---------\n", this);
|
kprintf("-------- TCP Domain %p ---------\n", this);
|
||||||
kprintf("%10s %20s %20s %8s %8s %12s\n", "address", "local", "peer",
|
kprintf("%10s %21s %21s %8s %8s %12s\n", "address", "local", "peer",
|
||||||
"recv-q", "send-q", "state");
|
"recv-q", "send-q", "state");
|
||||||
|
|
||||||
ConnectionTable::Iterator iterator = fConnectionHash.GetIterator();
|
ConnectionTable::Iterator iterator = fConnectionHash.GetIterator();
|
||||||
@@ -576,7 +582,7 @@ EndpointManager::Dump() const
|
|||||||
endpoint->LocalAddress().AsString(localBuf, sizeof(localBuf), true);
|
endpoint->LocalAddress().AsString(localBuf, sizeof(localBuf), true);
|
||||||
endpoint->PeerAddress().AsString(peerBuf, sizeof(peerBuf), true);
|
endpoint->PeerAddress().AsString(peerBuf, sizeof(peerBuf), true);
|
||||||
|
|
||||||
kprintf("%p %20s %20s %8lu %8lu %12s\n", endpoint, localBuf, peerBuf,
|
kprintf("%p %21s %21s %8lu %8lu %12s\n", endpoint, localBuf, peerBuf,
|
||||||
endpoint->fReceiveQueue.Available(), endpoint->fSendQueue.Used(),
|
endpoint->fReceiveQueue.Available(), endpoint->fSendQueue.Used(),
|
||||||
name_for_state(endpoint->State()));
|
name_for_state(endpoint->State()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -554,7 +554,7 @@ TCPEndpoint::Close()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
void
|
||||||
TCPEndpoint::Free()
|
TCPEndpoint::Free()
|
||||||
{
|
{
|
||||||
TRACE("Free()");
|
TRACE("Free()");
|
||||||
@@ -562,17 +562,16 @@ TCPEndpoint::Free()
|
|||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
if (fState <= SYNCHRONIZE_SENT)
|
if (fState <= SYNCHRONIZE_SENT)
|
||||||
return B_OK;
|
return;
|
||||||
|
|
||||||
// we are only interested in the timer, not in changing state
|
// we are only interested in the timer, not in changing state
|
||||||
_EnterTimeWait();
|
_EnterTimeWait();
|
||||||
|
|
||||||
fFlags |= FLAG_CLOSED;
|
fFlags |= FLAG_CLOSED;
|
||||||
if ((fFlags & FLAG_DELETE_ON_CLOSE) != 0)
|
if ((fFlags & FLAG_DELETE_ON_CLOSE) == 0) {
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
return B_BUSY;
|
|
||||||
// we'll be freed later when the 2MSL timer expires
|
// we'll be freed later when the 2MSL timer expires
|
||||||
|
gSocketModule->acquire_socket(socket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1169,7 +1168,7 @@ TCPEndpoint::_MarkEstablished()
|
|||||||
fState = ESTABLISHED;
|
fState = ESTABLISHED;
|
||||||
T(State(this));
|
T(State(this));
|
||||||
|
|
||||||
if (socket->parent != NULL) {
|
if (gSocketModule->has_parent(socket)) {
|
||||||
gSocketModule->set_connected(socket);
|
gSocketModule->set_connected(socket);
|
||||||
release_sem_etc(fAcceptSemaphore, 1, B_DO_NOT_RESCHEDULE);
|
release_sem_etc(fAcceptSemaphore, 1, B_DO_NOT_RESCHEDULE);
|
||||||
}
|
}
|
||||||
@@ -1211,13 +1210,11 @@ TCPEndpoint::_Close()
|
|||||||
fSendList.Signal();
|
fSendList.Signal();
|
||||||
_NotifyReader();
|
_NotifyReader();
|
||||||
|
|
||||||
if (socket->parent != NULL) {
|
if (gSocketModule->has_parent(socket)) {
|
||||||
// We still have a parent - obviously, we haven't been accepted yet,
|
// We still have a parent - obviously, we haven't been accepted yet,
|
||||||
// so no one could ever close us.
|
// so no one could ever close us.
|
||||||
// Since we can't just delete ourself here, we trigger an immediate
|
|
||||||
// time-wait timer.
|
|
||||||
_CancelConnectionTimers();
|
_CancelConnectionTimers();
|
||||||
gStackModule->set_timer(&fTimeWaitTimer, 0);
|
gSocketModule->set_aborted(socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1792,8 +1789,7 @@ TCPEndpoint::SegmentReceived(tcp_segment_header& segment, net_buffer* buffer)
|
|||||||
if ((fFlags & (FLAG_CLOSED | FLAG_DELETE_ON_CLOSE))
|
if ((fFlags & (FLAG_CLOSED | FLAG_DELETE_ON_CLOSE))
|
||||||
== (FLAG_CLOSED | FLAG_DELETE_ON_CLOSE)) {
|
== (FLAG_CLOSED | FLAG_DELETE_ON_CLOSE)) {
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
gSocketModule->delete_socket(socket);
|
gSocketModule->release_socket(socket);
|
||||||
// this will also delete us
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return segmentAction;
|
return segmentAction;
|
||||||
@@ -2293,7 +2289,7 @@ TCPEndpoint::_TimeWaitTimer(net_timer* timer, void* _endpoint)
|
|||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
gSocketModule->delete_socket(endpoint->socket);
|
gSocketModule->release_socket(endpoint->socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
status_t Open();
|
status_t Open();
|
||||||
status_t Close();
|
status_t Close();
|
||||||
status_t Free();
|
void Free();
|
||||||
status_t Connect(const struct sockaddr* address);
|
status_t Connect(const struct sockaddr* address);
|
||||||
status_t Accept(struct net_socket** _acceptedSocket);
|
status_t Accept(struct net_socket** _acceptedSocket);
|
||||||
status_t Bind(const sockaddr* address);
|
status_t Bind(const sockaddr* address);
|
||||||
|
|||||||
@@ -496,7 +496,8 @@ tcp_close(net_protocol* protocol)
|
|||||||
status_t
|
status_t
|
||||||
tcp_free(net_protocol* protocol)
|
tcp_free(net_protocol* protocol)
|
||||||
{
|
{
|
||||||
return ((TCPEndpoint*)protocol)->Free();
|
((TCPEndpoint*)protocol)->Free();
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -708,9 +709,10 @@ tcp_receive_data(net_buffer* buffer)
|
|||||||
|
|
||||||
TCPEndpoint* endpoint = endpointManager->FindConnection(
|
TCPEndpoint* endpoint = endpointManager->FindConnection(
|
||||||
buffer->destination, buffer->source);
|
buffer->destination, buffer->source);
|
||||||
if (endpoint != NULL)
|
if (endpoint != NULL) {
|
||||||
segmentAction = endpoint->SegmentReceived(segment, buffer);
|
segmentAction = endpoint->SegmentReceived(segment, buffer);
|
||||||
else if ((segment.flags & TCP_FLAG_RESET) == 0)
|
gSocketModule->release_socket(endpoint->socket);
|
||||||
|
} else if ((segment.flags & TCP_FLAG_RESET) == 0)
|
||||||
segmentAction = DROP | RESET;
|
segmentAction = DROP | RESET;
|
||||||
|
|
||||||
if ((segmentAction & RESET) != 0) {
|
if ((segmentAction & RESET) != 0) {
|
||||||
|
|||||||
@@ -16,13 +16,15 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
|
||||||
#include <Drivers.h>
|
#include <Drivers.h>
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <Select.h>
|
#include <Select.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <team.h>
|
#include <team.h>
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
#include <util/list.h>
|
#include <util/list.h>
|
||||||
|
#include <WeakReferenceable.h>
|
||||||
|
|
||||||
#include <fs/select_sync_pool.h>
|
#include <fs/select_sync_pool.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
@@ -41,8 +43,15 @@
|
|||||||
struct net_socket_private;
|
struct net_socket_private;
|
||||||
typedef DoublyLinkedList<net_socket_private> SocketList;
|
typedef DoublyLinkedList<net_socket_private> SocketList;
|
||||||
|
|
||||||
struct net_socket_private
|
struct net_socket_private : net_socket,
|
||||||
: net_socket, DoublyLinkedListLinkImpl<net_socket_private> {
|
DoublyLinkedListLinkImpl<net_socket_private>,
|
||||||
|
WeakReferenceable<net_socket_private> {
|
||||||
|
net_socket_private();
|
||||||
|
~net_socket_private();
|
||||||
|
|
||||||
|
void RemoveFromParent();
|
||||||
|
|
||||||
|
WeakPointer<net_socket_private>* parent;
|
||||||
team_id owner;
|
team_id owner;
|
||||||
uint32 max_backlog;
|
uint32 max_backlog;
|
||||||
uint32 child_count;
|
uint32 child_count;
|
||||||
@@ -56,7 +65,6 @@ struct net_socket_private
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void socket_delete(net_socket* socket);
|
|
||||||
int socket_bind(net_socket* socket, const struct sockaddr* address,
|
int socket_bind(net_socket* socket, const struct sockaddr* address,
|
||||||
socklen_t addressLength);
|
socklen_t addressLength);
|
||||||
int socket_setsockopt(net_socket* socket, int level, int option,
|
int socket_setsockopt(net_socket* socket, int level, int option,
|
||||||
@@ -67,6 +75,80 @@ static SocketList sSocketList;
|
|||||||
static mutex sSocketLock;
|
static mutex sSocketLock;
|
||||||
|
|
||||||
|
|
||||||
|
net_socket_private::net_socket_private()
|
||||||
|
: WeakReferenceable<net_socket_private>(this),
|
||||||
|
parent(NULL),
|
||||||
|
owner(-1),
|
||||||
|
max_backlog(0),
|
||||||
|
child_count(0),
|
||||||
|
select_pool(NULL),
|
||||||
|
is_connected(false)
|
||||||
|
{
|
||||||
|
first_protocol = NULL;
|
||||||
|
first_info = NULL;
|
||||||
|
options = 0;
|
||||||
|
linger = 0;
|
||||||
|
bound_to_device = 0;
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
address.ss_len = 0;
|
||||||
|
peer.ss_len = 0;
|
||||||
|
|
||||||
|
mutex_init(&lock, "socket");
|
||||||
|
|
||||||
|
// set defaults (may be overridden by the protocols)
|
||||||
|
send.buffer_size = 65535;
|
||||||
|
send.low_water_mark = 1;
|
||||||
|
send.timeout = B_INFINITE_TIMEOUT;
|
||||||
|
receive.buffer_size = 65535;
|
||||||
|
receive.low_water_mark = 1;
|
||||||
|
receive.timeout = B_INFINITE_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
net_socket_private::~net_socket_private()
|
||||||
|
{
|
||||||
|
if (parent != NULL)
|
||||||
|
panic("socket still has a parent!");
|
||||||
|
|
||||||
|
mutex_lock(&sSocketLock);
|
||||||
|
sSocketList.Remove(this);
|
||||||
|
mutex_unlock(&sSocketLock);
|
||||||
|
|
||||||
|
mutex_lock(&lock);
|
||||||
|
|
||||||
|
// also delete all children of this socket
|
||||||
|
while (net_socket_private* child = pending_children.RemoveHead()) {
|
||||||
|
child->RemoveFromParent();
|
||||||
|
}
|
||||||
|
while (net_socket_private* child = connected_children.RemoveHead()) {
|
||||||
|
child->RemoveFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
put_domain_protocols(this);
|
||||||
|
|
||||||
|
mutex_unlock(&lock);
|
||||||
|
mutex_destroy(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
net_socket_private::RemoveFromParent()
|
||||||
|
{
|
||||||
|
parent->RemoveReference();
|
||||||
|
parent = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&sSocketLock);
|
||||||
|
sSocketList.Add(this);
|
||||||
|
mutex_unlock(&sSocketLock);
|
||||||
|
|
||||||
|
RemoveReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
compute_user_iovec_length(iovec* userVec, uint32 count)
|
compute_user_iovec_length(iovec* userVec, uint32 count)
|
||||||
{
|
{
|
||||||
@@ -84,16 +166,6 @@ compute_user_iovec_length(iovec* userVec, uint32 count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
delete_children(SocketList& list)
|
|
||||||
{
|
|
||||||
while (net_socket_private* child = list.RemoveHead()) {
|
|
||||||
child->parent = NULL;
|
|
||||||
socket_delete(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
create_socket(int family, int type, int protocol, net_socket_private** _socket)
|
create_socket(int family, int type, int protocol, net_socket_private** _socket)
|
||||||
{
|
{
|
||||||
@@ -101,21 +173,10 @@ create_socket(int family, int type, int protocol, net_socket_private** _socket)
|
|||||||
if (socket == NULL)
|
if (socket == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
memset(socket, 0, sizeof(net_socket_private));
|
|
||||||
socket->family = family;
|
socket->family = family;
|
||||||
socket->type = type;
|
socket->type = type;
|
||||||
socket->protocol = protocol;
|
socket->protocol = protocol;
|
||||||
|
|
||||||
mutex_init(&socket->lock, "socket");
|
|
||||||
|
|
||||||
// set defaults (may be overridden by the protocols)
|
|
||||||
socket->send.buffer_size = 65535;
|
|
||||||
socket->send.low_water_mark = 1;
|
|
||||||
socket->send.timeout = B_INFINITE_TIMEOUT;
|
|
||||||
socket->receive.buffer_size = 65535;
|
|
||||||
socket->receive.low_water_mark = 1;
|
|
||||||
socket->receive.timeout = B_INFINITE_TIMEOUT;
|
|
||||||
|
|
||||||
status_t status = get_domain_protocols(socket);
|
status_t status = get_domain_protocols(socket);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
mutex_destroy(&socket->lock);
|
mutex_destroy(&socket->lock);
|
||||||
@@ -316,7 +377,7 @@ socket_open(int family, int type, int protocol, net_socket** _socket)
|
|||||||
|
|
||||||
status = socket->first_info->open(socket->first_protocol);
|
status = socket->first_info->open(socket->first_protocol);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
socket_delete(socket);
|
delete socket;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,15 +400,12 @@ socket_close(net_socket* _socket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
void
|
||||||
socket_free(net_socket* socket)
|
socket_free(net_socket* _socket)
|
||||||
{
|
{
|
||||||
status_t status = socket->first_info->free(socket->first_protocol);
|
net_socket_private* socket = (net_socket_private*)_socket;
|
||||||
if (status == B_BUSY)
|
socket->first_info->free(socket->first_protocol);
|
||||||
return B_OK;
|
socket->RemoveReference();
|
||||||
|
|
||||||
socket_delete(socket);
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -532,6 +590,22 @@ socket_get_next_stat(uint32* _cookie, int family, struct net_stat* stat)
|
|||||||
// #pragma mark - connections
|
// #pragma mark - connections
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_acquire(net_socket* _socket)
|
||||||
|
{
|
||||||
|
net_socket_private* socket = (net_socket_private*)_socket;
|
||||||
|
socket->AddReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
socket_release(net_socket* _socket)
|
||||||
|
{
|
||||||
|
net_socket_private* socket = (net_socket_private*)_socket;
|
||||||
|
return socket->RemoveReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
socket_spawn_pending(net_socket* _parent, net_socket** _socket)
|
socket_spawn_pending(net_socket* _parent, net_socket** _socket)
|
||||||
{
|
{
|
||||||
@@ -562,7 +636,7 @@ socket_spawn_pending(net_socket* _parent, net_socket** _socket)
|
|||||||
|
|
||||||
// add to the parent's list of pending connections
|
// add to the parent's list of pending connections
|
||||||
parent->pending_children.Add(socket);
|
parent->pending_children.Add(socket);
|
||||||
socket->parent = parent;
|
socket->parent = parent->GetWeakPointer();
|
||||||
parent->child_count++;
|
parent->child_count++;
|
||||||
|
|
||||||
*_socket = socket;
|
*_socket = socket;
|
||||||
@@ -570,42 +644,9 @@ socket_spawn_pending(net_socket* _parent, net_socket** _socket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
/*! Dequeues a connected child from a parent socket.
|
||||||
socket_delete(net_socket* _socket)
|
It also returns a reference with the child socket.
|
||||||
{
|
*/
|
||||||
net_socket_private* socket = (net_socket_private*)_socket;
|
|
||||||
net_socket_private* parent = (net_socket_private*)socket->parent;
|
|
||||||
|
|
||||||
if (parent != NULL) {
|
|
||||||
// The socket still has a parent
|
|
||||||
// TODO: we need to make sure our parent isn't deleted right now,
|
|
||||||
// or in the process of deleting its children...
|
|
||||||
MutexLocker _(parent->lock);
|
|
||||||
|
|
||||||
if (socket->is_connected)
|
|
||||||
parent->connected_children.Remove(socket);
|
|
||||||
else
|
|
||||||
parent->pending_children.Remove(socket);
|
|
||||||
|
|
||||||
parent->child_count--;
|
|
||||||
socket->parent = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&sSocketLock);
|
|
||||||
sSocketList.Remove(socket);
|
|
||||||
mutex_unlock(&sSocketLock);
|
|
||||||
|
|
||||||
// also delete all children of this socket
|
|
||||||
delete_children(socket->pending_children);
|
|
||||||
delete_children(socket->connected_children);
|
|
||||||
|
|
||||||
put_domain_protocols(socket);
|
|
||||||
|
|
||||||
mutex_destroy(&socket->lock);
|
|
||||||
delete socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
socket_dequeue_connected(net_socket* _parent, net_socket** _socket)
|
socket_dequeue_connected(net_socket* _parent, net_socket** _socket)
|
||||||
{
|
{
|
||||||
@@ -615,7 +656,8 @@ socket_dequeue_connected(net_socket* _parent, net_socket** _socket)
|
|||||||
|
|
||||||
net_socket_private* socket = parent->connected_children.RemoveHead();
|
net_socket_private* socket = parent->connected_children.RemoveHead();
|
||||||
if (socket != NULL) {
|
if (socket != NULL) {
|
||||||
socket->parent = NULL;
|
socket->AddReference();
|
||||||
|
socket->RemoveFromParent();
|
||||||
parent->child_count--;
|
parent->child_count--;
|
||||||
*_socket = socket;
|
*_socket = socket;
|
||||||
}
|
}
|
||||||
@@ -625,10 +667,6 @@ socket_dequeue_connected(net_socket* _parent, net_socket** _socket)
|
|||||||
if (socket == NULL)
|
if (socket == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
mutex_lock(&sSocketLock);
|
|
||||||
sSocketList.Add(socket);
|
|
||||||
mutex_unlock(&sSocketLock);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,13 +697,12 @@ socket_set_max_backlog(net_socket* _socket, uint32 backlog)
|
|||||||
net_socket_private* child;
|
net_socket_private* child;
|
||||||
while (socket->child_count > backlog
|
while (socket->child_count > backlog
|
||||||
&& (child = socket->pending_children.RemoveTail()) != NULL) {
|
&& (child = socket->pending_children.RemoveTail()) != NULL) {
|
||||||
child->parent = NULL;
|
child->RemoveFromParent();
|
||||||
socket->child_count--;
|
socket->child_count--;
|
||||||
}
|
}
|
||||||
while (socket->child_count > backlog
|
while (socket->child_count > backlog
|
||||||
&& (child = socket->connected_children.RemoveTail()) != NULL) {
|
&& (child = socket->connected_children.RemoveTail()) != NULL) {
|
||||||
child->parent = NULL;
|
child->RemoveFromParent();
|
||||||
socket_delete(child);
|
|
||||||
socket->child_count--;
|
socket->child_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,21 +711,34 @@ socket_set_max_backlog(net_socket* _socket, uint32 backlog)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Returns whether or not this socket has a parent. The parent might not be
|
||||||
|
valid anymore, though.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
socket_has_parent(net_socket* _socket)
|
||||||
|
{
|
||||||
|
net_socket_private* socket = (net_socket_private*)_socket;
|
||||||
|
return socket->parent != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! The socket has been connected. It will be moved to the connected queue
|
/*! The socket has been connected. It will be moved to the connected queue
|
||||||
of its parent socket.
|
of its parent socket.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
socket_connected(net_socket* socket)
|
socket_connected(net_socket* _socket)
|
||||||
{
|
{
|
||||||
net_socket_private* parent = (net_socket_private*)socket->parent;
|
net_socket_private* socket = (net_socket_private*)_socket;
|
||||||
|
|
||||||
|
WeakReference<net_socket_private> parent = socket->parent;
|
||||||
if (parent == NULL)
|
if (parent == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
MutexLocker _(&parent->lock);
|
MutexLocker _(parent->lock);
|
||||||
|
|
||||||
parent->pending_children.Remove((net_socket_private*)socket);
|
parent->pending_children.Remove(socket);
|
||||||
parent->connected_children.Add((net_socket_private*)socket);
|
parent->connected_children.Add(socket);
|
||||||
((net_socket_private*)socket)->is_connected = true;
|
socket->is_connected = true;
|
||||||
|
|
||||||
// notify parent
|
// notify parent
|
||||||
if (parent->select_pool)
|
if (parent->select_pool)
|
||||||
@@ -698,6 +748,32 @@ socket_connected(net_socket* socket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! The socket has been aborted. Steals the parent's reference, and releases
|
||||||
|
it.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
socket_aborted(net_socket* _socket)
|
||||||
|
{
|
||||||
|
net_socket_private* socket = (net_socket_private*)_socket;
|
||||||
|
|
||||||
|
WeakReference<net_socket_private> parent = socket->parent;
|
||||||
|
if (parent == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
MutexLocker _(parent->lock);
|
||||||
|
|
||||||
|
if (socket->is_connected)
|
||||||
|
parent->connected_children.Remove(socket);
|
||||||
|
else
|
||||||
|
parent->pending_children.Remove(socket);
|
||||||
|
|
||||||
|
parent->child_count--;
|
||||||
|
socket->RemoveFromParent();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - notifications
|
// #pragma mark - notifications
|
||||||
|
|
||||||
|
|
||||||
@@ -1551,12 +1627,15 @@ net_socket_module_info gNetSocketModule = {
|
|||||||
socket_get_next_stat,
|
socket_get_next_stat,
|
||||||
|
|
||||||
// connections
|
// connections
|
||||||
|
socket_acquire,
|
||||||
|
socket_release,
|
||||||
socket_spawn_pending,
|
socket_spawn_pending,
|
||||||
socket_delete,
|
|
||||||
socket_dequeue_connected,
|
socket_dequeue_connected,
|
||||||
socket_count_connected,
|
socket_count_connected,
|
||||||
socket_set_max_backlog,
|
socket_set_max_backlog,
|
||||||
|
socket_has_parent,
|
||||||
socket_connected,
|
socket_connected,
|
||||||
|
socket_aborted,
|
||||||
|
|
||||||
// notifications
|
// notifications
|
||||||
socket_request_notification,
|
socket_request_notification,
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ stack_interface_close(net_socket* socket)
|
|||||||
static status_t
|
static status_t
|
||||||
stack_interface_free(net_socket* socket)
|
stack_interface_free(net_socket* socket)
|
||||||
{
|
{
|
||||||
return gNetSocketModule.free(socket);
|
gNetSocketModule.free(socket);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user