diff --git a/headers/private/net/ProtocolUtilities.h b/headers/private/net/ProtocolUtilities.h index 255261d60e..a219742a48 100644 --- a/headers/private/net/ProtocolUtilities.h +++ b/headers/private/net/ProtocolUtilities.h @@ -348,6 +348,11 @@ DECL_DATAGRAM_SOCKET(inline bigtime_t)::_SocketTimeout(uint32 flags) const else if (timeout != 0 && timeout != B_INFINITE_TIMEOUT) timeout += system_time(); + if (ModuleBundle::Stack()->is_restarted_syscall()) + timeout = ModuleBundle::Stack()->restore_syscall_restart_timeout(); + else + ModuleBundle::Stack()->store_syscall_restart_timeout(timeout); + return timeout; } diff --git a/headers/private/net/net_stack.h b/headers/private/net/net_stack.h index 1a249d26bb..a5a5a572c4 100644 --- a/headers/private/net/net_stack.h +++ b/headers/private/net/net_stack.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef NET_STACK_H @@ -44,8 +44,9 @@ struct net_timer { bigtime_t due; }; -typedef int32 (*net_deframe_func)(struct net_device *device, struct net_buffer *buffer); -typedef status_t (*net_receive_func)(void *cookie, struct net_device *, +typedef int32 (*net_deframe_func)(struct net_device *device, + struct net_buffer *buffer); +typedef status_t (*net_receive_func)(void *cookie, struct net_device *device, struct net_buffer *buffer); enum { @@ -132,6 +133,11 @@ struct net_stack_module_info { void (*set_timer)(struct net_timer *timer, bigtime_t delay); bool (*cancel_timer)(struct net_timer *timer); bool (*is_timer_active)(struct net_timer *timer); + + // syscall restart + bool (*is_restarted_syscall)(void); + void (*store_syscall_restart_timeout)(bigtime_t timeout); + bigtime_t (*restore_syscall_restart_timeout)(void); }; #endif // NET_STACK_H diff --git a/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp b/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp index 720b632b4b..141fefcc7a 100644 --- a/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp +++ b/src/add-ons/kernel/drivers/network/stack/kernel_stack.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2002-2008, Haiku, Inc. All Rights Reserved. * This file may be used under the terms of the MIT License. */ @@ -10,16 +10,17 @@ #include -#include #include #include +#include +#include #include #include -#include -#include // IS_KERNEL_ADDRESS -#include // user_fd_kernel_ioctl +#include +#include +#include #include @@ -96,8 +97,9 @@ check_args_and_address(ArgType &args, sockaddr_storage &address, void *data, siz static status_t -check_message_args(message_args &args, msghdr &header, sockaddr_storage &address, - void *data, size_t length, sockaddr **originalAddress) +check_message_args(message_args &args, msghdr &header, + sockaddr_storage &address, void *data, size_t length, + sockaddr **originalAddress) { if (length < sizeof(message_args)) return B_BAD_VALUE; @@ -133,6 +135,7 @@ check_message_args(message_args &args, msghdr &header, sockaddr_storage &address return B_OK; } + template status_t check_args(ArgType &args, void *data, size_t length) { @@ -205,9 +208,9 @@ resolve_cookie(int kernel, int socket, net_stack_cookie **cookie) { if (kernel) return ioctl(socket, NET_STACK_GET_COOKIE, cookie, sizeof(*cookie)); - else - return user_fd_kernel_ioctl(socket, NET_STACK_GET_COOKIE, cookie, - sizeof(*cookie)); + + return user_fd_kernel_ioctl(socket, NET_STACK_GET_COOKIE, cookie, + sizeof(*cookie)); } @@ -251,7 +254,8 @@ net_stack_open(const char *name, uint32 flags, void **_cookie) } } - net_stack_cookie *cookie = (net_stack_cookie *)malloc(sizeof(net_stack_cookie)); + net_stack_cookie *cookie = (net_stack_cookie *)malloc( + sizeof(net_stack_cookie)); if (cookie == NULL) return B_NO_MEMORY; @@ -363,7 +367,10 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) if (status < B_OK) return status; - return sSocket->connect(cookie->socket, args.address, args.address_length); + status = sSocket->connect(cookie->socket, args.address, + args.address_length); + + return syscall_restart_ioctl_handle_post(status); } case NET_STACK_BIND: @@ -387,7 +394,8 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) sockaddr_storage address; accept_args args; - status = check_args_and_address(args, address, data, length, false); + status = check_args_and_address(args, address, data, length, + false); if (status < B_OK) return status; @@ -399,8 +407,9 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) status = sSocket->accept(cookie->socket, args.address, &args.address_length, &acceptCookie->socket); + if (status < B_OK) - return status; + return syscall_restart_ioctl_handle_post(status); return return_address(args, data); } @@ -415,13 +424,15 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) msghdr header; status = check_message_args(args, header, address, data, - length, NULL); + length, NULL); if (status < B_OK) return status; - return sSocket->send(cookie->socket, - args.header ? &header : NULL, - args.data, args.length, args.flags); + ssize_t bytesSent = sSocket->send(cookie->socket, + args.header ? &header : NULL, + args.data, args.length, args.flags); + + return syscall_restart_ioctl_handle_post(bytesSent); } case NET_STACK_RECEIVE: @@ -432,25 +443,25 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) msghdr header; status = check_message_args(args, header, address, data, - length, &originalAddress); + length, &originalAddress); if (status < B_OK) return status; ssize_t bytesRead = sSocket->receive(cookie->socket, - args.header ? &header : NULL, args.data, - args.length, args.flags); + args.header ? &header : NULL, args.data, + args.length, args.flags); if (bytesRead < B_OK) - return bytesRead; + return syscall_restart_ioctl_handle_post(bytesRead); if (args.header != NULL) { if (header.msg_name != NULL) { if (user_memcpy(originalAddress, header.msg_name, - header.msg_namelen) < B_OK) + header.msg_namelen) < B_OK) return B_BAD_ADDRESS; } if (user_memcpy(&args.header->msg_flags, &header.msg_flags, - sizeof(int)) < B_OK) + sizeof(int)) < B_OK) return B_BAD_ADDRESS; } @@ -468,13 +479,14 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) if (args.length > (int)sizeof(valueBuffer)) return ENOBUFS; - status = sSocket->getsockopt(cookie->socket, args.level, args.option, - valueBuffer, &args.length); + status = sSocket->getsockopt(cookie->socket, args.level, + args.option, valueBuffer, &args.length); if (status < B_OK) return status; if (user_memcpy(args.value, valueBuffer, args.length) < B_OK - || user_memcpy(&((sockopt_args *)data)->length, &args.length, sizeof(int)) < B_OK) + || user_memcpy(&((sockopt_args *)data)->length, + &args.length, sizeof(int)) < B_OK) return B_BAD_ADDRESS; return B_OK; @@ -493,15 +505,16 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) if (user_memcpy(valueBuffer, args.value, args.length) < B_OK) return B_BAD_ADDRESS; - return sSocket->setsockopt(cookie->socket, args.level, args.option, - valueBuffer, args.length); + return sSocket->setsockopt(cookie->socket, args.level, + args.option, valueBuffer, args.length); } case NET_STACK_GETSOCKNAME: { sockaddr_storage address; sockaddr_args args; - status = check_args_and_address(args, address, data, length, false); + status = check_args_and_address(args, address, data, length, + false); if (status < B_OK) return status; @@ -517,7 +530,8 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) { sockaddr_storage address; sockaddr_args args; - status = check_args_and_address(args, address, data, length, false); + status = check_args_and_address(args, address, data, length, + false); if (status < B_OK) return status; @@ -532,16 +546,16 @@ net_stack_control(void *_cookie, uint32 op, void *data, size_t length) case FIONBIO: { int value = (int)data; - return sSocket->setsockopt(cookie->socket, SOL_SOCKET, SO_NONBLOCK, - &value, sizeof(int)); + return sSocket->setsockopt(cookie->socket, SOL_SOCKET, + SO_NONBLOCK, &value, sizeof(int)); } case B_SET_BLOCKING_IO: case B_SET_NONBLOCKING_IO: { int value = op == B_SET_NONBLOCKING_IO; - return sSocket->setsockopt(cookie->socket, SOL_SOCKET, SO_NONBLOCK, - &value, sizeof(int)); + return sSocket->setsockopt(cookie->socket, SOL_SOCKET, + SO_NONBLOCK, &value, sizeof(int)); } default: diff --git a/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp b/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp index c6f4154f2f..c0a18ebd8e 100644 --- a/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp @@ -405,6 +405,9 @@ EndpointManager::ReplyWithReset(tcp_segment_header &segment, if ((segment.flags & TCP_FLAG_ACKNOWLEDGE) == 0) { outSegment.flags |= TCP_FLAG_ACKNOWLEDGE; outSegment.acknowledge = segment.sequence + buffer->size; + // TODO: Confirm: + if ((segment.flags & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH)) != 0) + outSegment.acknowledge++; } else outSegment.sequence = segment.acknowledge; diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index aea50eb0d0..1a497fe69f 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -170,6 +170,9 @@ state_needs_finish(int32 state) } +// #pragma mark - + + WaitList::WaitList(const char *name) { fCondition = 0; @@ -224,6 +227,9 @@ WaitList::Signal() } +// #pragma mark - + + TCPEndpoint::TCPEndpoint(net_socket *socket) : ProtocolSocket(socket), @@ -255,8 +261,7 @@ TCPEndpoint::TCPEndpoint(net_socket *socket) fCongestionWindow(0), fSlowStartThreshold(0), fState(CLOSED), - fFlags(FLAG_OPTION_WINDOW_SCALE | FLAG_OPTION_TIMESTAMP), - fError(B_OK) + fFlags(FLAG_OPTION_WINDOW_SCALE | FLAG_OPTION_TIMESTAMP) { //gStackModule->init_timer(&fTimer, _TimeWait, this); @@ -394,13 +399,23 @@ TCPEndpoint::Connect(const sockaddr *address) MutexLocker locker(fLock); + if (gStackModule->is_restarted_syscall()) { + bigtime_t timeout = gStackModule->restore_syscall_restart_timeout(); + status_t status = _WaitForEstablished(locker, timeout); + TRACE(" Connect(): Connection complete: %s (timeout was %llu)", + strerror(status), timeout); + return posix_error(status); + } + // Can only call connect() from CLOSED or LISTEN states // otherwise endpoint is considered already connected if (fState == LISTEN) { // this socket is about to connect; remove pending connections in the backlog gSocketModule->set_max_backlog(socket, 0); - } else if (fState != CLOSED) + } else if (fState == ESTABLISHED) { return EISCONN; + } else if (fState != CLOSED) + return EINPROGRESS; status_t status = _PrepareSendPath(address); if (status < B_OK) @@ -432,7 +447,10 @@ TCPEndpoint::Connect(const sockaddr *address) return EINPROGRESS; } - status = _WaitForEstablished(locker, absolute_timeout(timeout)); + bigtime_t absoluteTimeout = absolute_timeout(timeout); + gStackModule->store_syscall_restart_timeout(absoluteTimeout); + + status = _WaitForEstablished(locker, absoluteTimeout); TRACE(" Connect(): Connection complete: %s (timeout was %llu)", strerror(status), timeout); return posix_error(status); @@ -448,6 +466,10 @@ TCPEndpoint::Accept(struct net_socket **_acceptedSocket) status_t status; bigtime_t timeout = absolute_timeout(socket->receive.timeout); + if (gStackModule->is_restarted_syscall()) + timeout = gStackModule->restore_syscall_restart_timeout(); + else + gStackModule->store_syscall_restart_timeout(timeout); do { locker.Unlock(); @@ -567,6 +589,10 @@ TCPEndpoint::SendData(net_buffer *buffer) return ENOBUFS; bigtime_t timeout = absolute_timeout(socket->send.timeout); + if (gStackModule->is_restarted_syscall()) + timeout = gStackModule->restore_syscall_restart_timeout(); + else + gStackModule->store_syscall_restart_timeout(timeout); while (fSendQueue.Free() < buffer->size) { status_t status = fSendList.Wait(lock, timeout); @@ -632,6 +658,10 @@ TCPEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer) return ENOTCONN; bigtime_t timeout = absolute_timeout(socket->receive.timeout); + if (gStackModule->is_restarted_syscall()) + timeout = gStackModule->restore_syscall_restart_timeout(); + else + gStackModule->store_syscall_restart_timeout(timeout); if (fState == SYNCHRONIZE_SENT || fState == SYNCHRONIZE_RECEIVED) { if (flags & MSG_DONTWAIT) @@ -913,11 +943,27 @@ TCPEndpoint::DumpInternalState() const } +void +TCPEndpoint::_HandleReset(status_t error) +{ + gStackModule->cancel_timer(&fRetransmitTimer); + + socket->error = error; + fState = CLOSED; + + fSendList.Signal(); + _NotifyReader(); + + gSocketModule->notify(socket, B_SELECT_WRITE, error); + gSocketModule->notify(socket, B_SELECT_ERROR, error); +} + + int32 TCPEndpoint::_SynchronizeSentReceive(tcp_segment_header &segment, net_buffer *buffer) { - TRACE("SynchronizeSentReceive()"); + TRACE("_SynchronizeSentReceive()"); if ((segment.flags & TCP_FLAG_ACKNOWLEDGE) != 0 && (fInitialSendSequence >= segment.acknowledge @@ -925,8 +971,7 @@ TCPEndpoint::_SynchronizeSentReceive(tcp_segment_header &segment, return DROP | RESET; if (segment.flags & TCP_FLAG_RESET) { - fError = ECONNREFUSED; - fState = CLOSED; + _HandleReset(ECONNREFUSED); return DROP; } @@ -1040,8 +1085,10 @@ TCPEndpoint::_SegmentReceived(tcp_segment_header &segment, net_buffer *buffer) fReceiveWindow)) { TRACE(" Receive(): segment out of window, next: %lu wnd: %lu", (uint32)fReceiveNext, fReceiveWindow); - if (segment.flags & TCP_FLAG_RESET) + if (segment.flags & TCP_FLAG_RESET) { + // TODO: this doesn't look right - review! return DROP; + } return DROP | IMMEDIATE_ACKNOWLEDGE; } } @@ -1079,7 +1126,7 @@ TCPEndpoint::_CurrentFlags() return TCP_FLAG_ACKNOWLEDGE; default: - return B_ERROR; + return 0; } } @@ -1400,16 +1447,16 @@ TCPEndpoint::_Receive(tcp_segment_header &segment, net_buffer *buffer) if (fLastAcknowledgeSent <= segment.sequence && tcp_sequence(segment.sequence) < (fLastAcknowledgeSent + fReceiveWindow)) { + status_t error; if (fState == SYNCHRONIZE_RECEIVED) - fError = ECONNREFUSED; + error = ECONNREFUSED; else if (fState == CLOSING || fState == TIME_WAIT || fState == WAIT_FOR_FINISH_ACKNOWLEDGE) - fError = ENOTCONN; + error = ENOTCONN; else - fError = ECONNRESET; + error = ECONNRESET; - _NotifyReader(); - fState = CLOSED; + _HandleReset(error); } return DROP; @@ -1635,6 +1682,9 @@ status_t TCPEndpoint::_WaitForEstablished(MutexLocker &locker, bigtime_t timeout) { while (fState != ESTABLISHED) { + if (socket->error != B_OK) + return socket->error; + status_t status = fSendList.Wait(locker, timeout); if (status < B_OK) return status; @@ -1752,7 +1802,7 @@ TCPEndpoint::_Acknowledged(tcp_segment_header &segment) if (segment.options & TCP_HAS_TIMESTAMPS) _UpdateSRTT(tcp_diff_timestamp(segment.timestamp_reply)); else { - // TODO Fallback to RFC 793 type estimation + // TODO: Fallback to RFC 793 type estimation } if (is_writable(fState)) { diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h index b7447265e1..b8fd5b6377 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -42,141 +42,141 @@ private: class TCPEndpoint : public net_protocol, public ProtocolSocket { - public: - TCPEndpoint(net_socket *socket); - ~TCPEndpoint(); +public: + TCPEndpoint(net_socket *socket); + ~TCPEndpoint(); - status_t InitCheck() const; + status_t InitCheck() const; - status_t Open(); - status_t Close(); - status_t Free(); - status_t Connect(const struct sockaddr *address); - status_t Accept(struct net_socket **_acceptedSocket); - status_t Bind(const sockaddr *address); - status_t Unbind(struct sockaddr *address); - status_t Listen(int count); - status_t Shutdown(int direction); - status_t SendData(net_buffer *buffer); - ssize_t SendAvailable(); - status_t ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer); - ssize_t ReadAvailable(); + status_t Open(); + status_t Close(); + status_t Free(); + status_t Connect(const struct sockaddr *address); + status_t Accept(struct net_socket **_acceptedSocket); + status_t Bind(const sockaddr *address); + status_t Unbind(struct sockaddr *address); + status_t Listen(int count); + status_t Shutdown(int direction); + status_t SendData(net_buffer *buffer); + ssize_t SendAvailable(); + status_t ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer); + ssize_t ReadAvailable(); - status_t FillStat(struct net_stat *stat); + status_t FillStat(struct net_stat *stat); - status_t SetSendBufferSize(size_t length); - status_t SetReceiveBufferSize(size_t length); + status_t SetSendBufferSize(size_t length); + status_t SetReceiveBufferSize(size_t length); - status_t SetOption(int option, const void *value, int length); + status_t SetOption(int option, const void *value, int length); - tcp_state State() const { return fState; } - bool IsBound() const; + tcp_state State() const { return fState; } + bool IsBound() const; - status_t DelayedAcknowledge(); - status_t SendAcknowledge(bool force); - status_t UpdateTimeWait(); + status_t DelayedAcknowledge(); + status_t SendAcknowledge(bool force); + status_t UpdateTimeWait(); - int32 SegmentReceived(tcp_segment_header& segment, net_buffer *buffer); - int32 Spawn(TCPEndpoint *parent, tcp_segment_header& segment, - net_buffer *buffer); + int32 SegmentReceived(tcp_segment_header& segment, net_buffer *buffer); + int32 Spawn(TCPEndpoint *parent, tcp_segment_header& segment, + net_buffer *buffer); - void DumpInternalState() const; + void DumpInternalState() const; - private: - friend class EndpointManager; +private: + friend class EndpointManager; - void _StartPersistTimer(); - void _EnterTimeWait(); - uint8 _CurrentFlags(); - bool _ShouldSendSegment(tcp_segment_header &segment, uint32 length, - uint32 segmentMaxSize, uint32 flightSize); - status_t _SendQueued(bool force = false); - status_t _SendQueued(bool force, uint32 sendWindow); - int _MaxSegmentSize(const struct sockaddr *) const; - status_t _ShutdownEgress(bool closing); - ssize_t _AvailableData() const; - void _NotifyReader(); - bool _ShouldReceive() const; - int32 _ListenReceive(tcp_segment_header& segment, net_buffer *buffer); - int32 _SynchronizeSentReceive(tcp_segment_header& segment, - net_buffer *buffer); - int32 _SegmentReceived(tcp_segment_header& segment, net_buffer *buffer); - int32 _Receive(tcp_segment_header& segment, net_buffer *buffer); - void _UpdateTimestamps(tcp_segment_header& segment, - size_t segmentLength); - void _MarkEstablished(); - status_t _WaitForEstablished(MutexLocker &lock, bigtime_t timeout); - bool _AddData(tcp_segment_header &segment, net_buffer *buffer); - void _PrepareReceivePath(tcp_segment_header &segment); - status_t _PrepareSendPath(const sockaddr *peer); - void _Acknowledged(tcp_segment_header &segment); - void _Retransmit(); - void _UpdateSRTT(int32 roundTripTime); - void _ResetSlowStart(); - void _DuplicateAcknowledge(tcp_segment_header &segment); + void _StartPersistTimer(); + void _EnterTimeWait(); + uint8 _CurrentFlags(); + bool _ShouldSendSegment(tcp_segment_header &segment, uint32 length, + uint32 segmentMaxSize, uint32 flightSize); + status_t _SendQueued(bool force = false); + status_t _SendQueued(bool force, uint32 sendWindow); + int _MaxSegmentSize(const struct sockaddr *) const; + status_t _ShutdownEgress(bool closing); + ssize_t _AvailableData() const; + void _NotifyReader(); + bool _ShouldReceive() const; + void _HandleReset(status_t error); + int32 _ListenReceive(tcp_segment_header& segment, net_buffer *buffer); + int32 _SynchronizeSentReceive(tcp_segment_header& segment, + net_buffer *buffer); + int32 _SegmentReceived(tcp_segment_header& segment, net_buffer *buffer); + int32 _Receive(tcp_segment_header& segment, net_buffer *buffer); + void _UpdateTimestamps(tcp_segment_header& segment, + size_t segmentLength); + void _MarkEstablished(); + status_t _WaitForEstablished(MutexLocker &lock, bigtime_t timeout); + bool _AddData(tcp_segment_header &segment, net_buffer *buffer); + void _PrepareReceivePath(tcp_segment_header &segment); + status_t _PrepareSendPath(const sockaddr *peer); + void _Acknowledged(tcp_segment_header &segment); + void _Retransmit(); + void _UpdateSRTT(int32 roundTripTime); + void _ResetSlowStart(); + void _DuplicateAcknowledge(tcp_segment_header &segment); - static void _TimeWaitTimer(net_timer *timer, void *data); - static void _RetransmitTimer(net_timer *timer, void *data); - static void _PersistTimer(net_timer *timer, void *data); - static void _DelayedAcknowledgeTimer(net_timer *timer, void *data); + static void _TimeWaitTimer(net_timer *timer, void *data); + static void _RetransmitTimer(net_timer *timer, void *data); + static void _PersistTimer(net_timer *timer, void *data); + static void _DelayedAcknowledgeTimer(net_timer *timer, void *data); - EndpointManager *fManager; + EndpointManager *fManager; - HashTableLink fConnectionHashLink; - HashTableLink fEndpointHashLink; + HashTableLink fConnectionHashLink; + HashTableLink fEndpointHashLink; - friend class ConnectionHashDefinition; - friend class EndpointHashDefinition; + friend class ConnectionHashDefinition; + friend class EndpointHashDefinition; - mutex fLock; - WaitList fReceiveList; - WaitList fSendList; - sem_id fAcceptSemaphore; - uint8 fOptions; + mutex fLock; + WaitList fReceiveList; + WaitList fSendList; + sem_id fAcceptSemaphore; + uint8 fOptions; - uint8 fSendWindowShift; - uint8 fReceiveWindowShift; + uint8 fSendWindowShift; + uint8 fReceiveWindowShift; - tcp_sequence fSendUnacknowledged; - tcp_sequence fSendNext; - tcp_sequence fSendMax; - uint32 fSendWindow; - uint32 fSendMaxWindow; - uint32 fSendMaxSegmentSize; - BufferQueue fSendQueue; - tcp_sequence fLastAcknowledgeSent; - tcp_sequence fInitialSendSequence; - uint32 fDuplicateAcknowledgeCount; + tcp_sequence fSendUnacknowledged; + tcp_sequence fSendNext; + tcp_sequence fSendMax; + uint32 fSendWindow; + uint32 fSendMaxWindow; + uint32 fSendMaxSegmentSize; + BufferQueue fSendQueue; + tcp_sequence fLastAcknowledgeSent; + tcp_sequence fInitialSendSequence; + uint32 fDuplicateAcknowledgeCount; - net_route *fRoute; - // TODO: don't use a net_route, but a net_route_info!!! + net_route *fRoute; + // TODO: don't use a net_route, but a net_route_info!!! - tcp_sequence fReceiveNext; - tcp_sequence fReceiveMaxAdvertised; - uint32 fReceiveWindow; - uint32 fReceiveMaxSegmentSize; - BufferQueue fReceiveQueue; - tcp_sequence fInitialReceiveSequence; + tcp_sequence fReceiveNext; + tcp_sequence fReceiveMaxAdvertised; + uint32 fReceiveWindow; + uint32 fReceiveMaxSegmentSize; + BufferQueue fReceiveQueue; + tcp_sequence fInitialReceiveSequence; - // round trip time and retransmit timeout computation - int32 fRoundTripTime; - int32 fRoundTripDeviation; - bigtime_t fRetransmitTimeout; + // round trip time and retransmit timeout computation + int32 fRoundTripTime; + int32 fRoundTripDeviation; + bigtime_t fRetransmitTimeout; - uint32 fReceivedTimestamp; + uint32 fReceivedTimestamp; - uint32 fCongestionWindow; - uint32 fSlowStartThreshold; + uint32 fCongestionWindow; + uint32 fSlowStartThreshold; - tcp_state fState; - uint32 fFlags; - status_t fError; + tcp_state fState; + uint32 fFlags; - // timer - net_timer fRetransmitTimer; - net_timer fPersistTimer; - net_timer fDelayedAcknowledgeTimer; - net_timer fTimeWaitTimer; + // timer + net_timer fRetransmitTimer; + net_timer fPersistTimer; + net_timer fDelayedAcknowledgeTimer; + net_timer fTimeWaitTimer; }; #endif // TCP_ENDPOINT_H diff --git a/src/add-ons/kernel/network/stack/stack.cpp b/src/add-ons/kernel/network/stack/stack.cpp index 777384e806..2725a4169b 100644 --- a/src/add-ons/kernel/network/stack/stack.cpp +++ b/src/add-ons/kernel/network/stack/stack.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -932,6 +932,10 @@ net_stack_module_info gNetStackModule = { set_timer, cancel_timer, is_timer_active, + + is_restarted_syscall, + store_syscall_restart_timeout, + restore_syscall_restart_timeout, }; static module_info sNetStarterModule = { diff --git a/src/add-ons/kernel/network/stack/utility.cpp b/src/add-ons/kernel/network/stack/utility.cpp index 5e68e790be..caacfaba9d 100644 --- a/src/add-ons/kernel/network/stack/utility.cpp +++ b/src/add-ons/kernel/network/stack/utility.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -11,6 +11,7 @@ #include "utility.h" #include +#include #include #include @@ -570,3 +571,30 @@ uninit_timers(void) wait_for_thread(sTimerThread, &status); } + +// #pragma mark - Syscall restart + + +bool +is_restarted_syscall(void) +{ + return syscall_restart_ioctl_is_restarted(); +} + + +void +store_syscall_restart_timeout(bigtime_t timeout) +{ + struct thread* thread = thread_get_current_thread(); + if ((thread->flags & THREAD_FLAGS_IOCTL_SYSCALL) != 0) + *(bigtime_t*)thread->syscall_restart.parameters = timeout; +} + + +bigtime_t +restore_syscall_restart_timeout(void) +{ + struct thread* thread = thread_get_current_thread(); + return *(bigtime_t*)thread->syscall_restart.parameters; +} + diff --git a/src/add-ons/kernel/network/stack/utility.h b/src/add-ons/kernel/network/stack/utility.h index 9daa98f7d0..c27afce92e 100644 --- a/src/add-ons/kernel/network/stack/utility.h +++ b/src/add-ons/kernel/network/stack/utility.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -101,4 +101,9 @@ bool is_timer_active(net_timer *timer); status_t init_timers(void); void uninit_timers(void); +// syscall restart +bool is_restarted_syscall(void); +void store_syscall_restart_timeout(bigtime_t timeout); +bigtime_t restore_syscall_restart_timeout(void); + #endif // NET_UTILITY_H