* Moved the private kernel locking functions into kernelland_emu.cpp because the
actual versions cannot work in userland. * Extended the tcp_tester to be able to connect and quit connections. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19330 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -8,7 +8,6 @@ SharedLibrary libkernelland_emu.so :
|
|||||||
kernelland_emu.cpp
|
kernelland_emu.cpp
|
||||||
strlcpy.c
|
strlcpy.c
|
||||||
khash.c
|
khash.c
|
||||||
lock.c
|
|
||||||
list.c
|
list.c
|
||||||
|
|
||||||
: be stdc++.r4 ;
|
: be stdc++.r4 ;
|
||||||
@@ -20,10 +19,6 @@ SEARCH on [ FGristFiles
|
|||||||
strlcpy.c
|
strlcpy.c
|
||||||
] = [ FDirName $(HAIKU_TOP) src system libroot posix string ] ;
|
] = [ FDirName $(HAIKU_TOP) src system libroot posix string ] ;
|
||||||
|
|
||||||
SEARCH on [ FGristFiles
|
|
||||||
lock.c
|
|
||||||
] = [ FDirName $(HAIKU_TOP) src system kernel ] ;
|
|
||||||
|
|
||||||
SEARCH on [ FGristFiles
|
SEARCH on [ FGristFiles
|
||||||
list.c khash.c
|
list.c khash.c
|
||||||
] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// kernelland_emu.cpp
|
// kernelland_emu.cpp
|
||||||
|
|
||||||
#include <set>
|
#include <lock.h>
|
||||||
#include <stdio.h>
|
#include <fs/devfs.h>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
@@ -15,7 +14,9 @@
|
|||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include <fs/devfs.h>
|
#include <set>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
#undef TRACE
|
#undef TRACE
|
||||||
@@ -786,3 +787,234 @@ arch_int_are_interrupts_enabled(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Private locking functions
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
recursive_lock_get_recursion(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
thread_id thid = find_thread(NULL);
|
||||||
|
|
||||||
|
if (lock->holder == thid)
|
||||||
|
return lock->recursion;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
recursive_lock_init(recursive_lock *lock, const char *name)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "recursive lock";
|
||||||
|
|
||||||
|
lock->holder = -1;
|
||||||
|
lock->recursion = 0;
|
||||||
|
lock->sem = create_sem(1, name);
|
||||||
|
|
||||||
|
if (lock->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return lock->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
recursive_lock_destroy(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_sem(lock->sem);
|
||||||
|
lock->sem = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
recursive_lock_lock(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
thread_id thid = find_thread(NULL);
|
||||||
|
bool retval = false;
|
||||||
|
|
||||||
|
if (thid != lock->holder) {
|
||||||
|
acquire_sem(lock->sem);
|
||||||
|
|
||||||
|
lock->holder = thid;
|
||||||
|
retval = true;
|
||||||
|
}
|
||||||
|
lock->recursion++;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
recursive_lock_unlock(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
thread_id thid = find_thread(NULL);
|
||||||
|
bool retval = false;
|
||||||
|
|
||||||
|
if (thid != lock->holder)
|
||||||
|
panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
|
||||||
|
|
||||||
|
if (--lock->recursion == 0) {
|
||||||
|
lock->holder = -1;
|
||||||
|
release_sem(lock->sem);
|
||||||
|
retval = true;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
mutex_init(mutex *m, const char *name)
|
||||||
|
{
|
||||||
|
if (m == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "mutex_sem";
|
||||||
|
|
||||||
|
m->holder = -1;
|
||||||
|
|
||||||
|
m->sem = create_sem(1, name);
|
||||||
|
if (m->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return m->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mutex_destroy(mutex *mutex)
|
||||||
|
{
|
||||||
|
if (mutex == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mutex->sem >= 0) {
|
||||||
|
delete_sem(mutex->sem);
|
||||||
|
mutex->sem = -1;
|
||||||
|
}
|
||||||
|
mutex->holder = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mutex_lock(mutex *mutex)
|
||||||
|
{
|
||||||
|
thread_id me = find_thread(NULL);
|
||||||
|
|
||||||
|
// ToDo: if acquire_sem() fails, we shouldn't panic - but we should definitely
|
||||||
|
// change the mutex API to actually return the status code
|
||||||
|
if (acquire_sem(mutex->sem) == B_OK) {
|
||||||
|
if (me == mutex->holder)
|
||||||
|
panic("mutex_lock failure: mutex %p (sem = 0x%lx) acquired twice by thread 0x%lx\n", mutex, mutex->sem, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex->holder = me;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mutex_unlock(mutex *mutex)
|
||||||
|
{
|
||||||
|
thread_id me = find_thread(NULL);
|
||||||
|
|
||||||
|
if (me != mutex->holder)
|
||||||
|
panic("mutex_unlock failure: thread 0x%lx is trying to release mutex %p (current holder 0x%lx)\n",
|
||||||
|
me, mutex, mutex->holder);
|
||||||
|
|
||||||
|
mutex->holder = -1;
|
||||||
|
release_sem(mutex->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
benaphore_init(benaphore *ben, const char *name)
|
||||||
|
{
|
||||||
|
if (ben == NULL || name == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
ben->count = 1;
|
||||||
|
ben->sem = create_sem(0, name);
|
||||||
|
if (ben->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return ben->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
benaphore_destroy(benaphore *ben)
|
||||||
|
{
|
||||||
|
delete_sem(ben->sem);
|
||||||
|
ben->sem = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_init(rw_lock *lock, const char *name)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "r/w lock";
|
||||||
|
|
||||||
|
lock->sem = create_sem(RW_MAX_READERS, name);
|
||||||
|
if (lock->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return lock->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rw_lock_destroy(rw_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_sem(lock->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_read_lock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
return acquire_sem(lock->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_read_unlock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
return release_sem(lock->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_write_lock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
return acquire_sem_etc(lock->sem, RW_MAX_READERS, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_write_unlock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
return release_sem_etc(lock->sem, RW_MAX_READERS, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <module.h>
|
#include <module.h>
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <new>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -36,9 +38,9 @@ extern module_info *modules[];
|
|||||||
extern struct net_protocol_module_info gDomainModule;
|
extern struct net_protocol_module_info gDomainModule;
|
||||||
static struct net_protocol sDomainProtocol;
|
static struct net_protocol sDomainProtocol;
|
||||||
struct net_interface gInterface;
|
struct net_interface gInterface;
|
||||||
struct net_socket_module_info gNetSocketModule;
|
extern struct net_socket_module_info gNetSocketModule;
|
||||||
struct net_protocol_module_info *gTCPModule;
|
struct net_protocol_module_info *gTCPModule;
|
||||||
struct net_socket gServerSocket, gClientSocket;
|
struct net_socket *gServerSocket, *gClientSocket;
|
||||||
|
|
||||||
static struct net_domain sDomain = {
|
static struct net_domain sDomain = {
|
||||||
"ipv4",
|
"ipv4",
|
||||||
@@ -128,54 +130,68 @@ static net_stack_module_info gNetStackModule = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - protocol/socket
|
// #pragma mark - socket
|
||||||
|
|
||||||
|
|
||||||
net_protocol*
|
status_t
|
||||||
init_protocol(net_socket& socket)
|
socket_create(int family, int type, int protocol, net_socket **_socket)
|
||||||
{
|
{
|
||||||
memset(&socket, 0, sizeof(net_socket));
|
struct net_socket *socket = new (std::nothrow) net_socket;
|
||||||
socket.family = AF_INET;
|
if (socket == NULL)
|
||||||
socket.type = SOCK_STREAM;
|
return B_NO_MEMORY;
|
||||||
socket.protocol = IPPROTO_TCP;
|
|
||||||
|
memset(socket, 0, sizeof(net_socket));
|
||||||
|
socket->family = family;
|
||||||
|
socket->type = type;
|
||||||
|
socket->protocol = protocol;
|
||||||
|
|
||||||
|
status_t status = benaphore_init(&socket->lock, "socket");
|
||||||
|
if (status < B_OK)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
// set defaults (may be overridden by the protocols)
|
// set defaults (may be overridden by the protocols)
|
||||||
socket.send.buffer_size = 65536;
|
socket->send.buffer_size = 65536;
|
||||||
socket.send.low_water_mark = 1;
|
socket->send.low_water_mark = 1;
|
||||||
socket.send.timeout = B_INFINITE_TIMEOUT;
|
socket->send.timeout = B_INFINITE_TIMEOUT;
|
||||||
socket.receive.buffer_size = 65536;
|
socket->receive.buffer_size = 65536;
|
||||||
socket.receive.low_water_mark = 1;
|
socket->receive.low_water_mark = 1;
|
||||||
socket.receive.timeout = B_INFINITE_TIMEOUT;
|
socket->receive.timeout = B_INFINITE_TIMEOUT;
|
||||||
|
|
||||||
net_protocol* protocol = gTCPModule->init_protocol(&socket);
|
list_init_etc(&socket->pending_children, offsetof(net_socket, link));
|
||||||
if (protocol == NULL) {
|
list_init_etc(&socket->connected_children, offsetof(net_socket, link));
|
||||||
|
|
||||||
|
socket->first_protocol = gTCPModule->init_protocol(socket);
|
||||||
|
if (socket->first_protocol == NULL) {
|
||||||
fprintf(stderr, "tcp_tester: cannot create protocol\n");
|
fprintf(stderr, "tcp_tester: cannot create protocol\n");
|
||||||
return NULL;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.first_info = gTCPModule;
|
socket->first_info = gTCPModule;
|
||||||
socket.first_protocol = protocol;
|
|
||||||
|
|
||||||
protocol->next = &sDomainProtocol;
|
socket->first_protocol->next = &sDomainProtocol;
|
||||||
protocol->module = gTCPModule;
|
socket->first_protocol->module = gTCPModule;
|
||||||
protocol->socket = &socket;
|
socket->first_protocol->socket = socket;
|
||||||
|
|
||||||
status_t status = gTCPModule->open(protocol);
|
*_socket = socket;
|
||||||
if (status < B_OK) {
|
return B_OK;
|
||||||
fprintf(stderr, "tcp_tester: cannot open client: %s\n", strerror(status));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return protocol;
|
err2:
|
||||||
|
benaphore_destroy(&socket->lock);
|
||||||
|
err1:
|
||||||
|
delete socket;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
close_protocol(net_protocol* protocol)
|
socket_delete(net_socket *socket)
|
||||||
{
|
{
|
||||||
gTCPModule->close(protocol);
|
if (socket->parent != NULL)
|
||||||
gTCPModule->free(protocol);
|
panic("socket still has a parent!");
|
||||||
gTCPModule->uninit_protocol(protocol);
|
|
||||||
|
socket->first_info->uninit_protocol(socket->first_protocol);
|
||||||
|
benaphore_destroy(&socket->lock);
|
||||||
|
delete socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -261,6 +277,187 @@ socket_listen(net_socket *socket, int backlog)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
socket_spawn_pending(net_socket *parent, net_socket **_socket)
|
||||||
|
{
|
||||||
|
BenaphoreLocker locker(parent->lock);
|
||||||
|
|
||||||
|
// We actually accept more pending connections to compensate for those
|
||||||
|
// that never complete, and also make sure at least a single connection
|
||||||
|
// can always be accepted
|
||||||
|
if (parent->child_count > 3 * parent->max_backlog / 2)
|
||||||
|
return ENOBUFS;
|
||||||
|
|
||||||
|
net_socket *socket;
|
||||||
|
status_t status = socket_create(parent->family, parent->type, parent->protocol, &socket);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// inherit parent's properties
|
||||||
|
socket->send = parent->send;
|
||||||
|
socket->receive = parent->receive;
|
||||||
|
socket->options = parent->options & ~SO_ACCEPTCONN;
|
||||||
|
socket->linger = parent->linger;
|
||||||
|
memcpy(&socket->address, &parent->address, parent->address.ss_len);
|
||||||
|
memcpy(&socket->peer, &parent->peer, parent->peer.ss_len);
|
||||||
|
|
||||||
|
// add to the parent's list of pending connections
|
||||||
|
list_add_item(&parent->pending_children, socket);
|
||||||
|
parent->child_count++;
|
||||||
|
|
||||||
|
*_socket = socket;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
socket_dequeue_connected(net_socket *parent, net_socket **_socket)
|
||||||
|
{
|
||||||
|
benaphore_lock(&parent->lock);
|
||||||
|
|
||||||
|
net_socket *socket = (net_socket *)list_remove_head_item(&parent->connected_children);
|
||||||
|
if (socket != NULL) {
|
||||||
|
socket->parent = NULL;
|
||||||
|
parent->child_count--;
|
||||||
|
*_socket = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
benaphore_unlock(&parent->lock);
|
||||||
|
return socket != NULL ? B_OK : B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
socket_set_max_backlog(net_socket *socket, uint32 backlog)
|
||||||
|
{
|
||||||
|
// we enforce an upper limit of connections waiting to be accepted
|
||||||
|
if (backlog > 256)
|
||||||
|
backlog = 256;
|
||||||
|
|
||||||
|
benaphore_lock(&socket->lock);
|
||||||
|
|
||||||
|
// first remove the pending connections, then the already connected ones as needed
|
||||||
|
net_socket *child;
|
||||||
|
while (socket->child_count > backlog
|
||||||
|
&& (child = (net_socket *)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->parent = NULL;
|
||||||
|
socket_delete(child);
|
||||||
|
socket->child_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket->max_backlog = backlog;
|
||||||
|
benaphore_unlock(&socket->lock);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The socket has been connected. It will be moved to the connected queue
|
||||||
|
of its parent socket.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
socket_connected(net_socket *socket)
|
||||||
|
{
|
||||||
|
net_socket *parent = socket->parent;
|
||||||
|
if (parent == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
benaphore_lock(&parent->lock);
|
||||||
|
|
||||||
|
list_remove_item(&parent->pending_children, socket);
|
||||||
|
list_add_item(&parent->connected_children, socket);
|
||||||
|
|
||||||
|
benaphore_unlock(&parent->lock);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
net_socket_module_info gNetSocketModule = {
|
||||||
|
{
|
||||||
|
NET_SOCKET_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
std_ops
|
||||||
|
},
|
||||||
|
NULL, //socket_open,
|
||||||
|
NULL, //socket_close,
|
||||||
|
NULL, //socket_free,
|
||||||
|
|
||||||
|
NULL, //socket_readv,
|
||||||
|
NULL, //socket_writev,
|
||||||
|
NULL, //socket_control,
|
||||||
|
|
||||||
|
NULL, //socket_read_avail,
|
||||||
|
NULL, //socket_send_avail,
|
||||||
|
|
||||||
|
NULL, //socket_send_data,
|
||||||
|
NULL, //socket_receive_data,
|
||||||
|
|
||||||
|
// connections
|
||||||
|
socket_spawn_pending,
|
||||||
|
socket_delete,
|
||||||
|
socket_dequeue_connected,
|
||||||
|
socket_set_max_backlog,
|
||||||
|
socket_connected,
|
||||||
|
|
||||||
|
// notifications
|
||||||
|
NULL, //socket_request_notification,
|
||||||
|
NULL, //socket_cancel_notification,
|
||||||
|
NULL, //socket_notify,
|
||||||
|
|
||||||
|
// standard socket API
|
||||||
|
NULL, //socket_accept,
|
||||||
|
NULL, //socket_bind,
|
||||||
|
NULL, //socket_connect,
|
||||||
|
NULL, //socket_getpeername,
|
||||||
|
NULL, //socket_getsockname,
|
||||||
|
NULL, //socket_getsockopt,
|
||||||
|
NULL, //socket_listen,
|
||||||
|
NULL, //socket_recv,
|
||||||
|
NULL, //socket_recvfrom,
|
||||||
|
NULL, //socket_send,
|
||||||
|
NULL, //socket_sendto,
|
||||||
|
NULL, //socket_setsockopt,
|
||||||
|
NULL, //socket_shutdown,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - protocol
|
||||||
|
|
||||||
|
|
||||||
|
net_protocol*
|
||||||
|
init_protocol(net_socket** _socket)
|
||||||
|
{
|
||||||
|
net_socket *socket;
|
||||||
|
status_t status = socket_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &socket);
|
||||||
|
if (status < B_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
status = socket->first_info->open(socket->first_protocol);
|
||||||
|
if (status < B_OK) {
|
||||||
|
fprintf(stderr, "tcp_tester: cannot open client: %s\n", strerror(status));
|
||||||
|
socket_delete(socket);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_socket = socket;
|
||||||
|
return socket->first_protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
close_protocol(net_protocol* protocol)
|
||||||
|
{
|
||||||
|
gTCPModule->close(protocol);
|
||||||
|
gTCPModule->free(protocol);
|
||||||
|
gTCPModule->uninit_protocol(protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - datalink
|
// #pragma mark - datalink
|
||||||
|
|
||||||
|
|
||||||
@@ -493,7 +690,7 @@ server_thread(void *)
|
|||||||
net_socket* connectionSocket;
|
net_socket* connectionSocket;
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
uint32 size = sizeof(struct sockaddr_in);
|
uint32 size = sizeof(struct sockaddr_in);
|
||||||
status_t status = socket_accept(&gServerSocket, (struct sockaddr *)&address,
|
status_t status = socket_accept(gServerSocket, (struct sockaddr *)&address,
|
||||||
&size, &connectionSocket);
|
&size, &connectionSocket);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
fprintf(stderr, "SERVER: accepting failed: %s\n", strerror(status));
|
fprintf(stderr, "SERVER: accepting failed: %s\n", strerror(status));
|
||||||
@@ -523,7 +720,7 @@ do_connect(int argc, char** argv)
|
|||||||
address.sin_port = htons(port);
|
address.sin_port = htons(port);
|
||||||
address.sin_addr.s_addr = INADDR_ANY;
|
address.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
status_t status = socket_connect(&gClientSocket, (struct sockaddr *)&address,
|
status_t status = socket_connect(gClientSocket, (struct sockaddr *)&address,
|
||||||
sizeof(struct sockaddr));
|
sizeof(struct sockaddr));
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
fprintf(stderr, "tcp_tester: could not connect: %s\n", strerror(status));
|
fprintf(stderr, "tcp_tester: could not connect: %s\n", strerror(status));
|
||||||
@@ -561,6 +758,7 @@ main(int argc, char** argv)
|
|||||||
|
|
||||||
_add_builtin_module((module_info *)&gNetStackModule);
|
_add_builtin_module((module_info *)&gNetStackModule);
|
||||||
_add_builtin_module((module_info *)&gNetBufferModule);
|
_add_builtin_module((module_info *)&gNetBufferModule);
|
||||||
|
_add_builtin_module((module_info *)&gNetSocketModule);
|
||||||
_add_builtin_module((module_info *)&gNetDatalinkModule);
|
_add_builtin_module((module_info *)&gNetDatalinkModule);
|
||||||
_add_builtin_module(modules[0]);
|
_add_builtin_module(modules[0]);
|
||||||
|
|
||||||
@@ -568,6 +766,7 @@ main(int argc, char** argv)
|
|||||||
sockaddr_in interfaceAddress;
|
sockaddr_in interfaceAddress;
|
||||||
interfaceAddress.sin_len = sizeof(sockaddr_in);
|
interfaceAddress.sin_len = sizeof(sockaddr_in);
|
||||||
interfaceAddress.sin_family = AF_INET;
|
interfaceAddress.sin_family = AF_INET;
|
||||||
|
interfaceAddress.sin_addr.s_addr = htonl(0xc0a80001);
|
||||||
gInterface.address = (sockaddr*)&interfaceAddress;
|
gInterface.address = (sockaddr*)&interfaceAddress;
|
||||||
|
|
||||||
status = get_module("network/protocols/tcp/v1", (module_info **)&gTCPModule);
|
status = get_module("network/protocols/tcp/v1", (module_info **)&gTCPModule);
|
||||||
@@ -577,10 +776,10 @@ main(int argc, char** argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_protocol* client = init_protocol(gClientSocket);
|
net_protocol* client = init_protocol(&gClientSocket);
|
||||||
if (client == NULL)
|
if (client == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
net_protocol* server = init_protocol(gServerSocket);
|
net_protocol* server = init_protocol(&gServerSocket);
|
||||||
if (server == NULL)
|
if (server == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -594,12 +793,12 @@ main(int argc, char** argv)
|
|||||||
address.sin_port = htons(1024);
|
address.sin_port = htons(1024);
|
||||||
address.sin_addr.s_addr = INADDR_ANY;
|
address.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
status = socket_bind(&gServerSocket, (struct sockaddr *)&address, sizeof(struct sockaddr));
|
status = socket_bind(gServerSocket, (struct sockaddr *)&address, sizeof(struct sockaddr));
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
fprintf(stderr, "tcp_tester: cannot bind server: %s\n", strerror(status));
|
fprintf(stderr, "tcp_tester: cannot bind server: %s\n", strerror(status));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
status = socket_listen(&gServerSocket, 40);
|
status = socket_listen(gServerSocket, 40);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
fprintf(stderr, "tcp_tester: server cannot listen: %s\n", strerror(status));
|
fprintf(stderr, "tcp_tester: server cannot listen: %s\n", strerror(status));
|
||||||
return 1;
|
return 1;
|
||||||
@@ -639,13 +838,19 @@ main(int argc, char** argv)
|
|||||||
|| !strcmp(argv[0], "q"))
|
|| !strcmp(argv[0], "q"))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) {
|
for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) {
|
||||||
if (!strncmp(command->name, argv[0], length)) {
|
if (!strncmp(command->name, argv[0], length)) {
|
||||||
command->func(argc, argv);
|
command->func(argc, argv);
|
||||||
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
fprintf(stderr, "Unknown command \"%s\". Type \"help\" for a list of commands.\n", argv[0]);
|
||||||
|
|
||||||
free(argv);
|
free(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user