1 // InsecureChannel.cpp 2 3 #include <errno.h> 4 5 #ifdef HAIKU_TARGET_PLATFORM_BEOS 6 # include <socket.h> 7 #else 8 # include <unistd.h> 9 # include <netinet/in.h> 10 # include <sys/socket.h> 11 #endif 12 13 #include "Compatibility.h" 14 #include "DebugSupport.h" 15 #include "InsecureChannel.h" 16 #include "NetAddress.h" 17 #include "Utils.h" 18 19 static const int32 kMaxInterruptedTxCount = 20; 20 21 // constructor 22 InsecureChannel::InsecureChannel(int socket) 23 : Channel(), 24 fSocket(socket), 25 fClosed(false) 26 { 27 // set socket to blocking (with BONE a connection socket seems to inherit 28 // the non-blocking property of the listener socket) 29 if (fSocket >= 0) { 30 int dontBlock = 0; 31 setsockopt(fSocket, SOL_SOCKET, SO_NONBLOCK, &dontBlock, sizeof(int)); 32 33 #ifndef HAIKU_TARGET_PLATFORM_BEOS 34 int txLowWater = 1; 35 setsockopt(fSocket, SOL_SOCKET, SO_SNDLOWAT, &txLowWater, sizeof(int)); 36 setsockopt(fSocket, SOL_SOCKET, SO_RCVLOWAT, &txLowWater, sizeof(int)); 37 #endif 38 } 39 } 40 41 // destructor 42 InsecureChannel::~InsecureChannel() 43 { 44 Close(); 45 } 46 47 // Close 48 void 49 InsecureChannel::Close() 50 { 51 fClosed = true; 52 safe_closesocket(fSocket); 53 } 54 55 // Send 56 status_t 57 InsecureChannel::Send(const void* _buffer, int32 size) 58 { 59 if (size == 0) 60 return B_OK; 61 if (!_buffer || size < 0) 62 return B_BAD_VALUE; 63 const uint8* buffer = static_cast<const uint8*>(_buffer); 64 int32 remainingRetries = kMaxInterruptedTxCount; 65 while (size > 0) { 66 int32 bytesSent = send(fSocket, buffer, size, 0); 67 if (bytesSent < 0) { 68 status_t error = errno; 69 if (fClosed || errno != B_INTERRUPTED || --remainingRetries < 0) 70 { 71 if (!fClosed) { 72 PRINT(("InsecureChannel::Send(): B_INTERRUPTED\n")); 73 } 74 return error; 75 } 76 //PRINT(("InsecureChannel::Send: B_INTERRUPTED ignored, remaining retries: %ld\n", 77 //remainingRetries)); 78 bytesSent = 0; 79 } else if (bytesSent == 0) { 80 // This seems to indicate that the remote peer closed the 81 // connection. 82 PRINT(("Connection::Send(): sent 0 bytes. Assuming " 83 "that the remote peer closed the connection\n")); 84 return B_ERROR; 85 } else { 86 size -= bytesSent; 87 buffer += bytesSent; 88 remainingRetries = kMaxInterruptedTxCount; 89 //PRINT(("InsecureChannel::Send(): sent %ld bytes, still to sent: %lu\n", 90 //bytesSent, size)); 91 } 92 } 93 return B_OK; 94 } 95 96 // Receive 97 status_t 98 InsecureChannel::Receive(void* _buffer, int32 size) 99 { 100 if (size == 0) 101 return B_OK; 102 if (!_buffer || size < 0) 103 return B_BAD_VALUE; 104 uint8* buffer = static_cast<uint8*>(_buffer); 105 int32 remainingRetries = kMaxInterruptedTxCount; 106 while (size > 0) { 107 int32 bytesRead = recv(fSocket, buffer, size, 0); 108 if (bytesRead < 0) { 109 status_t error = errno; 110 if (fClosed || error != B_INTERRUPTED || --remainingRetries < 0) 111 { 112 if (!fClosed) { 113 PRINT(("InsecureChannel::Receive(): B_INTERRUPTED\n")); 114 } 115 return error; 116 } 117 //PRINT(("InsecureChannel::Receive(): B_INTERRUPTED ignored\n")); 118 } else if (bytesRead == 0) { 119 // This seems to indicate that the remote peer closed the 120 // connection. 121 PRINT(("Connection::Receive(): received 0 bytes. Assuming " 122 "that the remote peer closed the connection\n")); 123 return B_ERROR; 124 } else { 125 size -= bytesRead; 126 buffer += bytesRead; 127 remainingRetries = kMaxInterruptedTxCount; 128 //PRINT(("InsecureChannel::Receive(): received %ld bytes, still to read: %lu\n", 129 //bytesRead, size)); 130 } 131 } 132 return B_OK; 133 } 134 135 // GetPeerAddress 136 status_t 137 InsecureChannel::GetPeerAddress(NetAddress *address) const 138 { 139 if (!address) 140 return B_BAD_VALUE; 141 142 sockaddr_in addr; 143 socklen_t size = sizeof(sockaddr_in); 144 if (getpeername(fSocket, (sockaddr*)&addr, &size) < 0) 145 return errno; 146 if (addr.sin_family != AF_INET) 147 return B_BAD_VALUE; 148 149 address->SetAddress(addr); 150 return B_OK; 151 } 152 153