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 21BNetEndpoint::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 34BNetEndpoint::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 47BNetEndpoint::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 88BNetEndpoint::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(). 109BNetEndpoint::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 125BNetEndpoint& 126BNetEndpoint::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 152BNetEndpoint::~BNetEndpoint() 153{ 154 if (fSocket >= 0) 155 Close(); 156} 157 158 159// #pragma mark - 160 161 162status_t 163BNetEndpoint::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 200BArchivable* 201BNetEndpoint::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 221status_t 222BNetEndpoint::InitCheck() const 223{ 224 return fSocket == -1 ? B_NO_INIT : B_OK; 225} 226 227 228int 229BNetEndpoint::Socket() const 230{ 231 return fSocket; 232} 233 234 235const BNetAddress& 236BNetEndpoint::LocalAddr() const 237{ 238 return fAddr; 239} 240 241 242const BNetAddress& 243BNetEndpoint::RemoteAddr() const 244{ 245 return fPeer; 246} 247 248 249status_t 250BNetEndpoint::SetProtocol(int protocol) 251{ 252 Close(); 253 fType = protocol; // sic (protocol is SOCK_DGRAM or SOCK_STREAM) 254 return _SetupSocket(); 255} 256 257 258int 259BNetEndpoint::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 274int 275BNetEndpoint::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 300int 301BNetEndpoint::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 311void 312BNetEndpoint::SetTimeout(bigtime_t timeout) 313{ 314 fTimeout = timeout < 0 ? B_INFINITE_TIMEOUT : timeout; 315} 316 317 318int 319BNetEndpoint::Error() const 320{ 321 return (int)fStatus; 322} 323 324 325char* 326BNetEndpoint::ErrorStr() const 327{ 328 return strerror(fStatus); 329} 330 331 332// #pragma mark - 333 334 335void 336BNetEndpoint::Close() 337{ 338 if (fSocket >= 0) 339 close(fSocket); 340 341 fSocket = -1; 342 fStatus = B_NO_INIT; 343} 344 345 346status_t 347BNetEndpoint::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 375status_t 376BNetEndpoint::Bind(int port) 377{ 378 BNetAddress addr(INADDR_ANY, port); 379 return Bind(addr); 380} 381 382 383status_t 384BNetEndpoint::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 410status_t 411BNetEndpoint::Connect(const char *hostname, int port) 412{ 413 BNetAddress addr(hostname, port); 414 return Connect(addr); 415} 416 417 418status_t 419BNetEndpoint::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 433BNetEndpoint* 434BNetEndpoint::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 474bool 475BNetEndpoint::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 508int32 509BNetEndpoint::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 525int32 526BNetEndpoint::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 536int32 537BNetEndpoint::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 560int32 561BNetEndpoint::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 572int32 573BNetEndpoint::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 586int32 587BNetEndpoint::Send(BNetBuffer& buffer, int flags) 588{ 589 return Send(buffer.Data(), buffer.Size(), flags); 590} 591 592 593int32 594BNetEndpoint::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 613int32 614BNetEndpoint::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 624status_t 625BNetEndpoint::_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 637status_t BNetEndpoint::InitCheck() 638{ 639 return const_cast<const BNetEndpoint*>(this)->InitCheck(); 640} 641 642 643const BNetAddress& BNetEndpoint::LocalAddr() 644{ 645 return const_cast<const BNetEndpoint*>(this)->LocalAddr(); 646} 647 648 649const 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 659void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {} 660void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {} 661void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {} 662void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {} 663void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {} 664void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {} 665 666