1 /****************************************************************************** 2 / 3 / File: NetEndpoint.cpp 4 / 5 / Description: The Network API. 6 / 7 / Copyright 2002, OpenBeOS Project, All Rights Reserved. 8 / 9 ******************************************************************************/ 10 11 #include <string.h> 12 #include <sys/time.h> 13 #include <sys/types.h> 14 #include <sys/socket.h> 15 #include <netinet/in.h> 16 #include <netdb.h> 17 #include <fcntl.h> 18 #include <unistd.h> 19 #include <NetEndpoint.h> 20 21 BNetEndpoint::BNetEndpoint(int protocol) 22 : fStatus(B_OK), 23 fSocket(0), 24 fTimeout(B_INFINITE_TIMEOUT), 25 fLocalAddr(), 26 fRemoteAddr() 27 { 28 if ((fSocket = socket(AF_INET, protocol, 0)) < 0) 29 fStatus = B_ERROR; 30 } 31 32 BNetEndpoint::BNetEndpoint(int handle, bigtime_t timeout) 33 : fStatus(B_OK), 34 fSocket(0), 35 fTimeout(timeout), 36 fLocalAddr(), 37 fRemoteAddr() 38 { 39 if ((fSocket = dup(handle)) < 0) 40 fStatus = B_ERROR; 41 } 42 43 BNetEndpoint::BNetEndpoint(const BNetEndpoint & endpoint) 44 : fStatus(endpoint.fStatus), 45 fSocket(endpoint.fSocket), 46 fTimeout(endpoint.fTimeout), 47 fLocalAddr(endpoint.fLocalAddr), 48 fRemoteAddr(endpoint.fRemoteAddr) 49 { 50 } 51 52 BNetEndpoint::~BNetEndpoint() 53 { 54 Close(); 55 } 56 57 BNetEndpoint::BNetEndpoint(BMessage *archive) 58 : fStatus(B_OK), 59 fSocket(0), 60 fTimeout(B_INFINITE_TIMEOUT), 61 fLocalAddr(), 62 fRemoteAddr() 63 { 64 // TODO 65 fStatus = B_ERROR; 66 } 67 68 status_t BNetEndpoint::Archive(BMessage *into, bool deep = true) const 69 { 70 // TODO 71 return B_ERROR; 72 } 73 74 BArchivable *BNetEndpointInstantiate(BMessage *archive) 75 { 76 // TODO 77 return NULL; 78 } 79 80 status_t BNetEndpoint::InitCheck() const 81 { 82 return fStatus; 83 } 84 85 int BNetEndpoint::Socket() const 86 { 87 return fSocket; 88 } 89 90 const BNetAddress & BNetEndpoint::LocalAddr() const 91 { 92 return fLocalAddr; 93 } 94 95 const BNetAddress & BNetEndpoint::RemoteAddr() const 96 { 97 return fRemoteAddr; 98 } 99 100 status_t BNetEndpoint::SetProtocol(int protocol) 101 { 102 Close(); 103 if ((fSocket = ::socket(AF_INET, protocol, 0)) < 0) 104 return B_ERROR; 105 return B_OK; 106 } 107 108 status_t BNetEndpoint::SetOption(int32 option, int32 level, 109 const void * data, unsigned int length) 110 { 111 if (setsockopt(fSocket, level, option, data, length) < 0) 112 return B_ERROR; 113 return B_OK; 114 } 115 116 status_t BNetEndpoint::SetNonBlocking(bool enable) 117 { 118 int flags = fcntl(fSocket, F_GETFL); 119 if (enable) 120 flags |= O_NONBLOCK; 121 else 122 flags &= ~O_NONBLOCK; 123 if (fcntl(fSocket, F_SETFL, flags) < 0) 124 return B_ERROR; 125 return B_OK; 126 } 127 128 status_t BNetEndpoint::SetReuseAddr(bool enable) 129 { 130 return SetOption(SO_REUSEADDR, SOL_SOCKET, &enable, sizeof(enable)); 131 } 132 133 void BNetEndpoint::SetTimeout(bigtime_t timeout) 134 { 135 fTimeout = timeout; 136 } 137 138 status_t BNetEndpoint::Bind(const BNetAddress & address) 139 { 140 sockaddr_in addr; 141 if (address.GetAddr(addr) == B_OK) { 142 if (bind(fSocket, (sockaddr *) &addr, sizeof(addr)) >= 0) { 143 sockaddr_in name; 144 int length = sizeof(name); 145 146 if (getsockname(fSocket, (sockaddr *) &name, &length) >= 0) 147 fLocalAddr.SetTo(name); 148 149 return B_OK; 150 } 151 } 152 return B_ERROR; 153 } 154 155 status_t BNetEndpoint::Bind(int port) 156 { 157 char hostname[256]; 158 159 if (gethostname(hostname, sizeof(hostname)) >= 0) 160 return BNetEndpoint::Bind(BNetAddress(hostname, port)); 161 return B_ERROR; 162 } 163 164 void BNetEndpoint::Close() 165 { 166 close(fSocket); 167 fSocket = 0; 168 } 169 170 status_t BNetEndpoint::Connect(const BNetAddress & address) 171 { 172 sockaddr_in addr; 173 if (address.GetAddr(addr) == B_OK) { 174 if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) >= 0) { 175 sockaddr_in name; 176 int length = sizeof(name); 177 178 if (getpeername(fSocket, (sockaddr *) &name, &length) >= 0) 179 fRemoteAddr.SetTo(name); 180 return B_OK; 181 } 182 } 183 return B_ERROR; 184 } 185 186 status_t BNetEndpoint::Connect(const char * hostname, int port) 187 { 188 BNetAddress address(hostname, port); 189 190 return BNetEndpoint::Connect(address); 191 } 192 193 status_t BNetEndpoint::Listen(int backlog) 194 { 195 if (listen(fSocket, backlog) < 0) 196 return B_ERROR; 197 return B_OK; 198 } 199 200 BNetEndpoint *BNetEndpoint::Accept(int32 timeout) 201 { 202 if (IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) { 203 sockaddr_in name; 204 int length = sizeof(name); 205 206 int handle = accept(fSocket, (sockaddr *) &name, &length); 207 if (handle >= 0) { 208 BNetEndpoint * endpoint = new BNetEndpoint(handle, fTimeout); 209 if (endpoint != NULL) { 210 endpoint->fRemoteAddr.SetTo(name); 211 if (getsockname(handle, (sockaddr *) &name, &length) >= 0) 212 endpoint->fLocalAddr.SetTo(name); 213 } 214 return endpoint; 215 } 216 } 217 return NULL; 218 } 219 220 bool BNetEndpoint::IsDataPending(bigtime_t timeout) 221 { 222 fd_set fds; 223 struct timeval tv; 224 225 FD_ZERO(&fds); 226 FD_SET(fSocket, &fds); 227 228 tv.tv_sec = timeout / 1000000; 229 tv.tv_usec = (timeout % 1000000); 230 231 return (select(fSocket + 1, &fds, NULL, NULL, &tv) > 0); 232 } 233 234 int32 BNetEndpoint::Receive(void * buffer, size_t length, int flags) 235 { 236 if (IsDataPending(fTimeout)) 237 return recv(fSocket, buffer, length, flags); 238 return -1; 239 } 240 241 int32 BNetEndpoint::Receive(BNetBuffer & buffer, size_t length, int flags) 242 { 243 BNetBuffer chunk(length); 244 length = Receive(chunk.Data(), chunk.Size(), flags); 245 buffer.AppendData(chunk.Data(), length); 246 return length; 247 } 248 249 int32 BNetEndpoint::ReceiveFrom(void * buffer, size_t length, 250 const BNetAddress & address, int flags) 251 { 252 sockaddr_in addr; 253 int addrlen = sizeof(addr); 254 if (address.GetAddr(addr) == B_OK && IsDataPending(fTimeout)) 255 return recvfrom(fSocket, buffer, length, flags, 256 (sockaddr *) &addr, &addrlen); 257 return -1; 258 } 259 260 int32 BNetEndpoint::ReceiveFrom(BNetBuffer & buffer, 261 const BNetAddress & address, int flags) 262 { 263 return ReceiveFrom(buffer.Data(), buffer.Size(), address, flags); 264 } 265 266 int32 BNetEndpoint::Send(const void * buffer, size_t length, int flags) 267 { 268 return send(fSocket, (const char *) buffer, length, flags); 269 } 270 271 int32 BNetEndpoint::Send(const BNetBuffer & buffer, int flags) 272 { 273 return Send(buffer.Data(), buffer.Size(), flags); 274 } 275 276 int32 BNetEndpoint::SendTo(const void * buffer, size_t length, 277 const BNetAddress & address, int flags) 278 { 279 sockaddr_in addr; 280 address.GetAddr(addr); 281 return sendto(fSocket, buffer, length, flags, 282 (sockaddr *) &addr, sizeof(addr)); 283 } 284 285 int32 BNetEndpoint::SendTo(const BNetBuffer & buffer, 286 const BNetAddress & address, int flags) 287 { 288 return SendTo(buffer.Data(), buffer.Size(), address, flags); 289 } 290