* Moved some private members of net_socket into the new net_socket_private structure.
* Added an "owner" field that stores the team which created the socket (for netstat only); we would need a different storage for SIGURG if we ever want to support that. * Improved netstat address output: now prints "*" instead of INADDR_ANY. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19562 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <net_stat.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <team.h>
|
||||
#include <util/AutoLock.h>
|
||||
#include <util/list.h>
|
||||
#include <fs/select_sync_pool.h>
|
||||
@@ -24,6 +25,19 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
struct net_socket_private : net_socket {
|
||||
struct list_link link;
|
||||
team_id owner;
|
||||
uint32 max_backlog;
|
||||
uint32 child_count;
|
||||
struct list pending_children;
|
||||
struct list connected_children;
|
||||
|
||||
struct select_sync_pool *select_pool;
|
||||
benaphore lock;
|
||||
};
|
||||
|
||||
|
||||
void socket_delete(net_socket *socket);
|
||||
int socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength);
|
||||
|
||||
@@ -32,13 +46,13 @@ benaphore sSocketLock;
|
||||
|
||||
|
||||
static status_t
|
||||
create_socket(int family, int type, int protocol, net_socket **_socket)
|
||||
create_socket(int family, int type, int protocol, net_socket_private **_socket)
|
||||
{
|
||||
struct net_socket *socket = new (std::nothrow) net_socket;
|
||||
struct net_socket_private *socket = new (std::nothrow) net_socket_private;
|
||||
if (socket == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(socket, 0, sizeof(net_socket));
|
||||
memset(socket, 0, sizeof(net_socket_private));
|
||||
socket->family = family;
|
||||
socket->type = type;
|
||||
socket->protocol = protocol;
|
||||
@@ -55,8 +69,8 @@ create_socket(int family, int type, int protocol, net_socket **_socket)
|
||||
socket->receive.low_water_mark = 1;
|
||||
socket->receive.timeout = B_INFINITE_TIMEOUT;
|
||||
|
||||
list_init_etc(&socket->pending_children, offsetof(net_socket, link));
|
||||
list_init_etc(&socket->connected_children, offsetof(net_socket, link));
|
||||
list_init_etc(&socket->pending_children, offsetof(net_socket_private, link));
|
||||
list_init_etc(&socket->connected_children, offsetof(net_socket_private, link));
|
||||
|
||||
status = get_domain_protocols(socket);
|
||||
if (status < B_OK)
|
||||
@@ -79,7 +93,7 @@ err1:
|
||||
status_t
|
||||
socket_open(int family, int type, int protocol, net_socket **_socket)
|
||||
{
|
||||
net_socket *socket;
|
||||
net_socket_private *socket;
|
||||
status_t status = create_socket(family, type, protocol, &socket);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
@@ -90,6 +104,8 @@ socket_open(int family, int type, int protocol, net_socket **_socket)
|
||||
return status;
|
||||
}
|
||||
|
||||
socket->owner = team_get_current_team_id();
|
||||
|
||||
benaphore_lock(&sSocketLock);
|
||||
list_add_item(&sSocketList, socket);
|
||||
benaphore_unlock(&sSocketLock);
|
||||
@@ -100,8 +116,10 @@ socket_open(int family, int type, int protocol, net_socket **_socket)
|
||||
|
||||
|
||||
status_t
|
||||
socket_close(net_socket *socket)
|
||||
socket_close(net_socket *_socket)
|
||||
{
|
||||
net_socket_private *socket = (net_socket_private *)_socket;
|
||||
|
||||
if (socket->select_pool) {
|
||||
// notify all pending selects
|
||||
notify_select_event_pool(socket->select_pool, ~0);
|
||||
@@ -222,10 +240,11 @@ socket_get_next_stat(uint32 *_cookie, int family, struct net_stat *stat)
|
||||
{
|
||||
BenaphoreLocker locker(sSocketLock);
|
||||
|
||||
net_socket *socket = NULL;
|
||||
net_socket_private *socket = NULL;
|
||||
uint32 cookie = *_cookie;
|
||||
uint32 count = 0;
|
||||
while ((socket = (net_socket *)list_get_next_item(&sSocketList, socket)) != NULL) {
|
||||
while ((socket = (net_socket_private *)list_get_next_item(&sSocketList, socket)) != NULL) {
|
||||
// TODO: also traverse the pending connections
|
||||
if (count == cookie)
|
||||
break;
|
||||
|
||||
@@ -241,8 +260,7 @@ socket_get_next_stat(uint32 *_cookie, int family, struct net_stat *stat)
|
||||
stat->family = socket->family;
|
||||
stat->type = socket->type;
|
||||
stat->protocol = socket->protocol;
|
||||
stat->owner = -1;
|
||||
|
||||
stat->owner = socket->owner;
|
||||
stat->state[0] = '\0';
|
||||
memcpy(&stat->address, &socket->address, sizeof(struct sockaddr_storage));
|
||||
memcpy(&stat->peer, &socket->peer, sizeof(struct sockaddr_storage));
|
||||
@@ -260,8 +278,10 @@ socket_get_next_stat(uint32 *_cookie, int family, struct net_stat *stat)
|
||||
|
||||
|
||||
status_t
|
||||
socket_spawn_pending(net_socket *parent, net_socket **_socket)
|
||||
socket_spawn_pending(net_socket *_parent, net_socket **_socket)
|
||||
{
|
||||
net_socket_private *parent = (net_socket_private *)_parent;
|
||||
|
||||
BenaphoreLocker locker(parent->lock);
|
||||
|
||||
// We actually accept more pending connections to compensate for those
|
||||
@@ -270,8 +290,9 @@ socket_spawn_pending(net_socket *parent, net_socket **_socket)
|
||||
if (parent->child_count > 3 * parent->max_backlog / 2)
|
||||
return ENOBUFS;
|
||||
|
||||
net_socket *socket;
|
||||
status_t status = create_socket(parent->family, parent->type, parent->protocol, &socket);
|
||||
net_socket_private *socket;
|
||||
status_t status = create_socket(parent->family, parent->type, parent->protocol,
|
||||
&socket);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
@@ -280,6 +301,7 @@ socket_spawn_pending(net_socket *parent, net_socket **_socket)
|
||||
socket->receive = parent->receive;
|
||||
socket->options = parent->options & ~SO_ACCEPTCONN;
|
||||
socket->linger = parent->linger;
|
||||
socket->owner = parent->owner;
|
||||
memcpy(&socket->address, &parent->address, parent->address.ss_len);
|
||||
memcpy(&socket->peer, &parent->peer, parent->peer.ss_len);
|
||||
|
||||
@@ -294,8 +316,10 @@ socket_spawn_pending(net_socket *parent, net_socket **_socket)
|
||||
|
||||
|
||||
void
|
||||
socket_delete(net_socket *socket)
|
||||
socket_delete(net_socket *_socket)
|
||||
{
|
||||
net_socket_private *socket = (net_socket_private *)_socket;
|
||||
|
||||
if (socket->parent != NULL)
|
||||
panic("socket still has a parent!");
|
||||
|
||||
@@ -311,11 +335,14 @@ socket_delete(net_socket *socket)
|
||||
|
||||
|
||||
status_t
|
||||
socket_dequeue_connected(net_socket *parent, net_socket **_socket)
|
||||
socket_dequeue_connected(net_socket *_parent, net_socket **_socket)
|
||||
{
|
||||
net_socket_private *parent = (net_socket_private *)_parent;
|
||||
|
||||
benaphore_lock(&parent->lock);
|
||||
|
||||
net_socket *socket = (net_socket *)list_remove_head_item(&parent->connected_children);
|
||||
net_socket_private *socket = (net_socket_private *)list_remove_head_item(
|
||||
&parent->connected_children);
|
||||
if (socket != NULL) {
|
||||
socket->parent = NULL;
|
||||
parent->child_count--;
|
||||
@@ -336,8 +363,10 @@ socket_dequeue_connected(net_socket *parent, net_socket **_socket)
|
||||
|
||||
|
||||
status_t
|
||||
socket_set_max_backlog(net_socket *socket, uint32 backlog)
|
||||
socket_set_max_backlog(net_socket *_socket, uint32 backlog)
|
||||
{
|
||||
net_socket_private *socket = (net_socket_private *)_socket;
|
||||
|
||||
// we enforce an upper limit of connections waiting to be accepted
|
||||
if (backlog > 256)
|
||||
backlog = 256;
|
||||
@@ -345,14 +374,14 @@ socket_set_max_backlog(net_socket *socket, uint32 backlog)
|
||||
benaphore_lock(&socket->lock);
|
||||
|
||||
// first remove the pending connections, then the already connected ones as needed
|
||||
net_socket *child;
|
||||
net_socket_private *child;
|
||||
while (socket->child_count > backlog
|
||||
&& (child = (net_socket *)list_remove_tail_item(&socket->pending_children)) != NULL) {
|
||||
&& (child = (net_socket_private *)list_remove_tail_item(&socket->pending_children)) != NULL) {
|
||||
child->parent = NULL;
|
||||
socket->child_count--;
|
||||
}
|
||||
while (socket->child_count > backlog
|
||||
&& (child = (net_socket *)list_remove_tail_item(&socket->connected_children)) != NULL) {
|
||||
&& (child = (net_socket_private *)list_remove_tail_item(&socket->connected_children)) != NULL) {
|
||||
child->parent = NULL;
|
||||
socket_delete(child);
|
||||
socket->child_count--;
|
||||
@@ -371,7 +400,7 @@ socket_set_max_backlog(net_socket *socket, uint32 backlog)
|
||||
status_t
|
||||
socket_connected(net_socket *socket)
|
||||
{
|
||||
net_socket *parent = socket->parent;
|
||||
net_socket_private *parent = (net_socket_private *)socket->parent;
|
||||
if (parent == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
@@ -389,9 +418,11 @@ socket_connected(net_socket *socket)
|
||||
|
||||
|
||||
status_t
|
||||
socket_request_notification(net_socket *socket, uint8 event, uint32 ref,
|
||||
socket_request_notification(net_socket *_socket, uint8 event, uint32 ref,
|
||||
selectsync *sync)
|
||||
{
|
||||
net_socket_private *socket = (net_socket_private *)_socket;
|
||||
|
||||
benaphore_lock(&socket->lock);
|
||||
|
||||
status_t status = add_select_sync_pool_entry(&socket->select_pool, sync,
|
||||
@@ -430,8 +461,10 @@ socket_request_notification(net_socket *socket, uint8 event, uint32 ref,
|
||||
|
||||
|
||||
status_t
|
||||
socket_cancel_notification(net_socket *socket, uint8 event, selectsync *sync)
|
||||
socket_cancel_notification(net_socket *_socket, uint8 event, selectsync *sync)
|
||||
{
|
||||
net_socket_private *socket = (net_socket_private *)_socket;
|
||||
|
||||
benaphore_lock(&socket->lock);
|
||||
|
||||
status_t status = remove_select_sync_pool_entry(&socket->select_pool,
|
||||
@@ -443,8 +476,9 @@ socket_cancel_notification(net_socket *socket, uint8 event, selectsync *sync)
|
||||
|
||||
|
||||
status_t
|
||||
socket_notify(net_socket *socket, uint8 event, int32 value)
|
||||
socket_notify(net_socket *_socket, uint8 event, int32 value)
|
||||
{
|
||||
net_socket_private *socket = (net_socket_private *)_socket;
|
||||
bool notify = true;
|
||||
|
||||
switch (event) {
|
||||
@@ -492,7 +526,8 @@ socket_accept(net_socket *socket, struct sockaddr *address, socklen_t *_addressL
|
||||
return status;
|
||||
|
||||
if (address && *_addressLength > 0) {
|
||||
memcpy(address, &accepted->peer, min_c(*_addressLength, accepted->peer.ss_len));
|
||||
memcpy(address, &accepted->peer, min_c(*_addressLength,
|
||||
min_c(accepted->peer.ss_len, sizeof(sockaddr_storage))));
|
||||
*_addressLength = accepted->peer.ss_len;
|
||||
}
|
||||
|
||||
@@ -983,7 +1018,7 @@ socket_std_ops(int32 op, ...)
|
||||
// initialize the main stack if not done so already
|
||||
//module_info *module;
|
||||
//return get_module(NET_STARTER_MODULE_NAME, &module);
|
||||
list_init_etc(&sSocketList, offsetof(net_socket, link));
|
||||
list_init_etc(&sSocketList, offsetof(net_socket_private, link));
|
||||
return benaphore_init(&sSocketLock, "socket list");
|
||||
}
|
||||
case B_MODULE_UNINIT:
|
||||
|
||||
Reference in New Issue
Block a user