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 if (select(fSocket + 1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) < 0) { 494 fStatus = errno; 495 return false; 496 } 497 498 return FD_ISSET(fSocket, &fds); 499 } 500 501 502 int32 503 BNetEndpoint::Receive(void* buffer, size_t length, int flags) 504 { 505 if (fSocket < 0 && _SetupSocket() != B_OK) 506 return fStatus; 507 508 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 509 return 0; 510 511 ssize_t bytesReceived = recv(fSocket, buffer, length, flags); 512 if (bytesReceived < 0) 513 fStatus = errno; 514 515 return bytesReceived; 516 } 517 518 519 int32 520 BNetEndpoint::Receive(BNetBuffer& buffer, size_t length, int flags) 521 { 522 BNetBuffer chunk(length); 523 ssize_t bytesReceived = Receive(chunk.Data(), length, flags); 524 if (bytesReceived > 0) 525 buffer.AppendData(chunk.Data(), bytesReceived); 526 return bytesReceived; 527 } 528 529 530 int32 531 BNetEndpoint::ReceiveFrom(void* buffer, size_t length, 532 BNetAddress& address, int flags) 533 { 534 if (fSocket < 0 && _SetupSocket() != B_OK) 535 return fStatus; 536 537 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 538 return 0; 539 540 struct sockaddr_in addr; 541 socklen_t addrSize = sizeof(addr); 542 543 ssize_t bytesReceived = recvfrom(fSocket, buffer, length, flags, 544 (struct sockaddr *)&addr, &addrSize); 545 if (bytesReceived < 0) 546 fStatus = errno; 547 else 548 address.SetTo(addr); 549 550 return bytesReceived; 551 } 552 553 554 int32 555 BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length, 556 BNetAddress& address, int flags) 557 { 558 BNetBuffer chunk(length); 559 ssize_t bytesReceived = ReceiveFrom(chunk.Data(), length, address, flags); 560 if (bytesReceived > 0) 561 buffer.AppendData(chunk.Data(), bytesReceived); 562 return bytesReceived; 563 } 564 565 566 int32 567 BNetEndpoint::Send(const void* buffer, size_t length, int flags) 568 { 569 if (fSocket < 0 && _SetupSocket() != B_OK) 570 return fStatus; 571 572 ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags); 573 if (bytesSent < 0) 574 fStatus = errno; 575 576 return bytesSent; 577 } 578 579 580 int32 581 BNetEndpoint::Send(BNetBuffer& buffer, int flags) 582 { 583 return Send(buffer.Data(), buffer.Size(), flags); 584 } 585 586 587 int32 588 BNetEndpoint::SendTo(const void* buffer, size_t length, 589 const BNetAddress& address, int flags) 590 { 591 if (fSocket < 0 && _SetupSocket() != B_OK) 592 return fStatus; 593 594 struct sockaddr_in addr; 595 if (address.GetAddr(addr) != B_OK) 596 return B_ERROR; 597 598 ssize_t bytesSent = sendto(fSocket, buffer, length, flags, 599 (struct sockaddr *) &addr, sizeof(addr)); 600 if (bytesSent < 0) 601 fStatus = errno; 602 603 return bytesSent; 604 } 605 606 607 int32 608 BNetEndpoint::SendTo(BNetBuffer& buffer, 609 const BNetAddress& address, int flags) 610 { 611 return SendTo(buffer.Data(), buffer.Size(), address, flags); 612 } 613 614 615 // #pragma mark - 616 617 618 status_t 619 BNetEndpoint::_SetupSocket() 620 { 621 if ((fSocket = socket(fFamily, fType, fProtocol)) < 0) 622 fStatus = errno; 623 else 624 fStatus = B_OK; 625 return fStatus; 626 } 627 628 629 // #pragma mark - 630 631 status_t BNetEndpoint::InitCheck() 632 { 633 return const_cast<const BNetEndpoint*>(this)->InitCheck(); 634 } 635 636 637 const BNetAddress& BNetEndpoint::LocalAddr() 638 { 639 return const_cast<const BNetEndpoint*>(this)->LocalAddr(); 640 } 641 642 643 const BNetAddress& BNetEndpoint::RemoteAddr() 644 { 645 return const_cast<const BNetEndpoint*>(this)->RemoteAddr(); 646 } 647 648 649 // #pragma mark - 650 651 652 // These are virtuals, implemented for binary compatibility purpose 653 void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {} 654 void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {} 655 void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {} 656 void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {} 657 void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {} 658 void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {} 659 660