RakNetSocket2_WindowsStore8.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "EmptyHeader.h"
  11. #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
  12. #ifndef RAKNETSOCKET2_WINDOWS_STORE_8
  13. #define RAKNETSOCKET2_WINDOWS_STORE_8
  14. #if defined(WINDOWS_STORE_RT)
  15. #include <ppltasks.h>
  16. #include <collection.h>
  17. #include "RakString.h"
  18. using namespace Concurrency;
  19. using namespace Platform;
  20. using namespace Windows::ApplicationModel::Core;
  21. using namespace Windows::Foundation;
  22. using namespace Windows::Networking;
  23. using namespace Windows::Networking::Sockets;
  24. using namespace Windows::UI::Core;
  25. using namespace Windows::UI::Xaml;
  26. using namespace Windows::UI::Xaml::Controls;
  27. using namespace Windows::UI::Xaml::Navigation;
  28. using namespace Windows::Storage::Streams;
  29. //using namespace Platform::Collections;
  30. //using namespace Windows::Foundation::Collections;
  31. namespace RakNet
  32. {
  33. public ref class OutputStreamAndDataWriter sealed
  34. {
  35. public:
  36. // http://msdn.microsoft.com/en-us/library/windows/apps/hh755807.aspx
  37. property IOutputStream ^outputStream;
  38. /*
  39. {
  40. IOutputStream ^ get() {return outputStream;}
  41. void set(IOutputStream ^ value) {outputStream = value;}
  42. }
  43. */
  44. property DataWriter ^dataWriter;
  45. /*
  46. {
  47. DataWriter ^ get() {return dataWriter;}
  48. void set(DataWriter ^ value) {dataWriter = value;}
  49. }
  50. */
  51. private:
  52. };
  53. public ref class ListenerContext sealed
  54. {
  55. public:
  56. ListenerContext(Windows::Networking::Sockets::DatagramSocket^ listener);
  57. void OnMessage(Windows::Networking::Sockets::DatagramSocket^ socket, Windows::Networking::Sockets::DatagramSocketMessageReceivedEventArgs^ eventArguments);
  58. OutputStreamAndDataWriter ^GetOutputStreamAndDataWriter(uint64_t s_addr);
  59. private:
  60. ~ListenerContext();
  61. // CRITICAL_SECTION lock;
  62. SimpleMutex outputStreamMapMutex;
  63. Windows::Networking::Sockets::DatagramSocket^ listener;
  64. //Windows::Storage::Streams::IOutputStream^ outputStream;
  65. //Windows::Networking::HostName^ hostName;
  66. //Platform::String^ port;
  67. // http://msdn.microsoft.com/en-us/library/windows/apps/hh700103.aspx
  68. Platform::Collections::Map<uint64_t,OutputStreamAndDataWriter^>^ outputStreamMap;
  69. void EchoMessage(Windows::Networking::Sockets::DatagramSocketMessageReceivedEventArgs^ eventArguments);
  70. };
  71. }
  72. using namespace RakNet;
  73. ListenerContext::ListenerContext(Windows::Networking::Sockets::DatagramSocket^ listener)
  74. {
  75. this->listener = listener;
  76. // InitializeCriticalSectionEx(&lock, 0, 0);
  77. outputStreamMap = ref new Platform::Collections::Map<uint64_t,OutputStreamAndDataWriter^>();
  78. }
  79. ListenerContext::~ListenerContext()
  80. {
  81. // The listener can be closed in two ways:
  82. // - explicit: by using delete operator (the listener is closed even if there are outstanding references to it).
  83. // - implicit: by removing last reference to it (i.e. falling out-of-scope).
  84. // In this case this is the last reference to the listener so both will yield the same result.
  85. delete listener;
  86. listener = nullptr;
  87. // DeleteCriticalSection(&lock);
  88. }
  89. OutputStreamAndDataWriter ^ListenerContext::GetOutputStreamAndDataWriter(uint64_t s_addr)
  90. {
  91. outputStreamMapMutex.Lock();
  92. if (outputStreamMap->HasKey(s_addr))
  93. {
  94. OutputStreamAndDataWriter ^o = outputStreamMap->Lookup(s_addr);
  95. outputStreamMapMutex.Unlock();
  96. return o;
  97. }
  98. outputStreamMapMutex.Unlock();
  99. uint16_t port = s_addr & 0xFFFF;
  100. uint32_t addr = (uint32_t) (s_addr >> 32);
  101. //addr = ntohl(addr);
  102. char buf[64];
  103. unsigned char *ucp = (unsigned char *)&addr;
  104. sprintf(buf, "%d.%d.%d.%d",
  105. ucp[0] & 0xff,
  106. ucp[1] & 0xff,
  107. ucp[2] & 0xff,
  108. ucp[3] & 0xff);
  109. char portStr[32];
  110. _itoa(port, portStr, 10);
  111. RakNet::RakString rs1(buf);
  112. WCHAR *w_char1 = rs1.ToWideChar();
  113. HostName ^hostName = ref new HostName(ref new Platform::String(w_char1));
  114. RakNet::RakString rs2(portStr);
  115. WCHAR *w_char2 = rs2.ToWideChar();
  116. task< IOutputStream^ > op(listener->GetOutputStreamAsync(hostName, ref new Platform::String(w_char2)));
  117. op.wait();
  118. OutputStreamAndDataWriter ^outputStreamAndDataWriter = ref new OutputStreamAndDataWriter;
  119. outputStreamAndDataWriter->outputStream = op.get();
  120. outputStreamAndDataWriter->dataWriter = ref new DataWriter(outputStreamAndDataWriter->outputStream);
  121. rs1.DeallocWideChar(w_char1);
  122. rs2.DeallocWideChar(w_char2);
  123. outputStreamMapMutex.Lock();
  124. if (outputStreamMap->HasKey(s_addr)==false)
  125. {
  126. outputStreamMap->Insert(s_addr, outputStreamAndDataWriter);
  127. outputStreamMapMutex.Unlock();
  128. return outputStreamAndDataWriter;
  129. }
  130. else
  131. {
  132. // Just use the one that was inserted from another thread
  133. OutputStreamAndDataWriter ^o = outputStreamMap->Lookup(s_addr);
  134. outputStreamMapMutex.Unlock();
  135. return o;
  136. }
  137. }
  138. void ListenerContext::OnMessage(Windows::Networking::Sockets::DatagramSocket^ socket, Windows::Networking::Sockets::DatagramSocketMessageReceivedEventArgs^ eventArguments)
  139. {
  140. HostName ^remoteHost=eventArguments->RemoteAddress;
  141. eventArguments->RemoteAddress->DisplayName;
  142. eventArguments->RemotePort;
  143. RNS2_WindowsStore8 *rns2 = RNS2_WindowsStore8::GetRNS2FromDatagramSocket(socket);
  144. if (rns2==0)
  145. return;
  146. //auto platformBuffer = ref new Platform::Array<BYTE>((unsigned char*) sendParameters->data, (UINT)sendParameters->length);
  147. RNS2EventHandler *eventHandler = rns2->GetEventHandler();
  148. RNS2RecvStruct *recvFromStruct = eventHandler->AllocRNS2RecvStruct(_FILE_AND_LINE_);
  149. // http://stackoverflow.com/questions/11853838/getting-an-array-of-bytes-out-of-windowsstoragestreamsibuffer
  150. IBuffer ^uselessBuffer = eventArguments->GetDataReader()->DetachBuffer();
  151. Windows::Storage::Streams::DataReader^ uselessReader = Windows::Storage::Streams::DataReader::FromBuffer(uselessBuffer);
  152. Platform::Array<unsigned char>^ managedBytes = ref new Platform::Array<unsigned char>(uselessBuffer->Length);
  153. uselessReader->ReadBytes( managedBytes );
  154. for(unsigned int i = 0; i < uselessBuffer->Length; i++)
  155. recvFromStruct->data[i] = managedBytes[i];
  156. recvFromStruct->bytesRead = uselessBuffer->Length;
  157. char ip[64];
  158. RakString rs2;
  159. rs2.FromWideChar(eventArguments->RemoteAddress->DisplayName->Data());
  160. strcpy(ip, rs2.C_String());
  161. recvFromStruct->systemAddress.address.addr4.sin_addr.s_addr = RNS2_WindowsStore8::WinRTInet_Addr(ip);
  162. char portStr[64];
  163. rs2.FromWideChar(eventArguments->RemotePort->Data());
  164. strcpy(portStr, rs2.C_String());
  165. recvFromStruct->systemAddress.SetPortHostOrder(atoi(portStr));
  166. recvFromStruct->timeRead=RakNet::GetTimeUS();
  167. recvFromStruct->socket = rns2;
  168. eventHandler->OnRNS2Recv(recvFromStruct);
  169. /*
  170. if (outputStream != nullptr)
  171. {
  172. EchoMessage(eventArguments);
  173. return;
  174. }
  175. // We do not have an output stream yet so create one.
  176. task<IOutputStream^>(socket->GetOutputStreamAsync(eventArguments->RemoteAddress, eventArguments->RemotePort)).then([this, socket, eventArguments] (IOutputStream^ stream)
  177. {
  178. // It might happen that the OnMessage was invoked more than once before the GetOutputStreamAsync completed.
  179. // In this case we will end up with multiple streams - make sure we have just one of it.
  180. EnterCriticalSection(&lock);
  181. if (outputStream == nullptr)
  182. {
  183. outputStream = stream;
  184. hostName = eventArguments->RemoteAddress;
  185. port = eventArguments->RemotePort;
  186. }
  187. LeaveCriticalSection(&lock);
  188. EchoMessage(eventArguments);
  189. }).then([this, socket, eventArguments] (task<void> previousTask)
  190. {
  191. try
  192. {
  193. // Try getting all exceptions from the continuation chain above this point.
  194. previousTask.get();
  195. }
  196. catch (Exception^ exception)
  197. {
  198. // NotifyUserFromAsyncThread("Getting an output stream failed with error: " + exception->Message, NotifyType::ErrorMessage);
  199. }
  200. });
  201. */
  202. }
  203. void ListenerContext::EchoMessage(DatagramSocketMessageReceivedEventArgs^ eventArguments)
  204. {
  205. }
  206. RakNet::DataStructures::List<RNS2_WindowsStore8*> RNS2_WindowsStore8::rns2List;
  207. SimpleMutex RNS2_WindowsStore8::rns2ListMutex;
  208. RNS2_WindowsStore8::RNS2_WindowsStore8()
  209. {
  210. rns2ListMutex.Lock();
  211. rns2List.Insert(this, _FILE_AND_LINE_);
  212. rns2ListMutex.Unlock();
  213. }
  214. RNS2_WindowsStore8::~RNS2_WindowsStore8()
  215. {
  216. unsigned int i;
  217. rns2ListMutex.Lock();
  218. for (i=0; i < rns2List.Size(); i++)
  219. {
  220. if (rns2List[i]==this)
  221. {
  222. rns2List.RemoveAtIndexFast(i);
  223. break;
  224. }
  225. }
  226. rns2ListMutex.Unlock();
  227. }
  228. RNS2_WindowsStore8 *RNS2_WindowsStore8::GetRNS2FromDatagramSocket(Windows::Networking::Sockets::DatagramSocket^ s)
  229. {
  230. RNS2_WindowsStore8 *out=0;
  231. unsigned int i;
  232. rns2ListMutex.Lock();
  233. for (i=0; i < rns2List.Size(); i++)
  234. {
  235. if (rns2List[i]->listener==s)
  236. {
  237. out=rns2List[i];
  238. break;
  239. }
  240. }
  241. rns2ListMutex.Unlock();
  242. return out;
  243. }
  244. RNS2BindResult RNS2_WindowsStore8::Bind( Platform::String ^localServiceName ) {
  245. listener = ref new DatagramSocket();
  246. listenerContext = ref new ListenerContext(listener);
  247. listener->MessageReceived += ref new TypedEventHandler<DatagramSocket^, DatagramSocketMessageReceivedEventArgs^>(listenerContext, &ListenerContext::OnMessage);
  248. // http://msdn.microsoft.com/en-us/library/dd492427.aspx
  249. task<void> bindOp(listener->BindServiceNameAsync(localServiceName));
  250. try
  251. {
  252. bindOp.wait();
  253. }
  254. catch (Exception^ exception)
  255. {
  256. return BR_FAILED_TO_BIND_SOCKET;
  257. }
  258. return BR_SUCCESS;
  259. }
  260. void RNS2_WindowsStore8::GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] ) {RakAssert("GetMyIP Unsupported" && 0);}
  261. RNS2SendResult RNS2_WindowsStore8::Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line ) {
  262. uint64_t s_addr = sendParameters->systemAddress.address.addr4.sin_addr.s_addr;
  263. s_addr <<=32;
  264. s_addr |= sendParameters->systemAddress.debugPort;
  265. OutputStreamAndDataWriter ^outputStreamAndDataWriter = listenerContext->GetOutputStreamAndDataWriter(s_addr);
  266. // DataWriter ^dataWriter = ref new DataWriter(outputStream);
  267. auto platformBuffer = ref new Platform::Array<BYTE>((unsigned char*) sendParameters->data, (UINT)sendParameters->length);
  268. outputStreamAndDataWriter->dataWriter->WriteBytes(platformBuffer);
  269. // Write the locally buffered data to the network. Please note that write operation will succeed
  270. // even if the server is not listening.
  271. task<unsigned int>(outputStreamAndDataWriter->dataWriter->StoreAsync()).then([&] (task<unsigned int> writeTask)
  272. {
  273. try
  274. {
  275. // Try getting an excpetion.
  276. // writeTask.get();
  277. // SendOutput->Style = dynamic_cast<Windows::UI::Xaml::Style^>(rootPage->Resources->Lookup("StatusStyle"));
  278. // SendOutput->Text = "\"" + stringToSend + "\" sent successfully";
  279. }
  280. catch (Exception^ exception)
  281. {
  282. // rootPage->NotifyUser("Send failed with error: " + exception->Message, NotifyType::ErrorMessage);
  283. OutputDebugStringW(exception->Message->Data());
  284. }
  285. });
  286. return 0;
  287. }
  288. void RNS2_WindowsStore8::DomainNameToIP( const char *domainName, char ip[65] ) {
  289. ip[0]=0;
  290. // RakAssert("DomainNameToIP Unsupported" && 0);
  291. // std::string s_str = std::string(domainName);
  292. // std::wstring wid_str = std::wstring(s_str.begin(), s_str.end());
  293. // const wchar_t* w_char = wid_str.c_str();
  294. RakNet::RakString rs(domainName);
  295. WCHAR *w_char = rs.ToWideChar();
  296. // DatagramSocket ^listener = ref new DatagramSocket();
  297. // task<void> bindOp(listener->BindServiceNameAsync(ref new Platform::String()));
  298. //bindOp.wait();
  299. HostName ^hostName = ref new HostName(ref new Platform::String(w_char));
  300. //HostName ^hostName = ref new HostName(ref new Platform::String(L"microsoft.com"));
  301. //HostName ^hostName = ref new HostName(ref new Platform::String(L"127.0.0.1"));
  302. //task< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ > op(listener->GetEndpointPairsAsync(hostName, L"42"));
  303. //listener->GetEndpointPairsAsync(hostName, L"42");
  304. // task< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ > op(DatagramSocket::GetEndpointPairsAsync(hostName, L"42"));
  305. IAsyncOperation<Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^>^ op = DatagramSocket::GetEndpointPairsAsync(hostName, L"0");
  306. bool completed=false;
  307. op->Completed = ref new AsyncOperationCompletedHandler< Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^ >(
  308. [&] (
  309. IAsyncOperation< Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^>^ result,
  310. AsyncStatus status
  311. ) {
  312. Windows::Foundation::Collections::IVectorView<Windows::Networking::EndpointPair^>^ result2 = result->GetResults();
  313. if (result2->Size>0)
  314. {
  315. Platform::String ^name = result2->GetAt(0)->RemoteHostName->DisplayName;
  316. RakString rs2;
  317. rs2.FromWideChar(name->Data());
  318. strcpy(ip, rs2.C_String());
  319. }
  320. else
  321. {
  322. ip[0]=0;
  323. }
  324. result->Close();
  325. completed=true;
  326. }
  327. ) ;
  328. while (!completed)
  329. RakSleep(0);
  330. /*
  331. op->Completed = ref new AsyncOperationCompletedHandler< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ >(
  332. [](IAsyncOperation< Windows::Foundation::Collections::IVectorView<EndpointPair^>^ >^ operation)
  333. {
  334. operation->GetResults();
  335. });
  336. */
  337. // RakSleep(10000);
  338. /*
  339. try
  340. {
  341. op.wait();
  342. }
  343. catch (Exception^ exception)
  344. {
  345. int a=5;
  346. }
  347. Windows::Foundation::Collections::IVectorView<EndpointPair^>^view = op.get();
  348. if (view->Size>0)
  349. {
  350. Platform::String ^name = view->GetAt(0)->RemoteHostName->DisplayName;
  351. RakString rs2;
  352. rs2.FromWideChar(name->Data());
  353. strcpy(ip, rs2.C_String());
  354. }
  355. else
  356. {
  357. ip[0]=0;
  358. }
  359. */
  360. rs.DeallocWideChar(w_char);
  361. }
  362. int RNS2_WindowsStore8::WinRTInet_Addr(const char *str) {
  363. int parts[4];
  364. unsigned char curVal;
  365. const char *strIndex=str;
  366. int partsIndex;
  367. for (partsIndex=0; partsIndex < 4; partsIndex++)
  368. parts[partsIndex]=0;
  369. partsIndex=0;
  370. curVal=0;
  371. while (partsIndex < 4)
  372. {
  373. if (*strIndex < '0' || *strIndex > '9')
  374. {
  375. parts[partsIndex]=curVal;
  376. partsIndex++;
  377. curVal=0;
  378. if (*strIndex==0)
  379. break;
  380. }
  381. else
  382. {
  383. curVal*=10;
  384. curVal+=*strIndex-'0';
  385. }
  386. strIndex++;
  387. }
  388. return htonl((parts[0]<<24) | (parts[1]<<16) | (parts[2]<<8) | (parts[3]<<0) );
  389. }
  390. int RNS2_WindowsStore8::WinRTSetSockOpt(Windows::Networking::Sockets::DatagramSocket ^s,
  391. int level,
  392. int optname,
  393. const char * optval,
  394. socklen_t optlen) {RakAssert("WinRTSetSockOpt Unsupported" && 0); return 0;}
  395. int RNS2_WindowsStore8::WinRTIOCTLSocket(Windows::Networking::Sockets::DatagramSocket ^s,
  396. long cmd,
  397. unsigned long *argp) {RakAssert("WinRTIOCTLSocket Unsupported" && 0); return 0;}
  398. int RNS2_WindowsStore8::WinRTGetSockName(Windows::Networking::Sockets::DatagramSocket ^s,
  399. struct sockaddr *name,
  400. socklen_t* namelen) {RakAssert("WinRTGetSockName Unsupported" && 0); return 0;}
  401. #endif // WINDOWS_STORE_RT
  402. #endif // file header
  403. #endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
粤ICP备19079148号