1 /* 2 * Copyright 2002-2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <r5_compatibility.h> 8 9 #include <Message.h> 10 #include <NetEndpoint.h> 11 12 #include <errno.h> 13 #include <fcntl.h> 14 #include <netdb.h> 15 #include <netinet/in.h> 16 #include <new> 17 #include <string.h> 18 #include <sys/socket.h> 19 #include <sys/time.h> 20 #include <sys/types.h> 21 #include <unistd.h> 22 23 24 BNetEndpoint::BNetEndpoint(int type) 25 : 26 fInit(B_NO_INIT), 27 fSocket(-1), 28 fTimeout(B_INFINITE_TIMEOUT), 29 fLastError(0) 30 { 31 if ((fSocket = socket(__gR5Compatibility ? R5_AF_INET : AF_INET, type, 0)) < 0) 32 fLastError = errno; 33 else 34 fInit = B_OK; 35 } 36 37 38 BNetEndpoint::BNetEndpoint(int family, int type, int protocol) 39 : 40 fInit(B_NO_INIT), 41 fSocket(-1), 42 fTimeout(B_INFINITE_TIMEOUT), 43 fLastError(0) 44 { 45 if ((fSocket = socket(family, type, protocol)) < 0) 46 fLastError = errno; 47 else 48 fInit = B_OK; 49 } 50 51 52 BNetEndpoint::BNetEndpoint(BMessage* archive) 53 : 54 fInit(B_NO_INIT), 55 fSocket(-1), 56 fTimeout(B_INFINITE_TIMEOUT), 57 fLastError(0) 58 { 59 // TODO 60 if (! archive) 61 return; 62 63 BMessage msg; 64 if (archive->FindMessage("bnendp_peer", &msg) != B_OK) 65 return; 66 fPeer = BNetAddress(&msg); 67 68 if (archive->FindMessage("bnendp_addr", &msg) != B_OK) 69 return; 70 fAddr = BNetAddress(&msg); 71 72 fInit = B_OK; 73 } 74 75 76 BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint) 77 : 78 fInit(endpoint.fInit), 79 fTimeout(endpoint.fTimeout), 80 fLastError(endpoint.fLastError), 81 fAddr(endpoint.fAddr), 82 fPeer(endpoint.fPeer) 83 { 84 fSocket = -1; 85 if (endpoint.fSocket >= 0) { 86 fSocket = dup(endpoint.fSocket); 87 if (fSocket < 0) { 88 fLastError = errno; 89 fInit = B_NO_INIT; 90 } 91 } 92 } 93 94 95 BNetEndpoint& 96 BNetEndpoint::operator=(const BNetEndpoint& endpoint) 97 { 98 Close(); 99 100 fInit = endpoint.fInit; 101 fTimeout = endpoint.fTimeout; 102 fLastError = endpoint.fLastError; 103 fAddr = endpoint.fAddr; 104 fPeer = endpoint.fPeer; 105 106 fSocket = -1; 107 if (endpoint.fSocket >= 0) { 108 fSocket = dup(endpoint.fSocket); 109 if (fSocket < 0) { 110 fLastError = errno; 111 fInit = B_NO_INIT; 112 } 113 } 114 115 return *this; 116 } 117 118 119 BNetEndpoint::~BNetEndpoint() 120 { 121 Close(); 122 } 123 124 125 // #pragma mark - 126 127 128 status_t 129 BNetEndpoint::Archive(BMessage* into, bool deep) const 130 { 131 // TODO 132 if (into == 0) 133 return B_ERROR; 134 135 if (fInit != B_OK) 136 return B_NO_INIT; 137 138 BMessage msg; 139 if (fPeer.Archive(&msg) != B_OK) 140 return B_ERROR; 141 if (into->AddMessage("bnendp_peer", &msg) != B_OK) 142 return B_ERROR; 143 144 if (fAddr.Archive(&msg) != B_OK) 145 return B_ERROR; 146 if (into->AddMessage("bnendp_addr", &msg) != B_OK) 147 return B_ERROR; 148 149 return B_OK; 150 } 151 152 153 BArchivable* 154 BNetEndpoint::Instantiate(BMessage* archive) 155 { 156 if (!archive) 157 return NULL; 158 159 if (!validate_instantiation(archive, "BNetAddress")) 160 return NULL; 161 162 BNetEndpoint* endpoint = new BNetEndpoint(archive); 163 if (endpoint && endpoint->InitCheck() == B_OK) 164 return endpoint; 165 166 delete endpoint; 167 return NULL; 168 } 169 170 171 // #pragma mark - 172 173 174 status_t 175 BNetEndpoint::InitCheck() 176 { 177 return fInit; 178 } 179 180 181 int 182 BNetEndpoint::Socket() const 183 { 184 return fSocket; 185 } 186 187 188 const BNetAddress& 189 BNetEndpoint::LocalAddr() 190 { 191 return fAddr; 192 } 193 194 195 const BNetAddress& 196 BNetEndpoint::RemoteAddr() 197 { 198 return fPeer; 199 } 200 201 202 status_t 203 BNetEndpoint::SetProtocol(int protocol) 204 { 205 Close(); 206 if ((fSocket = socket(AF_INET, protocol, 0)) < 0) { 207 fLastError = errno; 208 return fLastError; 209 } 210 fInit = B_OK; 211 return fInit; 212 } 213 214 215 int 216 BNetEndpoint::SetOption(int32 option, int32 level, 217 const void* data, unsigned int length) 218 { 219 if (fSocket < 0) 220 return B_ERROR; 221 222 if (setsockopt(fSocket, level, option, data, length) < 0) { 223 fLastError = errno; 224 return B_ERROR; 225 } 226 227 return B_OK; 228 } 229 230 231 int 232 BNetEndpoint::SetNonBlocking(bool enable) 233 { 234 int flags = fcntl(fSocket, F_GETFL); 235 if (flags < 0) { 236 fLastError = errno; 237 return B_ERROR; 238 } 239 240 if (enable) 241 flags |= O_NONBLOCK; 242 else 243 flags &= ~O_NONBLOCK; 244 245 if (fcntl(fSocket, F_SETFL, flags) < 0) { 246 fLastError = errno; 247 return B_ERROR; 248 } 249 250 return B_OK; 251 } 252 253 254 int 255 BNetEndpoint::SetReuseAddr(bool enable) 256 { 257 int onoff = (int) enable; 258 return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff)); 259 } 260 261 262 void 263 BNetEndpoint::SetTimeout(bigtime_t timeout) 264 { 265 fTimeout = timeout; 266 } 267 268 269 int 270 BNetEndpoint::Error() const 271 { 272 return fLastError; 273 } 274 275 276 char* 277 BNetEndpoint::ErrorStr() const 278 { 279 return strerror(fLastError); 280 } 281 282 283 // #pragma mark - 284 285 286 void 287 BNetEndpoint::Close() 288 { 289 if (fSocket >= 0) 290 close(fSocket); 291 292 fSocket = -1; 293 fInit = B_NO_INIT; 294 } 295 296 297 status_t 298 BNetEndpoint::Bind(const BNetAddress& address) 299 { 300 struct sockaddr_in addr; 301 status_t status = address.GetAddr(addr); 302 if (status != B_OK) 303 return status; 304 305 if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 306 fLastError = errno; 307 Close(); 308 return B_ERROR; 309 } 310 311 socklen_t addrSize = sizeof(addr); 312 if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) { 313 fLastError = errno; 314 Close(); 315 return B_ERROR; 316 } 317 318 if (addr.sin_addr.s_addr == 0) { 319 // Grrr, buggy getsockname! 320 char hostname[MAXHOSTNAMELEN]; 321 gethostname(hostname, sizeof(hostname)); 322 struct hostent *host = gethostbyname(hostname); 323 if (host != NULL) 324 memcpy(&addr.sin_addr.s_addr, host->h_addr, sizeof(addr.sin_addr.s_addr)); 325 } 326 327 fAddr.SetTo(addr); 328 return B_OK; 329 } 330 331 332 status_t 333 BNetEndpoint::Bind(int port) 334 { 335 BNetAddress addr(INADDR_ANY, port); 336 return Bind(addr); 337 } 338 339 340 status_t 341 BNetEndpoint::Connect(const BNetAddress& address) 342 { 343 sockaddr_in addr; 344 if (address.GetAddr(addr) != B_OK) 345 return B_ERROR; 346 347 if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) { 348 Close(); 349 fLastError = errno; 350 return B_ERROR; 351 } 352 353 socklen_t addrSize = sizeof(addr); 354 if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) { 355 Close(); 356 return B_ERROR; 357 } 358 359 fPeer.SetTo(addr); 360 return B_OK; 361 } 362 363 364 status_t 365 BNetEndpoint::Connect(const char *hostname, int port) 366 { 367 BNetAddress addr(hostname, port); 368 return Connect(addr); 369 } 370 371 372 status_t 373 BNetEndpoint::Listen(int backlog) 374 { 375 if (listen(fSocket, backlog) < 0) { 376 Close(); 377 fLastError = errno; 378 return B_ERROR; 379 } 380 return B_OK; 381 } 382 383 384 BNetEndpoint* 385 BNetEndpoint::Accept(int32 timeout) 386 { 387 if (!IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) 388 return NULL; 389 390 struct sockaddr_in addr; 391 socklen_t addrSize = sizeof(addr); 392 393 int socket = accept(fSocket, (struct sockaddr *) &addr, &addrSize); 394 if (socket < 0) { 395 Close(); 396 fLastError = errno; 397 return NULL; 398 } 399 400 BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this); 401 if (endpoint == NULL) { 402 close(socket); 403 fLastError = B_NO_MEMORY; 404 return NULL; 405 } 406 407 endpoint->fSocket = socket; 408 endpoint->fPeer.SetTo(addr); 409 410 if (getsockname(socket, (struct sockaddr *)&addr, &addrSize) < 0) { 411 endpoint->Close(); 412 delete endpoint; 413 return NULL; 414 } 415 416 endpoint->fAddr.SetTo(addr); 417 return endpoint; 418 } 419 420 421 // #pragma mark - 422 423 424 bool 425 BNetEndpoint::IsDataPending(bigtime_t timeout) 426 { 427 struct timeval tv; 428 fd_set fds; 429 430 FD_ZERO(&fds); 431 FD_SET(fSocket, &fds); 432 433 if (timeout > 0) { 434 tv.tv_sec = timeout / 1000000; 435 tv.tv_usec = (timeout % 1000000); 436 } 437 438 if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) { 439 fLastError = errno; 440 return false; 441 } 442 443 return FD_ISSET(fSocket, &fds); 444 } 445 446 447 int32 448 BNetEndpoint::Receive(void* buffer, size_t length, int flags) 449 { 450 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 451 return 0; 452 453 ssize_t bytesReceived = recv(fSocket, buffer, length, flags); 454 if (bytesReceived < 0) 455 fLastError = errno; 456 457 return bytesReceived; 458 } 459 460 461 int32 462 BNetEndpoint::Receive(BNetBuffer& buffer, size_t length, int flags) 463 { 464 BNetBuffer chunk(length); 465 length = Receive(chunk.Data(), length, flags); 466 buffer.AppendData(chunk.Data(), length); 467 return length; 468 } 469 470 471 int32 472 BNetEndpoint::ReceiveFrom(void* buffer, size_t length, 473 BNetAddress& address, int flags) 474 { 475 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 476 return 0; 477 478 struct sockaddr_in addr; 479 socklen_t addrSize = sizeof(addr); 480 481 length = recvfrom(fSocket, buffer, length, flags, 482 (struct sockaddr *)&addr, &addrSize); 483 if (length < 0) 484 fLastError = errno; 485 else 486 address.SetTo(addr); 487 488 return length; 489 } 490 491 492 int32 493 BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length, 494 BNetAddress& address, int flags) 495 { 496 BNetBuffer chunk(length); 497 length = ReceiveFrom(chunk.Data(), length, address, flags); 498 buffer.AppendData(chunk.Data(), length); 499 return length; 500 } 501 502 503 int32 504 BNetEndpoint::Send(const void* buffer, size_t length, int flags) 505 { 506 ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags); 507 if (bytesSent < 0) 508 fLastError = errno; 509 510 return bytesSent; 511 } 512 513 514 int32 515 BNetEndpoint::Send(BNetBuffer& buffer, int flags) 516 { 517 return Send(buffer.Data(), buffer.Size(), flags); 518 } 519 520 521 int32 522 BNetEndpoint::SendTo(const void* buffer, size_t length, 523 const BNetAddress& address, int flags) 524 { 525 struct sockaddr_in addr; 526 if (address.GetAddr(addr) != B_OK) 527 return B_ERROR; 528 529 ssize_t bytesSent = sendto(fSocket, buffer, length, flags, 530 (struct sockaddr *) &addr, sizeof(addr)); 531 if (bytesSent < 0) 532 fLastError = errno; 533 534 return bytesSent; 535 } 536 537 538 int32 539 BNetEndpoint::SendTo(BNetBuffer& buffer, 540 const BNetAddress& address, int flags) 541 { 542 return SendTo(buffer.Data(), buffer.Size(), address, flags); 543 } 544 545 546 // #pragma mark - 547 548 549 // These are virtuals, implemented for binary compatibility purpose 550 void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {} 551 void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {} 552 void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {} 553 void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {} 554 void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {} 555 void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {} 556 557