mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-17 20:10:23 +03:00
* Initial commit.
:)
This commit is contained in:
467
thirdparty/raknet/RakNetSocket2_WindowsStore8.cpp
vendored
Normal file
467
thirdparty/raknet/RakNetSocket2_WindowsStore8.cpp
vendored
Normal file
@@ -0,0 +1,467 @@
|
||||
/*
|
||||
* 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_WINDOWS_STORE_8
|
||||
#define RAKNETSOCKET2_WINDOWS_STORE_8
|
||||
|
||||
#if defined(WINDOWS_STORE_RT)
|
||||
|
||||
#include <ppltasks.h>
|
||||
#include <collection.h>
|
||||
#include "RakString.h"
|
||||
|
||||
using namespace Concurrency;
|
||||
using namespace Platform;
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Networking;
|
||||
using namespace Windows::Networking::Sockets;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Navigation;
|
||||
using namespace Windows::Storage::Streams;
|
||||
//using namespace Platform::Collections;
|
||||
//using namespace Windows::Foundation::Collections;
|
||||
|
||||
namespace RakNet
|
||||
{
|
||||
|
||||
public ref class OutputStreamAndDataWriter sealed
|
||||
{
|
||||
public:
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/hh755807.aspx
|
||||
property IOutputStream ^outputStream;
|
||||
/*
|
||||
{
|
||||
IOutputStream ^ get() {return outputStream;}
|
||||
void set(IOutputStream ^ value) {outputStream = value;}
|
||||
}
|
||||
*/
|
||||
property DataWriter ^dataWriter;
|
||||
/*
|
||||
{
|
||||
DataWriter ^ get() {return dataWriter;}
|
||||
void set(DataWriter ^ value) {dataWriter = value;}
|
||||
}
|
||||
*/
|
||||
private:
|
||||
};
|
||||
|
||||
public ref class ListenerContext sealed
|
||||
{
|
||||
public:
|
||||
ListenerContext(Windows::Networking::Sockets::DatagramSocket^ listener);
|
||||
void OnMessage(Windows::Networking::Sockets::DatagramSocket^ socket, Windows::Networking::Sockets::DatagramSocketMessageReceivedEventArgs^ eventArguments);
|
||||
OutputStreamAndDataWriter ^GetOutputStreamAndDataWriter(uint64_t s_addr);
|
||||
|
||||
private:
|
||||
~ListenerContext();
|
||||
// CRITICAL_SECTION lock;
|
||||
SimpleMutex outputStreamMapMutex;
|
||||
Windows::Networking::Sockets::DatagramSocket^ listener;
|
||||
//Windows::Storage::Streams::IOutputStream^ outputStream;
|
||||
//Windows::Networking::HostName^ hostName;
|
||||
//Platform::String^ port;
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/hh700103.aspx
|
||||
Platform::Collections::Map<uint64_t,OutputStreamAndDataWriter^>^ outputStreamMap;
|
||||
|
||||
void EchoMessage(Windows::Networking::Sockets::DatagramSocketMessageReceivedEventArgs^ eventArguments);
|
||||
};
|
||||
}
|
||||
|
||||
using namespace RakNet;
|
||||
|
||||
ListenerContext::ListenerContext(Windows::Networking::Sockets::DatagramSocket^ listener)
|
||||
{
|
||||
this->listener = listener;
|
||||
// InitializeCriticalSectionEx(&lock, 0, 0);
|
||||
outputStreamMap = ref new Platform::Collections::Map<uint64_t,OutputStreamAndDataWriter^>();
|
||||
}
|
||||
|
||||
ListenerContext::~ListenerContext()
|
||||
{
|
||||
// The listener can be closed in two ways:
|
||||
// - explicit: by using delete operator (the listener is closed even if there are outstanding references to it).
|
||||
// - implicit: by removing last reference to it (i.e. falling out-of-scope).
|
||||
// In this case this is the last reference to the listener so both will yield the same result.
|
||||
delete listener;
|
||||
listener = nullptr;
|
||||
|
||||
// DeleteCriticalSection(&lock);
|
||||
}
|
||||
|
||||
OutputStreamAndDataWriter ^ListenerContext::GetOutputStreamAndDataWriter(uint64_t s_addr)
|
||||
{
|
||||
outputStreamMapMutex.Lock();
|
||||
if (outputStreamMap->HasKey(s_addr))
|
||||
{
|
||||
OutputStreamAndDataWriter ^o = outputStreamMap->Lookup(s_addr);
|
||||
outputStreamMapMutex.Unlock();
|
||||
return o;
|
||||
}
|
||||
outputStreamMapMutex.Unlock();
|
||||
uint16_t port = s_addr & 0xFFFF;
|
||||
uint32_t addr = (uint32_t) (s_addr >> 32);
|
||||
//addr = ntohl(addr);
|
||||
char buf[64];
|
||||
unsigned char *ucp = (unsigned char *)&addr;
|
||||
sprintf(buf, "%d.%d.%d.%d",
|
||||
ucp[0] & 0xff,
|
||||
ucp[1] & 0xff,
|
||||
ucp[2] & 0xff,
|
||||
ucp[3] & 0xff);
|
||||
char portStr[32];
|
||||
_itoa(port, portStr, 10);
|
||||
|
||||
RakNet::RakString rs1(buf);
|
||||
WCHAR *w_char1 = rs1.ToWideChar();
|
||||
HostName ^hostName = ref new HostName(ref new Platform::String(w_char1));
|
||||
RakNet::RakString rs2(portStr);
|
||||
WCHAR *w_char2 = rs2.ToWideChar();
|
||||
task< IOutputStream^ > op(listener->GetOutputStreamAsync(hostName, ref new Platform::String(w_char2)));
|
||||
op.wait();
|
||||
OutputStreamAndDataWriter ^outputStreamAndDataWriter = ref new OutputStreamAndDataWriter;
|
||||
outputStreamAndDataWriter->outputStream = op.get();
|
||||
outputStreamAndDataWriter->dataWriter = ref new DataWriter(outputStreamAndDataWriter->outputStream);
|
||||
|
||||
rs1.DeallocWideChar(w_char1);
|
||||
rs2.DeallocWideChar(w_char2);
|
||||
|
||||
outputStreamMapMutex.Lock();
|
||||
if (outputStreamMap->HasKey(s_addr)==false)
|
||||
{
|
||||
outputStreamMap->Insert(s_addr, outputStreamAndDataWriter);
|
||||
outputStreamMapMutex.Unlock();
|
||||
return outputStreamAndDataWriter;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just use the one that was inserted from another thread
|
||||
OutputStreamAndDataWriter ^o = outputStreamMap->Lookup(s_addr);
|
||||
outputStreamMapMutex.Unlock();
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
void ListenerContext::OnMessage(Windows::Networking::Sockets::DatagramSocket^ socket, Windows::Networking::Sockets::DatagramSocketMessageReceivedEventArgs^ eventArguments)
|
||||
{
|
||||
HostName ^remoteHost=eventArguments->RemoteAddress;
|
||||
eventArguments->RemoteAddress->DisplayName;
|
||||
eventArguments->RemotePort;
|
||||
|
||||
RNS2_WindowsStore8 *rns2 = RNS2_WindowsStore8::GetRNS2FromDatagramSocket(socket);
|
||||
if (rns2==0)
|
||||
return;
|
||||
|
||||
//auto platformBuffer = ref new Platform::Array<BYTE>((unsigned char*) sendParameters->data, (UINT)sendParameters->length);
|
||||
RNS2EventHandler *eventHandler = rns2->GetEventHandler();
|
||||
RNS2RecvStruct *recvFromStruct = eventHandler->AllocRNS2RecvStruct(_FILE_AND_LINE_);
|
||||
|
||||
// http://stackoverflow.com/questions/11853838/getting-an-array-of-bytes-out-of-windowsstoragestreamsibuffer
|
||||
IBuffer ^uselessBuffer = eventArguments->GetDataReader()->DetachBuffer();
|
||||
Windows::Storage::Streams::DataReader^ uselessReader = Windows::Storage::Streams::DataReader::FromBuffer(uselessBuffer);
|
||||
Platform::Array<unsigned char>^ managedBytes = ref new Platform::Array<unsigned char>(uselessBuffer->Length);
|
||||
uselessReader->ReadBytes( managedBytes );
|
||||
for(unsigned int i = 0; i < uselessBuffer->Length; i++)
|
||||
recvFromStruct->data[i] = managedBytes[i];
|
||||
recvFromStruct->bytesRead = uselessBuffer->Length;
|
||||
char ip[64];
|
||||
RakString rs2;
|
||||
rs2.FromWideChar(eventArguments->RemoteAddress->DisplayName->Data());
|
||||
strcpy(ip, rs2.C_String());
|
||||
recvFromStruct->systemAddress.address.addr4.sin_addr.s_addr = RNS2_WindowsStore8::WinRTInet_Addr(ip);
|
||||
char portStr[64];
|
||||
rs2.FromWideChar(eventArguments->RemotePort->Data());
|
||||
strcpy(portStr, rs2.C_String());
|
||||
recvFromStruct->systemAddress.SetPortHostOrder(atoi(portStr));
|
||||
recvFromStruct->timeRead=RakNet::GetTimeUS();
|
||||
recvFromStruct->socket = rns2;
|
||||
eventHandler->OnRNS2Recv(recvFromStruct);
|
||||
|
||||
/*
|
||||
if (outputStream != nullptr)
|
||||
{
|
||||
EchoMessage(eventArguments);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// We do not have an output stream yet so create one.
|
||||
task<IOutputStream^>(socket->GetOutputStreamAsync(eventArguments->RemoteAddress, eventArguments->RemotePort)).then([this, socket, eventArguments] (IOutputStream^ stream)
|
||||
{
|
||||
// It might happen that the OnMessage was invoked more than once before the GetOutputStreamAsync completed.
|
||||
// In this case we will end up with multiple streams - make sure we have just one of it.
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
if (outputStream == nullptr)
|
||||
{
|
||||
outputStream = stream;
|
||||
hostName = eventArguments->RemoteAddress;
|
||||
port = eventArguments->RemotePort;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
EchoMessage(eventArguments);
|
||||
}).then([this, socket, eventArguments] (task<void> previousTask)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try getting all exceptions from the continuation chain above this point.
|
||||
previousTask.get();
|
||||
}
|
||||
catch (Exception^ exception)
|
||||
{
|
||||
// NotifyUserFromAsyncThread("Getting an output stream failed with error: " + exception->Message, NotifyType::ErrorMessage);
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
void ListenerContext::EchoMessage(DatagramSocketMessageReceivedEventArgs^ eventArguments)
|
||||
{
|
||||
}
|
||||
RakNet::DataStructures::List<RNS2_WindowsStore8*> RNS2_WindowsStore8::rns2List;
|
||||
SimpleMutex RNS2_WindowsStore8::rns2ListMutex;
|
||||
RNS2_WindowsStore8::RNS2_WindowsStore8()
|
||||
{
|
||||
rns2ListMutex.Lock();
|
||||
rns2List.Insert(this, _FILE_AND_LINE_);
|
||||
rns2ListMutex.Unlock();
|
||||
}
|
||||
RNS2_WindowsStore8::~RNS2_WindowsStore8()
|
||||
{
|
||||
unsigned int i;
|
||||
rns2ListMutex.Lock();
|
||||
for (i=0; i < rns2List.Size(); i++)
|
||||
{
|
||||
if (rns2List[i]==this)
|
||||
{
|
||||
rns2List.RemoveAtIndexFast(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rns2ListMutex.Unlock();
|
||||
}
|
||||
RNS2_WindowsStore8 *RNS2_WindowsStore8::GetRNS2FromDatagramSocket(Windows::Networking::Sockets::DatagramSocket^ s)
|
||||
{
|
||||
RNS2_WindowsStore8 *out=0;
|
||||
unsigned int i;
|
||||
rns2ListMutex.Lock();
|
||||
for (i=0; i < rns2List.Size(); i++)
|
||||
{
|
||||
if (rns2List[i]->listener==s)
|
||||
{
|
||||
out=rns2List[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
rns2ListMutex.Unlock();
|
||||
return out;
|
||||
}
|
||||
RNS2BindResult RNS2_WindowsStore8::Bind( Platform::String ^localServiceName ) {
|
||||
|
||||
listener = ref new DatagramSocket();
|
||||
listenerContext = ref new ListenerContext(listener);
|
||||
listener->MessageReceived += ref new TypedEventHandler<DatagramSocket^, DatagramSocketMessageReceivedEventArgs^>(listenerContext, &ListenerContext::OnMessage);
|
||||
// http://msdn.microsoft.com/en-us/library/dd492427.aspx
|
||||
task<void> bindOp(listener->BindServiceNameAsync(localServiceName));
|
||||
try
|
||||
{
|
||||
bindOp.wait();
|
||||
}
|
||||
catch (Exception^ exception)
|
||||
{
|
||||
return BR_FAILED_TO_BIND_SOCKET;
|
||||
}
|
||||
|
||||
return BR_SUCCESS;
|
||||
}
|
||||
void RNS2_WindowsStore8::GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] ) {RakAssert("GetMyIP Unsupported" && 0);}
|
||||
RNS2SendResult RNS2_WindowsStore8::Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line ) {
|
||||
uint64_t s_addr = sendParameters->systemAddress.address.addr4.sin_addr.s_addr;
|
||||
s_addr <<=32;
|
||||
s_addr |= sendParameters->systemAddress.debugPort;
|
||||
OutputStreamAndDataWriter ^outputStreamAndDataWriter = listenerContext->GetOutputStreamAndDataWriter(s_addr);
|
||||
// DataWriter ^dataWriter = ref new DataWriter(outputStream);
|
||||
|
||||
auto platformBuffer = ref new Platform::Array<BYTE>((unsigned char*) sendParameters->data, (UINT)sendParameters->length);
|
||||
outputStreamAndDataWriter->dataWriter->WriteBytes(platformBuffer);
|
||||
|
||||
|
||||
// Write the locally buffered data to the network. Please note that write operation will succeed
|
||||
// even if the server is not listening.
|
||||
task<unsigned int>(outputStreamAndDataWriter->dataWriter->StoreAsync()).then([&] (task<unsigned int> writeTask)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try getting an excpetion.
|
||||
// writeTask.get();
|
||||
// SendOutput->Style = dynamic_cast<Windows::UI::Xaml::Style^>(rootPage->Resources->Lookup("StatusStyle"));
|
||||
// SendOutput->Text = "\"" + stringToSend + "\" sent successfully";
|
||||
}
|
||||
catch (Exception^ exception)
|
||||
{
|
||||
// rootPage->NotifyUser("Send failed with error: " + exception->Message, NotifyType::ErrorMessage);
|
||||
OutputDebugStringW(exception->Message->Data());
|
||||
}
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
void RNS2_WindowsStore8::DomainNameToIP( const char *domainName, char ip[65] ) {
|
||||
ip[0]=0;
|
||||
|
||||
// RakAssert("DomainNameToIP Unsupported" && 0);
|
||||
|
||||
// std::string s_str = std::string(domainName);
|
||||
// std::wstring wid_str = std::wstring(s_str.begin(), s_str.end());
|
||||
// const wchar_t* w_char = wid_str.c_str();
|
||||
|
||||
RakNet::RakString rs(domainName);
|
||||
WCHAR *w_char = rs.ToWideChar();
|
||||
|
||||
// DatagramSocket ^listener = ref new DatagramSocket();
|
||||
|
||||
|
||||
// task<void> bindOp(listener->BindServiceNameAsync(ref new Platform::String()));
|
||||
//bindOp.wait();
|
||||
|
||||
HostName ^hostName = ref new HostName(ref new Platform::String(w_char));
|
||||
//HostName ^hostName = ref new HostName(ref new Platform::String(L"microsoft.com"));
|
||||
//HostName ^hostName = ref new HostName(ref new Platform::String(L"127.0.0.1"));
|
||||
//task< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ > op(listener->GetEndpointPairsAsync(hostName, L"42"));
|
||||
//listener->GetEndpointPairsAsync(hostName, L"42");
|
||||
// task< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ > op(DatagramSocket::GetEndpointPairsAsync(hostName, L"42"));
|
||||
|
||||
IAsyncOperation<Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^>^ op = DatagramSocket::GetEndpointPairsAsync(hostName, L"0");
|
||||
|
||||
bool completed=false;
|
||||
op->Completed = ref new AsyncOperationCompletedHandler< Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^ >(
|
||||
[&] (
|
||||
IAsyncOperation< Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^>^ result,
|
||||
AsyncStatus status
|
||||
) {
|
||||
Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^ result2 = result->GetResults();
|
||||
if (result2->Size>0)
|
||||
{
|
||||
Platform::String ^name = result2->GetAt(0)->RemoteHostName->DisplayName;
|
||||
RakString rs2;
|
||||
rs2.FromWideChar(name->Data());
|
||||
strcpy(ip, rs2.C_String());
|
||||
}
|
||||
else
|
||||
{
|
||||
ip[0]=0;
|
||||
}
|
||||
|
||||
result->Close();
|
||||
completed=true;
|
||||
}
|
||||
) ;
|
||||
|
||||
while (!completed)
|
||||
RakSleep(0);
|
||||
/*
|
||||
op->Completed = ref new AsyncOperationCompletedHandler< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ >(
|
||||
[](IAsyncOperation< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ >^ operation)
|
||||
{
|
||||
operation->GetResults();
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
// RakSleep(10000);
|
||||
/*
|
||||
try
|
||||
{
|
||||
op.wait();
|
||||
}
|
||||
catch (Exception^ exception)
|
||||
{
|
||||
int a=5;
|
||||
}
|
||||
Windows::Foundation::Collections::IVectorView<EndpointPair^>^view = op.get();
|
||||
if (view->Size>0)
|
||||
{
|
||||
Platform::String ^name = view->GetAt(0)->RemoteHostName->DisplayName;
|
||||
RakString rs2;
|
||||
rs2.FromWideChar(name->Data());
|
||||
strcpy(ip, rs2.C_String());
|
||||
}
|
||||
else
|
||||
{
|
||||
ip[0]=0;
|
||||
}
|
||||
*/
|
||||
|
||||
rs.DeallocWideChar(w_char);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int RNS2_WindowsStore8::WinRTInet_Addr(const char *str) {
|
||||
int parts[4];
|
||||
unsigned char curVal;
|
||||
|
||||
const char *strIndex=str;
|
||||
int partsIndex;
|
||||
|
||||
for (partsIndex=0; partsIndex < 4; partsIndex++)
|
||||
parts[partsIndex]=0;
|
||||
|
||||
partsIndex=0;
|
||||
curVal=0;
|
||||
while (partsIndex < 4)
|
||||
{
|
||||
if (*strIndex < '0' || *strIndex > '9')
|
||||
{
|
||||
parts[partsIndex]=curVal;
|
||||
partsIndex++;
|
||||
curVal=0;
|
||||
|
||||
if (*strIndex==0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
curVal*=10;
|
||||
curVal+=*strIndex-'0';
|
||||
}
|
||||
strIndex++;
|
||||
}
|
||||
|
||||
return htonl((parts[0]<<24) | (parts[1]<<16) | (parts[2]<<8) | (parts[3]<<0) );
|
||||
}
|
||||
|
||||
int RNS2_WindowsStore8::WinRTSetSockOpt(Windows::Networking::Sockets::DatagramSocket ^s,
|
||||
int level,
|
||||
int optname,
|
||||
const char * optval,
|
||||
socklen_t optlen) {RakAssert("WinRTSetSockOpt Unsupported" && 0); return 0;}
|
||||
|
||||
int RNS2_WindowsStore8::WinRTIOCTLSocket(Windows::Networking::Sockets::DatagramSocket ^s,
|
||||
long cmd,
|
||||
unsigned long *argp) {RakAssert("WinRTIOCTLSocket Unsupported" && 0); return 0;}
|
||||
|
||||
int RNS2_WindowsStore8::WinRTGetSockName(Windows::Networking::Sockets::DatagramSocket ^s,
|
||||
struct sockaddr *name,
|
||||
socklen_t* namelen) {RakAssert("WinRTGetSockName Unsupported" && 0); return 0;}
|
||||
|
||||
#endif // WINDOWS_STORE_RT
|
||||
|
||||
#endif // file header
|
||||
|
||||
#endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
|
||||
Reference in New Issue
Block a user