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 BNetEndpoint& 109 BNetEndpoint::operator=(const BNetEndpoint& endpoint) 110 { 111 if (this == &endpoint) 112 return *this; 113 114 Close(); 115 116 fStatus = endpoint.fStatus; 117 fFamily = endpoint.fFamily; 118 fType = endpoint.fType; 119 fProtocol = endpoint.fProtocol; 120 fTimeout = endpoint.fTimeout; 121 fAddr = endpoint.fAddr; 122 fPeer = endpoint.fPeer; 123 124 fSocket = -1; 125 if (endpoint.fSocket >= 0) { 126 fSocket = dup(endpoint.fSocket); 127 if (fSocket < 0) 128 fStatus = errno; 129 } 130 131 return *this; 132 } 133 134 135 BNetEndpoint::~BNetEndpoint() 136 { 137 if (fSocket >= 0) 138 Close(); 139 } 140 141 142 // #pragma mark - 143 144 145 status_t 146 BNetEndpoint::Archive(BMessage* into, bool deep) const 147 { 148 if (!into) 149 return B_ERROR; 150 151 status_t status = BArchivable::Archive(into, deep); 152 if (status != B_OK) 153 return status; 154 155 in_addr addr, peer; 156 unsigned short addrPort, peerPort; 157 158 status = fAddr.GetAddr(addr, &addrPort); 159 if (status == B_OK) { 160 status = into->AddInt32("_BNetEndpoint_addr_addr", addr.s_addr); 161 if (status == B_OK) 162 status = into->AddInt16("_BNetEndpoint_addr_port", addrPort); 163 if (status != B_OK) 164 return status; 165 } 166 status = fPeer.GetAddr(peer, &peerPort); 167 if (status == B_OK) { 168 status = into->AddInt32("_BNetEndpoint_peer_addr", peer.s_addr); 169 if (status == B_OK) 170 status = into->AddInt16("_BNetEndpoint_peer_port", peerPort); 171 if (status != B_OK) 172 return status; 173 } 174 175 status = into->AddInt64("_BNetEndpoint_timeout", fTimeout); 176 if (status == B_OK) 177 status = into->AddInt32("_BNetEndpoint_proto", fType); 178 179 return status; 180 } 181 182 183 BArchivable* 184 BNetEndpoint::Instantiate(BMessage* archive) 185 { 186 if (!archive) 187 return NULL; 188 189 if (!validate_instantiation(archive, "BNetEndpoint")) 190 return NULL; 191 192 BNetEndpoint* endpoint = new BNetEndpoint(archive); 193 if (endpoint && endpoint->InitCheck() == B_OK) 194 return endpoint; 195 196 delete endpoint; 197 return NULL; 198 } 199 200 201 // #pragma mark - 202 203 204 status_t 205 BNetEndpoint::InitCheck() const 206 { 207 return fSocket == -1 ? B_NO_INIT : B_OK; 208 } 209 210 211 int 212 BNetEndpoint::Socket() const 213 { 214 return fSocket; 215 } 216 217 218 const BNetAddress& 219 BNetEndpoint::LocalAddr() const 220 { 221 return fAddr; 222 } 223 224 225 const BNetAddress& 226 BNetEndpoint::RemoteAddr() const 227 { 228 return fPeer; 229 } 230 231 232 status_t 233 BNetEndpoint::SetProtocol(int protocol) 234 { 235 Close(); 236 fType = protocol; // sic (protocol is SOCK_DGRAM or SOCK_STREAM) 237 return _SetupSocket(); 238 } 239 240 241 int 242 BNetEndpoint::SetOption(int32 option, int32 level, 243 const void* data, unsigned int length) 244 { 245 if (fSocket < 0 && _SetupSocket() != B_OK) 246 return fStatus; 247 248 if (setsockopt(fSocket, level, option, data, length) < 0) { 249 fStatus = errno; 250 return B_ERROR; 251 } 252 253 return B_OK; 254 } 255 256 257 int 258 BNetEndpoint::SetNonBlocking(bool enable) 259 { 260 if (fSocket < 0 && _SetupSocket() != B_OK) 261 return fStatus; 262 263 int flags = fcntl(fSocket, F_GETFL); 264 if (flags < 0) { 265 fStatus = errno; 266 return B_ERROR; 267 } 268 269 if (enable) 270 flags |= O_NONBLOCK; 271 else 272 flags &= ~O_NONBLOCK; 273 274 if (fcntl(fSocket, F_SETFL, flags) < 0) { 275 fStatus = errno; 276 return B_ERROR; 277 } 278 279 return B_OK; 280 } 281 282 283 int 284 BNetEndpoint::SetReuseAddr(bool enable) 285 { 286 if (fSocket < 0 && _SetupSocket() != B_OK) 287 return fStatus; 288 289 int onoff = (int) enable; 290 return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff)); 291 } 292 293 294 void 295 BNetEndpoint::SetTimeout(bigtime_t timeout) 296 { 297 fTimeout = timeout; 298 // TODO: Map value < 0 to B_INFINITE_TIMEOUT or use -1 by default. 299 } 300 301 302 int 303 BNetEndpoint::Error() const 304 { 305 return (int)fStatus; 306 } 307 308 309 char* 310 BNetEndpoint::ErrorStr() const 311 { 312 return strerror(fStatus); 313 } 314 315 316 // #pragma mark - 317 318 319 void 320 BNetEndpoint::Close() 321 { 322 if (fSocket >= 0) 323 close(fSocket); 324 325 fSocket = -1; 326 fStatus = B_NO_INIT; 327 } 328 329 330 status_t 331 BNetEndpoint::Bind(const BNetAddress& address) 332 { 333 if (fSocket < 0 && _SetupSocket() != B_OK) 334 return fStatus; 335 336 struct sockaddr_in addr; 337 status_t status = address.GetAddr(addr); 338 if (status != B_OK) 339 return status; 340 341 if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 342 fStatus = errno; 343 Close(); 344 return B_ERROR; 345 } 346 347 socklen_t addrSize = sizeof(addr); 348 if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) { 349 fStatus = errno; 350 Close(); 351 return B_ERROR; 352 } 353 354 fAddr.SetTo(addr); 355 return B_OK; 356 } 357 358 359 status_t 360 BNetEndpoint::Bind(int port) 361 { 362 BNetAddress addr(INADDR_ANY, port); 363 return Bind(addr); 364 } 365 366 367 status_t 368 BNetEndpoint::Connect(const BNetAddress& address) 369 { 370 if (fSocket < 0 && _SetupSocket() != B_OK) 371 return fStatus; 372 373 sockaddr_in addr; 374 if (address.GetAddr(addr) != B_OK) 375 return B_ERROR; 376 377 if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) { 378 Close(); 379 fStatus = errno; 380 return B_ERROR; 381 } 382 383 socklen_t addrSize = sizeof(addr); 384 if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) { 385 Close(); 386 fStatus = errno; 387 return B_ERROR; 388 } 389 fPeer.SetTo(addr); 390 return B_OK; 391 } 392 393 394 status_t 395 BNetEndpoint::Connect(const char *hostname, int port) 396 { 397 BNetAddress addr(hostname, port); 398 return Connect(addr); 399 } 400 401 402 status_t 403 BNetEndpoint::Listen(int backlog) 404 { 405 if (fSocket < 0 && _SetupSocket() != B_OK) 406 return fStatus; 407 408 if (listen(fSocket, backlog) < 0) { 409 Close(); 410 fStatus = errno; 411 return B_ERROR; 412 } 413 return B_OK; 414 } 415 416 417 BNetEndpoint* 418 BNetEndpoint::Accept(int32 timeout) 419 { 420 // TODO: IsDataPending() expects 0 as special value for infinite timeout, 421 // hence the following call is broken for timeout < 0 and timeout == 0. 422 if (!IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) 423 return NULL; 424 425 struct sockaddr_in addr; 426 socklen_t addrSize = sizeof(addr); 427 428 int socket = accept(fSocket, (struct sockaddr *) &addr, &addrSize); 429 if (socket < 0) { 430 Close(); 431 fStatus = errno; 432 return NULL; 433 } 434 435 BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this); 436 if (endpoint == NULL) { 437 close(socket); 438 fStatus = B_NO_MEMORY; 439 return NULL; 440 } 441 442 endpoint->fSocket = socket; 443 endpoint->fPeer.SetTo(addr); 444 445 if (getsockname(socket, (struct sockaddr *)&addr, &addrSize) < 0) { 446 delete endpoint; 447 fStatus = errno; 448 return NULL; 449 } 450 451 endpoint->fAddr.SetTo(addr); 452 return endpoint; 453 } 454 455 456 // #pragma mark - 457 458 459 bool 460 BNetEndpoint::IsDataPending(bigtime_t timeout) 461 { 462 struct timeval tv; 463 fd_set fds; 464 465 FD_ZERO(&fds); 466 FD_SET(fSocket, &fds); 467 468 if (timeout > 0) { 469 tv.tv_sec = timeout / 1000000; 470 // TODO: A big value (e.g. B_INFINITE_TIMEOUT) will overflow! 471 tv.tv_usec = (timeout % 1000000); 472 } 473 474 if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) { 475 fStatus = errno; 476 return false; 477 } 478 479 return FD_ISSET(fSocket, &fds); 480 } 481 482 483 int32 484 BNetEndpoint::Receive(void* buffer, size_t length, int flags) 485 { 486 if (fSocket < 0 && _SetupSocket() != B_OK) 487 return fStatus; 488 489 // TODO: For fTimeout == 0 this is broken as IsDataPending(0) means wait 490 // without timeout. Furthermore the default fTimeout is B_INFINITE_TIMEOUT. 491 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 492 return 0; 493 494 ssize_t bytesReceived = recv(fSocket, buffer, length, flags); 495 if (bytesReceived < 0) 496 fStatus = errno; 497 498 return bytesReceived; 499 } 500 501 502 int32 503 BNetEndpoint::Receive(BNetBuffer& buffer, size_t length, int flags) 504 { 505 BNetBuffer chunk(length); 506 length = Receive(chunk.Data(), length, flags); 507 buffer.AppendData(chunk.Data(), length); 508 return length; 509 } 510 511 512 int32 513 BNetEndpoint::ReceiveFrom(void* buffer, size_t length, 514 BNetAddress& address, int flags) 515 { 516 if (fSocket < 0 && _SetupSocket() != B_OK) 517 return fStatus; 518 519 // TODO: For fTimeout == 0 this is broken as IsDataPending(0) means wait 520 // without timeout. Furthermore the default fTimeout is B_INFINITE_TIMEOUT. 521 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 522 return 0; 523 524 struct sockaddr_in addr; 525 socklen_t addrSize = sizeof(addr); 526 527 length = recvfrom(fSocket, buffer, length, flags, 528 (struct sockaddr *)&addr, &addrSize); 529 if (length < 0) 530 fStatus = errno; 531 else 532 address.SetTo(addr); 533 534 return length; 535 } 536 537 538 int32 539 BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length, 540 BNetAddress& address, int flags) 541 { 542 BNetBuffer chunk(length); 543 length = ReceiveFrom(chunk.Data(), length, address, flags); 544 buffer.AppendData(chunk.Data(), length); 545 return length; 546 } 547 548 549 int32 550 BNetEndpoint::Send(const void* buffer, size_t length, int flags) 551 { 552 if (fSocket < 0 && _SetupSocket() != B_OK) 553 return fStatus; 554 555 ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags); 556 if (bytesSent < 0) 557 fStatus = errno; 558 559 return bytesSent; 560 } 561 562 563 int32 564 BNetEndpoint::Send(BNetBuffer& buffer, int flags) 565 { 566 return Send(buffer.Data(), buffer.Size(), flags); 567 } 568 569 570 int32 571 BNetEndpoint::SendTo(const void* buffer, size_t length, 572 const BNetAddress& address, int flags) 573 { 574 if (fSocket < 0 && _SetupSocket() != B_OK) 575 return fStatus; 576 577 struct sockaddr_in addr; 578 if (address.GetAddr(addr) != B_OK) 579 return B_ERROR; 580 581 ssize_t bytesSent = sendto(fSocket, buffer, length, flags, 582 (struct sockaddr *) &addr, sizeof(addr)); 583 if (bytesSent < 0) 584 fStatus = errno; 585 586 return bytesSent; 587 } 588 589 590 int32 591 BNetEndpoint::SendTo(BNetBuffer& buffer, 592 const BNetAddress& address, int flags) 593 { 594 return SendTo(buffer.Data(), buffer.Size(), address, flags); 595 } 596 597 598 // #pragma mark - 599 600 601 status_t 602 BNetEndpoint::_SetupSocket() 603 { 604 if ((fSocket = socket(fFamily, fType, fProtocol)) < 0) 605 fStatus = errno; 606 else 607 fStatus = B_OK; 608 return fStatus; 609 } 610 611 612 // #pragma mark - 613 614 status_t BNetEndpoint::InitCheck() 615 { 616 return const_cast<const BNetEndpoint*>(this)->InitCheck(); 617 } 618 619 620 const BNetAddress& BNetEndpoint::LocalAddr() 621 { 622 return const_cast<const BNetEndpoint*>(this)->LocalAddr(); 623 } 624 625 626 const BNetAddress& BNetEndpoint::RemoteAddr() 627 { 628 return const_cast<const BNetEndpoint*>(this)->RemoteAddr(); 629 } 630 631 632 // #pragma mark - 633 634 635 // These are virtuals, implemented for binary compatibility purpose 636 void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {} 637 void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {} 638 void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {} 639 void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {} 640 void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {} 641 void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {} 642 643