123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965(* $Id$ *)openPrintfmoduleDebug=structletenable=reffalseendletdlog=Netlog.Debug.mk_dlog"Netsys" Debug.enableletdlogr=Netlog.Debug.mk_dlogr"Netsys"Debug.enablelet()=Netlog.Debug.register_module"Netsys"Debug.enableexceptionShutdown_not_supportedletis_win32=Sys.os_type="Win32"externalnetsys_is_darwin:unit->bool="netsys_is_darwin"letis_darwin=netsys_is_darwin()external int64_of_file_descr:Unix.file_descr->int64="netsys_int64_of_file_descr"(* Also occurs in netsys_win32.ml! *)letis_letter=function|'a'..'z' ->true|'A'..'Z'->true|_->falseletis_absolutepath=ifis_win32then(String.lengthpath>=3&&is_letter path.[0]&&path.[1]=':' &&(path.[2]='/'||path.[2]='\\'))||(String.lengthpath>=2&&(path.[0]='/'||path.[0]='\\')&&(path.[1]='/'||path.[1]='\\'))elsepath<>""&&path.[0]='/'letabspath_w32path=(* full path: resolves relative paths, and eliminates . and ..
long path: gets away with 8.3 paths, and converts file name case
*)Netsys_win32.get_long_path_name(Netsys_win32.get_full_path_namepath)letabspathpath=ifis_win32thenabspath_w32 pathelsetryNetsys_posix.realpathpathwith|Invalid_argument _->(* this is sub-standard, let's hope we never run into this *)ifis_absolutepaththenpathelseFilename.concat(Unix.getcwd())pathlet restart=Netsys_impl_util.restartletrestart_tmo=Netsys_impl_util.restart_tmoletrestarting_selectfd_rdfd_wrfd_oobtmo=restart_tmo(Unix.selectfd_rdfd_wrfd_oob)tmoletsleept=letselect=ifis_win32thenNetsys_win32.real_selectelseUnix.selectinlet_,_,_=select [][][]tin()letrestarting_sleep t=restart_tmosleeptletgetpeernamefd=tryUnix.getpeername fdwith|Unix.Unix_error(Unix.EINVAL,a1,a2)->(* SUS defines EINVAL as "socket has been shut down". This is a bit
* surprising for developers of Open Source OS where this is reported
* as ENOTCONN. We map it here.
*)raise(Unix.Unix_error(Unix.ENOTCONN,a1,a2))letdomain_of_inet_addraddr=Unix.domain_of_sockaddr(Unix.ADDR_INET(addr,0))letprotostring_of_inet_addrip=(Obj.magicip)letinet_addr_of_protostring s=letl=String.lengthsinifl=4||l=16then(Obj.magics)elseinvalid_arg"Netsys.inet_addr_of_protostring"external_exit:int->unit="netsys__exit";;(* same external also in netsys_signal.ml *)letbinop_inet_addrf(ip1:Unix.inet_addr)(ip2:Unix.inet_addr)=lets1=(Obj.magicip1 :string)inlets2=(Obj.magicip2:string)inletl=String.length s1inifl<>String.lengths2thenfailwith"logand_inet_addr";lets3=Bytes.createlinfork=0tol-1doBytes.sets3k(Char.chr(f(Char.codes1.[k])(Char.codes2.[k])));done;(Obj.magics3:Unix.inet_addr)letlogand_inet_addr=binop_inet_addr(land)letlogor_inet_addr=binop_inet_addr(lor)letlogxor_inet_addr=binop_inet_addr(lxor)letlognot_inet_addrip=binop_inet_addr(fun p1p2->lnotp1)ipipletnorm_inet_addr(ip:Unix.inet_addr)=ifString.length(Obj.magicip)=16thenletip1=logand_inet_addrip(Unix.inet_addr_of_string"ffff:ffff:ffff:ffff:ffff:ffff::0")inif(ip1=(Unix.inet_addr_of_string"0000:0000:0000:0000:0000:ffff::0")||ip1=(Unix.inet_addr_of_string"0000:0000:0000:0000:0000:0000::0"))&&ip<>Unix.inet6_addr_any&&ip<>Unix.inet6_addr_loopbackthenObj.magic(String.sub(Obj.magicip)124)elseipelseipletipv6_inet_addr(ip:Unix.inet_addr)=ifString.length(Obj.magicip)=4thenObj.magic(String.make10'\x00'^String.make2'\xff'^Obj.magicip)elseipletis_ipv4_inet_addr (ip :Unix.inet_addr)=String.length(Obj.magic (norm_inet_addrip))=4letis_ipv6_inet_addr(ip:Unix.inet_addr)=String.length(Obj.magic (norm_inet_addrip))=16letis_multicast_inet_addrip=letip1=norm_inet_addr ipinif String.length(Obj.magicip1)=4thenlogand_inet_addrip1(Unix.inet_addr_of_string"240.0.0.0")=(Unix.inet_addr_of_string"224.0.0.0")elseifString.length(Obj.magicip1)=16thenlogand_inet_addrip1(Unix.inet_addr_of_string"ffff::0")=(Unix.inet_addr_of_string"ff00::0")elsefalseexternaltest_for_ip6_global_addr:unit->bool="netsys_test_for_ip6_global_addr"letipv6=ref(test_for_ip6_global_addr())letis_ipv6_system()=!ipv6letset_ipv6_systemb=ipv6:=btypefd_style =[`Read_write|`Recv_sendofUnix.sockaddr*Unix.sockaddr|`Recv_send_implied|`Recvfrom_sendto|`W32_pipe|`W32_pipe_server|`W32_event|`W32_process|`W32_input_thread|`W32_output_thread|`TLSofNetsys_crypto_types.file_tls_endpoint]letget_fd_stylefd=letw32_obj_opt=trySome(Netsys_win32.lookupfd)withNot_found->Noneinmatchw32_obj_optwith|Some(Netsys_win32.W32_pipe_)->`W32_pipe|Some(Netsys_win32.W32_pipe_server_)->`W32_pipe_server|Some(Netsys_win32.W32_event_)->`W32_event|Some(Netsys_win32.W32_process_)->`W32_process|Some(Netsys_win32.W32_input_thread_)->`W32_input_thread|Some(Netsys_win32.W32_output_thread_)->`W32_output_thread|None->(* Check whether we have a socket or not: *)trylet_socktype=Unix.getsockopt_intfdUnix.SO_TYPEin(* Now check whether the socket is connected or not: *)tryletsockaddr=Unix.getsocknamefdinletpeeraddr=getpeernamefdin(* fd is a connected socket *)`Recv_send(sockaddr,peeraddr)with|Unix.Unix_error(Unix.ENOTCONN,_,_)->(* fd is an unconnected socket *)`Recvfrom_sendto|Unix.Unix_error(Unix.ENOTSOCK,_,_)->failwith"Got unexpected ENOTSOCK"(* hopefully we never see this *)|_e->(* There are various error codes in use for socket types that
do not use addresses, e.g. socketpairs are considered
as not having addresses by some OS. Common are
EAFNOSUPPORT, EOPNOTSUPP, EINVAL. For simplicity we catch
here all, which is allowed as we already know that fd is a
socket.
*)`Recv_send_impliedwith|Unix.Unix_error((Unix.ENOTSOCK|Unix.EINVAL),_,_)->(* Note: EINVAL is used by some oldish OS in this case *)(* fd is not a socket *)`Read_write|Unix.Unix_error((Unix.ENOENT,_,_))whenis_win32->`Read_write|e->Netlog.log`Crit("get_fd_style: Exception: "^Netexn.to_stringe);assertfalseletstring_of_sockaddr?(norm=false)=function|Unix.ADDR_INET(inet,port)->letinet=ifnormthennorm_inet_addrinetelseinetin(matchdomain_of_inet_addrinetwith|Unix.PF_INET->Unix.string_of_inet_addrinet^":"^string_of_intport|Unix.PF_INET6->"["^Unix.string_of_inet_addrinet^"]:"^string_of_intport|_->assertfalse)|Unix.ADDR_UNIXpath->String.escapedpathletstring_of_fd_style=function|`Read_write->"Read_write"|`Recv_send(sockaddr,peeraddr)->"Recv_send("^string_of_sockaddr sockaddr^","^string_of_sockaddrpeeraddr^")"|`Recv_send_implied->"Recv_send_implied"|`Recvfrom_sendto->"Recvfrom_sendto"|`W32_pipe->"W32_pipe"|`W32_pipe_server->"W32_pipe_server"|`W32_event->"W32_event"|`W32_process->"W32_process"|`W32_input_thread->"W32_input_thread"|`W32_output_thread->"W32_output_thread"|`TLS_->"TLS"letstring_of_fdfd=letst=get_fd_style fdinletfdi=int64_of_file_descrfdinmatchstwith|`Read_write->sprintf"fd<%Ld>"fdi|`Recv_send(sockaddr,peeraddr)->sprintf"fd<%Ld=socket(%s,%s)>"fdi(string_of_sockaddrsockaddr)(string_of_sockaddrpeeraddr)|`Recv_send_implied->sprintf"fd<%Ld=socket>"fdi|`Recvfrom_sendto->sprintf"fd<%Ld=socket>"fdi|`W32_pipe->letp=Netsys_win32.lookup_pipefdinsprintf"fd<%Ld=w32_pipe(%s)>" fdi(Netsys_win32.pipe_namep)|`W32_pipe_server->letp=Netsys_win32.lookup_pipe_serverfdinsprintf"fd<%Ld=w32_pipe_server(%s)>"fdi(Netsys_win32.pipe_server_namep)|`W32_event->sprintf"fd<%Ld=w32_event>"fdi|`W32_process->letp=Netsys_win32.lookup_processfdinsprintf"fd<%Ld=w32_process(%d)>" fdi(Netsys_win32.win_pidp)|`W32_input_thread->sprintf"fd<%Ld=w32_input_thread>"fdi|`W32_output_thread->sprintf"fd<%Ld=w32_output_thread>"fdiletwait_until_readablefd_stylefdtmo=dlogr(fun()->sprintf "wait_until_readable fd=%Ld tmo=%f"(int64_of_file_descrfd)tmo);ifNetsys_posix.have_poll()thenrestart_tmo(Netsys_posix.poll_singlefdtruefalsefalse)tmoelsematchfd_stylewith|`Read_writewhenis_win32->(* effectively not supported! *)true|`W32_pipe->letph=Netsys_win32.lookup_pipefdinNetsys_win32.pipe_wait_rd phtmo|`W32_pipe_server->letph=Netsys_win32.lookup_pipe_serverfdinNetsys_win32.pipe_wait_connectphtmo|`W32_event->let eo=Netsys_win32.lookup_eventfdinNetsys_win32.event_waiteotmo|`W32_input_thread ->letithr=Netsys_win32.lookup_input_threadfdinleteo=Netsys_win32.input_thread_eventithrinNetsys_win32.event_waiteotmo|`W32_process|`W32_output_thread->sleeptmo;false(* never *)|`TLSep->letmoduleEndpoint=(valep:Netsys_crypto_types.FILE_TLS_ENDPOINT)inEndpoint.TLS.recv_will_not_blockEndpoint.endpoint||(letl,_,_=restart_tmo(Unix.select[Endpoint.rd_file][][])tmoinl<>[])|_->letl,_,_=restart_tmo(Unix.select[fd][][])tmoinl<>[]letwait_until_writablefd_stylefdtmo=dlogr(fun()->sprintf "wait_until_writable fd=%Ld tmo=%f"(int64_of_file_descrfd)tmo);ifNetsys_posix.have_poll()thenrestart_tmo(Netsys_posix.poll_singlefdfalsetruefalse)tmoelsematchfd_stylewith|`Read_writewhenis_win32->(* effectively not supported! *)true|`W32_pipe->letph=Netsys_win32.lookup_pipefdinNetsys_win32.pipe_wait_wr phtmo|`W32_pipe_server->letph=Netsys_win32.lookup_pipe_serverfdinNetsys_win32.pipe_wait_connectphtmo|`W32_event->let eo=Netsys_win32.lookup_eventfdinNetsys_win32.event_waiteotmo|`W32_output_thread->letothr=Netsys_win32.lookup_output_threadfdinleteo=Netsys_win32.output_thread_eventothrinNetsys_win32.event_waiteotmo|`W32_input_thread |`W32_process->sleeptmo;false(* never *)|`TLSep->letmoduleEndpoint=(valep:Netsys_crypto_types.FILE_TLS_ENDPOINT)inletl,_,_=restart_tmo(Unix.select[][Endpoint.wr_file][])tmoinl<>[]|_->let_,l,_=restart_tmo(Unix.select[][fd][])tmoinl<>[]letwait_until_prirdfd_style fdtmo=dlogr(fun()->sprintf "wait_until_prird fd=%Ld tmo=%f"(int64_of_file_descrfd)tmo);ifNetsys_posix.have_poll()thenrestart_tmo(Netsys_posix.poll_singlefdfalsefalsetrue)tmoelsematchfd_stylewith|`Read_writewhenis_win32->(* effectively not supported! *)true|`W32_pipe->sleeptmo;false(* never *)|`W32_pipe_server->letph=Netsys_win32.lookup_pipe_serverfdinNetsys_win32.pipe_wait_connectphtmo|`W32_event->let eo=Netsys_win32.lookup_eventfdinNetsys_win32.event_waiteotmo|`W32_input_thread|`W32_output_thread|`W32_process->sleeptmo;false(* never *)|_->let_,_,l=restart_tmo(Unix.select[][][fd])tmoinl<>[]letis_readablefd_stylefd=wait_until_readablefd_stylefd0.0letis_writablefd_stylefd=wait_until_writablefd_stylefd0.0letis_prirdfd_stylefd=wait_until_prirdfd_stylefd0.0letrecrestart_waitmodefd_stylefdfarg=tryfargwith|Unix.Unix_error(Unix.EINTR,_,_)->restart_waitmodefd_stylefdfarg|Unix.Unix_error(Unix.EAGAIN,_,_)|Unix.Unix_error(Unix.EWOULDBLOCK,_,_)->(matchmodewith|`R->ignore(wait_until_readablefd_stylefd(-1.0));restart_wait modefd_stylefdfarg|`W->ignore(wait_until_writablefd_stylefd(-1.0));restart_wait modefd_stylefdfarg)|Netsys_types.EAGAIN_RD->ignore(wait_until_readablefd_stylefd(-1.0));restart_wait modefd_stylefdfarg|Netsys_types.EAGAIN_WR ->ignore(wait_until_writablefd_stylefd(-1.0));restart_wait modefd_stylefdfargletgwrite_tstrfd_stylefdtsposlen=dlogr(fun ()->sprintf"gwrite fd=%Ld len=%d"(int64_of_file_descrfd)len);matchfd_stylewith|`Read_write->(matchtswith|`Bytess->Unix.single_writefdsposlen|`String s->#ifdefHAVE_BYTESUnix.single_write_substringfdsposlen#elseUnix.single_writefdsposlen#endif|`Memorys->Netsys_mem.mem_writefdspos len)|`Recv_send_|`Recv_send_implied->(matchtswith|`Bytess->Unix.sendfdspos len[]|`Strings->#ifdefHAVE_BYTESUnix.send_substringfdsposlen[]#elseUnix.sendfdsposlen[]#endif|`Memorys->Netsys_mem.mem_sendfdsposlen[])|`Recvfrom_sendto->failwith"Netsys.gwrite: the socket is unconnected"|`W32_pipe->letph=Netsys_win32.lookup_pipefdin(matchtswith|`Bytess->Netsys_win32.pipe_writephsposlen|`Strings->Netsys_win32.pipe_write_stringphsposlen|`Memorys->letb=Netsys_mem.bytes_of_memory(Bigarray.Array1.subsposlen)inNetsys_win32.pipe_writephb0len)|`W32_pipe_server->failwith"Netsys.gwrite: cannot write to pipe servers"|`W32_event->failwith"Netsys.gwrite: cannot write to event descriptor"|`W32_process->failwith"Netsys.gwrite: cannot write to process descriptor"|`W32_input_thread->failwith"Netsys.gwrite: cannot write to input thread"|`W32_output_thread->let othr=Netsys_win32.lookup_output_threadfdin(matchtswith|`Bytess->Netsys_win32.output_thread_writeothrsposlen|`Strings->Netsys_win32.output_thread_write_stringothrsposlen|`Memorys->letb=Netsys_mem.bytes_of_memory(Bigarray.Array1.subsposlen)inNetsys_win32.output_thread_writeothrb0len)|`TLSendpoint ->letep=Netsys_tls.endpointendpointin(matchtswith|`Bytes s->Netsys_tls.sendepsposlen|`Strings->Netsys_tls.str_sendepsposlen|`Memorys->Netsys_tls.mem_sendepsposlen)letgwritefd_stylefdsposlen=gwrite_tstrfd_stylefd(`Bytess)pos lenletgwrite_tbuffd_stylefdtbposlen=letts=matchtbwith|`Bytess->`Bytess|`Strings->`Bytess|`Memory m->`Memory mingwrite_tstrfd_style fdtsposlenletrecreally_gwrite_tstrfd_stylefdtsposlen =tryletn=gwrite_tstrfd_stylefdtsposleninifn>0thenreally_gwrite_tstrfd_stylefdts(pos+n)(len-n)with|Unix.Unix_error(Unix.EINTR,_,_)->really_gwrite_tstrfd_stylefdtsposlen|Unix.Unix_error((Unix.EAGAIN|Unix.EWOULDBLOCK),_,_)|Netsys_types.EAGAIN_WR->ignore(wait_until_writablefd_stylefd(-1.0));really_gwrite_tstrfd_stylefdtsposlen|Netsys_types.EAGAIN_RD->ignore(wait_until_readablefd_stylefd(-1.0));really_gwrite_tstrfd_stylefdtspos lenletreally_gwritefd_stylefd sposlen=really_gwrite_tstrfd_stylefd(`Bytes s)poslenletreally_gwrite_tbuffd_stylefdtbposlen=letts=matchtbwith|`Bytess->`Bytess|`Strings->`Bytess|`Memorym->`Memoryminreally_gwrite_tstrfd_stylefdtspos lenletgread_tbuffd_style fdbufposlen=dlogr(fun()->sprintf"gread fd=%Ld len=%d"(int64_of_file_descrfd)len);matchfd_stylewith|`Read_write->(matchbufwith|`Bytess|`Strings->Unix.readfdsposlen|`Memorys->Netsys_mem.mem_readfdsposlen)|`Recv_send_|`Recv_send_implied->(matchbufwith|`Bytess|`Strings->Unix.recvfdsposlen[]|`Memorys->Netsys_mem.mem_recvfdsposlen[])|`Recvfrom_sendto->failwith"Netsys.gread: the socket is unconnected"|`W32_pipe->letph=Netsys_win32.lookup_pipefdin(matchbufwith|`Bytess|`Strings->Netsys_win32.pipe_readphsposlen|`Memorys->letb=Bytes.createleninletn=Netsys_win32.pipe_readphb0leninNetsys_mem.blit_bytes_to_memoryb0s0n;n)|`W32_pipe_server->failwith"Netsys.gwrite: cannot read from pipe servers"|`W32_event->failwith"Netsys.gread: cannot read from event descriptor"|`W32_process->failwith"Netsys.gread: cannot read from process descriptor"|`W32_output_thread->failwith"Netsys.gread: cannot read from output thread"|`W32_input_thread->letithr=Netsys_win32.lookup_input_threadfdin(matchbufwith|`Bytess|`Strings->Netsys_win32.input_thread_readithrsposlen|`Memorys->letb=Bytes.createleninletn=Netsys_win32.input_thread_readithrb0leninNetsys_mem.blit_bytes_to_memoryb0s0n;n)|`TLSendpoint ->letep=Netsys_tls.endpointendpointin(matchbufwith|`Bytess|`Strings->Netsys_tls.recvepsposlen|`Memorys->Netsys_tls.mem_recvepsposlen)letgreadfd_style fdbufposlen=gread_tbuffd_stylefd(`Bytesbuf)poslenletblocking_gread_tbuffd_stylefdspos len=letrecloopposlenp=iflen>=0thentryletn=gread_tbuffd_stylefdsposleninifn=0thenpelseloop(pos+n)(len-n)(p+n)with|Unix.Unix_error(Unix.EINTR,_,_)->loopposlenp|Unix.Unix_error((Unix.EAGAIN|Unix.EWOULDBLOCK),_,_)|Netsys_types.EAGAIN_RD ->ignore(wait_until_readablefd_stylefd(-1.0));loopposlenp|Netsys_types.EAGAIN_WR ->ignore(wait_until_writablefd_stylefd(-1.0));loop poslenpelsepinloopposlen 0letblocking_greadfd_stylefdsposlen=blocking_gread_tbuffd_stylefd(`Bytess)poslenletreally_gread_tbuffd_stylefdtsposlen =letp=blocking_gread_tbuffd_stylefdtsposleninifp<lenthenraiseEnd_of_file;()letreally_greadfd_stylefdsposlen=really_gread_tbuf fd_stylefd(`Bytess)poslenletwait_until_connectedfdtmo=dlogr(fun()->sprintf"wait_until_connected fd=%Ld tmo=%f"(int64_of_file_descrfd)tmo);ifis_win32thentryletw32=Netsys_win32.lookupfdin(matchw32with|Netsys_win32.W32_pipe_->true(* immediately connected *)|_->failwith"Netsys.wait_until_connected: bad descriptor type")with|Not_found->(* socket case *)letl1,_,l2=Netsys_win32.real_select[][fd][fd]tmoinl1<>[]||l2<>[]elsewait_until_writable `Recv_send fdtmoletcatch_exnlabelgetdetailfarg=tryfargwith|error->letdetail=getdetailargin(try(* be careful here, logging might not work *)Netlog.logf`Crit"%s (%s): Exception %s"labeldetail(Netexn.to_stringerror)with|_->())letis_stdfdstd_fdstd_num=ifis_win32thenNetsys_win32.is_crt_fdfdstd_numelsefd=std_fdletis_stdin fd=is_stdfdUnix.stdin 0letis_stdoutfd=is_stdfdUnix.stdout 1letis_stderrfd=is_stdfdUnix.stderr2letset_close_on_execfd=ifis_win32thenNetsys_win32.modify_close_on_execfdtrueelseUnix.set_close_on_execfdletclear_close_on_execfd=ifis_win32thenNetsys_win32.modify_close_on_execfd falseelseUnix.clear_close_on_exec fdletgshutdownfd_stylefdcmd=dlogr(fun()->sprintf"gshutdown fd=%Ld cmd=%s"(int64_of_file_descrfd)(matchcmdwith|Unix.SHUTDOWN_SEND->"SEND"|Unix.SHUTDOWN_RECEIVE->"RECEIVE"|Unix.SHUTDOWN_ALL ->"ALL"));matchfd_stylewith|`Recv_send_|`Recv_send_implied->(tryUnix.shutdownfdcmdwith|Unix.Unix_error(Unix.ENOTCONN,_,_)->())|`W32_pipe->ifcmd<>Unix.SHUTDOWN_ALLthenraise(Unix.Unix_error(Unix.EPERM,"Netsys.gshutdown",""));letp=Netsys_win32.lookup_pipefdinNetsys_win32.pipe_shutdownp|`W32_pipe_server->ifcmd<>Unix.SHUTDOWN_ALLthenraise(Unix.Unix_error(Unix.EPERM,"Netsys.gshutdown",""));letp=Netsys_win32.lookup_pipe_serverfdinNetsys_win32.pipe_shutdown_serverp|`W32_output_thread->ifcmd <>Unix.SHUTDOWN_RECEIVEthen(let othr=Netsys_win32.lookup_output_thread fdinNetsys_win32.close_output_threadothr)|`TLSendpoint->Netsys_tls.shutdown(Netsys_tls.endpointendpoint)cmd|_->raiseShutdown_not_supportedletgclose fd_stylefd=dlogr(fun()->sprintf "gclose fd=%Ld"(int64_of_file_descrfd));letfd_detailfd=Printf.sprintf"fd %Ld"(int64_of_file_descrfd)inletpipe_detail(fd,p)=Printf.sprintf"fd %Ld as pipe %s"(int64_of_file_descrfd)(Netsys_win32.pipe_namep)inletpsrv_detail(fd,p)=Printf.sprintf"fd %Ld as pipe server %s"(int64_of_file_descrfd)(Netsys_win32.pipe_server_namep)inletithr_detail(fd,p)=Printf.sprintf"fd %Ld as input thread for %Ld"(int64_of_file_descrfd)(int64_of_file_descr(Netsys_win32.input_thread_descr p))inletothr_detail(fd,p)=Printf.sprintf"fd %Ld as output thread for %Ld"(int64_of_file_descrfd)(int64_of_file_descr(Netsys_win32.output_thread_descrp))inmatchfd_stylewith|`Read_write|`Recvfrom_sendto->catch_exn"Unix.close"fd_detailUnix.closefd|`Recv_send_|`Recv_send_implied->catch_exn"Unix.shutdown"fd_detail(funfd->tryUnix.shutdownfdUnix.SHUTDOWN_ALLwith|Unix.Unix_error(Unix.ENOTCONN,_,_)->())fd;catch_exn"Unix.close"fd_detailUnix.closefd|`W32_pipe->letp=Netsys_win32.lookup_pipefdincatch_exn"Netsys_win32.pipe_shutdown"pipe_detail(fun(fd,p)->Netsys_win32.pipe_shutdownp)(fd,p);catch_exn"Unix.close"fd_detailUnix.closefd;Netsys_win32.unregisterfd|`W32_pipe_server->letp=Netsys_win32.lookup_pipe_serverfdincatch_exn"Netsys_win32.pipe_server_shutdown"psrv_detail(fun(fd,p)->Netsys_win32.pipe_shutdown_serverp)(fd,p);catch_exn"Unix.close"fd_detailUnix.closefd;Netsys_win32.unregisterfd|`W32_event|`W32_process->(* Events are automatically closed *)catch_exn"Unix.close"fd_detailUnix.closefd;Netsys_win32.unregisterfd|`W32_input_thread->letithr=Netsys_win32.lookup_input_threadfdincatch_exn"Netsys_win32.cancel_input_thread"ithr_detail(fun(fd,ithr)->Netsys_win32.cancel_input_threadithr)(fd,ithr);catch_exn"Unix.close"fd_detailUnix.closefd;Netsys_win32.unregisterfd|`W32_output_thread->let othr=Netsys_win32.lookup_output_threadfdincatch_exn"Netsys_win32.cancel_output_thread"othr_detail(fun(fd,othr)->Netsys_win32.cancel_output_threadothr)(fd,othr);catch_exn"Unix.close"fd_detailUnix.closefd;Netsys_win32.unregisterfd|`TLSendpoint->Netsys_tls.shutdown(Netsys_tls.endpointendpoint)Unix.SHUTDOWN_ALL;letmoduleEndpoint=(valendpoint:Netsys_crypto_types.FILE_TLS_ENDPOINT)incatch_exn"Unix.close"fd_detailUnix.closeEndpoint.rd_file;ifEndpoint.wr_file<>Endpoint.rd_filethencatch_exn"Unix.close"fd_detailUnix.closeEndpoint.wr_file;iffd<>Endpoint.rd_filethencatch_exn"Unix.close"fd_detailUnix.closefdexternalunix_error_of_code:int ->Unix.error="netsys_unix_error_of_code"letconnect_checkfd=letdo_check=ifis_win32thentrylet w32=Netsys_win32.lookupfdin(matchw32with|Netsys_win32.W32_pipe_->false(* immediately connected *)|_->failwith"Netsys.connect_check: bad descriptor type")with|Not_found->(* socket case *)trueelsetrueinifdo_checkthen (lete_opt=Unix.getsockopt_errorfdintryignore(getpeernamefd);()with|Unix.Unix_error(Unix.ENOTCONN,_,_)->letdetail=tryletown_addr=Unix.getsocknamefdinstring_of_sockaddrown_addrwith_->"n/a"inmatche_optwith|Somee->raise(Unix.Unix_error(e,"connect_check",detail))|None->raise(Unix.Unix_error(Unix.ENOTCONN,"connect_check",detail)))external mcast_set_loop :Unix.file_descr->bool->unit="netsys_mcast_set_loop"externalmcast_set_ttl:Unix.file_descr ->int->unit="netsys_mcast_set_ttl"externalmcast_add_membership :Unix.file_descr->Unix.inet_addr->Unix.inet_addr ->unit="netsys_mcast_add_membership"externalmcast_drop_membership:Unix.file_descr->Unix.inet_addr->Unix.inet_addr ->unit="netsys_mcast_drop_membership"letf_moncontrol=ref(fun_->())letmoncontrol b=!f_moncontrolbletset_moncontrolf=f_moncontrol:=f(* Compatibility with older ocamlnet versions *)letreally_write=really_gwrite`Read_writeletblocking_read=blocking_gread`Read_writeletreally_read=really_gread`Read_writeletint_of_file_descr=Netsys_posix.int_of_file_descrletfile_descr_of_int=Netsys_posix.file_descr_of_intlethave_posix_shm=Netsys_posix.have_posix_shmtypeshm_open_flag=Netsys_posix.shm_open_flag=|SHM_O_RDONLY|SHM_O_RDWR|SHM_O_CREAT|SHM_O_EXCL|SHM_O_TRUNCletshm_open =Netsys_posix.shm_openletshm_unlink=Netsys_posix.shm_unlink