ovr_sdk

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