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; 315 // TODO: Map value < 0 to B_INFINITE_TIMEOUT or use -1 by default. 316 } 317 318 319 int 320 BNetEndpoint::Error() const 321 { 322 return (int)fStatus; 323 } 324 325 326 char* 327 BNetEndpoint::ErrorStr() const 328 { 329 return strerror(fStatus); 330 } 331 332 333 // #pragma mark - 334 335 336 void 337 BNetEndpoint::Close() 338 { 339 if (fSocket >= 0) 340 close(fSocket); 341 342 fSocket = -1; 343 fStatus = B_NO_INIT; 344 } 345 346 347 status_t 348 BNetEndpoint::Bind(const BNetAddress& address) 349 { 350 if (fSocket < 0 && _SetupSocket() != B_OK) 351 return fStatus; 352 353 struct sockaddr_in addr; 354 status_t status = address.GetAddr(addr); 355 if (status != B_OK) 356 return status; 357 358 if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 359 fStatus = errno; 360 Close(); 361 return B_ERROR; 362 } 363 364 socklen_t addrSize = sizeof(addr); 365 if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) { 366 fStatus = errno; 367 Close(); 368 return B_ERROR; 369 } 370 371 fAddr.SetTo(addr); 372 return B_OK; 373 } 374 375 376 status_t 377 BNetEndpoint::Bind(int port) 378 { 379 BNetAddress addr(INADDR_ANY, port); 380 return Bind(addr); 381 } 382 383 384 status_t 385 BNetEndpoint::Connect(const BNetAddress& address) 386 { 387 if (fSocket < 0 && _SetupSocket() != B_OK) 388 return fStatus; 389 390 sockaddr_in addr; 391 if (address.GetAddr(addr) != B_OK) 392 return B_ERROR; 393 394 if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) { 395 Close(); 396 fStatus = errno; 397 return B_ERROR; 398 } 399 400 socklen_t addrSize = sizeof(addr); 401 if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) { 402 Close(); 403 fStatus = errno; 404 return B_ERROR; 405 } 406 fPeer.SetTo(addr); 407 return B_OK; 408 } 409 410 411 status_t 412 BNetEndpoint::Connect(const char *hostname, int port) 413 { 414 BNetAddress addr(hostname, port); 415 return Connect(addr); 416 } 417 418 419 status_t 420 BNetEndpoint::Listen(int backlog) 421 { 422 if (fSocket < 0 && _SetupSocket() != B_OK) 423 return fStatus; 424 425 if (listen(fSocket, backlog) < 0) { 426 Close(); 427 fStatus = errno; 428 return B_ERROR; 429 } 430 return B_OK; 431 } 432 433 434 BNetEndpoint* 435 BNetEndpoint::Accept(int32 timeout) 436 { 437 // TODO: IsDataPending() expects 0 as special value for infinite timeout, 438 // hence the following call is broken for timeout < 0 and timeout == 0. 439 if (!IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) 440 return NULL; 441 442 struct sockaddr_in peerAddress; 443 socklen_t peerAddressSize = sizeof(peerAddress); 444 445 int socket 446 = accept(fSocket, (struct sockaddr *)&peerAddress, &peerAddressSize); 447 if (socket < 0) { 448 Close(); 449 fStatus = errno; 450 return NULL; 451 } 452 453 struct sockaddr_in localAddress; 454 socklen_t localAddressSize = sizeof(localAddress); 455 if (getsockname(socket, (struct sockaddr *)&localAddress, 456 &localAddressSize) < 0) { 457 fStatus = errno; 458 return NULL; 459 } 460 461 BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this, socket, 462 localAddress, peerAddress); 463 if (endpoint == NULL) { 464 close(socket); 465 fStatus = B_NO_MEMORY; 466 return NULL; 467 } 468 469 return endpoint; 470 } 471 472 473 // #pragma mark - 474 475 476 bool 477 BNetEndpoint::IsDataPending(bigtime_t timeout) 478 { 479 struct timeval tv; 480 fd_set fds; 481 482 FD_ZERO(&fds); 483 FD_SET(fSocket, &fds); 484 485 if (timeout > 0) { 486 tv.tv_sec = timeout / 1000000; 487 // TODO: A big value (e.g. B_INFINITE_TIMEOUT) will overflow! 488 tv.tv_usec = (timeout % 1000000); 489 } 490 491 if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) { 492 fStatus = errno; 493 return false; 494 } 495 496 return FD_ISSET(fSocket, &fds); 497 } 498 499 500 int32 501 BNetEndpoint::Receive(void* buffer, size_t length, int flags) 502 { 503 if (fSocket < 0 && _SetupSocket() != B_OK) 504 return fStatus; 505 506 // TODO: For fTimeout == 0 this is broken as IsDataPending(0) means wait 507 // without timeout. Furthermore the default fTimeout is B_INFINITE_TIMEOUT. 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 length = Receive(chunk.Data(), length, flags); 524 buffer.AppendData(chunk.Data(), length); 525 return length; 526 } 527 528 529 int32 530 BNetEndpoint::ReceiveFrom(void* buffer, size_t length, 531 BNetAddress& address, int flags) 532 { 533 if (fSocket < 0 && _SetupSocket() != B_OK) 534 return fStatus; 535 536 // TODO: For fTimeout == 0 this is broken as IsDataPending(0) means wait 537 // without timeout. Furthermore the default fTimeout is B_INFINITE_TIMEOUT. 538 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 539 return 0; 540 541 struct sockaddr_in addr; 542 socklen_t addrSize = sizeof(addr); 543 544 length = recvfrom(fSocket, buffer, length, flags, 545 (struct sockaddr *)&addr, &addrSize); 546 if (length < 0) 547 fStatus = errno; 548 else 549 address.SetTo(addr); 550 551 return length; 552 } 553 554 555 int32 556 BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length, 557 BNetAddress& address, int flags) 558 { 559 BNetBuffer chunk(length); 560 length = ReceiveFrom(chunk.Data(), length, address, flags); 561 buffer.AppendData(chunk.Data(), length); 562 return length; 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