Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file tls_io.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178openRresultlet(<.>)fgx=f(gx)(* XXX(dinosaure): (c) Hannes Menhert, this code is [tls_mirage.ml]
* with the possibility to define your [+'a io]. *)moduletypeFLOW=sigtypettypeerrortype+'aiovalread:t->bytes->int->int->([`End|`Lenofint],error)resultiovalfully_write:t->string->int->int->(unit,error)resultiovalclose:t->unitiovalbind:'aio->('a->'bio)->'biovalmap:('a->'b)->'aio->'biovalreturn:'a->'aioendmoduleMake(Flow:FLOW)=structtypeerror=|AlertofTls.Packet.alert_type|FailureofTls.Engine.failure|Flow_errorofFlow.error|Closedlet(>>=)=Flow.bindlet(>>|)xf=Flow.mapfxletreturn=Flow.returntypet={socket:Flow.t;mutablestate:[`ActiveofTls.Engine.state|`Read_closedofTls.Engine.state|`Write_closedofTls.Engine.state|`Closed|`Erroroferror];mutablelinger:Cstruct.tlist;}letfully_writesocket({Cstruct.len;_}ascs)=Flow.fully_writesocket(Cstruct.to_stringcs)0lenletreadsocket=letbuf=Bytes.create0x1000inFlow.readsocketbuf0(Bytes.lengthbuf)>>|function|Ok`End->Ok`Eof|Ok(`Lenlen)->Ok(`Data(Cstruct.of_bytesbuf~off:0~len))|Error_aserr->errlethalf_closestatemode=matchstate,modewith|`Activetls,`read->`Read_closedtls|`Activetls,`write->`Write_closedtls|`Active_,`read_write->`Closed|`Read_closedtls,`read->`Read_closedtls|`Read_closed_,(`write|`read_write)->`Closed|`Write_closedtls,`write->`Write_closedtls|`Write_closed_,(`read|`read_write)->`Closed|(`Closed|`Error_)ase,(`read|`write|`read_write)->eletinject_statetls=function|`Active_->`Activetls|`Read_closed_->`Read_closedtls|`Write_closed_->`Write_closedtls|(`Closed|`Error_)ase->eletwrite_flowflowbuf=fully_writeflow.socketbuf>>=function|Ok_aso->returno|Errore->flow.state<-`Error(Flow_errore);return(Error(Flow_errore))letread_reactflow=lethandletlsbuf=matchTls.Engine.handle_tlstlsbufwith|Ok(state,eof,`Responseresp,`Datadata)->letstate=inject_statestateflow.stateinletstate=Option.(value~default:state(map(fun`Eof->half_closestate`read)eof))inflow.state<-state;(matchrespwith|None->return(Ok())|Somebuf->write_flowflowbuf)>>=fun_->return@@`Okdata|Error(fail,`Responseresp)->letr=`Error(Failurefail)inflow.state<-r;fully_writeflow.socketresp>>=fun_->returnrinmatchflow.statewith|`Error_ase->returne|`Read_closed_|`Closed->return`Eof|`Active_|`Write_closed_->readflow.socket>>=function|Errore->flow.state<-`Error(Flow_errore);return(`Error(Flow_errore))|Ok`Eof->flow.state<-half_closeflow.state`read;return`Eof|Ok`Databuf->matchflow.statewith|`Activetls|`Write_closedtls->handletlsbuf|`Read_closed_|`Closed->return`Eof|`Error_ase->returneletrecreadflow=matchflow.lingerwith|[]->(read_reactflow>>=function|`OkNone->readflow|`Ok(Somebuf)->return(Result.Ok(`Databuf))|`Eof->return(Result.Ok`Eof)|`Errore->return(Result.Errore))|bufs->flow.linger<-[];return@@Ok(`Data(Cstruct.concat@@List.revbufs))letwritevflowbufs=matchflow.statewith|`Closed|`Write_closed_->return(Result.ErrorClosed)|`Errorerr->return(Result.Errorerr)|`Activetls|`Read_closedtls->matchTls.Engine.send_application_datatlsbufswith|Some(tls,answer)->flow.state<-`Activetls;write_flowflowanswer|None->(* "Impossible" due to handshake draining. *)assertfalseletwriteflowcs=writevflow[cs]letcloseflow=(matchflow.statewith|`Activetls|`Read_closedtls->lettls,buf=Tls.Engine.send_close_notifytlsinflow.state<-inject_statetlsflow.state;flow.state<-`Closed;fully_writeflow.socketbuf>>=fun_->return()|`Write_closed_->flow.state<-`Closed;return()|_->return())>>=fun()->Flow.closeflow.socketletrecdrain_handshakeflow=matchflow.statewith|`Activetlswhennot(Tls.Engine.handshake_in_progresstls)->return(Okflow)|_->(read_reactflow>>=function|`Ok(Somembuf)->flow.linger<-mbuf::flow.linger;drain_handshakeflow|`OkNone->drain_handshakeflow|`Errorerr->return(Result.Errorerr)|`Eof->return(Result.ErrorClosed))letinit_clientcfgsocket=lettls,init=Tls.Engine.clientcfginletflow={socket;state=`Activetls;linger=[]}infully_writesocketinit>>=fun_->drain_handshakeflowletinit_servercfgsocket=letflow={socket;state=`Active(Tls.Engine.servercfg);linger=[]}indrain_handshakeflowend