/* * Copyright (c) 2014, Oculus VR, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ #include "EmptyHeader.h" #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS #ifndef RAKNETSOCKET2_NATIVE_CLIENT_CPP #define RAKNETSOCKET2_NATIVE_CLIENT_CPP #if defined(__native_client__) using namespace pp; RNS2BindResult RNS2_NativeClient::Bind( NativeClientBindParameters *bindParameters, const char *file, unsigned int line ) { memcpy(&binding, bindParameters, sizeof(NativeClientBindParameters)); if(Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_PRIVATE_INTERFACE_0_4)) { rns2Socket = ((PPB_UDPSocket_Private_0_4*) Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_PRIVATE_INTERFACE_0_4))->Create(bindParameters->nativeClientInstance); RAKNET_DEBUG_PRINTF("CreateChromeSocket(%d,%s,0x%08x,%d) ==> 0x%08x\n", bindParameters->port, bindParameters->forceHostAddress?bindParameters->forceHostAddress:"(null)",bindParameters->nativeClientInstance,bindParameters->is_ipv6, rns2Socket); // Enable the broadcast feature on the socket (must happen before the // bind call) ((PPB_UDPSocket_Private_0_4*) pp::Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_PRIVATE_INTERFACE_0_4))->SetSocketFeature(rns2Socket, PP_UDPSOCKETFEATURE_BROADCAST, PP_MakeBool(PP_TRUE)); PP_NetAddress_Private client_addr; uint8_t ipv6[16], ipv4[4]; if (bindParameters->forceHostAddress) { unsigned int ipIdx=0; char * pch; pch = strtok ((char*) bindParameters->forceHostAddress,"."); if (bindParameters->is_ipv6) { while (pch != NULL && ipIdx<16) { ipv6[ipIdx++]=atoi(pch); pch = strtok (NULL, "."); } NetAddressPrivate::CreateFromIPv6Address(ipv6,0,bindParameters->port,&client_addr); } else { while (pch != NULL && ipIdx<4) { ipv4[ipIdx++]=atoi(pch); pch = strtok (NULL, "."); } NetAddressPrivate::CreateFromIPv4Address(ipv4,bindParameters->port,&client_addr); } } else { NetAddressPrivate::GetAnyAddress(bindParameters->is_ipv6, &client_addr); NetAddressPrivate::ReplacePort(client_addr, bindParameters->port, &client_addr); } bindState = BS_IN_PROGRESS; RAKNET_DEBUG_PRINTF("attempting to bind to %s\n", NetAddressPrivate::Describe(client_addr, true).c_str()); PP_CompletionCallback cc = PP_MakeCompletionCallback(RNS2_NativeClient::onSocketBound, this); ((PPB_UDPSocket_Private_0_4*) Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_PRIVATE_INTERFACE_0_4))->Bind(rns2Socket, &client_addr, cc); return BR_SUCCESS; } return BR_FAILED_TO_BIND_SOCKET; } void RNS2_NativeClient::SendImmediate(RNS2_SendParameters_NativeClient *sp) { // Assuming data does not have to remain valid until callback called PP_NetAddress_Private client_addr; #if RAKNET_SUPPORT_IPV6==1 NetAddressPrivate::CreateFromIPv6Address(sp->systemAddress.address.addr6.sin6_addr.u.Byte,0,sp->systemAddress.GetPort(),&client_addr); #else NetAddressPrivate::CreateFromIPv4Address((const uint8_t*) &sp->systemAddress.address.addr4.sin_addr,sp->systemAddress.GetPort(),&client_addr); #endif // sp remains in memory until the callback completes PP_CompletionCallback cc = PP_MakeCompletionCallback(onSendTo, sp); ((PPB_UDPSocket_Private_0_4*) Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_PRIVATE_INTERFACE_0_4))->SendTo(sp->socket2->rns2Socket, sp->data, sp->length, &client_addr, cc); } void RNS2_NativeClient::onRecvFrom(void* pData, int32_t dataSize) { RNS2RecvStruct *recvStruct = (RNS2RecvStruct *) pData; RNS2_NativeClient *socket2 = (RNS2_NativeClient *) recvStruct->socket; //any error codes will be given to us in the dataSize value; see pp_errors.h for a list of errors if(dataSize <=0 || !pData ) { // Free data socket2->eventHandler->DeallocRNS2RecvStruct(recvStruct, _FILE_AND_LINE_); // This value indicates failure due to an asynchronous operation being // interrupted. The most common cause of this error code is destroying // a resource that still has a callback pending. All callbacks are // guaranteed to execute, so any callbacks pending on a destroyed // resource will be issued with PP_ERROR_ABORTED. if(dataSize==PP_ERROR_ABORTED) { RAKNET_DEBUG_PRINTF("onRecvFrom error PP_ERROR_ABORTED, killing recvfrom loop\n"); } else { RAKNET_DEBUG_PRINTF("onRecvFrom error %d\n", dataSize); // Reissue call socket2->IssueReceiveCall(); } return; } recvStruct->bytesRead=dataSize; recvStruct->timeRead=RakNet::GetTimeUS(); PP_NetAddress_Private addr; bool ok=false; if(((PPB_UDPSocket_Private_0_4*) Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_PRIVATE_INTERFACE_0_4))->GetRecvFromAddress(socket2->rns2Socket, &addr) == PP_TRUE) { PP_NetAddressFamily_Private family = NetAddressPrivate::GetFamily(addr); if (family == PP_NETADDRESSFAMILY_IPV4) { ok = NetAddressPrivate::GetAddress(addr, &recvStruct->systemAddress.address.addr4.sin_addr, sizeof(in_addr)); } #if RAKNET_SUPPORT_IPV6==1 else { ok = NetAddressPrivate::GetAddress(addr, &recvStruct->systemAddress.address.addr6.sin6_addr, sizeof(in6_addr)); } #endif } if(ok) { recvStruct->systemAddress.SetPortHostOrder(pp::NetAddressPrivate::GetPort(addr)); socket2->binding.eventHandler->OnRNS2Recv(recvStruct); } // Reissue call socket2->IssueReceiveCall(); } void RNS2_NativeClient::IssueReceiveCall(void) { RNS2RecvStruct *recvFromStruct; recvFromStruct=binding.eventHandler->AllocRNS2RecvStruct(_FILE_AND_LINE_); if (recvFromStruct != NULL) { recvFromStruct->socket=this; PP_CompletionCallback cc = PP_MakeCompletionCallback(onRecvFrom, recvFromStruct); ((PPB_UDPSocket_Private_0_4*) Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_PRIVATE_INTERFACE_0_4))->RecvFrom(rns2Socket, recvFromStruct->data, MAXIMUM_MTU_SIZE, cc); } } #endif // defined(__native_client__) #endif // file header #endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS