// InsecureChannel.cpp #include #ifdef HAIKU_TARGET_PLATFORM_BEOS # include #else # include # include # include #endif #include "Compatibility.h" #include "DebugSupport.h" #include "InsecureChannel.h" #include "NetAddress.h" #include "Utils.h" static const int32 kMaxInterruptedTxCount = 20; // constructor InsecureChannel::InsecureChannel(int socket) : Channel(), fSocket(socket), fClosed(false) { // set socket to blocking (with BONE a connection socket seems to inherit // the non-blocking property of the listener socket) if (fSocket >= 0) { int dontBlock = 0; setsockopt(fSocket, SOL_SOCKET, SO_NONBLOCK, &dontBlock, sizeof(int)); #ifndef HAIKU_TARGET_PLATFORM_BEOS int txLowWater = 1; setsockopt(fSocket, SOL_SOCKET, SO_SNDLOWAT, &txLowWater, sizeof(int)); setsockopt(fSocket, SOL_SOCKET, SO_RCVLOWAT, &txLowWater, sizeof(int)); #endif } } // destructor InsecureChannel::~InsecureChannel() { Close(); } // Close void InsecureChannel::Close() { fClosed = true; safe_closesocket(fSocket); } // Send status_t InsecureChannel::Send(const void* _buffer, int32 size) { if (size == 0) return B_OK; if (!_buffer || size < 0) return B_BAD_VALUE; const uint8* buffer = static_cast(_buffer); int32 remainingRetries = kMaxInterruptedTxCount; while (size > 0) { int32 bytesSent = send(fSocket, buffer, size, 0); if (bytesSent < 0) { status_t error = errno; if (fClosed || errno != B_INTERRUPTED || --remainingRetries < 0) { if (!fClosed) { PRINT(("InsecureChannel::Send(): B_INTERRUPTED\n")); } return error; } //PRINT(("InsecureChannel::Send: B_INTERRUPTED ignored, remaining retries: %ld\n", //remainingRetries)); bytesSent = 0; } else if (bytesSent == 0) { // This seems to indicate that the remote peer closed the // connection. PRINT(("Connection::Send(): sent 0 bytes. Assuming " "that the remote peer closed the connection\n")); return B_ERROR; } else { size -= bytesSent; buffer += bytesSent; remainingRetries = kMaxInterruptedTxCount; //PRINT(("InsecureChannel::Send(): sent %ld bytes, still to sent: %lu\n", //bytesSent, size)); } } return B_OK; } // Receive status_t InsecureChannel::Receive(void* _buffer, int32 size) { if (size == 0) return B_OK; if (!_buffer || size < 0) return B_BAD_VALUE; uint8* buffer = static_cast(_buffer); int32 remainingRetries = kMaxInterruptedTxCount; while (size > 0) { int32 bytesRead = recv(fSocket, buffer, size, 0); if (bytesRead < 0) { status_t error = errno; if (fClosed || error != B_INTERRUPTED || --remainingRetries < 0) { if (!fClosed) { PRINT(("InsecureChannel::Receive(): B_INTERRUPTED\n")); } return error; } //PRINT(("InsecureChannel::Receive(): B_INTERRUPTED ignored\n")); } else if (bytesRead == 0) { // This seems to indicate that the remote peer closed the // connection. PRINT(("Connection::Receive(): received 0 bytes. Assuming " "that the remote peer closed the connection\n")); return B_ERROR; } else { size -= bytesRead; buffer += bytesRead; remainingRetries = kMaxInterruptedTxCount; //PRINT(("InsecureChannel::Receive(): received %ld bytes, still to read: %lu\n", //bytesRead, size)); } } return B_OK; } // GetPeerAddress status_t InsecureChannel::GetPeerAddress(NetAddress *address) const { if (!address) return B_BAD_VALUE; sockaddr_in addr; socklen_t size = sizeof(sockaddr_in); if (getpeername(fSocket, (sockaddr*)&addr, &size) < 0) return errno; if (addr.sin_family != AF_INET) return B_BAD_VALUE; address->SetAddress(addr); return B_OK; }