Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file conduit_mirage.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293(*
* Copyright (c) 2014 Anil Madhavapeddy <anil@recoil.org>
* Copyright (c) 2015 Thomas Gazagnaire <thomas@gazagnaire.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)letsrc=Logs.Src.create"conduit_mirage"~doc:"Conduit Mirage"moduleLog=(valLogs.src_logsrc:Logs.LOG)openSexplib0.Sexp_convlet(>>=)=Lwt.(>>=)let(>|=)=Lwt.(>|=)letfailfmt=Fmt.failwithfmtleterr_tcp_not_supported=fail"%s: TCP is not supported"leterr_tls_not_supported=fail"%s: TLS is not supported"leterr_domain_sockets_not_supported=fail"%s: Unix domain sockets are not supported inside Unikernels"leterr_vchan_not_supported=fail"%s: VCHAN is not supported"leterr_unknown=fail"%s: unknown endpoint type"leterr_not_supported=function|`TLS_->err_tls_not_supported|`TCP_->err_tcp_not_supported|`Vchan_->err_vchan_not_supportedmoduleTls_config=structtypeclient=Tls.Config.clientletsexp_of_client_=failwith"converting a TLS client config into S-Expression is not supported"letclient_of_sexp_=failwith"converting a S-Expression into a TLS client config is not supported"typeserver=Tls.Config.serverletsexp_of_server_=failwith"converting a TLS server config into S-Expression is not supported"letserver_of_sexp_=failwith"converting a S-Expression into a TLS server config is not supported"endmoduleVchan_port=structtypet=Vchan.Port.tletsexp_of_t_=failwith"converting a vchan port into S-Expression is not supported"lett_of_sexp_=failwith"converting a S-Expression into a vchant port is not supported"endtypeclient=[`TCPofIpaddr_sexp.t*int|`TLSofTls_config.client*client|`Vchanof[`Directofint*Vchan_port.t|`Domain_socketofstring*Vchan_port.t]][@@derivingsexp]typeserver=[`TCPofint|`TLSofTls_config.server*server|`Vchanof[`Directofint*Vchan_port.t|`Domain_socket]][@@derivingsexp]moduletypeS=sigtypettypeflowmoduleFlow:Mirage_flow.Swithtypeflow=flowvalconnect:t->client->flowLwt.tvallisten:t->server->(flow->unitLwt.t)->unitLwt.tend(* TCP *)lettcp_clientip=Lwt.return(`TCP(i,p))lettcp_server_p=Lwt.return(`TCPp)moduleTCP(S:Tcpip.Stack.V4V6)=structmoduleFlow=S.TCPtypeflow=Flow.flowtypet=S.tleterr_tcpe=Format.kasprintffailwith"TCP connection failed: %a"S.TCP.pp_erroreletconnect(t:t)(c:client)=matchcwith|`TCP(ip,port)->(S.TCP.create_connection(S.tcpt)(ip,port)>>=function|Errore->err_tcpe|Okflow->Lwt.returnflow)|_->err_not_supportedc"connect"letlisten(t:t)(s:server)fn=matchswith|`TCPport->lets,_u=Lwt.task()inS.TCP.listen(S.tcpt)~port(funflow->fnflow);s|_->err_not_supporteds"listen"end(* VCHAN *)leterr_vchan_port=fail"%s: invalid Vchan port"letportp=matchVchan.Port.of_stringpwith|Error(`Msgs)->err_vchan_ports|Okp->Lwt.returnpletvchan_client=function|`Vchan_direct(i,p)->portp>|=funp->`Vchan(`Direct(i,p))|`Vchan_domain_socket(i,p)->portp>|=funp->`Vchan(`Domain_socket(i,p))letvchan_server=function|`Vchan_direct(i,p)->portp>|=funp->`Vchan(`Direct(i,p))|`Vchan_domain_socket_->Lwt.return(`Vchan`Domain_socket)moduleVchan(Xs:Xs_client_lwt.S)(V:Vchan.S.ENDPOINTwithtypeport=Vchan.Port.t)=structmoduleFlow=VmoduleXS=Conduit_xenstore.Make(Xs)typeflow=Flow.flowtypet=XS.tletregister=XS.registerletrecconnect(t:t)(c:client)=matchcwith|`Vchan(`Domain_socket(uid,port))->XS.connectt~remote_name:uid~port>>=funendp->connectt(`Vchanendp:>client)|`Vchan(`Direct(domid,port))->V.client~domid~port()|_->err_not_supportedc"connect"letlisten(t:t)(s:server)fn=matchswith|`Vchan(`Direct(domid,port))->V.server~domid~port()>>=fn|`Vchan`Domain_socket->XS.listent>>=funconns->Lwt_stream.iter_p(function`Direct(domid,port)->V.server~domid~port()>>=fn)conns|_->err_not_supporteds"listen"end(* TLS *)lettls_client~host~authenticatorx=letpeer_name=Result.to_option(Result.bind(Domain_name.of_stringhost)Domain_name.host)inmatchTls.Config.client?peer_name~authenticator()with|Error(`Msgmsg)->failwith("tls configuration problem: "^msg)|Okcfg->`TLS(cfg,x)lettls_server?authenticatorx=matchTls.Config.server?authenticator()with|Error(`Msgmsg)->failwith("tls configuration problem: "^msg)|Okcfg->`TLS(cfg,x)moduleTLS(S:S)=structmoduleTLS=Tls_mirage.Make(S.Flow)typeflow=TLSofTLS.flow|ClearofS.flowtypet=S.tmoduleFlow=structtypenonrecflow=flowtypeerror=[`FlowofS.Flow.error|`TLSofTLS.error]typewrite_error=[Mirage_flow.write_error|`FlowofS.Flow.write_error|`TLSofTLS.write_error]letpp_errorppf=function|`Flowe->S.Flow.pp_errorppfe|`TLSe->TLS.pp_errorppfeletpp_write_errorppf=function|#Mirage_flow.write_errorase->Mirage_flow.pp_write_errorppfe|`Flowe->S.Flow.pp_write_errorppfe|`TLSe->TLS.pp_write_errorppfelettls_err=functionOk_asx->x|Errore->Error(`TLSe)letflow_err=functionOk_asx->x|Errore->Error(`Flowe)lettls_write_err=function|Ok_asx->x|Error`Closedasx->x|Errore->Error(`TLSe)letflow_write_err=function|Ok_asx->x|Error`Closedasx->x|Errore->Error(`Flowe)letread=function|TLSf->TLS.readf>|=tls_err|Clearf->S.Flow.readf>|=flow_errletwritetx=matchtwith|TLSf->TLS.writefx>|=tls_write_err|Clearf->S.Flow.writefx>|=flow_write_errletwritevtx=matchtwith|TLSf->TLS.writevfx>|=tls_err|Clearf->S.Flow.writevfx>|=flow_errletclose=functionTLSf->TLS.closef|Clearf->S.Flow.closefletshutdownfmode=matchfwith|TLSf->TLS.shutdownfmode|Clearf->S.Flow.shutdownfmodeendletconnect(t:t)(c:client)=matchcwith|`TLS(c,x)->(S.connecttx>>=funflow->TLS.client_of_flowcflow>>=function|Errore->fail"connect: %a"TLS.pp_write_errore|Okflow->Lwt.return(TLSflow))|_->S.connecttc>|=funt->Cleartletlisten(t:t)(s:server)fn=matchswith|`TLS(c,x)->S.listentx(funflow->TLS.server_of_flowcflow>>=function|Errore->Log.info(funm->m"listen: %a"TLS.pp_write_errore);Lwt.return_unit|Okflow->fn(TLSflow))|_->S.listents(funf->fn(Clearf))endmoduleEndpoint=structletnss_authenticator=matchCa_certs_nss.authenticator()with|Oka->a|Error(`Msgmsg)->failwithmsgletrecclient?(tls_authenticator=nss_authenticator)e=matchewith|`TCP(x,y)->tcp_clientxy|`Unix_domain_socket_->err_domain_sockets_not_supported"client"|(`Vchan_direct_|`Vchan_domain_socket_)asx->vchan_clientx|`TLS(host,y)->client~tls_authenticatory>|=tls_client~host~authenticator:tls_authenticator|`Unknowns->err_unknownsletrecserver?tls_authenticatore=matchewith|`TCP(x,y)->tcp_serverxy|`Unix_domain_socket_->err_domain_sockets_not_supported"server"|(`Vchan_direct_|`Vchan_domain_socket_)asx->vchan_serverx|`TLS(_host,y)->servery>|=tls_server?authenticator:tls_authenticator|`Unknowns->err_unknownsend