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 } 299 300 301 int 302 BNetEndpoint::Error() const 303 { 304 return (int)fStatus; 305 } 306 307 308 char* 309 BNetEndpoint::ErrorStr() const 310 { 311 return strerror(fStatus); 312 } 313 314 315 // #pragma mark - 316 317 318 void 319 BNetEndpoint::Close() 320 { 321 if (fSocket >= 0) 322 close(fSocket); 323 324 fSocket = -1; 325 fStatus = B_NO_INIT; 326 } 327 328 329 status_t 330 BNetEndpoint::Bind(const BNetAddress& address) 331 { 332 if (fSocket < 0 && _SetupSocket() != B_OK) 333 return fStatus; 334 335 struct sockaddr_in addr; 336 status_t status = address.GetAddr(addr); 337 if (status != B_OK) 338 return status; 339 340 if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 341 fStatus = errno; 342 Close(); 343 return B_ERROR; 344 } 345 346 socklen_t addrSize = sizeof(addr); 347 if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) { 348 fStatus = errno; 349 Close(); 350 return B_ERROR; 351 } 352 353 fAddr.SetTo(addr); 354 return B_OK; 355 } 356 357 358 status_t 359 BNetEndpoint::Bind(int port) 360 { 361 BNetAddress addr(INADDR_ANY, port); 362 return Bind(addr); 363 } 364 365 366 status_t 367 BNetEndpoint::Connect(const BNetAddress& address) 368 { 369 if (fSocket < 0 && _SetupSocket() != B_OK) 370 return fStatus; 371 372 sockaddr_in addr; 373 if (address.GetAddr(addr) != B_OK) 374 return B_ERROR; 375 376 if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) { 377 Close(); 378 fStatus = errno; 379 return B_ERROR; 380 } 381 382 socklen_t addrSize = sizeof(addr); 383 if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) { 384 Close(); 385 fStatus = errno; 386 return B_ERROR; 387 } 388 fPeer.SetTo(addr); 389 return B_OK; 390 } 391 392 393 status_t 394 BNetEndpoint::Connect(const char *hostname, int port) 395 { 396 BNetAddress addr(hostname, port); 397 return Connect(addr); 398 } 399 400 401 status_t 402 BNetEndpoint::Listen(int backlog) 403 { 404 if (fSocket < 0 && _SetupSocket() != B_OK) 405 return fStatus; 406 407 if (listen(fSocket, backlog) < 0) { 408 Close(); 409 fStatus = errno; 410 return B_ERROR; 411 } 412 return B_OK; 413 } 414 415 416 BNetEndpoint* 417 BNetEndpoint::Accept(int32 timeout) 418 { 419 if (!IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) 420 return NULL; 421 422 struct sockaddr_in addr; 423 socklen_t addrSize = sizeof(addr); 424 425 int socket = accept(fSocket, (struct sockaddr *) &addr, &addrSize); 426 if (socket < 0) { 427 Close(); 428 fStatus = errno; 429 return NULL; 430 } 431 432 BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this); 433 if (endpoint == NULL) { 434 close(socket); 435 fStatus = B_NO_MEMORY; 436 return NULL; 437 } 438 439 endpoint->fSocket = socket; 440 endpoint->fPeer.SetTo(addr); 441 442 if (getsockname(socket, (struct sockaddr *)&addr, &addrSize) < 0) { 443 delete endpoint; 444 fStatus = errno; 445 return NULL; 446 } 447 448 endpoint->fAddr.SetTo(addr); 449 return endpoint; 450 } 451 452 453 // #pragma mark - 454 455 456 bool 457 BNetEndpoint::IsDataPending(bigtime_t timeout) 458 { 459 struct timeval tv; 460 fd_set fds; 461 462 FD_ZERO(&fds); 463 FD_SET(fSocket, &fds); 464 465 if (timeout > 0) { 466 tv.tv_sec = timeout / 1000000; 467 tv.tv_usec = (timeout % 1000000); 468 } 469 470 if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) { 471 fStatus = errno; 472 return false; 473 } 474 475 return FD_ISSET(fSocket, &fds); 476 } 477 478 479 int32 480 BNetEndpoint::Receive(void* buffer, size_t length, int flags) 481 { 482 if (fSocket < 0 && _SetupSocket() != B_OK) 483 return fStatus; 484 485 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 486 return 0; 487 488 ssize_t bytesReceived = recv(fSocket, buffer, length, flags); 489 if (bytesReceived < 0) 490 fStatus = errno; 491 492 return bytesReceived; 493 } 494 495 496 int32 497 BNetEndpoint::Receive(BNetBuffer& buffer, size_t length, int flags) 498 { 499 BNetBuffer chunk(length); 500 length = Receive(chunk.Data(), length, flags); 501 buffer.AppendData(chunk.Data(), length); 502 return length; 503 } 504 505 506 int32 507 BNetEndpoint::ReceiveFrom(void* buffer, size_t length, 508 BNetAddress& address, int flags) 509 { 510 if (fSocket < 0 && _SetupSocket() != B_OK) 511 return fStatus; 512 513 if (fTimeout >= 0 && IsDataPending(fTimeout) == false) 514 return 0; 515 516 struct sockaddr_in addr; 517 socklen_t addrSize = sizeof(addr); 518 519 length = recvfrom(fSocket, buffer, length, flags, 520 (struct sockaddr *)&addr, &addrSize); 521 if (length < 0) 522 fStatus = errno; 523 else 524 address.SetTo(addr); 525 526 return length; 527 } 528 529 530 int32 531 BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length, 532 BNetAddress& address, int flags) 533 { 534 BNetBuffer chunk(length); 535 length = ReceiveFrom(chunk.Data(), length, address, flags); 536 buffer.AppendData(chunk.Data(), length); 537 return length; 538 } 539 540 541 int32 542 BNetEndpoint::Send(const void* buffer, size_t length, int flags) 543 { 544 if (fSocket < 0 && _SetupSocket() != B_OK) 545 return fStatus; 546 547 ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags); 548 if (bytesSent < 0) 549 fStatus = errno; 550 551 return bytesSent; 552 } 553 554 555 int32 556 BNetEndpoint::Send(BNetBuffer& buffer, int flags) 557 { 558 return Send(buffer.Data(), buffer.Size(), flags); 559 } 560 561 562 int32 563 BNetEndpoint::SendTo(const void* buffer, size_t length, 564 const BNetAddress& address, int flags) 565 { 566 if (fSocket < 0 && _SetupSocket() != B_OK) 567 return fStatus; 568 569 struct sockaddr_in addr; 570 if (address.GetAddr(addr) != B_OK) 571 return B_ERROR; 572 573 ssize_t bytesSent = sendto(fSocket, buffer, length, flags, 574 (struct sockaddr *) &addr, sizeof(addr)); 575 if (bytesSent < 0) 576 fStatus = errno; 577 578 return bytesSent; 579 } 580 581 582 int32 583 BNetEndpoint::SendTo(BNetBuffer& buffer, 584 const BNetAddress& address, int flags) 585 { 586 return SendTo(buffer.Data(), buffer.Size(), address, flags); 587 } 588 589 590 // #pragma mark - 591 592 593 status_t 594 BNetEndpoint::_SetupSocket() 595 { 596 if ((fSocket = socket(fFamily, fType, fProtocol)) < 0) 597 fStatus = errno; 598 else 599 fStatus = B_OK; 600 return fStatus; 601 } 602 603 604 // #pragma mark - 605 606 status_t BNetEndpoint::InitCheck() 607 { 608 return const_cast<const BNetEndpoint*>(this)->InitCheck(); 609 } 610 611 612 const BNetAddress& BNetEndpoint::LocalAddr() 613 { 614 return const_cast<const BNetEndpoint*>(this)->LocalAddr(); 615 } 616 617 618 const BNetAddress& BNetEndpoint::RemoteAddr() 619 { 620 return const_cast<const BNetEndpoint*>(this)->RemoteAddr(); 621 } 622 623 624 // #pragma mark - 625 626 627 // These are virtuals, implemented for binary compatibility purpose 628 void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {} 629 void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {} 630 void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {} 631 void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {} 632 void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {} 633 void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {} 634 635