12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460 |
- #include "il2cpp-config.h"
- #include "icalls/System/System.Net.Sockets/Socket.h"
- #include "il2cpp-class-internals.h"
- #include "gc/WriteBarrier.h"
- #include "os/Socket.h"
- #include "os/Mutex.h"
- #include "os/Thread.h"
- #include "utils/StringUtils.h"
- #include "vm/Array.h"
- #include "vm/Assembly.h"
- #include "vm/Class.h"
- #include "vm/Exception.h"
- #include "vm/Field.h"
- #include "vm/Object.h"
- #include "vm/String.h"
- #include "vm/Thread.h"
- #include "Baselib.h"
- #include "Cpp/ReentrantLock.h"
- namespace il2cpp
- {
- namespace icalls
- {
- namespace System
- {
- namespace System
- {
- namespace Net
- {
- namespace Sockets
- {
- static os::AddressFamily convert_address_family(AddressFamily family)
- {
- switch (family)
- {
- case kAddressFamilyUnknown:
- case kAddressFamilyImpLink:
- case kAddressFamilyPup:
- case kAddressFamilyChaos:
- case kAddressFamilyIso:
- case kAddressFamilyEcma:
- case kAddressFamilyDataKit:
- case kAddressFamilyCcitt:
- case kAddressFamilyDataLink:
- case kAddressFamilyLat:
- case kAddressFamilyHyperChannel:
- case kAddressFamilyNetBios:
- case kAddressFamilyVoiceView:
- case kAddressFamilyFireFox:
- case kAddressFamilyBanyan:
- case kAddressFamilyAtm:
- case kAddressFamilyCluster:
- case kAddressFamilyIeee12844:
- case kAddressFamilyNetworkDesigners:
- // Unsupported
- return os::kAddressFamilyError;
- case kAddressFamilyUnspecified:
- return os::kAddressFamilyUnspecified;
- case kAddressFamilyUnix:
- return os::kAddressFamilyUnix;
- case kAddressFamilyInterNetwork:
- return os::kAddressFamilyInterNetwork;
- case kAddressFamilyIpx:
- return os::kAddressFamilyIpx;
- case kAddressFamilySna:
- return os::kAddressFamilySna;
- case kAddressFamilyDecNet:
- return os::kAddressFamilyDecNet;
- case kAddressFamilyAppleTalk:
- return os::kAddressFamilyAppleTalk;
- case kAddressFamilyInterNetworkV6:
- return os::kAddressFamilyInterNetworkV6;
- case kAddressFamilyIrda:
- return os::kAddressFamilyIrda;
- default:
- return os::kAddressFamilyError;
- }
- return os::kAddressFamilyError;
- }
- static os::SocketType convert_socket_type(SocketType type)
- {
- switch (type)
- {
- case kSocketTypeStream:
- return os::kSocketTypeStream;
- case kSocketTypeDgram:
- return os::kSocketTypeDgram;
- case kSocketTypeRaw:
- return os::kSocketTypeRaw;
- case kSocketTypeRdm:
- return os::kSocketTypeRdm;
- case kSocketTypeSeqpacket:
- return os::kSocketTypeSeqpacket;
- default:
- return os::kSocketTypeError;
- }
- return os::kSocketTypeError;
- }
- static os::ProtocolType convert_socket_protocol(ProtocolType protocol)
- {
- switch (protocol)
- {
- case kProtocolTypeIP:
- case kProtocolTypeIPv6:
- case kProtocolTypeIcmp:
- case kProtocolTypeIgmp:
- case kProtocolTypeGgp:
- case kProtocolTypeTcp:
- case kProtocolTypePup:
- case kProtocolTypeUdp:
- case kProtocolTypeIdp:
- case kProtocolTypeIcmpV6:
- // In this case the enum values map exactly.
- return (os::ProtocolType)protocol;
- case kProtocolTypeND:
- case kProtocolTypeRaw:
- case kProtocolTypeIpx:
- case kProtocolTypeSpx:
- case kProtocolTypeSpxII:
- case kProtocolTypeUnknown:
- // Everything else in unsupported
- return os::kProtocolTypeUnknown;
- default:
- return os::kProtocolTypeUnknown;
- }
- return os::kProtocolTypeUnknown;
- }
- static AddressFamily convert_from_os_address_family(os::AddressFamily family)
- {
- switch (family)
- {
- case os::kAddressFamilyUnspecified:
- return kAddressFamilyUnspecified;
- case os::kAddressFamilyUnix:
- return kAddressFamilyUnix;
- case os::kAddressFamilyInterNetwork:
- return kAddressFamilyInterNetwork;
- // #ifdef AF_IPX
- case os::kAddressFamilyIpx:
- return kAddressFamilyIpx;
- // #endif
- case os::kAddressFamilySna:
- return kAddressFamilySna;
- case os::kAddressFamilyDecNet:
- return kAddressFamilyDecNet;
- case os::kAddressFamilyAppleTalk:
- return kAddressFamilyAppleTalk;
- // #ifdef AF_INET6
- case os::kAddressFamilyInterNetworkV6:
- return kAddressFamilyInterNetworkV6;
- // #endif
- // #ifdef AF_IRDA
- case os::kAddressFamilyIrda:
- return kAddressFamilyIrda;
- // #endif
- default:
- break;
- }
- return kAddressFamilyUnknown;
- }
- static os::SocketFlags convert_socket_flags(SocketFlags flags)
- {
- return (os::SocketFlags)flags;
- }
- static Il2CppSocketAddress* end_point_info_to_socket_address(const os::EndPointInfo &info)
- {
- static Il2CppClass *System_Net_SocketAddress = NULL;
- Il2CppSocketAddress *socket_address = NULL;
- if (!System_Net_SocketAddress)
- {
- System_Net_SocketAddress = vm::Class::FromName(
- vm::Assembly::GetImage(
- vm::Assembly::Load("System.dll")),
- "System.Net", "SocketAddress");
- }
- socket_address = (Il2CppSocketAddress*)vm::Object::New(System_Net_SocketAddress);
- const AddressFamily family = convert_from_os_address_family(info.family);
- if (info.family == os::kAddressFamilyInterNetwork)
- {
- socket_address->m_Size = 8;
- IL2CPP_OBJECT_SETREF(socket_address, data, vm::Array::New(il2cpp_defaults.byte_class, 8));
- const uint16_t port = info.data.inet.port;
- const uint32_t address = info.data.inet.address;
- il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 2, (port >> 8) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 3, (port >> 0) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 4, (address >> 24) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 5, (address >> 16) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 6, (address >> 8) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 7, (address >> 0) & 0xFF);
- }
- else if (info.family == os::kAddressFamilyUnix)
- {
- const int32_t path_len = (int32_t)strlen(info.data.path);
- socket_address->m_Size = 3 + path_len;
- IL2CPP_OBJECT_SETREF(socket_address, data, vm::Array::New(il2cpp_defaults.byte_class, 3 + path_len));
- il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF);
- for (int32_t i = 0; i <= path_len; i++)
- il2cpp_array_set(socket_address->data, uint8_t, i + 2, info.data.path[i]);
- il2cpp_array_set(socket_address->data, uint8_t, 2 + path_len, 0);
- }
- else if (info.family == os::kAddressFamilyInterNetworkV6)
- {
- socket_address->m_Size = 28;
- IL2CPP_OBJECT_SETREF(socket_address, data, vm::Array::New(il2cpp_defaults.byte_class, 28));
- il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF);
- il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF);
- // Note that we start at the 3rd byte in both the managed array, where the first
- // two bytes are the family, set just above this. We also start at the third byte
- // in the info.data.raw array, as the first two bytes are unused and garbage data.
- for (int i = 2; i < 28; ++i)
- il2cpp_array_set(socket_address->data, uint8_t, i, info.data.raw[i]);
- }
- else
- {
- // Not supported
- return NULL;
- }
- return socket_address;
- }
- static bool check_thread_status()
- {
- static baselib::ReentrantLock _mutex;
- os::FastAutoLock lock(&_mutex);
- Il2CppThread *current_thread = vm::Thread::Current();
- const vm::ThreadState state = vm::Thread::GetState(current_thread);
- if (state & vm::kThreadStateAbortRequested)
- return false;
- if (state & vm::kThreadStateSuspendRequested)
- {
- IL2CPP_ASSERT(0 && "kThreadStateSuspendRequested not supported yet!");
- return true;
- }
- if (state & vm::kThreadStateStopRequested)
- return false;
- if (current_thread->GetInternalThread()->interruption_requested)
- {
- IL2CPP_ASSERT(0 && "thread->interruption_requested not supported yet!");
- return false;
- }
- return true;
- }
- /// Acquire os::SocketHandle in IntPtr "socket" for the current scope.
- #define AUTO_ACQUIRE_SOCKET \
- os::SocketHandleWrapper socketHandle (os::PointerToSocketHandle (reinterpret_cast<void*>(socket)))
- #define RETURN_IF_SOCKET_IS_INVALID(...) \
- if (!socketHandle.IsValid ()) \
- { \
- *error = os::kErrorCodeInvalidHandle; \
- return __VA_ARGS__; \
- }
- intptr_t Socket::Accept_icall(intptr_t socket, int32_t* error, bool blocking)
- {
- *error = 0;
- os::Socket *new_sock = NULL;
- AUTO_ACQUIRE_SOCKET;
- if (socketHandle.IsValid())
- {
- const os::WaitStatus status = socketHandle->Accept(&new_sock);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else
- {
- *error = os::kErrorCodeInvalidHandle;
- }
- intptr_t ret;
- if (new_sock)
- ret = static_cast<intptr_t>(os::CreateSocketHandle(new_sock));
- else
- ret = static_cast<intptr_t>(os::kInvalidSocketHandle);
- return ret;
- }
- bool Socket::SupportsPortReuse(int32_t proto)
- {
- IL2CPP_NOT_IMPLEMENTED_ICALL(Socket::SupportsPortReuse);
- return false;
- }
- int32_t Socket::Available_icall(intptr_t socket, int32_t* error)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(0);
- int32_t available = 0;
- const os::WaitStatus status = socketHandle->Available(&available);
- if (status == kWaitStatusFailure)
- {
- *error = socketHandle->GetLastError();
- return 0;
- }
- return available;
- }
- void UnpackIPv6AddressFromBuffer(const uint8_t* buffer, int32_t length, uint16_t* port, uint8_t* address, uint32_t* scope)
- {
- if (length < 28)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return;
- }
- *port = ((buffer[2] << 8) | buffer[3]);
- for (int i = 0; i < ipv6AddressSize; i++)
- address[i] = buffer[i + 8];
- *scope = (uint32_t)((buffer[27] << 24) +
- (buffer[26] << 16) +
- (buffer[25] << 8) +
- (buffer[24]));
- }
- void Socket::Bind_icall(intptr_t socket, Il2CppSocketAddress* socket_address, int32_t* error)
- {
- *error = 0;
- const int32_t length = ARRAY_LENGTH_AS_INT32(socket_address->data->max_length);
- const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data);
- if (length < 2)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return;
- }
- const os::AddressFamily family = convert_address_family((AddressFamily)(buffer[0] | (buffer[1] << 8)));
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- if (family == os::kAddressFamilyInterNetwork)
- {
- if (length < 8)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return;
- }
- const uint16_t port = ((buffer[2] << 8) | buffer[3]);
- const uint32_t address = ((buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]);
- const os::WaitStatus status = socketHandle->Bind(address, port);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyUnix)
- {
- if (length - 2 >= END_POINT_MAX_PATH_LEN)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return;
- }
- char path[END_POINT_MAX_PATH_LEN] = {0};
- for (int32_t i = 0; i < (length - 2); ++i)
- {
- path[i] = (char)buffer[i + 2];
- }
- const os::WaitStatus status = socketHandle->Bind(path);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyInterNetworkV6)
- {
- uint16_t port;
- uint8_t address[ipv6AddressSize] = {0};
- uint32_t scope;
- UnpackIPv6AddressFromBuffer(buffer, length, &port, address, &scope);
- auto status = socketHandle->Bind(address, scope, port);
- vm::Exception::RaiseIfError(status.GetError());
- if (status.Get() == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else
- {
- *error = os::kWSAeafnosupport;
- return;
- }
- }
- void Socket::Blocking_icall(intptr_t socket, bool block, int32_t* error)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- const os::WaitStatus status = socketHandle->SetBlocking(block);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- void Socket::Close_icall(intptr_t socket, int32_t* error)
- {
- *error = 0;
- // Socket::Close get invoked when running the finalizers; in case Socket_internal
- // didn't succeed, the socket has a NULL value and thus we don't need to do
- // anything here.
- if (os::PointerToSocketHandle(reinterpret_cast<void*>(socket)) == os::kInvalidSocketHandle)
- return;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- // There is an implicit acquisition happening when we create the socket which we undo
- // now that we have closed the socket.
- os::ReleaseSocketHandle(socketHandle.GetHandle(), socketHandle.GetSocket(), true);
- socketHandle->Close();
- }
- void Socket::Connect_icall(intptr_t socket, Il2CppSocketAddress* socket_address, int32_t* error, bool blocking)
- {
- *error = 0;
- const int32_t length = ARRAY_LENGTH_AS_INT32(socket_address->data->max_length);
- const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data);
- if (length < 2)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return;
- }
- const os::AddressFamily family = convert_address_family((AddressFamily)(buffer[0] | (buffer[1] << 8)));
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- if (family == os::kAddressFamilyInterNetwork)
- {
- if (length < 8)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return;
- }
- const uint16_t port = ((buffer[2] << 8) | buffer[3]);
- const uint32_t address = ((buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]);
- const os::WaitStatus status = socketHandle->Connect(address, port);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyUnix)
- {
- if (length - 2 >= END_POINT_MAX_PATH_LEN)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return;
- }
- char path[END_POINT_MAX_PATH_LEN] = {0};
- for (int32_t i = 0; i < (length - 2); ++i)
- {
- path[i] = (char)buffer[i + 2];
- }
- const os::WaitStatus status = socketHandle->Connect(path);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyInterNetworkV6)
- {
- uint16_t port;
- uint8_t address[ipv6AddressSize] = {0};
- uint32_t scope;
- UnpackIPv6AddressFromBuffer(buffer, length, &port, address, &scope);
- auto status = socketHandle->Connect(address, scope, port);
- vm::Exception::RaiseIfError(status.GetError());
- if (status.Get() == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else
- {
- *error = os::kWSAeafnosupport;
- return;
- }
- }
- void Socket::Disconnect_icall(intptr_t socket, bool reuse, int32_t* error)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- const os::WaitStatus status = socketHandle->Disconnect(reuse);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- void Socket::GetSocketOption_arr_icall(intptr_t socket, SocketOptionLevel level, SocketOptionName name, Il2CppArray** byte_val, int32_t *error)
- {
- *error = 0;
- // Note: for now the options map one to one.
- const os::SocketOptionName system_name = (os::SocketOptionName)(name);
- const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level);
- int32_t length = ARRAY_LENGTH_AS_INT32((*byte_val)->max_length);
- uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress((*byte_val));
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- const os::WaitStatus status = socketHandle->GetSocketOption(system_level, system_name, buffer, &length);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- void Socket::GetSocketOption_obj_icall(intptr_t socket, SocketOptionLevel level, SocketOptionName name, Il2CppObject** obj_val, int32_t *error)
- {
- *error = 0;
- // Note: for now the options map one to one.
- const os::SocketOptionName system_name = (os::SocketOptionName)(name);
- const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level);
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- int32_t first = 0;
- int32_t second = 0;
- const os::WaitStatus status = socketHandle->GetSocketOptionFull(system_level, system_name, &first, &second);
- if (status == kWaitStatusFailure)
- {
- *error = socketHandle->GetLastError();
- return;
- }
- switch (name)
- {
- case kSocketOptionNameLinger:
- {
- static Il2CppClass *System_Net_Sockets_LingerOption = NULL;
- if (!System_Net_Sockets_LingerOption)
- {
- System_Net_Sockets_LingerOption = vm::Class::FromName(
- vm::Assembly::GetImage(
- vm::Assembly::Load("System.dll")),
- "System.Net.Sockets", "LingerOption");
- }
- *obj_val = vm::Object::New(System_Net_Sockets_LingerOption);
- const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "enabled");
- const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "lingerTime");
- *((bool*)((char*)(*obj_val) + enabled_field_info->offset)) = (first ? 1 : 0);
- *((int32_t*)((char*)(*obj_val) + seconds_field_info->offset)) = second;
- }
- break;
- case kSocketOptionNameDontLinger:
- case kSocketOptionNameSendTimeout:
- case kSocketOptionNameReceiveTimeout:
- default:
- *obj_val = vm::Object::Box(il2cpp_defaults.int32_class, &first);
- break;
- }
- }
- void Socket::Listen_icall(intptr_t socket, int32_t backlog, int32_t* error)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- const os::WaitStatus status = socketHandle->Listen(backlog);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- static os::PollFlags select_mode_to_poll_flags(SelectMode mode)
- {
- switch (mode)
- {
- case kSelectModeSelectRead:
- return os::kPollFlagsIn;
- case kSelectModeSelectWrite:
- return os::kPollFlagsOut;
- case kSelectModeSelectError:
- return os::kPollFlagsErr;
- }
- return os::kPollFlagsNone;
- }
- bool Socket::Poll_icall(intptr_t socket, SelectMode mode, int32_t timeout, int32_t* error)
- {
- *error = 0;
- os::PollRequest request;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(false);
- request.fd = socketHandle.GetSocket()->GetDescriptor();
- request.events = select_mode_to_poll_flags(mode);
- request.revents = os::kPollFlagsNone;
- if (request.events == os::kPollFlagsNone)
- {
- *error = os::kWSAefault;
- return false;
- }
- std::vector<os::PollRequest> requests;
- requests.push_back(request);
- // The timeout from managed code is in microseconds. Convert it to milliseconds
- // for the poll implementation.
- timeout = (timeout >= 0) ? (timeout / 1000) : -1;
- int32_t results = 0;
- const os::WaitStatus result = os::Socket::Poll(requests, timeout, &results, error);
- if (result == kWaitStatusFailure || results == 0)
- return false;
- return (requests[0].revents != os::kPollFlagsNone);
- }
- int32_t Socket::Receive_array_icall(intptr_t socket, os::WSABuf* bufarray, int32_t count, SocketFlags flags, int32_t *error, bool blocking)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(0);
- const os::SocketFlags c_flags = convert_socket_flags(flags);
- int32_t len = 0;
- const os::WaitStatus status = socketHandle->ReceiveArray(bufarray, count, &len, c_flags);
- if (status == kWaitStatusFailure)
- {
- *error = socketHandle->GetLastError();
- return 0;
- }
- return len;
- }
- int32_t Socket::Receive_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, int32_t* error, bool blocking)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(0);
- const os::SocketFlags c_flags = convert_socket_flags(flags);
- int32_t len = 0;
- const os::WaitStatus status = socketHandle->Receive(buffer, count, c_flags, &len);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- return len;
- }
- int32_t Socket::ReceiveFrom_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, Il2CppSocketAddress** socket_address, int32_t* error, bool blocking)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(0);
- const os::SocketFlags c_flags = convert_socket_flags(flags);
- int32_t len = 0;
- const int32_t length = ARRAY_LENGTH_AS_INT32((*socket_address)->data->max_length);
- const uint8_t *socket_buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress((*socket_address)->data);
- if (length < 2)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return 0;
- }
- const os::AddressFamily family = convert_address_family((AddressFamily)(socket_buffer[0] | (socket_buffer[1] << 8)));
- os::EndPointInfo info;
- info.family = os::kAddressFamilyError;
- if (family == os::kAddressFamilyInterNetwork)
- {
- if (length < 8)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return 0;
- }
- const uint16_t port = ((socket_buffer[2] << 8) | socket_buffer[3]);
- const uint32_t address = ((socket_buffer[4] << 24) | (socket_buffer[5] << 16) | (socket_buffer[6] << 8) | socket_buffer[7]);
- const os::WaitStatus status = socketHandle->RecvFrom(address, port, buffer, count, c_flags, &len, info);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyUnix)
- {
- if (length - 2 >= END_POINT_MAX_PATH_LEN)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return 0;
- }
- char path[END_POINT_MAX_PATH_LEN] = {0};
- for (int32_t i = 0; i < (length - 2); ++i)
- {
- path[i] = (char)socket_buffer[i + 2];
- }
- auto status = socketHandle->RecvFrom(path, buffer, count, c_flags, &len, info);
- vm::Exception::RaiseIfError(status.GetError());
- if (status.Get() == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyInterNetworkV6)
- {
- uint16_t port;
- uint8_t address[ipv6AddressSize] = {0};
- uint32_t scope;
- UnpackIPv6AddressFromBuffer(socket_buffer, length, &port, address, &scope);
- auto status = socketHandle->RecvFrom(address, scope, port, buffer, count, c_flags, &len, info);
- vm::Exception::RaiseIfError(status.GetError());
- if (status.Get() == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else
- {
- *error = os::kWSAeafnosupport;
- return 0;
- }
- *socket_address = (info.family == os::kAddressFamilyError) ? NULL : end_point_info_to_socket_address(info);
- return len;
- }
- Il2CppSocketAddress* Socket::LocalEndPoint_icall(intptr_t socket, int32_t family, int32_t* error)
- {
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(NULL);
- os::EndPointInfo info;
- memset(&info, 0x00, sizeof(os::EndPointInfo));
- const os::WaitStatus status = socketHandle->GetLocalEndPointInfo(info);
- if (status == kWaitStatusFailure)
- {
- *error = socketHandle->GetLastError();
- return NULL;
- }
- Il2CppSocketAddress *socket_address = end_point_info_to_socket_address(info);
- if (socket_address == NULL)
- *error = os::kWSAeafnosupport;
- return socket_address;
- }
- Il2CppSocketAddress* Socket::RemoteEndPoint_icall(intptr_t socket, int32_t family, int32_t* error)
- {
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(NULL);
- os::EndPointInfo info;
- memset(&info, 0x00, sizeof(os::EndPointInfo));
- const os::WaitStatus status = socketHandle->GetRemoteEndPointInfo(info);
- if (status == kWaitStatusFailure)
- {
- *error = socketHandle->GetLastError();
- return NULL;
- }
- Il2CppSocketAddress *socket_address = end_point_info_to_socket_address(info);
- if (socket_address == NULL)
- *error = os::kWSAeafnosupport;
- return socket_address;
- }
- void Socket::Select_icall(Il2CppArray** sockets, int32_t timeout, int32_t* error)
- {
- *error = 0;
- // Layout: READ, null, WRITE, null, ERROR, null
- const uint32_t input_sockets_count = ARRAY_LENGTH_AS_INT32((*sockets)->max_length);
- std::vector<os::PollRequest> requests;
- std::vector<os::SocketHandleWrapper> socketHandles;
- requests.reserve(input_sockets_count - 3);
- int32_t mode = 0;
- for (uint32_t i = 0; i < input_sockets_count; ++i)
- {
- Il2CppObject *obj = il2cpp_array_get(*sockets, Il2CppObject*, i);
- if (obj == NULL)
- {
- if (++mode > 3)
- {
- // Something very bad happened here (ie: the input array was wrong)
- // so we gracefully terminate the method.
- *error = os::kWSAefault;
- return;
- }
- continue;
- }
- FieldInfo *safe_handle_field_info = vm::Class::GetFieldFromName(obj->klass, "m_Handle");
- const Il2CppObject* value = NULL;
- vm::Field::GetValue(obj, safe_handle_field_info, &value);
- const FieldInfo *handle_field_info = vm::Class::GetFieldFromName(value->klass, "handle");
- intptr_t& intPtr = *((intptr_t*)((char*)value + handle_field_info->offset));
- // Acquire socket.
- socketHandles.push_back(os::SocketHandleWrapper());
- os::SocketHandleWrapper& socketHandle = socketHandles.back();
- socketHandle.Acquire(os::PointerToSocketHandle(reinterpret_cast<void*>(intPtr)));
- os::PollRequest request;
- // May 'invalid socket' (-1); we want the error from Poll() in that case.
- request.fd = socketHandle.GetSocket() == NULL ? -1 : socketHandle.GetSocket()->GetDescriptor();
- request.events = (mode == 0 ? os::kPollFlagsIn : (mode == 1 ? os::kPollFlagsOut : os::kPollFlagsErr));
- request.revents = os::kPollFlagsNone;
- requests.push_back(request);
- }
- if (requests.size() == 0)
- return;
- int32_t results = 0;
- // The timeout from managed code is in microseconds. Convert it to milliseconds
- // for the poll implementation.
- timeout = (timeout >= 0) ? (timeout / 1000) : -1;
- const os::WaitStatus result = os::Socket::Poll(requests, timeout, &results, error);
- if (result == kWaitStatusFailure)
- {
- *sockets = NULL;
- return;
- }
- Il2CppArray *new_sockets = vm::Array::New(((Il2CppObject*)(*sockets))->klass->element_class, results + 3);
- if (results > 0)
- {
- mode = 0;
- uint32_t request_index = 0;
- // This odd loop is due to the layout of the sockets input array:
- // Layout: READ, null, WRITE, null, ERROR, null
- // We need to iterate each request and iterate the sockets array, skipping
- // the null entries. We try to avoid an infinite loop here as well.
- uint32_t add_index = 0;
- while (request_index < requests.size())
- {
- const uint32_t input_sockets_index = (request_index + mode);
- if (input_sockets_index > input_sockets_count - 1)
- break; // We have exhausted the input sockets array, so exit.
- Il2CppObject *obj = il2cpp_array_get(*sockets, Il2CppObject*, input_sockets_index);
- if (obj == NULL)
- {
- ++mode;
- continue; // Here is a null entry, skip it without updated the next request index.
- }
- os::PollRequest &request = requests[request_index];
- if (request.revents != os::kPollFlagsNone)
- {
- switch (mode)
- {
- case 0:
- if (request.revents & (os::kPollFlagsIn | os::kPollFlagsErr))
- {
- il2cpp_array_setref(new_sockets, (add_index + mode), obj);
- add_index++;
- }
- break;
- case 1:
- if (request.revents & (os::kPollFlagsOut | os::kPollFlagsErr))
- {
- il2cpp_array_setref(new_sockets, (add_index + mode), obj);
- add_index++;
- }
- break;
- default:
- if (request.revents & os::kPollFlagsErr)
- {
- il2cpp_array_setref(new_sockets, (add_index + mode), obj);
- add_index++;
- }
- break;
- }
- }
- ++request_index;
- }
- }
- *sockets = new_sockets;
- }
- bool Socket::SendFile_icall(intptr_t socket, Il2CppString* filename, Il2CppArray* pre_buffer, Il2CppArray* post_buffer, TransmitFileOptions flags, int32_t* error, bool blocking)
- {
- if (filename == NULL)
- return false;
- os::TransmitFileBuffers t_buffers = {0};
- if (pre_buffer != NULL)
- {
- t_buffers.head = il2cpp_array_addr(pre_buffer, uint8_t, 0);
- t_buffers.head_length = ARRAY_LENGTH_AS_INT32(pre_buffer->max_length);
- }
- if (post_buffer != NULL)
- {
- t_buffers.tail = il2cpp_array_addr(post_buffer, uint8_t, 0);
- t_buffers.tail_length = ARRAY_LENGTH_AS_INT32(post_buffer->max_length);
- }
- AUTO_ACQUIRE_SOCKET;
- if (!socketHandle.IsValid())
- return false;
- const Il2CppChar* ustr = utils::StringUtils::GetChars(filename);
- const std::string str = utils::StringUtils::Utf16ToUtf8(ustr);
- // Note: for now they map 1-1
- const os::TransmitFileOptions o_flags = (os::TransmitFileOptions)flags;
- const os::WaitStatus status = socketHandle->SendFile(str.c_str(), &t_buffers, o_flags);
- if (status == kWaitStatusFailure)
- {
- // TODO: mono stores socketHandle->GetLastError into a threadlocal global variable
- // that can be retrieved later by other icalls.
- return false;
- }
- if ((flags & kTransmitFileOptionsDisconnect) == kTransmitFileOptionsDisconnect)
- socketHandle->Disconnect(true);
- return true;
- }
- int32_t Socket::SendTo_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, Il2CppSocketAddress* socket_address, int32_t* error, bool blocking)
- {
- *error = 0;
- const os::SocketFlags c_flags = convert_socket_flags(flags);
- int32_t len = 0;
- const int32_t length = ARRAY_LENGTH_AS_INT32(socket_address->data->max_length);
- const uint8_t *socket_buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data);
- if (length < 2)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return 0;
- }
- const os::AddressFamily family = convert_address_family((AddressFamily)(socket_buffer[0] | (socket_buffer[1] << 8)));
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(0);
- if (family == os::kAddressFamilyInterNetwork)
- {
- if (length < 8)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return 0;
- }
- const uint16_t port = ((socket_buffer[2] << 8) | socket_buffer[3]);
- const uint32_t address = ((socket_buffer[4] << 24) | (socket_buffer[5] << 16) | (socket_buffer[6] << 8) | socket_buffer[7]);
- const os::WaitStatus status = socketHandle->SendTo(address, port, buffer, count, c_flags, &len);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyUnix)
- {
- if (length - 2 >= END_POINT_MAX_PATH_LEN)
- {
- vm::Exception::Raise(vm::Exception::GetSystemException());
- return 0;
- }
- char path[END_POINT_MAX_PATH_LEN] = {0};
- for (int32_t i = 0; i < (length - 2); ++i)
- {
- path[i] = (char)socket_buffer[i + 2];
- }
- auto status = socketHandle->SendTo(path, buffer, count, c_flags, &len);
- vm::Exception::RaiseIfError(status.GetError());
- if (status.Get() == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else if (family == os::kAddressFamilyInterNetworkV6)
- {
- uint16_t port;
- uint8_t address[ipv6AddressSize] = {0};
- uint32_t scope;
- UnpackIPv6AddressFromBuffer(socket_buffer, length, &port, address, &scope);
- auto status = socketHandle->SendTo(address, scope, port, buffer, count, c_flags, &len);
- vm::Exception::RaiseIfError(status.GetError());
- if (status.Get() == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- else
- {
- *error = os::kWSAeafnosupport;
- return 0;
- }
- return len;
- }
- int32_t Socket::Send_array_icall(intptr_t socket, os::WSABuf* bufarray, int32_t count, SocketFlags flags, int32_t* error, bool blocking)
- {
- *error = 0;
- const os::SocketFlags c_flags = convert_socket_flags(flags);
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(0);
- int32_t sent = 0;
- const os::WaitStatus status = socketHandle->SendArray(bufarray, count, &sent, c_flags);
- if (status == kWaitStatusFailure)
- {
- *error = socketHandle->GetLastError();
- return 0;
- }
- return sent;
- }
- int32_t Socket::Send_icall(intptr_t socket, uint8_t* buffer, int32_t count, SocketFlags flags, int32_t* error, bool blocking)
- {
- *error = 0;
- const os::SocketFlags c_flags = convert_socket_flags(flags);
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(0);
- int32_t len = 0;
- const os::WaitStatus status = socketHandle->Send(buffer, count, c_flags, &len);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- return len;
- }
- #if IL2CPP_SUPPORT_IPV6
- static os::IPv6Address ipaddress_to_ipv6_addr(Il2CppObject *ipaddr)
- {
- FieldInfo* numbersFieldInfo = vm::Class::GetFieldFromName(ipaddr->klass, "_numbers");
- IL2CPP_ASSERT(numbersFieldInfo);
- Il2CppArray* data = (Il2CppArray*)vm::Field::GetValueObject(numbersFieldInfo, ipaddr);
- os::IPv6Address ipv6;
- for (int i = 0; i < 8; i++)
- {
- uint16_t s = il2cpp_array_get(data, uint16_t, i);
- ipv6.addr[2 * i] = (s >> 8) & 0xff;
- ipv6.addr[2 * i + 1] = s & 0xff;
- }
- return ipv6;
- }
- static void GetAddressAndInterfaceFromObject(Il2CppObject* object, const char* groupField, const char* interfaceField,
- os::IPv6Address& ipv6, uint64_t& interfaceOffset)
- {
- FieldInfo* groupFieldInfo = vm::Class::GetFieldFromName(object->klass, groupField);
- IL2CPP_ASSERT(groupFieldInfo);
- Il2CppObject* address = vm::Field::GetValueObject(groupFieldInfo, object);
- if (address)
- ipv6 = ipaddress_to_ipv6_addr(address);
- FieldInfo* interfaceFieldInfo = vm::Class::GetFieldFromName(object->klass, interfaceField);
- IL2CPP_ASSERT(interfaceFieldInfo);
- vm::Field::GetValue(object, interfaceFieldInfo, &interfaceOffset);
- }
- #endif // IL2CPP_SUPPORT_IPV6
- void Socket::SetSocketOption_icall(intptr_t socket, SocketOptionLevel level, SocketOptionName name, Il2CppObject* obj_val, Il2CppArray* byte_val, int32_t int_val, int32_t* error)
- {
- *error = 0;
- // Note: for now the options map one to one.
- const os::SocketOptionName system_name = (os::SocketOptionName)(name);
- const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level);
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- os::WaitStatus status = kWaitStatusFailure;
- if (byte_val != NULL)
- {
- const int32_t length = ARRAY_LENGTH_AS_INT32(byte_val->max_length);
- const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(byte_val);
- status = socketHandle->SetSocketOptionArray(system_level, system_name, buffer, length);
- }
- else if (obj_val != NULL)
- {
- switch (name)
- {
- case kSocketOptionNameLinger:
- {
- const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(obj_val->klass, "enabled");
- const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(obj_val->klass, "lingerTime");
- const bool enabled = *((bool*)((char*)obj_val + enabled_field_info->offset));
- const int32_t seconds = *((int32_t*)((char*)obj_val + seconds_field_info->offset));
- status = socketHandle->SetSocketOptionLinger(system_level, system_name, enabled, seconds);
- }
- break;
- case kSocketOptionNameAddMembership:
- case kSocketOptionNameDropMembership:
- {
- #if IL2CPP_SUPPORT_IPV6
- if (system_level == (os::SocketOptionLevel)kSocketOptionLevelIPv6)
- {
- os::IPv6Address ipv6 = {{0}};
- uint64_t interfaceOffset;
- GetAddressAndInterfaceFromObject(obj_val, "m_Group", "m_Interface", ipv6, interfaceOffset);
- status = socketHandle->SetSocketOptionMembership(system_level, system_name, ipv6, interfaceOffset);
- }
- else if (system_level == (os::SocketOptionLevel)kSocketOptionLevelIP)
- #endif // IL2CPP_SUPPORT_IPV6
- {
- FieldInfo *group_field_info = vm::Class::GetFieldFromName(obj_val->klass, "group");
- Il2CppObject* group_obj = vm::Field::GetValueObject(group_field_info, obj_val);
- const FieldInfo *group_address_field_info = vm::Class::GetFieldFromName(group_obj->klass, "_addressOrScopeId");
- IL2CPP_ASSERT(group_address_field_info != NULL);
- const uint32_t group_address = *((uint32_t*)(uint64_t*)((char*)group_obj + group_address_field_info->offset));
- uint32_t local_address = 0;
- FieldInfo *local_field_info = vm::Class::GetFieldFromName(obj_val->klass, "localAddress");
- if (local_field_info != NULL)
- {
- Il2CppObject* local_obj = vm::Field::GetValueObject(local_field_info, obj_val);
- if (local_obj != NULL)
- {
- const FieldInfo *local_address_field_info = vm::Class::GetFieldFromName(local_obj->klass, "_addressOrScopeId");
- IL2CPP_ASSERT(local_address_field_info != NULL);
- local_address = *((uint32_t*)(uint64_t*)((char*)local_obj + local_address_field_info->offset));
- }
- }
- status = socketHandle->SetSocketOptionMembership(system_level, system_name, group_address, local_address);
- }
- }
- break;
- default:
- *error = os::kWSAeinval;
- return; // early out
- }
- }
- else
- status = socketHandle->SetSocketOption(system_level, system_name, int_val);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- void Socket::Shutdown_icall(intptr_t socket, SocketShutdown how, int32_t* error)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID();
- const os::WaitStatus status = socketHandle->Shutdown(how);
- if (status == kWaitStatusFailure)
- *error = socketHandle->GetLastError();
- }
- intptr_t Socket::Socket_icall(AddressFamily family, SocketType type, ProtocolType protocol, int32_t* error)
- {
- intptr_t socket = static_cast<intptr_t>(os::kInvalidSocketHandle);
- *error = 0;
- os::AddressFamily n_family = convert_address_family(family);
- os::SocketType n_type = convert_socket_type(type);
- os::ProtocolType n_protocol = convert_socket_protocol(protocol);
- if (n_family == os::kAddressFamilyError)
- {
- *error = os::kWSAeafnosupport;
- return socket;
- }
- if (n_type == os::kSocketTypeError)
- {
- *error = os::kWSAesocktnosupport;
- return socket;
- }
- if (n_protocol == os::kProtocolTypeUnknown)
- {
- *error = os::kWSAeprotonosupport;
- return socket;
- }
- os::Socket *sock = new os::Socket(check_thread_status);
- const os::WaitStatus status = sock->Create(n_family, n_type, n_protocol);
- if (status == kWaitStatusFailure)
- {
- *error = sock->GetLastError();
- // Okay to delete socket directly. We haven't created a handle yet.
- delete sock;
- return socket;
- }
- os::SocketHandle socketHandle = os::CreateSocketHandle(sock);
- socket = static_cast<intptr_t>(socketHandle);
- return socket;
- }
- int32_t Socket::IOControl_icall(intptr_t socket, int32_t ioctl_code, Il2CppArray* input, Il2CppArray* output, int32_t* error)
- {
- *error = 0;
- AUTO_ACQUIRE_SOCKET;
- RETURN_IF_SOCKET_IS_INVALID(-1);
- if (ioctl_code == 0x5421 /* FIONBIO */)
- {
- // Invalid command. Must use Socket.Blocking
- return -1;
- }
- const int32_t in_length = (input ? ARRAY_LENGTH_AS_INT32(input->max_length) : 0);
- const uint8_t *in_buffer = (input ? (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(input) : NULL);
- const int32_t out_length = (output ? ARRAY_LENGTH_AS_INT32(output->max_length) : 0);
- uint8_t *out_buffer = (output ? (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(output) : NULL);
- int32_t output_bytes = 0;
- const os::WaitStatus status = socketHandle->Ioctl(ioctl_code, in_buffer, in_length, out_buffer, out_length, &output_bytes);
- if (status == kWaitStatusFailure)
- {
- *error = socketHandle->GetLastError();
- return -1;
- }
- return output_bytes;
- }
- static void STDCALL
- abort_apc(void* param)
- {
- }
- void Socket::cancel_blocking_socket_operation(Il2CppObject* thread)
- {
- Il2CppThread* t = reinterpret_cast<Il2CppThread*>(thread);
- t->internal_thread->handle->QueueUserAPC(abort_apc, NULL);
- // IL2CPP_NOT_IMPLEMENTED_ICALL(Socket::cancel_blocking_socket_operation);
- //IL2CPP_UNREACHABLE;
- }
- bool Socket::Duplicate_icall(intptr_t handle, int32_t targetProcessId, intptr_t* duplicateHandle, int32_t* error)
- {
- IL2CPP_NOT_IMPLEMENTED_ICALL(Socket::Duplicate_icall);
- return false;
- }
- bool Socket::IsProtocolSupported_internal(int32_t networkInterface)
- {
- // The networkInterface argument is from the
- // System.Net.NetworkInformation.NetworkInterfaceComponent enum
- // 0 => IPv4
- // 1 => IPv6
- #if IL2CPP_SUPPORT_IPV6_SUPPORT_QUERY
- return networkInterface == 1 ? os::Socket::IsIPv6Supported() : true;
- #elif IL2CPP_SUPPORT_IPV6
- // This platform supports both IPv6 and IPv4.
- return true;
- #else
- // This platform only supports IPv4.
- return networkInterface == 0;
- #endif
- }
- } /* namespace Sockets */
- } /* namespace Net */
- } /* namespace System */
- } /* namespace System */
- } /* namespace icalls */
- } /* namespace il2cpp */
|