1 /****************************************************************************** 2 / 3 / File: NetEndpoint.cpp 4 / 5 / Description: The Network API. 6 / 7 / Copyright 2002, OpenBeOS Project, All Rights Reserved. 8 / 9 ******************************************************************************/ 10 11 #include <string.h> 12 #include <sys/time.h> 13 #include <sys/types.h> 14 #include <sys/socket.h> 15 #include <netinet/in.h> 16 #include <netdb.h> 17 #include <fcntl.h> 18 #include <unistd.h> 19 #include <errno.h> 20 21 #include <Message.h> 22 #include <NetEndpoint.h> 23 24 25 BNetEndpoint::BNetEndpoint(int protocol) 26 : m_init(B_NO_INIT), m_socket(-1), m_timeout(B_INFINITE_TIMEOUT), m_last_error(0) 27 { 28 if ((m_socket = socket(AF_INET, protocol, 0)) < 0) 29 m_last_error = errno; 30 else 31 m_init = B_OK; 32 } 33 34 35 BNetEndpoint::BNetEndpoint(int family, int type, int protocol) 36 : m_init(B_NO_INIT), m_socket(-1), m_timeout(B_INFINITE_TIMEOUT), m_last_error(0) 37 { 38 if ((m_socket = socket(family, type, protocol)) < 0) 39 m_last_error = errno; 40 else 41 m_init = B_OK; 42 } 43 44 45 BNetEndpoint::BNetEndpoint(BMessage *archive) 46 : m_init(B_NO_INIT), 47 m_socket(-1), 48 m_timeout(B_INFINITE_TIMEOUT), 49 m_last_error(0) 50 { 51 // TODO 52 if (! archive) 53 return; 54 55 BMessage msg; 56 57 if (archive->FindMessage("bnendp_peer", &msg) != B_OK) 58 return; 59 m_peer = BNetAddress(&msg); 60 61 if (archive->FindMessage("bnendp_addr", &msg) != B_OK) 62 return; 63 m_addr = BNetAddress(&msg); 64 65 if (archive->FindMessage("bnendp_conaddr", &msg) != B_OK) 66 return; 67 m_conaddr = BNetAddress(&msg); 68 69 m_init = B_OK; 70 } 71 72 73 BNetEndpoint::BNetEndpoint(const BNetEndpoint & ep) 74 : m_init(ep.m_init), m_timeout(ep.m_timeout), m_last_error(ep.m_last_error), 75 m_addr(ep.m_addr), m_peer(ep.m_peer) 76 { 77 m_socket = -1; 78 if (ep.m_socket >= 0) 79 m_socket = dup(ep.m_socket); 80 } 81 82 83 BNetEndpoint & BNetEndpoint::operator=(const BNetEndpoint & ep) 84 { 85 Close(); 86 87 m_init = ep.m_init; 88 m_timeout = ep.m_timeout; 89 m_last_error = ep.m_last_error; 90 m_addr = ep.m_addr; 91 m_peer = ep.m_peer; 92 93 m_socket = -1; 94 if (ep.m_socket >= 0) 95 m_socket = dup(ep.m_socket); 96 97 if (m_socket >= 0) 98 m_init = B_OK; 99 100 return *this; 101 } 102 103 BNetEndpoint::~BNetEndpoint() 104 { 105 Close(); 106 } 107 108 // #pragma mark - 109 110 status_t BNetEndpoint::Archive(BMessage *into, bool deep = true) const 111 { 112 // TODO 113 114 if( into == 0 ) 115 return B_ERROR; 116 117 if ( m_init != B_OK ) 118 return B_NO_INIT; 119 120 BMessage msg; 121 122 if (m_peer.Archive(&msg) != B_OK) 123 return B_ERROR; 124 if (into->AddMessage("bnendp_peer", &msg) != B_OK) 125 return B_ERROR; 126 127 if (m_addr.Archive(&msg) != B_OK) 128 return B_ERROR; 129 if (into->AddMessage("bnendp_addr", &msg) != B_OK) 130 return B_ERROR; 131 132 if (m_conaddr.Archive(&msg) != B_OK) 133 return B_ERROR; 134 if (into->AddMessage("bnendp_conaddr", &msg) != B_OK) 135 return B_ERROR; 136 137 return B_OK; 138 } 139 140 141 BArchivable *BNetEndpoint::Instantiate(BMessage *archive) 142 { 143 if (! archive) 144 return NULL; 145 146 if (! validate_instantiation(archive, "BNetAddress") ) 147 return NULL; 148 149 BNetEndpoint *ep = new BNetEndpoint(archive); 150 if (ep && ep->InitCheck() == B_OK) 151 return ep; 152 153 delete ep; 154 return NULL; 155 } 156 157 // #pragma mark - 158 159 160 status_t BNetEndpoint::InitCheck() 161 { 162 return m_init; 163 } 164 165 166 int BNetEndpoint::Socket() const 167 { 168 return m_socket; 169 } 170 171 172 const BNetAddress & BNetEndpoint::LocalAddr() 173 { 174 return m_addr; 175 } 176 177 178 const BNetAddress & BNetEndpoint::RemoteAddr() 179 { 180 return m_peer; 181 } 182 183 184 status_t BNetEndpoint::SetProtocol(int protocol) 185 { 186 Close(); 187 if ((m_socket = socket(AF_INET, protocol, 0)) < 0) { 188 m_last_error = errno; 189 return m_last_error; 190 } 191 m_init = B_OK; 192 return m_init; 193 } 194 195 196 int BNetEndpoint::SetOption(int32 option, int32 level, 197 const void * data, unsigned int length) 198 { 199 if (m_socket < 0) 200 return B_ERROR; 201 202 if (setsockopt(m_socket, level, option, data, length) < 0) { 203 m_last_error = errno; 204 return B_ERROR; 205 } 206 return B_OK; 207 } 208 209 210 int BNetEndpoint::SetNonBlocking(bool enable) 211 { 212 int flags = fcntl(m_socket, F_GETFL); 213 214 if (enable) 215 flags |= O_NONBLOCK; 216 else 217 flags &= ~O_NONBLOCK; 218 219 if (fcntl(m_socket, F_SETFL, flags) < 0) { 220 m_last_error = errno; 221 return B_ERROR; 222 } 223 224 return B_OK; 225 } 226 227 228 int BNetEndpoint::SetReuseAddr(bool enable) 229 { 230 int onoff = (int) enable; 231 return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff)); 232 } 233 234 235 void BNetEndpoint::SetTimeout(bigtime_t timeout) 236 { 237 m_timeout = timeout; 238 } 239 240 241 int BNetEndpoint::Error() const 242 { 243 return m_last_error; 244 } 245 246 247 char * BNetEndpoint::ErrorStr() const 248 { 249 return strerror(m_last_error); 250 } 251 252 253 // #pragma mark - 254 255 void BNetEndpoint::Close() 256 { 257 if (m_socket >= 0) 258 close(m_socket); 259 m_socket = -1; 260 m_init = B_NO_INIT; 261 } 262 263 264 status_t BNetEndpoint::Bind(const BNetAddress & address) 265 { 266 struct sockaddr_in addr; 267 status_t status; 268 269 status = address.GetAddr(addr); 270 if (status != B_OK) 271 return status; 272 273 if (bind(m_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 274 m_last_error = errno; 275 Close(); 276 return B_ERROR; 277 } 278 279 int sz = sizeof(addr); 280 281 if (getsockname(m_socket, (struct sockaddr *) &addr, &sz) < 0) { 282 m_last_error = errno; 283 Close(); 284 return B_ERROR; 285 } 286 287 #ifdef _NETDB_H_ 288 if (addr.sin_addr.s_addr == 0) { 289 // Grrr, buggy getsockname! 290 char hostname[MAXHOSTNAMELEN]; 291 struct hostent *he; 292 gethostname(hostname, sizeof(hostname)); 293 he = gethostbyname(hostname); 294 if (he) 295 memcpy(&addr.sin_addr.s_addr, he->h_addr, sizeof(addr.sin_addr.s_addr)); 296 } 297 #endif 298 m_addr.SetTo(addr); 299 return B_OK; 300 } 301 302 303 status_t BNetEndpoint::Bind(int port) 304 { 305 BNetAddress addr(INADDR_ANY, port); 306 return Bind(addr); 307 } 308 309 310 status_t BNetEndpoint::Connect(const BNetAddress & address) 311 { 312 sockaddr_in addr; 313 314 if (address.GetAddr(addr) != B_OK) 315 return B_ERROR; 316 317 if (connect(m_socket, (sockaddr *) &addr, sizeof(addr)) < 0) { 318 Close(); 319 m_last_error = errno; 320 return B_ERROR; 321 } 322 323 int sz = sizeof(addr); 324 if (getpeername(m_socket, (sockaddr *) &addr, &sz) < 0) { 325 Close(); 326 return B_ERROR; 327 } 328 329 m_peer.SetTo(addr); 330 return B_OK; 331 } 332 333 334 status_t BNetEndpoint::Connect(const char *hostname, int port) 335 { 336 BNetAddress addr(hostname, port); 337 return Connect(addr); 338 } 339 340 341 status_t BNetEndpoint::Listen(int backlog) 342 { 343 if (listen(m_socket, backlog) < 0) { 344 Close(); 345 m_last_error = errno; 346 return B_ERROR; 347 } 348 return B_OK; 349 } 350 351 352 BNetEndpoint * BNetEndpoint::Accept(int32 timeout) 353 { 354 if (! IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) 355 return NULL; 356 357 struct sockaddr_in addr; 358 int sz = sizeof(addr); 359 360 int handle = accept(m_socket, (struct sockaddr *) &addr, &sz); 361 if (handle < 0) { 362 Close(); 363 m_last_error = errno; 364 return NULL; 365 } 366 367 BNetEndpoint * ep = new BNetEndpoint(*this); 368 if (! ep) { 369 close(handle); 370 return NULL; 371 } 372 373 ep->m_socket = handle; 374 ep->m_peer.SetTo(addr); 375 if (getsockname(handle, (struct sockaddr *) &addr, &sz) < 0) { 376 ep->Close(); 377 delete ep; 378 return NULL; 379 } 380 381 ep->m_addr.SetTo(addr); 382 return ep; 383 } 384 385 // #pragma mark - 386 387 bool BNetEndpoint::IsDataPending(bigtime_t timeout) 388 { 389 fd_set fds; 390 struct timeval tv, *tv_ptr = NULL; 391 392 FD_ZERO(&fds); 393 FD_SET(m_socket, &fds); 394 395 if (timeout > 0) { 396 tv.tv_sec = timeout / 1000000; 397 tv.tv_usec = (timeout % 1000000); 398 tv_ptr = &tv; 399 } 400 401 if (select(m_socket + 1, &fds, NULL, NULL, &tv) < 0) { 402 m_last_error = errno; 403 return false; 404 } 405 406 return FD_ISSET(m_socket, &fds); 407 } 408 409 410 int32 BNetEndpoint::Receive(void * buffer, size_t length, int flags) 411 { 412 if (m_timeout >= 0 && IsDataPending(m_timeout) == false) 413 return 0; 414 415 ssize_t sz = recv(m_socket, buffer, length, flags); 416 if (sz < 0) 417 m_last_error = errno; 418 return sz; 419 } 420 421 422 int32 BNetEndpoint::Receive(BNetBuffer & buffer, size_t length, int flags) 423 { 424 BNetBuffer chunk(length); 425 length = Receive(chunk.Data(), length, flags); 426 buffer.AppendData(chunk.Data(), length); 427 return length; 428 } 429 430 431 int32 BNetEndpoint::ReceiveFrom(void * buffer, size_t length, 432 BNetAddress & address, int flags) 433 { 434 if (m_timeout >= 0 && IsDataPending(m_timeout) == false) 435 return 0; 436 437 struct sockaddr_in addr; 438 int sz = sizeof(addr); 439 440 length = recvfrom(m_socket, buffer, length, flags, 441 (struct sockaddr *) &addr, &sz); 442 if (length < 0) 443 m_last_error = errno; 444 else 445 address.SetTo(addr); 446 return length; 447 } 448 449 450 int32 BNetEndpoint::ReceiveFrom(BNetBuffer & buffer, size_t length, 451 BNetAddress & address, int flags) 452 { 453 BNetBuffer chunk(length); 454 length = ReceiveFrom(chunk.Data(), length, address, flags); 455 buffer.AppendData(chunk.Data(), length); 456 return length; 457 } 458 459 460 int32 BNetEndpoint::Send(const void * buffer, size_t length, int flags) 461 { 462 ssize_t sz; 463 464 sz = send(m_socket, (const char *) buffer, length, flags); 465 if (sz < 0) 466 m_last_error = errno; 467 return sz; 468 } 469 470 471 int32 BNetEndpoint::Send(BNetBuffer & buffer, int flags) 472 { 473 return Send(buffer.Data(), buffer.Size(), flags); 474 } 475 476 477 int32 BNetEndpoint::SendTo(const void * buffer, size_t length, 478 const BNetAddress & address, int flags) 479 { 480 ssize_t sz; 481 struct sockaddr_in addr; 482 483 if (address.GetAddr(addr) != B_OK) 484 return B_ERROR; 485 486 sz = sendto(m_socket, buffer, length, flags, 487 (struct sockaddr *) &addr, sizeof(addr)); 488 if (sz < 0) 489 m_last_error = errno; 490 return sz; 491 } 492 493 int32 BNetEndpoint::SendTo(BNetBuffer & buffer, 494 const BNetAddress & address, int flags) 495 { 496 return SendTo(buffer.Data(), buffer.Size(), address, flags); 497 } 498 499 // #pragma mark - 500 501 // These are virtuals, implemented for binary compatibility purpose 502 void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() 503 { 504 } 505 506 507 void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() 508 { 509 } 510 511 512 void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() 513 { 514 } 515 516 517 void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() 518 { 519 } 520 521 522 void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() 523 { 524 } 525 526 527 void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() 528 { 529 } 530 531