Socket.cpp 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. #include "il2cpp-config.h"
  2. #include "icalls/System/System.Net.Sockets/Socket.h"
  3. #include "il2cpp-class-internals.h"
  4. #include "gc/WriteBarrier.h"
  5. #include "os/Socket.h"
  6. #include "os/Mutex.h"
  7. #include "os/Thread.h"
  8. #include "utils/StringUtils.h"
  9. #include "vm/Array.h"
  10. #include "vm/Assembly.h"
  11. #include "vm/Class.h"
  12. #include "vm/Exception.h"
  13. #include "vm/Field.h"
  14. #include "vm/Object.h"
  15. #include "vm/String.h"
  16. #include "vm/Thread.h"
  17. #include "Baselib.h"
  18. #include "Cpp/ReentrantLock.h"
  19. namespace il2cpp
  20. {
  21. namespace icalls
  22. {
  23. namespace System
  24. {
  25. namespace System
  26. {
  27. namespace Net
  28. {
  29. namespace Sockets
  30. {
  31. static os::AddressFamily convert_address_family(AddressFamily family)
  32. {
  33. switch (family)
  34. {
  35. case kAddressFamilyUnknown:
  36. case kAddressFamilyImpLink:
  37. case kAddressFamilyPup:
  38. case kAddressFamilyChaos:
  39. case kAddressFamilyIso:
  40. case kAddressFamilyEcma:
  41. case kAddressFamilyDataKit:
  42. case kAddressFamilyCcitt:
  43. case kAddressFamilyDataLink:
  44. case kAddressFamilyLat:
  45. case kAddressFamilyHyperChannel:
  46. case kAddressFamilyNetBios:
  47. case kAddressFamilyVoiceView:
  48. case kAddressFamilyFireFox:
  49. case kAddressFamilyBanyan:
  50. case kAddressFamilyAtm:
  51. case kAddressFamilyCluster:
  52. case kAddressFamilyIeee12844:
  53. case kAddressFamilyNetworkDesigners:
  54. // Unsupported
  55. return os::kAddressFamilyError;
  56. case kAddressFamilyUnspecified:
  57. return os::kAddressFamilyUnspecified;
  58. case kAddressFamilyUnix:
  59. return os::kAddressFamilyUnix;
  60. case kAddressFamilyInterNetwork:
  61. return os::kAddressFamilyInterNetwork;
  62. case kAddressFamilyIpx:
  63. return os::kAddressFamilyIpx;
  64. case kAddressFamilySna:
  65. return os::kAddressFamilySna;
  66. case kAddressFamilyDecNet:
  67. return os::kAddressFamilyDecNet;
  68. case kAddressFamilyAppleTalk:
  69. return os::kAddressFamilyAppleTalk;
  70. case kAddressFamilyInterNetworkV6:
  71. return os::kAddressFamilyInterNetworkV6;
  72. case kAddressFamilyIrda:
  73. return os::kAddressFamilyIrda;
  74. default:
  75. return os::kAddressFamilyError;
  76. }
  77. return os::kAddressFamilyError;
  78. }
  79. static os::SocketType convert_socket_type(SocketType type)
  80. {
  81. switch (type)
  82. {
  83. case kSocketTypeStream:
  84. return os::kSocketTypeStream;
  85. case kSocketTypeDgram:
  86. return os::kSocketTypeDgram;
  87. case kSocketTypeRaw:
  88. return os::kSocketTypeRaw;
  89. case kSocketTypeRdm:
  90. return os::kSocketTypeRdm;
  91. case kSocketTypeSeqpacket:
  92. return os::kSocketTypeSeqpacket;
  93. default:
  94. return os::kSocketTypeError;
  95. }
  96. return os::kSocketTypeError;
  97. }
  98. static os::ProtocolType convert_socket_protocol(ProtocolType protocol)
  99. {
  100. switch (protocol)
  101. {
  102. case kProtocolTypeIP:
  103. case kProtocolTypeIPv6:
  104. case kProtocolTypeIcmp:
  105. case kProtocolTypeIgmp:
  106. case kProtocolTypeGgp:
  107. case kProtocolTypeTcp:
  108. case kProtocolTypePup:
  109. case kProtocolTypeUdp:
  110. case kProtocolTypeIdp:
  111. case kProtocolTypeIcmpV6:
  112. // In this case the enum values map exactly.
  113. return (os::ProtocolType)protocol;
  114. case kProtocolTypeND:
  115. case kProtocolTypeRaw:
  116. case kProtocolTypeIpx:
  117. case kProtocolTypeSpx:
  118. case kProtocolTypeSpxII:
  119. case kProtocolTypeUnknown:
  120. // Everything else in unsupported
  121. return os::kProtocolTypeUnknown;
  122. default:
  123. return os::kProtocolTypeUnknown;
  124. }
  125. return os::kProtocolTypeUnknown;
  126. }
  127. static AddressFamily convert_from_os_address_family(os::AddressFamily family)
  128. {
  129. switch (family)
  130. {
  131. case os::kAddressFamilyUnspecified:
  132. return kAddressFamilyUnspecified;
  133. case os::kAddressFamilyUnix:
  134. return kAddressFamilyUnix;
  135. case os::kAddressFamilyInterNetwork:
  136. return kAddressFamilyInterNetwork;
  137. // #ifdef AF_IPX
  138. case os::kAddressFamilyIpx:
  139. return kAddressFamilyIpx;
  140. // #endif
  141. case os::kAddressFamilySna:
  142. return kAddressFamilySna;
  143. case os::kAddressFamilyDecNet:
  144. return kAddressFamilyDecNet;
  145. case os::kAddressFamilyAppleTalk:
  146. return kAddressFamilyAppleTalk;
  147. // #ifdef AF_INET6
  148. case os::kAddressFamilyInterNetworkV6:
  149. return kAddressFamilyInterNetworkV6;
  150. // #endif
  151. // #ifdef AF_IRDA
  152. case os::kAddressFamilyIrda:
  153. return kAddressFamilyIrda;
  154. // #endif
  155. default:
  156. break;
  157. }
  158. return kAddressFamilyUnknown;
  159. }
  160. static os::SocketFlags convert_socket_flags(SocketFlags flags)
  161. {
  162. return (os::SocketFlags)flags;
  163. }
  164. static Il2CppSocketAddress* end_point_info_to_socket_address(const os::EndPointInfo &info)
  165. {
  166. static Il2CppClass *System_Net_SocketAddress = NULL;
  167. Il2CppSocketAddress *socket_address = NULL;
  168. if (!System_Net_SocketAddress)
  169. {
  170. System_Net_SocketAddress = vm::Class::FromName(
  171. vm::Assembly::GetImage(
  172. vm::Assembly::Load("System.dll")),
  173. "System.Net", "SocketAddress");
  174. }
  175. socket_address = (Il2CppSocketAddress*)vm::Object::New(System_Net_SocketAddress);
  176. const AddressFamily family = convert_from_os_address_family(info.family);
  177. if (info.family == os::kAddressFamilyInterNetwork)
  178. {
  179. socket_address->m_Size = 8;
  180. IL2CPP_OBJECT_SETREF(socket_address, data, vm::Array::New(il2cpp_defaults.byte_class, 8));
  181. const uint16_t port = info.data.inet.port;
  182. const uint32_t address = info.data.inet.address;
  183. il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF);
  184. il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF);
  185. il2cpp_array_set(socket_address->data, uint8_t, 2, (port >> 8) & 0xFF);
  186. il2cpp_array_set(socket_address->data, uint8_t, 3, (port >> 0) & 0xFF);
  187. il2cpp_array_set(socket_address->data, uint8_t, 4, (address >> 24) & 0xFF);
  188. il2cpp_array_set(socket_address->data, uint8_t, 5, (address >> 16) & 0xFF);
  189. il2cpp_array_set(socket_address->data, uint8_t, 6, (address >> 8) & 0xFF);
  190. il2cpp_array_set(socket_address->data, uint8_t, 7, (address >> 0) & 0xFF);
  191. }
  192. else if (info.family == os::kAddressFamilyUnix)
  193. {
  194. const int32_t path_len = (int32_t)strlen(info.data.path);
  195. socket_address->m_Size = 3 + path_len;
  196. IL2CPP_OBJECT_SETREF(socket_address, data, vm::Array::New(il2cpp_defaults.byte_class, 3 + path_len));
  197. il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF);
  198. il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF);
  199. for (int32_t i = 0; i <= path_len; i++)
  200. il2cpp_array_set(socket_address->data, uint8_t, i + 2, info.data.path[i]);
  201. il2cpp_array_set(socket_address->data, uint8_t, 2 + path_len, 0);
  202. }
  203. else if (info.family == os::kAddressFamilyInterNetworkV6)
  204. {
  205. socket_address->m_Size = 28;
  206. IL2CPP_OBJECT_SETREF(socket_address, data, vm::Array::New(il2cpp_defaults.byte_class, 28));
  207. il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF);
  208. il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF);
  209. // Note that we start at the 3rd byte in both the managed array, where the first
  210. // two bytes are the family, set just above this. We also start at the third byte
  211. // in the info.data.raw array, as the first two bytes are unused and garbage data.
  212. for (int i = 2; i < 28; ++i)
  213. il2cpp_array_set(socket_address->data, uint8_t, i, info.data.raw[i]);
  214. }
  215. else
  216. {
  217. // Not supported
  218. return NULL;
  219. }
  220. return socket_address;
  221. }
  222. static bool check_thread_status()
  223. {
  224. static baselib::ReentrantLock _mutex;
  225. os::FastAutoLock lock(&_mutex);
  226. Il2CppThread *current_thread = vm::Thread::Current();
  227. const vm::ThreadState state = vm::Thread::GetState(current_thread);
  228. if (state & vm::kThreadStateAbortRequested)
  229. return false;
  230. if (state & vm::kThreadStateSuspendRequested)
  231. {
  232. IL2CPP_ASSERT(0 && "kThreadStateSuspendRequested not supported yet!");
  233. return true;
  234. }
  235. if (state & vm::kThreadStateStopRequested)
  236. return false;
  237. if (current_thread->GetInternalThread()->interruption_requested)
  238. {
  239. IL2CPP_ASSERT(0 && "thread->interruption_requested not supported yet!");
  240. return false;
  241. }
  242. return true;
  243. }
  244. /// Acquire os::SocketHandle in IntPtr "socket" for the current scope.
  245. #define AUTO_ACQUIRE_SOCKET \
  246. os::SocketHandleWrapper socketHandle (os::PointerToSocketHandle (reinterpret_cast<void*>(socket)))
  247. #define RETURN_IF_SOCKET_IS_INVALID(...) \
  248. if (!socketHandle.IsValid ()) \
  249. { \
  250. *error = os::kErrorCodeInvalidHandle; \
  251. return __VA_ARGS__; \
  252. }
  253. intptr_t Socket::Accept_icall(intptr_t socket, int32_t* error, bool blocking)
  254. {
  255. *error = 0;
  256. os::Socket *new_sock = NULL;
  257. AUTO_ACQUIRE_SOCKET;
  258. if (socketHandle.IsValid())
  259. {
  260. const os::WaitStatus status = socketHandle->Accept(&new_sock);
  261. if (status == kWaitStatusFailure)
  262. *error = socketHandle->GetLastError();
  263. }
  264. else
  265. {
  266. *error = os::kErrorCodeInvalidHandle;
  267. }
  268. intptr_t ret;
  269. if (new_sock)
  270. ret = static_cast<intptr_t>(os::CreateSocketHandle(new_sock));
  271. else
  272. ret = static_cast<intptr_t>(os::kInvalidSocketHandle);
  273. return ret;
  274. }
  275. bool Socket::SupportsPortReuse(int32_t proto)
  276. {
  277. IL2CPP_NOT_IMPLEMENTED_ICALL(Socket::SupportsPortReuse);
  278. return false;
  279. }
  280. int32_t Socket::Available_icall(intptr_t socket, int32_t* error)
  281. {
  282. *error = 0;
  283. AUTO_ACQUIRE_SOCKET;
  284. RETURN_IF_SOCKET_IS_INVALID(0);
  285. int32_t available = 0;
  286. const os::WaitStatus status = socketHandle->Available(&available);
  287. if (status == kWaitStatusFailure)
  288. {
  289. *error = socketHandle->GetLastError();
  290. return 0;
  291. }
  292. return available;
  293. }
  294. void UnpackIPv6AddressFromBuffer(const uint8_t* buffer, int32_t length, uint16_t* port, uint8_t* address, uint32_t* scope)
  295. {
  296. if (length < 28)
  297. {
  298. vm::Exception::Raise(vm::Exception::GetSystemException());
  299. return;
  300. }
  301. *port = ((buffer[2] << 8) | buffer[3]);
  302. for (int i = 0; i < ipv6AddressSize; i++)
  303. address[i] = buffer[i + 8];
  304. *scope = (uint32_t)((buffer[27] << 24) +
  305. (buffer[26] << 16) +
  306. (buffer[25] << 8) +
  307. (buffer[24]));
  308. }
  309. void Socket::Bind_icall(intptr_t socket, Il2CppSocketAddress* socket_address, int32_t* error)
  310. {
  311. *error = 0;
  312. const int32_t length = ARRAY_LENGTH_AS_INT32(socket_address->data->max_length);
  313. const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data);
  314. if (length < 2)
  315. {
  316. vm::Exception::Raise(vm::Exception::GetSystemException());
  317. return;
  318. }
  319. const os::AddressFamily family = convert_address_family((AddressFamily)(buffer[0] | (buffer[1] << 8)));
  320. AUTO_ACQUIRE_SOCKET;
  321. RETURN_IF_SOCKET_IS_INVALID();
  322. if (family == os::kAddressFamilyInterNetwork)
  323. {
  324. if (length < 8)
  325. {
  326. vm::Exception::Raise(vm::Exception::GetSystemException());
  327. return;
  328. }
  329. const uint16_t port = ((buffer[2] << 8) | buffer[3]);
  330. const uint32_t address = ((buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]);
  331. const os::WaitStatus status = socketHandle->Bind(address, port);
  332. if (status == kWaitStatusFailure)
  333. *error = socketHandle->GetLastError();
  334. }
  335. else if (family == os::kAddressFamilyUnix)
  336. {
  337. if (length - 2 >= END_POINT_MAX_PATH_LEN)
  338. {
  339. vm::Exception::Raise(vm::Exception::GetSystemException());
  340. return;
  341. }
  342. char path[END_POINT_MAX_PATH_LEN] = {0};
  343. for (int32_t i = 0; i < (length - 2); ++i)
  344. {
  345. path[i] = (char)buffer[i + 2];
  346. }
  347. const os::WaitStatus status = socketHandle->Bind(path);
  348. if (status == kWaitStatusFailure)
  349. *error = socketHandle->GetLastError();
  350. }
  351. else if (family == os::kAddressFamilyInterNetworkV6)
  352. {
  353. uint16_t port;
  354. uint8_t address[ipv6AddressSize] = {0};
  355. uint32_t scope;
  356. UnpackIPv6AddressFromBuffer(buffer, length, &port, address, &scope);
  357. auto status = socketHandle->Bind(address, scope, port);
  358. vm::Exception::RaiseIfError(status.GetError());
  359. if (status.Get() == kWaitStatusFailure)
  360. *error = socketHandle->GetLastError();
  361. }
  362. else
  363. {
  364. *error = os::kWSAeafnosupport;
  365. return;
  366. }
  367. }
  368. void Socket::Blocking_icall(intptr_t socket, bool block, int32_t* error)
  369. {
  370. *error = 0;
  371. AUTO_ACQUIRE_SOCKET;
  372. RETURN_IF_SOCKET_IS_INVALID();
  373. const os::WaitStatus status = socketHandle->SetBlocking(block);
  374. if (status == kWaitStatusFailure)
  375. *error = socketHandle->GetLastError();
  376. }
  377. void Socket::Close_icall(intptr_t socket, int32_t* error)
  378. {
  379. *error = 0;
  380. // Socket::Close get invoked when running the finalizers; in case Socket_internal
  381. // didn't succeed, the socket has a NULL value and thus we don't need to do
  382. // anything here.
  383. if (os::PointerToSocketHandle(reinterpret_cast<void*>(socket)) == os::kInvalidSocketHandle)
  384. return;
  385. AUTO_ACQUIRE_SOCKET;
  386. RETURN_IF_SOCKET_IS_INVALID();
  387. // There is an implicit acquisition happening when we create the socket which we undo
  388. // now that we have closed the socket.
  389. os::ReleaseSocketHandle(socketHandle.GetHandle(), socketHandle.GetSocket(), true);
  390. socketHandle->Close();
  391. }
  392. void Socket::Connect_icall(intptr_t socket, Il2CppSocketAddress* socket_address, int32_t* error, bool blocking)
  393. {
  394. *error = 0;
  395. const int32_t length = ARRAY_LENGTH_AS_INT32(socket_address->data->max_length);
  396. const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data);
  397. if (length < 2)
  398. {
  399. vm::Exception::Raise(vm::Exception::GetSystemException());
  400. return;
  401. }
  402. const os::AddressFamily family = convert_address_family((AddressFamily)(buffer[0] | (buffer[1] << 8)));
  403. AUTO_ACQUIRE_SOCKET;
  404. RETURN_IF_SOCKET_IS_INVALID();
  405. if (family == os::kAddressFamilyInterNetwork)
  406. {
  407. if (length < 8)
  408. {
  409. vm::Exception::Raise(vm::Exception::GetSystemException());
  410. return;
  411. }
  412. const uint16_t port = ((buffer[2] << 8) | buffer[3]);
  413. const uint32_t address = ((buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]);
  414. const os::WaitStatus status = socketHandle->Connect(address, port);
  415. if (status == kWaitStatusFailure)
  416. *error = socketHandle->GetLastError();
  417. }
  418. else if (family == os::kAddressFamilyUnix)
  419. {
  420. if (length - 2 >= END_POINT_MAX_PATH_LEN)
  421. {
  422. vm::Exception::Raise(vm::Exception::GetSystemException());
  423. return;
  424. }
  425. char path[END_POINT_MAX_PATH_LEN] = {0};
  426. for (int32_t i = 0; i < (length - 2); ++i)
  427. {
  428. path[i] = (char)buffer[i + 2];
  429. }
  430. const os::WaitStatus status = socketHandle->Connect(path);
  431. if (status == kWaitStatusFailure)
  432. *error = socketHandle->GetLastError();
  433. }
  434. else if (family == os::kAddressFamilyInterNetworkV6)
  435. {
  436. uint16_t port;
  437. uint8_t address[ipv6AddressSize] = {0};
  438. uint32_t scope;
  439. UnpackIPv6AddressFromBuffer(buffer, length, &port, address, &scope);
  440. auto status = socketHandle->Connect(address, scope, port);
  441. vm::Exception::RaiseIfError(status.GetError());
  442. if (status.Get() == kWaitStatusFailure)
  443. *error = socketHandle->GetLastError();
  444. }
  445. else
  446. {
  447. *error = os::kWSAeafnosupport;
  448. return;
  449. }
  450. }
  451. void Socket::Disconnect_icall(intptr_t socket, bool reuse, int32_t* error)
  452. {
  453. *error = 0;
  454. AUTO_ACQUIRE_SOCKET;
  455. RETURN_IF_SOCKET_IS_INVALID();
  456. const os::WaitStatus status = socketHandle->Disconnect(reuse);
  457. if (status == kWaitStatusFailure)
  458. *error = socketHandle->GetLastError();
  459. }
  460. void Socket::GetSocketOption_arr_icall(intptr_t socket, SocketOptionLevel level, SocketOptionName name, Il2CppArray** byte_val, int32_t *error)
  461. {
  462. *error = 0;
  463. // Note: for now the options map one to one.
  464. const os::SocketOptionName system_name = (os::SocketOptionName)(name);
  465. const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level);
  466. int32_t length = ARRAY_LENGTH_AS_INT32((*byte_val)->max_length);
  467. uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress((*byte_val));
  468. AUTO_ACQUIRE_SOCKET;
  469. RETURN_IF_SOCKET_IS_INVALID();
  470. const os::WaitStatus status = socketHandle->GetSocketOption(system_level, system_name, buffer, &length);
  471. if (status == kWaitStatusFailure)
  472. *error = socketHandle->GetLastError();
  473. }
  474. void Socket::GetSocketOption_obj_icall(intptr_t socket, SocketOptionLevel level, SocketOptionName name, Il2CppObject** obj_val, int32_t *error)
  475. {
  476. *error = 0;
  477. // Note: for now the options map one to one.
  478. const os::SocketOptionName system_name = (os::SocketOptionName)(name);
  479. const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level);
  480. AUTO_ACQUIRE_SOCKET;
  481. RETURN_IF_SOCKET_IS_INVALID();
  482. int32_t first = 0;
  483. int32_t second = 0;
  484. const os::WaitStatus status = socketHandle->GetSocketOptionFull(system_level, system_name, &first, &second);
  485. if (status == kWaitStatusFailure)
  486. {
  487. *error = socketHandle->GetLastError();
  488. return;
  489. }
  490. switch (name)
  491. {
  492. case kSocketOptionNameLinger:
  493. {
  494. static Il2CppClass *System_Net_Sockets_LingerOption = NULL;
  495. if (!System_Net_Sockets_LingerOption)
  496. {
  497. System_Net_Sockets_LingerOption = vm::Class::FromName(
  498. vm::Assembly::GetImage(
  499. vm::Assembly::Load("System.dll")),
  500. "System.Net.Sockets", "LingerOption");
  501. }
  502. *obj_val = vm::Object::New(System_Net_Sockets_LingerOption);
  503. const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "enabled");
  504. const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "lingerTime");
  505. *((bool*)((char*)(*obj_val) + enabled_field_info->offset)) = (first ? 1 : 0);
  506. *((int32_t*)((char*)(*obj_val) + seconds_field_info->offset)) = second;
  507. }
  508. break;
  509. case kSocketOptionNameDontLinger:
  510. case kSocketOptionNameSendTimeout:
  511. case kSocketOptionNameReceiveTimeout:
  512. default:
  513. *obj_val = vm::Object::Box(il2cpp_defaults.int32_class, &first);
  514. break;
  515. }
  516. }
  517. void Socket::Listen_icall(intptr_t socket, int32_t backlog, int32_t* error)
  518. {
  519. *error = 0;
  520. AUTO_ACQUIRE_SOCKET;
  521. RETURN_IF_SOCKET_IS_INVALID();
  522. const os::WaitStatus status = socketHandle->Listen(backlog);
  523. if (status == kWaitStatusFailure)
  524. *error = socketHandle->GetLastError();
  525. }
  526. static os::PollFlags select_mode_to_poll_flags(SelectMode mode)
  527. {
  528. switch (mode)
  529. {
  530. case kSelectModeSelectRead:
  531. return os::kPollFlagsIn;
  532. case kSelectModeSelectWrite:
  533. return os::kPollFlagsOut;
  534. case kSelectModeSelectError:
  535. return os::kPollFlagsErr;
  536. }
  537. return os::kPollFlagsNone;
  538. }
  539. bool Socket::Poll_icall(intptr_t socket, SelectMode mode, int32_t timeout, int32_t* error)
  540. {
  541. *error = 0;
  542. os::PollRequest request;
  543. AUTO_ACQUIRE_SOCKET;
  544. RETURN_IF_SOCKET_IS_INVALID(false);
  545. request.fd = socketHandle.GetSocket()->GetDescriptor();
  546. request.events = select_mode_to_poll_flags(mode);
  547. request.revents = os::kPollFlagsNone;
  548. if (request.events == os::kPollFlagsNone)
  549. {
  550. *error = os::kWSAefault;
  551. return false;
  552. }
  553. std::vector<os::PollRequest> requests;
  554. requests.push_back(request);
  555. // The timeout from managed code is in microseconds. Convert it to milliseconds
  556. // for the poll implementation.
  557. timeout = (timeout >= 0) ? (timeout / 1000) : -1;
  558. int32_t results = 0;
  559. const os::WaitStatus result = os::Socket::Poll(requests, timeout, &results, error);
  560. if (result == kWaitStatusFailure || results == 0)
  561. return false;
  562. return (requests[0].revents != os::kPollFlagsNone);
  563. }
  564. int32_t Socket::Receive_array_icall(intptr_t socket, os::WSABuf* bufarray, int32_t count, SocketFlags flags, int32_t *error, bool blocking)
  565. {
  566. *error = 0;
  567. AUTO_ACQUIRE_SOCKET;
  568. RETURN_IF_SOCKET_IS_INVALID(0);
  569. const os::SocketFlags c_flags = convert_socket_flags(flags);
  570. int32_t len = 0;
  571. const os::WaitStatus status = socketHandle->ReceiveArray(bufarray, count, &len, c_flags);
  572. if (status == kWaitStatusFailure)
  573. {
  574. *error = socketHandle->GetLastError();
  575. return 0;
  576. }
  577. return len;
  578. }
  579. int32_t Socket::Receive_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, int32_t* error, bool blocking)
  580. {
  581. *error = 0;
  582. AUTO_ACQUIRE_SOCKET;
  583. RETURN_IF_SOCKET_IS_INVALID(0);
  584. const os::SocketFlags c_flags = convert_socket_flags(flags);
  585. int32_t len = 0;
  586. const os::WaitStatus status = socketHandle->Receive(buffer, count, c_flags, &len);
  587. if (status == kWaitStatusFailure)
  588. *error = socketHandle->GetLastError();
  589. return len;
  590. }
  591. int32_t Socket::ReceiveFrom_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, Il2CppSocketAddress** socket_address, int32_t* error, bool blocking)
  592. {
  593. *error = 0;
  594. AUTO_ACQUIRE_SOCKET;
  595. RETURN_IF_SOCKET_IS_INVALID(0);
  596. const os::SocketFlags c_flags = convert_socket_flags(flags);
  597. int32_t len = 0;
  598. const int32_t length = ARRAY_LENGTH_AS_INT32((*socket_address)->data->max_length);
  599. const uint8_t *socket_buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress((*socket_address)->data);
  600. if (length < 2)
  601. {
  602. vm::Exception::Raise(vm::Exception::GetSystemException());
  603. return 0;
  604. }
  605. const os::AddressFamily family = convert_address_family((AddressFamily)(socket_buffer[0] | (socket_buffer[1] << 8)));
  606. os::EndPointInfo info;
  607. info.family = os::kAddressFamilyError;
  608. if (family == os::kAddressFamilyInterNetwork)
  609. {
  610. if (length < 8)
  611. {
  612. vm::Exception::Raise(vm::Exception::GetSystemException());
  613. return 0;
  614. }
  615. const uint16_t port = ((socket_buffer[2] << 8) | socket_buffer[3]);
  616. const uint32_t address = ((socket_buffer[4] << 24) | (socket_buffer[5] << 16) | (socket_buffer[6] << 8) | socket_buffer[7]);
  617. const os::WaitStatus status = socketHandle->RecvFrom(address, port, buffer, count, c_flags, &len, info);
  618. if (status == kWaitStatusFailure)
  619. *error = socketHandle->GetLastError();
  620. }
  621. else if (family == os::kAddressFamilyUnix)
  622. {
  623. if (length - 2 >= END_POINT_MAX_PATH_LEN)
  624. {
  625. vm::Exception::Raise(vm::Exception::GetSystemException());
  626. return 0;
  627. }
  628. char path[END_POINT_MAX_PATH_LEN] = {0};
  629. for (int32_t i = 0; i < (length - 2); ++i)
  630. {
  631. path[i] = (char)socket_buffer[i + 2];
  632. }
  633. auto status = socketHandle->RecvFrom(path, buffer, count, c_flags, &len, info);
  634. vm::Exception::RaiseIfError(status.GetError());
  635. if (status.Get() == kWaitStatusFailure)
  636. *error = socketHandle->GetLastError();
  637. }
  638. else if (family == os::kAddressFamilyInterNetworkV6)
  639. {
  640. uint16_t port;
  641. uint8_t address[ipv6AddressSize] = {0};
  642. uint32_t scope;
  643. UnpackIPv6AddressFromBuffer(socket_buffer, length, &port, address, &scope);
  644. auto status = socketHandle->RecvFrom(address, scope, port, buffer, count, c_flags, &len, info);
  645. vm::Exception::RaiseIfError(status.GetError());
  646. if (status.Get() == kWaitStatusFailure)
  647. *error = socketHandle->GetLastError();
  648. }
  649. else
  650. {
  651. *error = os::kWSAeafnosupport;
  652. return 0;
  653. }
  654. *socket_address = (info.family == os::kAddressFamilyError) ? NULL : end_point_info_to_socket_address(info);
  655. return len;
  656. }
  657. Il2CppSocketAddress* Socket::LocalEndPoint_icall(intptr_t socket, int32_t family, int32_t* error)
  658. {
  659. AUTO_ACQUIRE_SOCKET;
  660. RETURN_IF_SOCKET_IS_INVALID(NULL);
  661. os::EndPointInfo info;
  662. memset(&info, 0x00, sizeof(os::EndPointInfo));
  663. const os::WaitStatus status = socketHandle->GetLocalEndPointInfo(info);
  664. if (status == kWaitStatusFailure)
  665. {
  666. *error = socketHandle->GetLastError();
  667. return NULL;
  668. }
  669. Il2CppSocketAddress *socket_address = end_point_info_to_socket_address(info);
  670. if (socket_address == NULL)
  671. *error = os::kWSAeafnosupport;
  672. return socket_address;
  673. }
  674. Il2CppSocketAddress* Socket::RemoteEndPoint_icall(intptr_t socket, int32_t family, int32_t* error)
  675. {
  676. AUTO_ACQUIRE_SOCKET;
  677. RETURN_IF_SOCKET_IS_INVALID(NULL);
  678. os::EndPointInfo info;
  679. memset(&info, 0x00, sizeof(os::EndPointInfo));
  680. const os::WaitStatus status = socketHandle->GetRemoteEndPointInfo(info);
  681. if (status == kWaitStatusFailure)
  682. {
  683. *error = socketHandle->GetLastError();
  684. return NULL;
  685. }
  686. Il2CppSocketAddress *socket_address = end_point_info_to_socket_address(info);
  687. if (socket_address == NULL)
  688. *error = os::kWSAeafnosupport;
  689. return socket_address;
  690. }
  691. void Socket::Select_icall(Il2CppArray** sockets, int32_t timeout, int32_t* error)
  692. {
  693. *error = 0;
  694. // Layout: READ, null, WRITE, null, ERROR, null
  695. const uint32_t input_sockets_count = ARRAY_LENGTH_AS_INT32((*sockets)->max_length);
  696. std::vector<os::PollRequest> requests;
  697. std::vector<os::SocketHandleWrapper> socketHandles;
  698. requests.reserve(input_sockets_count - 3);
  699. int32_t mode = 0;
  700. for (uint32_t i = 0; i < input_sockets_count; ++i)
  701. {
  702. Il2CppObject *obj = il2cpp_array_get(*sockets, Il2CppObject*, i);
  703. if (obj == NULL)
  704. {
  705. if (++mode > 3)
  706. {
  707. // Something very bad happened here (ie: the input array was wrong)
  708. // so we gracefully terminate the method.
  709. *error = os::kWSAefault;
  710. return;
  711. }
  712. continue;
  713. }
  714. FieldInfo *safe_handle_field_info = vm::Class::GetFieldFromName(obj->klass, "m_Handle");
  715. const Il2CppObject* value = NULL;
  716. vm::Field::GetValue(obj, safe_handle_field_info, &value);
  717. const FieldInfo *handle_field_info = vm::Class::GetFieldFromName(value->klass, "handle");
  718. intptr_t& intPtr = *((intptr_t*)((char*)value + handle_field_info->offset));
  719. // Acquire socket.
  720. socketHandles.push_back(os::SocketHandleWrapper());
  721. os::SocketHandleWrapper& socketHandle = socketHandles.back();
  722. socketHandle.Acquire(os::PointerToSocketHandle(reinterpret_cast<void*>(intPtr)));
  723. os::PollRequest request;
  724. // May 'invalid socket' (-1); we want the error from Poll() in that case.
  725. request.fd = socketHandle.GetSocket() == NULL ? -1 : socketHandle.GetSocket()->GetDescriptor();
  726. request.events = (mode == 0 ? os::kPollFlagsIn : (mode == 1 ? os::kPollFlagsOut : os::kPollFlagsErr));
  727. request.revents = os::kPollFlagsNone;
  728. requests.push_back(request);
  729. }
  730. if (requests.size() == 0)
  731. return;
  732. int32_t results = 0;
  733. // The timeout from managed code is in microseconds. Convert it to milliseconds
  734. // for the poll implementation.
  735. timeout = (timeout >= 0) ? (timeout / 1000) : -1;
  736. const os::WaitStatus result = os::Socket::Poll(requests, timeout, &results, error);
  737. if (result == kWaitStatusFailure)
  738. {
  739. *sockets = NULL;
  740. return;
  741. }
  742. Il2CppArray *new_sockets = vm::Array::New(((Il2CppObject*)(*sockets))->klass->element_class, results + 3);
  743. if (results > 0)
  744. {
  745. mode = 0;
  746. uint32_t request_index = 0;
  747. // This odd loop is due to the layout of the sockets input array:
  748. // Layout: READ, null, WRITE, null, ERROR, null
  749. // We need to iterate each request and iterate the sockets array, skipping
  750. // the null entries. We try to avoid an infinite loop here as well.
  751. uint32_t add_index = 0;
  752. while (request_index < requests.size())
  753. {
  754. const uint32_t input_sockets_index = (request_index + mode);
  755. if (input_sockets_index > input_sockets_count - 1)
  756. break; // We have exhausted the input sockets array, so exit.
  757. Il2CppObject *obj = il2cpp_array_get(*sockets, Il2CppObject*, input_sockets_index);
  758. if (obj == NULL)
  759. {
  760. ++mode;
  761. continue; // Here is a null entry, skip it without updated the next request index.
  762. }
  763. os::PollRequest &request = requests[request_index];
  764. if (request.revents != os::kPollFlagsNone)
  765. {
  766. switch (mode)
  767. {
  768. case 0:
  769. if (request.revents & (os::kPollFlagsIn | os::kPollFlagsErr))
  770. {
  771. il2cpp_array_setref(new_sockets, (add_index + mode), obj);
  772. add_index++;
  773. }
  774. break;
  775. case 1:
  776. if (request.revents & (os::kPollFlagsOut | os::kPollFlagsErr))
  777. {
  778. il2cpp_array_setref(new_sockets, (add_index + mode), obj);
  779. add_index++;
  780. }
  781. break;
  782. default:
  783. if (request.revents & os::kPollFlagsErr)
  784. {
  785. il2cpp_array_setref(new_sockets, (add_index + mode), obj);
  786. add_index++;
  787. }
  788. break;
  789. }
  790. }
  791. ++request_index;
  792. }
  793. }
  794. *sockets = new_sockets;
  795. }
  796. bool Socket::SendFile_icall(intptr_t socket, Il2CppString* filename, Il2CppArray* pre_buffer, Il2CppArray* post_buffer, TransmitFileOptions flags, int32_t* error, bool blocking)
  797. {
  798. if (filename == NULL)
  799. return false;
  800. os::TransmitFileBuffers t_buffers = {0};
  801. if (pre_buffer != NULL)
  802. {
  803. t_buffers.head = il2cpp_array_addr(pre_buffer, uint8_t, 0);
  804. t_buffers.head_length = ARRAY_LENGTH_AS_INT32(pre_buffer->max_length);
  805. }
  806. if (post_buffer != NULL)
  807. {
  808. t_buffers.tail = il2cpp_array_addr(post_buffer, uint8_t, 0);
  809. t_buffers.tail_length = ARRAY_LENGTH_AS_INT32(post_buffer->max_length);
  810. }
  811. AUTO_ACQUIRE_SOCKET;
  812. if (!socketHandle.IsValid())
  813. return false;
  814. const Il2CppChar* ustr = utils::StringUtils::GetChars(filename);
  815. const std::string str = utils::StringUtils::Utf16ToUtf8(ustr);
  816. // Note: for now they map 1-1
  817. const os::TransmitFileOptions o_flags = (os::TransmitFileOptions)flags;
  818. const os::WaitStatus status = socketHandle->SendFile(str.c_str(), &t_buffers, o_flags);
  819. if (status == kWaitStatusFailure)
  820. {
  821. // TODO: mono stores socketHandle->GetLastError into a threadlocal global variable
  822. // that can be retrieved later by other icalls.
  823. return false;
  824. }
  825. if ((flags & kTransmitFileOptionsDisconnect) == kTransmitFileOptionsDisconnect)
  826. socketHandle->Disconnect(true);
  827. return true;
  828. }
  829. int32_t Socket::SendTo_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, Il2CppSocketAddress* socket_address, int32_t* error, bool blocking)
  830. {
  831. *error = 0;
  832. const os::SocketFlags c_flags = convert_socket_flags(flags);
  833. int32_t len = 0;
  834. const int32_t length = ARRAY_LENGTH_AS_INT32(socket_address->data->max_length);
  835. const uint8_t *socket_buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data);
  836. if (length < 2)
  837. {
  838. vm::Exception::Raise(vm::Exception::GetSystemException());
  839. return 0;
  840. }
  841. const os::AddressFamily family = convert_address_family((AddressFamily)(socket_buffer[0] | (socket_buffer[1] << 8)));
  842. AUTO_ACQUIRE_SOCKET;
  843. RETURN_IF_SOCKET_IS_INVALID(0);
  844. if (family == os::kAddressFamilyInterNetwork)
  845. {
  846. if (length < 8)
  847. {
  848. vm::Exception::Raise(vm::Exception::GetSystemException());
  849. return 0;
  850. }
  851. const uint16_t port = ((socket_buffer[2] << 8) | socket_buffer[3]);
  852. const uint32_t address = ((socket_buffer[4] << 24) | (socket_buffer[5] << 16) | (socket_buffer[6] << 8) | socket_buffer[7]);
  853. const os::WaitStatus status = socketHandle->SendTo(address, port, buffer, count, c_flags, &len);
  854. if (status == kWaitStatusFailure)
  855. *error = socketHandle->GetLastError();
  856. }
  857. else if (family == os::kAddressFamilyUnix)
  858. {
  859. if (length - 2 >= END_POINT_MAX_PATH_LEN)
  860. {
  861. vm::Exception::Raise(vm::Exception::GetSystemException());
  862. return 0;
  863. }
  864. char path[END_POINT_MAX_PATH_LEN] = {0};
  865. for (int32_t i = 0; i < (length - 2); ++i)
  866. {
  867. path[i] = (char)socket_buffer[i + 2];
  868. }
  869. auto status = socketHandle->SendTo(path, buffer, count, c_flags, &len);
  870. vm::Exception::RaiseIfError(status.GetError());
  871. if (status.Get() == kWaitStatusFailure)
  872. *error = socketHandle->GetLastError();
  873. }
  874. else if (family == os::kAddressFamilyInterNetworkV6)
  875. {
  876. uint16_t port;
  877. uint8_t address[ipv6AddressSize] = {0};
  878. uint32_t scope;
  879. UnpackIPv6AddressFromBuffer(socket_buffer, length, &port, address, &scope);
  880. auto status = socketHandle->SendTo(address, scope, port, buffer, count, c_flags, &len);
  881. vm::Exception::RaiseIfError(status.GetError());
  882. if (status.Get() == kWaitStatusFailure)
  883. *error = socketHandle->GetLastError();
  884. }
  885. else
  886. {
  887. *error = os::kWSAeafnosupport;
  888. return 0;
  889. }
  890. return len;
  891. }
  892. int32_t Socket::Send_array_icall(intptr_t socket, os::WSABuf* bufarray, int32_t count, SocketFlags flags, int32_t* error, bool blocking)
  893. {
  894. *error = 0;
  895. const os::SocketFlags c_flags = convert_socket_flags(flags);
  896. AUTO_ACQUIRE_SOCKET;
  897. RETURN_IF_SOCKET_IS_INVALID(0);
  898. int32_t sent = 0;
  899. const os::WaitStatus status = socketHandle->SendArray(bufarray, count, &sent, c_flags);
  900. if (status == kWaitStatusFailure)
  901. {
  902. *error = socketHandle->GetLastError();
  903. return 0;
  904. }
  905. return sent;
  906. }
  907. int32_t Socket::Send_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, int32_t* error, bool blocking)
  908. {
  909. *error = 0;
  910. const os::SocketFlags c_flags = convert_socket_flags(flags);
  911. AUTO_ACQUIRE_SOCKET;
  912. RETURN_IF_SOCKET_IS_INVALID(0);
  913. int32_t len = 0;
  914. const os::WaitStatus status = socketHandle->Send(buffer, count, c_flags, &len);
  915. if (status == kWaitStatusFailure)
  916. *error = socketHandle->GetLastError();
  917. return len;
  918. }
  919. #if IL2CPP_SUPPORT_IPV6
  920. static os::IPv6Address ipaddress_to_ipv6_addr(Il2CppObject *ipaddr)
  921. {
  922. FieldInfo* numbersFieldInfo = vm::Class::GetFieldFromName(ipaddr->klass, "_numbers");
  923. IL2CPP_ASSERT(numbersFieldInfo);
  924. Il2CppArray* data = (Il2CppArray*)vm::Field::GetValueObject(numbersFieldInfo, ipaddr);
  925. os::IPv6Address ipv6;
  926. for (int i = 0; i < 8; i++)
  927. {
  928. uint16_t s = il2cpp_array_get(data, uint16_t, i);
  929. ipv6.addr[2 * i] = (s >> 8) & 0xff;
  930. ipv6.addr[2 * i + 1] = s & 0xff;
  931. }
  932. return ipv6;
  933. }
  934. static void GetAddressAndInterfaceFromObject(Il2CppObject* object, const char* groupField, const char* interfaceField,
  935. os::IPv6Address& ipv6, uint64_t& interfaceOffset)
  936. {
  937. FieldInfo* groupFieldInfo = vm::Class::GetFieldFromName(object->klass, groupField);
  938. IL2CPP_ASSERT(groupFieldInfo);
  939. Il2CppObject* address = vm::Field::GetValueObject(groupFieldInfo, object);
  940. if (address)
  941. ipv6 = ipaddress_to_ipv6_addr(address);
  942. FieldInfo* interfaceFieldInfo = vm::Class::GetFieldFromName(object->klass, interfaceField);
  943. IL2CPP_ASSERT(interfaceFieldInfo);
  944. vm::Field::GetValue(object, interfaceFieldInfo, &interfaceOffset);
  945. }
  946. #endif // IL2CPP_SUPPORT_IPV6
  947. void Socket::SetSocketOption_icall(intptr_t socket, SocketOptionLevel level, SocketOptionName name, Il2CppObject* obj_val, Il2CppArray* byte_val, int32_t int_val, int32_t* error)
  948. {
  949. *error = 0;
  950. // Note: for now the options map one to one.
  951. const os::SocketOptionName system_name = (os::SocketOptionName)(name);
  952. const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level);
  953. AUTO_ACQUIRE_SOCKET;
  954. RETURN_IF_SOCKET_IS_INVALID();
  955. os::WaitStatus status = kWaitStatusFailure;
  956. if (byte_val != NULL)
  957. {
  958. const int32_t length = ARRAY_LENGTH_AS_INT32(byte_val->max_length);
  959. const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(byte_val);
  960. status = socketHandle->SetSocketOptionArray(system_level, system_name, buffer, length);
  961. }
  962. else if (obj_val != NULL)
  963. {
  964. switch (name)
  965. {
  966. case kSocketOptionNameLinger:
  967. {
  968. const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(obj_val->klass, "enabled");
  969. const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(obj_val->klass, "lingerTime");
  970. const bool enabled = *((bool*)((char*)obj_val + enabled_field_info->offset));
  971. const int32_t seconds = *((int32_t*)((char*)obj_val + seconds_field_info->offset));
  972. status = socketHandle->SetSocketOptionLinger(system_level, system_name, enabled, seconds);
  973. }
  974. break;
  975. case kSocketOptionNameAddMembership:
  976. case kSocketOptionNameDropMembership:
  977. {
  978. #if IL2CPP_SUPPORT_IPV6
  979. if (system_level == (os::SocketOptionLevel)kSocketOptionLevelIPv6)
  980. {
  981. os::IPv6Address ipv6 = {{0}};
  982. uint64_t interfaceOffset;
  983. GetAddressAndInterfaceFromObject(obj_val, "m_Group", "m_Interface", ipv6, interfaceOffset);
  984. status = socketHandle->SetSocketOptionMembership(system_level, system_name, ipv6, interfaceOffset);
  985. }
  986. else if (system_level == (os::SocketOptionLevel)kSocketOptionLevelIP)
  987. #endif // IL2CPP_SUPPORT_IPV6
  988. {
  989. FieldInfo *group_field_info = vm::Class::GetFieldFromName(obj_val->klass, "group");
  990. Il2CppObject* group_obj = vm::Field::GetValueObject(group_field_info, obj_val);
  991. const FieldInfo *group_address_field_info = vm::Class::GetFieldFromName(group_obj->klass, "_addressOrScopeId");
  992. IL2CPP_ASSERT(group_address_field_info != NULL);
  993. const uint32_t group_address = *((uint32_t*)(uint64_t*)((char*)group_obj + group_address_field_info->offset));
  994. uint32_t local_address = 0;
  995. FieldInfo *local_field_info = vm::Class::GetFieldFromName(obj_val->klass, "localAddress");
  996. if (local_field_info != NULL)
  997. {
  998. Il2CppObject* local_obj = vm::Field::GetValueObject(local_field_info, obj_val);
  999. if (local_obj != NULL)
  1000. {
  1001. const FieldInfo *local_address_field_info = vm::Class::GetFieldFromName(local_obj->klass, "_addressOrScopeId");
  1002. IL2CPP_ASSERT(local_address_field_info != NULL);
  1003. local_address = *((uint32_t*)(uint64_t*)((char*)local_obj + local_address_field_info->offset));
  1004. }
  1005. }
  1006. status = socketHandle->SetSocketOptionMembership(system_level, system_name, group_address, local_address);
  1007. }
  1008. }
  1009. break;
  1010. default:
  1011. *error = os::kWSAeinval;
  1012. return; // early out
  1013. }
  1014. }
  1015. else
  1016. status = socketHandle->SetSocketOption(system_level, system_name, int_val);
  1017. if (status == kWaitStatusFailure)
  1018. *error = socketHandle->GetLastError();
  1019. }
  1020. void Socket::Shutdown_icall(intptr_t socket, SocketShutdown how, int32_t* error)
  1021. {
  1022. *error = 0;
  1023. AUTO_ACQUIRE_SOCKET;
  1024. RETURN_IF_SOCKET_IS_INVALID();
  1025. const os::WaitStatus status = socketHandle->Shutdown(how);
  1026. if (status == kWaitStatusFailure)
  1027. *error = socketHandle->GetLastError();
  1028. }
  1029. intptr_t Socket::Socket_icall(AddressFamily family, SocketType type, ProtocolType protocol, int32_t* error)
  1030. {
  1031. intptr_t socket = static_cast<intptr_t>(os::kInvalidSocketHandle);
  1032. *error = 0;
  1033. os::AddressFamily n_family = convert_address_family(family);
  1034. os::SocketType n_type = convert_socket_type(type);
  1035. os::ProtocolType n_protocol = convert_socket_protocol(protocol);
  1036. if (n_family == os::kAddressFamilyError)
  1037. {
  1038. *error = os::kWSAeafnosupport;
  1039. return socket;
  1040. }
  1041. if (n_type == os::kSocketTypeError)
  1042. {
  1043. *error = os::kWSAesocktnosupport;
  1044. return socket;
  1045. }
  1046. if (n_protocol == os::kProtocolTypeUnknown)
  1047. {
  1048. *error = os::kWSAeprotonosupport;
  1049. return socket;
  1050. }
  1051. os::Socket *sock = new os::Socket(check_thread_status);
  1052. const os::WaitStatus status = sock->Create(n_family, n_type, n_protocol);
  1053. if (status == kWaitStatusFailure)
  1054. {
  1055. *error = sock->GetLastError();
  1056. // Okay to delete socket directly. We haven't created a handle yet.
  1057. delete sock;
  1058. return socket;
  1059. }
  1060. os::SocketHandle socketHandle = os::CreateSocketHandle(sock);
  1061. socket = static_cast<intptr_t>(socketHandle);
  1062. return socket;
  1063. }
  1064. int32_t Socket::IOControl_icall(intptr_t socket, int32_t ioctl_code, Il2CppArray* input, Il2CppArray* output, int32_t* error)
  1065. {
  1066. *error = 0;
  1067. AUTO_ACQUIRE_SOCKET;
  1068. RETURN_IF_SOCKET_IS_INVALID(-1);
  1069. if (ioctl_code == 0x5421 /* FIONBIO */)
  1070. {
  1071. // Invalid command. Must use Socket.Blocking
  1072. return -1;
  1073. }
  1074. const int32_t in_length = (input ? ARRAY_LENGTH_AS_INT32(input->max_length) : 0);
  1075. const uint8_t *in_buffer = (input ? (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(input) : NULL);
  1076. const int32_t out_length = (output ? ARRAY_LENGTH_AS_INT32(output->max_length) : 0);
  1077. uint8_t *out_buffer = (output ? (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(output) : NULL);
  1078. int32_t output_bytes = 0;
  1079. const os::WaitStatus status = socketHandle->Ioctl(ioctl_code, in_buffer, in_length, out_buffer, out_length, &output_bytes);
  1080. if (status == kWaitStatusFailure)
  1081. {
  1082. *error = socketHandle->GetLastError();
  1083. return -1;
  1084. }
  1085. return output_bytes;
  1086. }
  1087. static void STDCALL
  1088. abort_apc(void* param)
  1089. {
  1090. }
  1091. void Socket::cancel_blocking_socket_operation(Il2CppObject* thread)
  1092. {
  1093. Il2CppThread* t = reinterpret_cast<Il2CppThread*>(thread);
  1094. t->internal_thread->handle->QueueUserAPC(abort_apc, NULL);
  1095. // IL2CPP_NOT_IMPLEMENTED_ICALL(Socket::cancel_blocking_socket_operation);
  1096. //IL2CPP_UNREACHABLE;
  1097. }
  1098. bool Socket::Duplicate_icall(intptr_t handle, int32_t targetProcessId, intptr_t* duplicateHandle, int32_t* error)
  1099. {
  1100. IL2CPP_NOT_IMPLEMENTED_ICALL(Socket::Duplicate_icall);
  1101. return false;
  1102. }
  1103. bool Socket::IsProtocolSupported_internal(int32_t networkInterface)
  1104. {
  1105. // The networkInterface argument is from the
  1106. // System.Net.NetworkInformation.NetworkInterfaceComponent enum
  1107. // 0 => IPv4
  1108. // 1 => IPv6
  1109. #if IL2CPP_SUPPORT_IPV6_SUPPORT_QUERY
  1110. return networkInterface == 1 ? os::Socket::IsIPv6Supported() : true;
  1111. #elif IL2CPP_SUPPORT_IPV6
  1112. // This platform supports both IPv6 and IPv4.
  1113. return true;
  1114. #else
  1115. // This platform only supports IPv4.
  1116. return networkInterface == 0;
  1117. #endif
  1118. }
  1119. } /* namespace Sockets */
  1120. } /* namespace Net */
  1121. } /* namespace System */
  1122. } /* namespace System */
  1123. } /* namespace icalls */
  1124. } /* namespace il2cpp */