forked from facebookarchive/RakNet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRakNetSocket2_NativeClient.cpp
169 lines (143 loc) · 6.12 KB
/
RakNetSocket2_NativeClient.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
* 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