Files
mcpe/thirdparty/raknet/RakNetSocket2_NativeClient.cpp
iProgramInCpp 9642818a88 * Initial commit.
:)
2023-07-30 22:22:02 +03:00

170 lines
6.0 KiB
C++

/*
* 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