1 /* 2 * Copyright 2002-2008, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <Message.h> 7 #include <NetEndpoint.h> 8 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <netdb.h> 12 #include <netinet/in.h> 13 #include <new> 14 #include <string.h> 15 #include <sys/socket.h> 16 #include <sys/time.h> 17 #include <sys/types.h> 18 #include <unistd.h> 19 20 21 BNetEndpoint::BNetEndpoint(int type) 22 : 23 fStatus(B_NO_INIT), 24 fFamily(AF_INET), 25 fType(type), 26 fProtocol(0), 27 fSocket(-1), 28 fTimeout(B_INFINITE_TIMEOUT) 29 { 30 _SetupSocket(); 31 } 32 33 34 BNetEndpoint::BNetEndpoint(int family, int type, int protocol) 35 : 36 fStatus(B_NO_INIT), 37 fFamily(family), 38 fType(type), 39 fProtocol(protocol), 40 fSocket(-1), 41 fTimeout(B_INFINITE_TIMEOUT) 42 { 43 _SetupSocket(); 44 } 45 46 47 BNetEndpoint::BNetEndpoint(BMessage* archive) 48 : 49 fStatus(B_NO_INIT), 50 fFamily(AF_INET), 51 fProtocol(0), 52 fSocket(-1), 53 fTimeout(B_INFINITE_TIMEOUT) 54 { 55 if (!archive) 56 return; 57 58 in_addr addr, peer; 59 unsigned short addrPort = 0, peerPort = 0; 60 61 fStatus = archive->FindInt32("_BNetEndpoint_addr_addr", 62 (int32 *)&addr.s_addr); 63 if (fStatus == B_OK) { 64 fStatus = archive->FindInt16("_BNetEndpoint_addr_port", 65 (int16 *)&addrPort); 66 if (fStatus == B_OK) 67 fStatus = fAddr.SetTo(addr, addrPort); 68 } 69 70 fStatus = archive->FindInt32("_BNetEndpoint_peer_addr", 71 (int32 *)&peer.s_addr); 72 if (fStatus == B_OK) { 73 fStatus = archive->FindInt16("_BNetEndpoint_peer_port", 74 (int16 *)&peerPort); 75 if (fStatus == B_OK) 76 fStatus = fPeer.SetTo(peer, peerPort); 77 } 78 79 fStatus = archive->FindInt64("_BNetEndpoint_timeout", (int64 *)&fTimeout); 80 if (fStatus == B_OK) 81 fStatus = archive->FindInt32("_BNetEndpoint_proto", (int32 *)&fType); 82 83 if (fStatus == B_OK) 84 _SetupSocket(); 85 } 86 87 88 BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint) 89 : 90 fStatus(endpoint.fStatus), 91 fFamily(endpoint.fFamily), 92 fType(endpoint.fType), 93 fProtocol(endpoint.fProtocol), 94 fSocket(-1), 95 fTimeout(endpoint.fTimeout), 96 fAddr(endpoint.fAddr), 97 fPeer(endpoint.fPeer) 98 99 { 100 if (endpoint.fSocket >= 0) { 101 fSocket = dup(endpoint.fSocket); 102 if (fSocket < 0) 103 fStatus = errno; 104 } 105 } 106 107 108 // Private constructor only used from BNetEndpoint::Accept(). 109 BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint, int socket, 110 const struct sockaddr_in& localAddress, 111 const struct sockaddr_in& peerAddress) 112 : 113 fStatus(endpoint.fStatus), 114 fFamily(endpoint.fFamily), 115 fType(endpoint.fType), 116 fProtocol(endpoint.fProtocol), 117 fSocket(socket), 118 fTimeout(endpoint.fTimeout), 119 fAddr(localAddress), 120 fPeer(peerAddress) 121 { 122 } 123 124 125 BNetEndpoint& 126 BNetEndpoint::operator=(const BNetEndpoint& endpoint) 127 { 128 if (this == &endpoint) 129 return *this; 130 131 Close(); 132 133 fStatus = endpoint.fStatus; 134 fFamily = endpoint.fFamily; 135 fType = endpoint.fType; 136 fProtocol = endpoint.fProtocol; 137 fTimeout = endpoint.fTimeout; 138 fAddr = endpoint.fAddr; 139 fPeer = endpoint.fPeer; 140 141 fSocket = -1; 142 if (endpoint.fSocket >= 0) { 143 fSocket = dup(endpoint.fSocket); 144 if (fSocket < 0) 145 fStatus = errno; 146 } 147 148 return *this; 149 } 150 151 152 BNetEndpoint::~BNetEndpoint() 153 { 154 if (fSocket >= 0) 155 Close(); 156 } 157 158 159 // #pragma mark - 160 161 162 status_t 163 BNetEndpoint::Archive(BMessage* into, bool deep) const 164 { 165 if (!into) 166 return B_ERROR; 167 168 status_t status = BArchivable::Archive(into, deep); 169 if (status != B_OK) 170 return status; 171 172 in_addr addr, peer; 173 unsigned short addrPort, peerPort; 174 175 status = fAddr.GetAddr(addr, &addrPort); 176 if (status == B_OK) { 177 status = into->AddInt32("_BNetEndpoint_addr_addr", addr.s_addr); 178 if (status == B_OK) 179 status = into->AddInt16("_BNetEndpoint_addr_port", addrPort); 180 if (status != B_OK) 181 return status; 182 } 183 status = fPeer.GetAddr(peer, &peerPort); 184 if (status == B_OK) { 185 status = into->AddInt32("_BNetEndpoint_peer_addr", peer.s_addr); 186 if (status == B_OK) 187 status = into->AddInt16("_BNetEndpoint_peer_port", peerPort); 188 if (status != B_OK) 189 return status; 190 } 191 192 status = into->AddInt64("_BNetEndpoint_timeout", fTimeout); 193 if (status == B_OK) 194 status = into->AddInt32("_BNetEndpoint_proto", fType); 195 196 return status; 197 } 198 199 200 BArchivable* 201 BNetEndpoint::Instantiate(BMessage* archive) 202 { 203 if (!archive) 204 return NULL; 205 206 if (!validate_instantiation(archive, "BNetEndpoint")) 207 return NULL; 208 209 BNetEndpoint* endpoint = new BNetEndpoint(archive); 210 if (endpoint && endpoint->InitCheck() == B_OK) 211 return endpoint; 212 213 delete endpoint; 214 return NULL; 215 } 216 217 218 // #pragma mark - 219 220 221 status_t 222 BNetEndpoint::InitCheck() const 223 { 224 return fSocket == -1 ? B_NO_INIT : B_OK; 225 } 226 227 228 int 229 BNetEndpoint::Socket() const 230 { 231 return fSocket; 232 } 233 234 235 const BNetAddress& 236 BNetEndpoint::LocalAddr() const 237 { 238 return fAddr; 239 } 240 241 242 const BNetAddress& 243 BNetEndpoint::RemoteAddr() const 244 { 245 return fPeer; 246 } 247 248 249 status_t 250 BNetEndpoint::SetProtocol(int protocol) 251 { 252 Close(); 253 fType = protocol; // sic (protocol is SOCK_DGRAM or SOCK_STREAM) 254 return _SetupSocket(); 255 } 256 257 258 int 259 BNetEndpoint::SetOption(int32 option, int32 level, 260 const void* data, unsigned int length) 261 { 262 if (fSocket < 0 && _SetupSocket() != B_OK) 263 return fStatus; 264 265 if (setsockopt(fSocket, level, option, data, length) < 0) { 266 fStatus = errno; 267 return B_ERROR; 268 } 269 270 return B_OK; 271 } 272 273 274 int 275 BNetEndpoint::SetNonBlocking(bool enable) 276 { 277 if (fSocket < 0 && _SetupSocket() != B_OK) 278 return fStatus; 279 280 int flags = fcntl(fSocket, F_GETFL); 281 if (flags < 0) { 282 fStatus = errno; 283 return B_ERROR; 284 } 285 286 if (enable) 287 flags |= O_NONBLOCK; 288 else 289 flags &= ~O_NONBLOCK; 290 291 if (fcntl(fSocket, F_SETFL, flags) < 0) { 292 fStatus = errno; 293 return B_ERROR; 294 } 295 296 return B_OK; 297 } 298 299 300 int 301 BNetEndpoint::SetReuseAddr(bool enable) 302 { 303 if (fSocket < 0 && _SetupSocket() != B_OK) 304 return fStatus; 305 306 int onoff = (int) enable; 307 return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff)); 308 } 309 310 311 void 312 BNetEndpoint::SetTimeout(bigtime_t timeout) 313 { 314 fTimeout = timeout < 0 ? B_INFINITE_TIMEOUT : timeout; 315 } 316 317 318 int 319 BNetEndpoint::Error() const 320 { 321 return (int)fStatus; 322 } 323 324 325 char* 326 BNetEndpoint::ErrorStr() const 327 { 328 return strerror(fStatus); 329 } 330 331 332 // #pragma mark - 333 334 335 void 336 BNetEndpoint::Close() 337 { 338 if (fSocket >= 0) 339 close(fSocket); 340 341 fSocket = -1; 342 fStatus = B_NO_INIT; 343 } 344 345 346 status_t 347 BNetEndpoint::Bind(const BNetAddress& address) 348 { 349 if (fSocket < 0 && _SetupSocket() != B_OK) 350 return fStatus; 351 352 struct sockaddr_in addr; 353 status_t status = address.GetAddr(addr); 354 if (status != B_OK) 355 return status; 356 357 if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 358 fStatus = errno; 359 Close(); 360 return B_ERROR; 361 } 362 363 socklen_t addrSize = sizeof(addr); 364 if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) { 365 fStatus = errno; 366 Close(); 367 return B_ERROR; 368 } 369 370 fAddr.SetTo(addr); 371 return B_OK; 372 } 373 374 375 status_t 376 BNetEndpoint::Bind(int port) 377 { 378 BNetAddress addr(INADDR_ANY, port); 379 return Bind(addr); 380 } 381 382 383 status_t 384 BNetEndpoint::Connect(const BNetAddress& address) 385 { 386 if (fSocket < 0 && _SetupSocket() != B_OK) 387 return fStatus; 388 389 sockaddr_in addr; 390 if (address.GetAddr(addr) != B_OK) 391 return B_ERROR; 392 393 if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) { 394 Close(); 395 fStatus = errno; 396 return B_ERROR; 397 } 398 399 socklen_t addrSize = sizeof(addr); 400 if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) { 401 Close(); 402 fStatus = errno; 403 return B_ERROR; 404 } 405 fPeer.SetTo(addr); 406 return B_OK; 407 } 408 409 410 status_t 411 BNetEndpoint::Connect(const char *hostname, int port) 412 { 413 BNetAddress addr(hostname, port); 414 return Connect(addr); 415 } 416 417 418 status_t 419 BNetEndpoint::Listen(int backlog) 420 { 421 if (fSocket < 0 && _SetupSocket() != B_OK) 422 return fStatus; 423 424 if (listen(fSocket, backlog) < 0) { 425 Close(); 426 fStatus = errno; 427 return B_ERROR; 428 } 429 return B_OK; 430 } 431 432 433 BNetEndpoint* 434 BNetEndpoint::Accept(int32 timeout) 435 { 436 if (!IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) 437 return NULL; 438 439 struct sockaddr_in peerAddress; 440 socklen_t peerAddressSize = sizeof(peerAddress); 441 442 int socket 443 = accept(fSocket, (struct sockaddr *)&peerAddress, &peerAddressSize); 444 if (socket < 0) { 445 Close(); 446 fStatus = errno; 447 return NULL; 448 } 449 450 struct sockaddr_in localAddress; 451 socklen_t localAddressSize = sizeof(localAddress); 452 if (getsockname(socket, (struct sockaddr *)&localAddress, 453 &localAddressSize) < 0) { 454 close(socket); 455 fStatus = errno; 456 return NULL; 457 } 458 459 BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this, socket, 460 localAddress, peerAddress); 461 if (endpoint == NULL) { 462 close(socket); 463 fStatus = B_NO_MEMORY; 464 return NULL; 465 } 466 467 return endpoint; 468 } 469 470 471 // #pragma mark - 472 473 474 bool 475 BNetEndpoint::IsDataPending(bigtime_t timeout) 476 { 477 struct timeval tv; 478 fd_set fds; 479 480 FD_ZERO(&fds); 481 FD_SET(fSocket, &fds); 482 483 // Make sure the timeout does not overflow. If it does, have an infinite 484 // timeout instead. Note that this conveniently includes B_INFINITE_TIMEOUT. 485 if (timeout > INT32_MAX * 1000000ll) 486 timeout = -1; 487 488 if (timeout >= 0) { 489 tv.tv_sec = timeout / 1000000; 490 tv.tv_usec = (timeout % 1000000); 491 } 492 493 int status; 494 do { 495 status = select(fSocket + 1, &fds, NULL, NULL, 496 timeout >= 0 ? &tv : NULL); 497 } while (status == -1 && errno == EINTR); 498 499 if (status < 0) { 500 fStatus = errno; 501 return false; 502 } 503 504 return FD_ISSET(fSocket, &fds); 505 } 506 507 508 int32 509 BNetEndpoint::Receive(void* buffer, size_t length, int flags) 510 { 511 if (fSocket < 0 && _SetupSocket() != B_OK) 512 return fStatus; 513 514 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 515 return 0; 516 517 ssize_t bytesReceived = recv(fSocket, buffer, length, flags); 518 if (bytesReceived < 0) 519 fStatus = errno; 520 521 return bytesReceived; 522 } 523 524 525 int32 526 BNetEndpoint::Receive(BNetBuffer& buffer, size_t length, int flags) 527 { 528 BNetBuffer chunk(length); 529 ssize_t bytesReceived = Receive(chunk.Data(), length, flags); 530 if (bytesReceived > 0) 531 buffer.AppendData(chunk.Data(), bytesReceived); 532 return bytesReceived; 533 } 534 535 536 int32 537 BNetEndpoint::ReceiveFrom(void* buffer, size_t length, 538 BNetAddress& address, int flags) 539 { 540 if (fSocket < 0 && _SetupSocket() != B_OK) 541 return fStatus; 542 543 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 544 return 0; 545 546 struct sockaddr_in addr; 547 socklen_t addrSize = sizeof(addr); 548 549 ssize_t bytesReceived = recvfrom(fSocket, buffer, length, flags, 550 (struct sockaddr *)&addr, &addrSize); 551 if (bytesReceived < 0) 552 fStatus = errno; 553 else 554 address.SetTo(addr); 555 556 return bytesReceived; 557 } 558 559 560 int32 561 BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length, 562 BNetAddress& address, int flags) 563 { 564 BNetBuffer chunk(length); 565 ssize_t bytesReceived = ReceiveFrom(chunk.Data(), length, address, flags); 566 if (bytesReceived > 0) 567 buffer.AppendData(chunk.Data(), bytesReceived); 568 return bytesReceived; 569 } 570 571 572 int32 573 BNetEndpoint::Send(const void* buffer, size_t length, int flags) 574 { 575 if (fSocket < 0 && _SetupSocket() != B_OK) 576 return fStatus; 577 578 ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags); 579 if (bytesSent < 0) 580 fStatus = errno; 581 582 return bytesSent; 583 } 584 585 586 int32 587 BNetEndpoint::Send(BNetBuffer& buffer, int flags) 588 { 589 return Send(buffer.Data(), buffer.Size(), flags); 590 } 591 592 593 int32 594 BNetEndpoint::SendTo(const void* buffer, size_t length, 595 const BNetAddress& address, int flags) 596 { 597 if (fSocket < 0 && _SetupSocket() != B_OK) 598 return fStatus; 599 600 struct sockaddr_in addr; 601 if (address.GetAddr(addr) != B_OK) 602 return B_ERROR; 603 604 ssize_t bytesSent = sendto(fSocket, buffer, length, flags, 605 (struct sockaddr *) &addr, sizeof(addr)); 606 if (bytesSent < 0) 607 fStatus = errno; 608 609 return bytesSent; 610 } 611 612 613 int32 614 BNetEndpoint::SendTo(BNetBuffer& buffer, 615 const BNetAddress& address, int flags) 616 { 617 return SendTo(buffer.Data(), buffer.Size(), address, flags); 618 } 619 620 621 // #pragma mark - 622 623 624 status_t 625 BNetEndpoint::_SetupSocket() 626 { 627 if ((fSocket = socket(fFamily, fType, fProtocol)) < 0) 628 fStatus = errno; 629 else 630 fStatus = B_OK; 631 return fStatus; 632 } 633 634 635 // #pragma mark - 636 637 status_t BNetEndpoint::InitCheck() 638 { 639 return const_cast<const BNetEndpoint*>(this)->InitCheck(); 640 } 641 642 643 const BNetAddress& BNetEndpoint::LocalAddr() 644 { 645 return const_cast<const BNetEndpoint*>(this)->LocalAddr(); 646 } 647 648 649 const BNetAddress& BNetEndpoint::RemoteAddr() 650 { 651 return const_cast<const BNetEndpoint*>(this)->RemoteAddr(); 652 } 653 654 655 // #pragma mark - 656 657 658 // These are virtuals, implemented for binary compatibility purpose 659 void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {} 660 void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {} 661 void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {} 662 void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {} 663 void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {} 664 void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {} 665 666