ovr_sdk

annotate LibOVR/Src/Net/OVR_Unix_Socket.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 Filename : OVR_Unix_Socket.cpp
nuclear@0 4 Content : Berkley sockets networking implementation
nuclear@0 5 Created : July 1, 2014
nuclear@0 6 Authors : Kevin Jenkins
nuclear@0 7
nuclear@0 8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 9
nuclear@0 10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 11 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 12 which is provided at the time of installation or download, or which
nuclear@0 13 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 14
nuclear@0 15 You may obtain a copy of the License at
nuclear@0 16
nuclear@0 17 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 18
nuclear@0 19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 20 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 22 See the License for the specific language governing permissions and
nuclear@0 23 limitations under the License.
nuclear@0 24
nuclear@0 25 ************************************************************************************/
nuclear@0 26
nuclear@0 27 #include "OVR_Unix_Socket.h"
nuclear@0 28 #include "../Kernel/OVR_Std.h"
nuclear@0 29 #include "../Kernel/OVR_Allocator.h"
nuclear@0 30 #include "../Kernel/OVR_Threads.h" // Thread::MSleep
nuclear@0 31 #include "../Kernel/OVR_Log.h"
nuclear@0 32
nuclear@0 33 #include <errno.h>
nuclear@0 34
nuclear@0 35 namespace OVR { namespace Net {
nuclear@0 36
nuclear@0 37 //-----------------------------------------------------------------------------
nuclear@0 38 // BerkleySocket
nuclear@0 39
nuclear@0 40 void BerkleySocket::Close()
nuclear@0 41 {
nuclear@0 42 if (TheSocket != INVALID_SOCKET)
nuclear@0 43 {
nuclear@0 44 close(TheSocket);
nuclear@0 45 TheSocket = INVALID_SOCKET;
nuclear@0 46 }
nuclear@0 47 }
nuclear@0 48
nuclear@0 49 SInt32 BerkleySocket::GetSockname(SockAddr *pSockAddrOut)
nuclear@0 50 {
nuclear@0 51 struct sockaddr_in6 sa;
nuclear@0 52 memset(&sa,0,sizeof(sa));
nuclear@0 53 socklen_t size = sizeof(sa);
nuclear@0 54 SInt32 i = getsockname(TheSocket, (sockaddr*)&sa, &size);
nuclear@0 55 if (i>=0)
nuclear@0 56 {
nuclear@0 57 pSockAddrOut->Set(&sa);
nuclear@0 58 }
nuclear@0 59 return i;
nuclear@0 60 }
nuclear@0 61
nuclear@0 62
nuclear@0 63 //-----------------------------------------------------------------------------
nuclear@0 64 // BitStream overloads for SockAddr
nuclear@0 65
nuclear@0 66 BitStream& operator<<(BitStream& out, SockAddr& in)
nuclear@0 67 {
nuclear@0 68 out.WriteBits((const unsigned char*) &in.Addr6, sizeof(in.Addr6)*8, true);
nuclear@0 69 return out;
nuclear@0 70 }
nuclear@0 71
nuclear@0 72 BitStream& operator>>(BitStream& in, SockAddr& out)
nuclear@0 73 {
nuclear@0 74 bool success = in.ReadBits((unsigned char*) &out.Addr6, sizeof(out.Addr6)*8, true);
nuclear@0 75 OVR_ASSERT(success);
nuclear@0 76 OVR_UNUSED(success);
nuclear@0 77 return in;
nuclear@0 78 }
nuclear@0 79
nuclear@0 80
nuclear@0 81 //-----------------------------------------------------------------------------
nuclear@0 82 // SockAddr
nuclear@0 83
nuclear@0 84 SockAddr::SockAddr()
nuclear@0 85 {
nuclear@0 86 }
nuclear@0 87
nuclear@0 88 SockAddr::SockAddr(SockAddr* address)
nuclear@0 89 {
nuclear@0 90 Set(&address->Addr6);
nuclear@0 91 }
nuclear@0 92
nuclear@0 93 SockAddr::SockAddr(sockaddr_storage* storage)
nuclear@0 94 {
nuclear@0 95 Set(storage);
nuclear@0 96 }
nuclear@0 97
nuclear@0 98 SockAddr::SockAddr(sockaddr_in6* address)
nuclear@0 99 {
nuclear@0 100 Set(address);
nuclear@0 101 }
nuclear@0 102
nuclear@0 103 SockAddr::SockAddr(const char* hostAddress, UInt16 port, int sockType)
nuclear@0 104 {
nuclear@0 105 Set(hostAddress, port, sockType);
nuclear@0 106 }
nuclear@0 107
nuclear@0 108 void SockAddr::Set(const sockaddr_storage* storage)
nuclear@0 109 {
nuclear@0 110 memcpy(&Addr6, storage, sizeof(Addr6));
nuclear@0 111 }
nuclear@0 112
nuclear@0 113 void SockAddr::Set(const sockaddr_in6* address)
nuclear@0 114 {
nuclear@0 115 memcpy(&Addr6, address, sizeof(Addr6));
nuclear@0 116 }
nuclear@0 117
nuclear@0 118 void SockAddr::Set(const char* hostAddress, UInt16 port, int sockType)
nuclear@0 119 {
nuclear@0 120 memset(&Addr6, 0, sizeof(Addr6));
nuclear@0 121
nuclear@0 122 struct addrinfo hints;
nuclear@0 123
nuclear@0 124 // make sure the struct is empty
nuclear@0 125 memset(&hints, 0, sizeof (addrinfo));
nuclear@0 126
nuclear@0 127 hints.ai_socktype = sockType; // SOCK_DGRAM or SOCK_STREAM
nuclear@0 128 hints.ai_flags = AI_PASSIVE; // fill in my IP for me
nuclear@0 129 hints.ai_family = AF_UNSPEC ;
nuclear@0 130
nuclear@0 131 if (SOCK_DGRAM == sockType)
nuclear@0 132 {
nuclear@0 133 hints.ai_protocol = IPPROTO_UDP;
nuclear@0 134 }
nuclear@0 135 else if (SOCK_STREAM == sockType)
nuclear@0 136 {
nuclear@0 137 hints.ai_protocol = IPPROTO_TCP;
nuclear@0 138 }
nuclear@0 139
nuclear@0 140 struct addrinfo* servinfo = NULL; // will point to the results
nuclear@0 141
nuclear@0 142 char portStr[32];
nuclear@0 143 OVR_itoa(port, portStr, sizeof(portStr), 10);
nuclear@0 144 int errcode = getaddrinfo(hostAddress, portStr, &hints, &servinfo);
nuclear@0 145
nuclear@0 146 if (0 != errcode)
nuclear@0 147 {
nuclear@0 148 OVR::LogError("getaddrinfo error: %s", gai_strerror(errcode));
nuclear@0 149 }
nuclear@0 150
nuclear@0 151 OVR_ASSERT(servinfo);
nuclear@0 152
nuclear@0 153 if (servinfo)
nuclear@0 154 {
nuclear@0 155 memcpy(&Addr6, servinfo->ai_addr, sizeof(Addr6));
nuclear@0 156
nuclear@0 157 freeaddrinfo(servinfo);
nuclear@0 158 }
nuclear@0 159 }
nuclear@0 160
nuclear@0 161 UInt16 SockAddr::GetPort()
nuclear@0 162 {
nuclear@0 163 return htons(Addr6.sin6_port);
nuclear@0 164 }
nuclear@0 165
nuclear@0 166 String SockAddr::ToString(bool writePort, char portDelineator) const
nuclear@0 167 {
nuclear@0 168 char dest[INET6_ADDRSTRLEN + 1];
nuclear@0 169
nuclear@0 170 int ret = getnameinfo((struct sockaddr*)&Addr6,
nuclear@0 171 sizeof(struct sockaddr_in6),
nuclear@0 172 dest,
nuclear@0 173 INET6_ADDRSTRLEN,
nuclear@0 174 NULL,
nuclear@0 175 0,
nuclear@0 176 NI_NUMERICHOST);
nuclear@0 177 if (ret != 0)
nuclear@0 178 {
nuclear@0 179 dest[0] = '\0';
nuclear@0 180 }
nuclear@0 181
nuclear@0 182 if (writePort)
nuclear@0 183 {
nuclear@0 184 unsigned char ch[2];
nuclear@0 185 ch[0]=portDelineator;
nuclear@0 186 ch[1]=0;
nuclear@0 187 OVR_strcat(dest, 16, (const char*) ch);
nuclear@0 188 OVR_itoa(ntohs(Addr6.sin6_port), dest+strlen(dest), 16, 10);
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 return String(dest);
nuclear@0 192 }
nuclear@0 193 bool SockAddr::IsLocalhost() const
nuclear@0 194 {
nuclear@0 195 static const unsigned char localhost_bytes[] =
nuclear@0 196 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
nuclear@0 197
nuclear@0 198 return memcmp(Addr6.sin6_addr.s6_addr, localhost_bytes, 16) == 0;
nuclear@0 199 }
nuclear@0 200 bool SockAddr::operator==( const SockAddr& right ) const
nuclear@0 201 {
nuclear@0 202 return memcmp(&Addr6, &right.Addr6, sizeof(Addr6)) == 0;
nuclear@0 203 }
nuclear@0 204
nuclear@0 205 bool SockAddr::operator!=( const SockAddr& right ) const
nuclear@0 206 {
nuclear@0 207 return !(*this == right);
nuclear@0 208 }
nuclear@0 209
nuclear@0 210 bool SockAddr::operator>( const SockAddr& right ) const
nuclear@0 211 {
nuclear@0 212 return memcmp(&Addr6, &right.Addr6, sizeof(Addr6)) > 0;
nuclear@0 213 }
nuclear@0 214
nuclear@0 215 bool SockAddr::operator<( const SockAddr& right ) const
nuclear@0 216 {
nuclear@0 217 return memcmp(&Addr6, &right.Addr6, sizeof(Addr6)) < 0;
nuclear@0 218 }
nuclear@0 219
nuclear@0 220
nuclear@0 221 // Returns true on success
nuclear@0 222 static bool SetSocketOptions(SocketHandle sock)
nuclear@0 223 {
nuclear@0 224 bool failed = false;
nuclear@0 225 int sock_opt;
nuclear@0 226 int sockError = 0;
nuclear@0 227
nuclear@0 228 // This doubles the max throughput rate
nuclear@0 229 sock_opt=1024*256;
nuclear@0 230 sockError = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
nuclear@0 231 if (sockError != 0)
nuclear@0 232 {
nuclear@0 233 int errsv = errno;
nuclear@0 234 OVR::LogError("[Socket] Failed SO_RCVBUF setsockopt, errno: %d", errsv);
nuclear@0 235 failed = true;
nuclear@0 236 }
nuclear@0 237
nuclear@0 238 // This doesn't make much difference: 10% maybe
nuclear@0 239 // Not supported on console 2
nuclear@0 240 sock_opt=1024*16;
nuclear@0 241 sockError = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
nuclear@0 242 if (sockError != 0)
nuclear@0 243 {
nuclear@0 244 int errsv = errno;
nuclear@0 245 OVR::LogError("[Socket] Failed SO_SNDBUF setsockopt, errno: %d", errsv);
nuclear@0 246 failed = true;
nuclear@0 247 }
nuclear@0 248
nuclear@0 249 // NOTE: This should be OVR_OS_BSD, not Mac.
nuclear@0 250 #ifdef OVR_OS_MAC
nuclear@0 251 int value = 1;
nuclear@0 252 sockError = setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
nuclear@0 253 if (sockError != 0)
nuclear@0 254 {
nuclear@0 255 int errsv = errno;
nuclear@0 256 OVR::LogError("[Socket] Failed SO_NOSIGPIPE setsockopt, errno: %d", errsv);
nuclear@0 257 failed = true;
nuclear@0 258 }
nuclear@0 259 #endif
nuclear@0 260
nuclear@0 261 // Reuse address is only needed for posix platforms, as it is the default
nuclear@0 262 // on Windows platforms.
nuclear@0 263 int optval = 1;
nuclear@0 264 sockError = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
nuclear@0 265 if (sockError != 0)
nuclear@0 266 {
nuclear@0 267 int errsv = errno;
nuclear@0 268 OVR::LogError("[Socket] Failed SO_REUSEADDR setsockopt, errno: %d", errsv);
nuclear@0 269 failed = true;
nuclear@0 270 }
nuclear@0 271
nuclear@0 272 return !failed;
nuclear@0 273 }
nuclear@0 274
nuclear@0 275 void _Ioctlsocket(SocketHandle sock, unsigned long nonblocking)
nuclear@0 276 {
nuclear@0 277 int flags = fcntl(sock, F_GETFL, 0);
nuclear@0 278 if (flags < 0) return; // return false
nuclear@0 279 if (nonblocking == 0) { flags &= ~O_NONBLOCK; }
nuclear@0 280 else { flags |= O_NONBLOCK; }
nuclear@0 281 fcntl(sock, F_SETFL, flags);
nuclear@0 282 }
nuclear@0 283
nuclear@0 284 static SocketHandle BindShared(int ai_family, int ai_socktype, BerkleyBindParameters *pBindParameters)
nuclear@0 285 {
nuclear@0 286 SocketHandle sock;
nuclear@0 287
nuclear@0 288 struct addrinfo hints;
nuclear@0 289 memset(&hints, 0, sizeof (addrinfo)); // make sure the struct is empty
nuclear@0 290 hints.ai_family = ai_family;
nuclear@0 291 hints.ai_socktype = ai_socktype;
nuclear@0 292 hints.ai_flags = AI_PASSIVE; // fill in my IP for me
nuclear@0 293 struct addrinfo *servinfo=0, *aip; // will point to the results
nuclear@0 294 char portStr[32];
nuclear@0 295 OVR_itoa(pBindParameters->Port, portStr, sizeof(portStr), 10);
nuclear@0 296
nuclear@0 297 int errcode = 0;
nuclear@0 298 if (!pBindParameters->Address.IsEmpty())
nuclear@0 299 errcode = getaddrinfo(pBindParameters->Address.ToCStr(), portStr, &hints, &servinfo);
nuclear@0 300 else
nuclear@0 301 errcode = getaddrinfo(0, portStr, &hints, &servinfo);
nuclear@0 302
nuclear@0 303 if (0 != errcode)
nuclear@0 304 {
nuclear@0 305 OVR::LogError("getaddrinfo error: %s", gai_strerror(errcode));
nuclear@0 306 }
nuclear@0 307
nuclear@0 308 for (aip = servinfo; aip != NULL; aip = aip->ai_next)
nuclear@0 309 {
nuclear@0 310 // Open socket. The address type depends on what
nuclear@0 311 // getaddrinfo() gave us.
nuclear@0 312 sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
nuclear@0 313 if (sock != 0)
nuclear@0 314 {
nuclear@0 315 SetSocketOptions(sock);
nuclear@0 316 int ret = bind( sock, aip->ai_addr, (int) aip->ai_addrlen );
nuclear@0 317 if (ret>=0)
nuclear@0 318 {
nuclear@0 319 // The actual socket is always non-blocking
nuclear@0 320 // I control blocking or not using WSAEventSelect
nuclear@0 321 _Ioctlsocket(sock, 1);
nuclear@0 322 freeaddrinfo(servinfo);
nuclear@0 323 return sock;
nuclear@0 324 }
nuclear@0 325 else
nuclear@0 326 {
nuclear@0 327 close(sock);
nuclear@0 328 }
nuclear@0 329 }
nuclear@0 330 }
nuclear@0 331
nuclear@0 332 if (servinfo) { freeaddrinfo(servinfo); }
nuclear@0 333 return INVALID_SOCKET;
nuclear@0 334 }
nuclear@0 335
nuclear@0 336
nuclear@0 337 //-----------------------------------------------------------------------------
nuclear@0 338 // UDPSocket
nuclear@0 339
nuclear@0 340 UDPSocket::UDPSocket()
nuclear@0 341 {
nuclear@0 342 RecvBuf = new UByte[RecvBufSize];
nuclear@0 343 }
nuclear@0 344
nuclear@0 345 UDPSocket::~UDPSocket()
nuclear@0 346 {
nuclear@0 347 delete[] RecvBuf;
nuclear@0 348 }
nuclear@0 349
nuclear@0 350 SocketHandle UDPSocket::Bind(BerkleyBindParameters *pBindParameters)
nuclear@0 351 {
nuclear@0 352 SocketHandle s = BindShared(AF_INET6, SOCK_DGRAM, pBindParameters);
nuclear@0 353 if (s < 0)
nuclear@0 354 return s;
nuclear@0 355
nuclear@0 356 Close();
nuclear@0 357 TheSocket = s;
nuclear@0 358
nuclear@0 359 return TheSocket;
nuclear@0 360 }
nuclear@0 361
nuclear@0 362 void UDPSocket::OnRecv(SocketEvent_UDP* eventHandler, UByte* pData, int bytesRead, SockAddr* address)
nuclear@0 363 {
nuclear@0 364 eventHandler->UDP_OnRecv(this, pData, bytesRead, address);
nuclear@0 365 }
nuclear@0 366
nuclear@0 367 int UDPSocket::Send(const void* pData, int bytes, SockAddr* address)
nuclear@0 368 {
nuclear@0 369 // NOTE: This should be OVR_OS_BSD
nuclear@0 370 #ifdef OVR_OS_MAC
nuclear@0 371 int flags = 0;
nuclear@0 372 #else
nuclear@0 373 int flags = MSG_NOSIGNAL;
nuclear@0 374 #endif
nuclear@0 375
nuclear@0 376 return (int)sendto(TheSocket, (const char*)pData, bytes, flags, (const sockaddr*)&address->Addr6, sizeof(address->Addr6));
nuclear@0 377 }
nuclear@0 378
nuclear@0 379 void UDPSocket::Poll(SocketEvent_UDP *eventHandler)
nuclear@0 380 {
nuclear@0 381 struct sockaddr_storage win32_addr;
nuclear@0 382 socklen_t fromlen;
nuclear@0 383 int bytesRead;
nuclear@0 384
nuclear@0 385 // FIXME: Implement blocking poll wait for UDP
nuclear@0 386
nuclear@0 387 // While some bytes are read,
nuclear@0 388 while (fromlen = sizeof(win32_addr), // Must set fromlen each time
nuclear@0 389 bytesRead = (int)recvfrom(TheSocket, (char*)RecvBuf, RecvBufSize, 0, (sockaddr*)&win32_addr, &fromlen),
nuclear@0 390 bytesRead > 0)
nuclear@0 391 {
nuclear@0 392 SockAddr address(&win32_addr); // Wrap address
nuclear@0 393
nuclear@0 394 OnRecv(eventHandler, RecvBuf, bytesRead, &address);
nuclear@0 395 }
nuclear@0 396 }
nuclear@0 397
nuclear@0 398
nuclear@0 399 //-----------------------------------------------------------------------------
nuclear@0 400 // TCPSocket
nuclear@0 401
nuclear@0 402 TCPSocket::TCPSocket()
nuclear@0 403 {
nuclear@0 404 IsConnecting = false;
nuclear@0 405 IsListenSocket = false;
nuclear@0 406 }
nuclear@0 407 TCPSocket::TCPSocket(SocketHandle boundHandle, bool isListenSocket)
nuclear@0 408 {
nuclear@0 409 TheSocket = boundHandle;
nuclear@0 410 IsListenSocket = isListenSocket;
nuclear@0 411 IsConnecting = false;
nuclear@0 412 SetSocketOptions(TheSocket);
nuclear@0 413
nuclear@0 414 // The actual socket is always non-blocking
nuclear@0 415 _Ioctlsocket(TheSocket, 1);
nuclear@0 416 }
nuclear@0 417
nuclear@0 418 TCPSocket::~TCPSocket()
nuclear@0 419 {
nuclear@0 420 }
nuclear@0 421
nuclear@0 422 void TCPSocket::OnRecv(SocketEvent_TCP* eventHandler, UByte* pData, int bytesRead)
nuclear@0 423 {
nuclear@0 424 eventHandler->TCP_OnRecv(this, pData, bytesRead);
nuclear@0 425 }
nuclear@0 426
nuclear@0 427 SocketHandle TCPSocket::Bind(BerkleyBindParameters* pBindParameters)
nuclear@0 428 {
nuclear@0 429 SocketHandle s = BindShared(AF_INET6, SOCK_STREAM, pBindParameters);
nuclear@0 430 if (s < 0)
nuclear@0 431 return s;
nuclear@0 432
nuclear@0 433 Close();
nuclear@0 434
nuclear@0 435 SetBlockingTimeout(pBindParameters->blockingTimeout);
nuclear@0 436 TheSocket = s;
nuclear@0 437
nuclear@0 438 return TheSocket;
nuclear@0 439 }
nuclear@0 440
nuclear@0 441 int TCPSocket::Listen()
nuclear@0 442 {
nuclear@0 443 if (IsListenSocket)
nuclear@0 444 {
nuclear@0 445 return 0;
nuclear@0 446 }
nuclear@0 447
nuclear@0 448 int i = listen(TheSocket, SOMAXCONN);
nuclear@0 449 if (i >= 0)
nuclear@0 450 {
nuclear@0 451 IsListenSocket = true;
nuclear@0 452 }
nuclear@0 453
nuclear@0 454 return i;
nuclear@0 455 }
nuclear@0 456
nuclear@0 457 int TCPSocket::Connect(SockAddr* address)
nuclear@0 458 {
nuclear@0 459 int retval;
nuclear@0 460
nuclear@0 461 retval = connect(TheSocket, (struct sockaddr *) &address->Addr6, sizeof(address->Addr6));
nuclear@0 462 if (retval < 0)
nuclear@0 463 {
nuclear@0 464 int errsv = errno;
nuclear@0 465 // EINPROGRESS should not be checked on windows but should
nuclear@0 466 // be checked on POSIX platforms.
nuclear@0 467 if (errsv == EWOULDBLOCK || errsv == EINPROGRESS)
nuclear@0 468 {
nuclear@0 469 IsConnecting = true;
nuclear@0 470 return 0;
nuclear@0 471 }
nuclear@0 472
nuclear@0 473 OVR::LogText( "TCPSocket::Connect failed:Error code - %d\n", errsv );
nuclear@0 474 }
nuclear@0 475
nuclear@0 476 return retval;
nuclear@0 477 }
nuclear@0 478
nuclear@0 479 int TCPSocket::Send(const void* pData, int bytes)
nuclear@0 480 {
nuclear@0 481 if (bytes <= 0)
nuclear@0 482 {
nuclear@0 483 return 0;
nuclear@0 484 }
nuclear@0 485 else
nuclear@0 486 {
nuclear@0 487 return (int)send(TheSocket, (const char*)pData, bytes, 0);
nuclear@0 488 }
nuclear@0 489 }
nuclear@0 490
nuclear@0 491
nuclear@0 492 //// TCPSocketPollState
nuclear@0 493
nuclear@0 494 TCPSocketPollState::TCPSocketPollState()
nuclear@0 495 {
nuclear@0 496 FD_ZERO(&readFD);
nuclear@0 497 FD_ZERO(&exceptionFD);
nuclear@0 498 FD_ZERO(&writeFD);
nuclear@0 499 largestDescriptor = INVALID_SOCKET;
nuclear@0 500 }
nuclear@0 501
nuclear@0 502 bool TCPSocketPollState::IsValid() const
nuclear@0 503 {
nuclear@0 504 return largestDescriptor != INVALID_SOCKET;
nuclear@0 505 }
nuclear@0 506
nuclear@0 507 void TCPSocketPollState::Add(TCPSocket* tcpSocket)
nuclear@0 508 {
nuclear@0 509 if (!tcpSocket)
nuclear@0 510 {
nuclear@0 511 return;
nuclear@0 512 }
nuclear@0 513
nuclear@0 514 SocketHandle handle = tcpSocket->GetSocketHandle();
nuclear@0 515
nuclear@0 516 if (handle == INVALID_SOCKET)
nuclear@0 517 {
nuclear@0 518 return;
nuclear@0 519 }
nuclear@0 520
nuclear@0 521 if (largestDescriptor == INVALID_SOCKET ||
nuclear@0 522 largestDescriptor < handle)
nuclear@0 523 {
nuclear@0 524 largestDescriptor = handle;
nuclear@0 525 }
nuclear@0 526
nuclear@0 527 FD_SET(handle, &readFD);
nuclear@0 528 FD_SET(handle, &exceptionFD);
nuclear@0 529
nuclear@0 530 if (tcpSocket->IsConnecting)
nuclear@0 531 {
nuclear@0 532 FD_SET(handle, &writeFD);
nuclear@0 533 }
nuclear@0 534 }
nuclear@0 535
nuclear@0 536 bool TCPSocketPollState::Poll(long usec, long seconds)
nuclear@0 537 {
nuclear@0 538 timeval tv;
nuclear@0 539 tv.tv_sec = seconds;
nuclear@0 540 tv.tv_usec = (int)usec;
nuclear@0 541
nuclear@0 542 return select(largestDescriptor + 1, &readFD, &writeFD, &exceptionFD, &tv) > 0;
nuclear@0 543 }
nuclear@0 544
nuclear@0 545 void TCPSocketPollState::HandleEvent(TCPSocket* tcpSocket, SocketEvent_TCP* eventHandler)
nuclear@0 546 {
nuclear@0 547 if (!tcpSocket || !eventHandler)
nuclear@0 548 {
nuclear@0 549 return;
nuclear@0 550 }
nuclear@0 551
nuclear@0 552 SocketHandle handle = tcpSocket->GetSocketHandle();
nuclear@0 553
nuclear@0 554 if (tcpSocket->IsConnecting && FD_ISSET(handle, &writeFD))
nuclear@0 555 {
nuclear@0 556 tcpSocket->IsConnecting = false;
nuclear@0 557 eventHandler->TCP_OnConnected(tcpSocket);
nuclear@0 558 }
nuclear@0 559
nuclear@0 560 if (FD_ISSET(handle, &readFD))
nuclear@0 561 {
nuclear@0 562 if (!tcpSocket->IsListenSocket)
nuclear@0 563 {
nuclear@0 564 static const int BUFF_SIZE = 8096;
nuclear@0 565 char data[BUFF_SIZE];
nuclear@0 566
nuclear@0 567 int bytesRead = (int)recv(handle, data, BUFF_SIZE, 0);
nuclear@0 568 if (bytesRead > 0)
nuclear@0 569 {
nuclear@0 570 tcpSocket->OnRecv(eventHandler, (UByte*)data, bytesRead);
nuclear@0 571 }
nuclear@0 572 else // Disconnection event:
nuclear@0 573 {
nuclear@0 574 tcpSocket->IsConnecting = false;
nuclear@0 575 eventHandler->TCP_OnClosed(tcpSocket);
nuclear@0 576 }
nuclear@0 577 }
nuclear@0 578 else
nuclear@0 579 {
nuclear@0 580 struct sockaddr_storage sockAddr;
nuclear@0 581 socklen_t sockAddrSize = sizeof(sockAddr);
nuclear@0 582
nuclear@0 583 SocketHandle newSock = accept(handle, (sockaddr*)&sockAddr, (socklen_t*)&sockAddrSize);
nuclear@0 584 if (newSock > 0)
nuclear@0 585 {
nuclear@0 586 SockAddr sa(&sockAddr);
nuclear@0 587 eventHandler->TCP_OnAccept(tcpSocket, &sa, newSock);
nuclear@0 588 }
nuclear@0 589 }
nuclear@0 590 }
nuclear@0 591
nuclear@0 592 if (FD_ISSET(handle, &exceptionFD))
nuclear@0 593 {
nuclear@0 594 tcpSocket->IsConnecting = false;
nuclear@0 595 eventHandler->TCP_OnClosed(tcpSocket);
nuclear@0 596 }
nuclear@0 597 }
nuclear@0 598
nuclear@0 599
nuclear@0 600 }} // namespace OVR::Net