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
InsecureChannel(int socket)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
~InsecureChannel()42 InsecureChannel::~InsecureChannel()
43 {
44 Close();
45 }
46
47 // Close
48 void
Close()49 InsecureChannel::Close()
50 {
51 fClosed = true;
52 safe_closesocket(fSocket);
53 }
54
55 // Send
56 status_t
Send(const void * _buffer,int32 size)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
Receive(void * _buffer,int32 size)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
GetPeerAddress(NetAddress * address) const137 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