Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file state.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176(*
* Copyright (c) 2012 Balraj Singh <bs375@cl.cam.ac.uk>
*
* 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.
*)openLwt.Infixletsrc=Logs.Src.create"tcp.state"~doc:"Mirage TCP State module"moduleLog=(valLogs.src_logsrc:Logs.LOG)typeaction=|Passive_open|Recv_rst|Recv_synackofSequence.t|Recv_ackofSequence.t|Recv_fin(* | Recv_finack of Sequence.t *)|Send_synofSequence.t|Send_synackofSequence.t|Send_rst|Send_finofSequence.t|Timeouttypetcpstate=|Closed|Listen|Syn_rcvdofSequence.t|Syn_sentofSequence.t|Established|Close_wait|Last_ackofSequence.t|Fin_wait_1ofSequence.t|Fin_wait_2ofint|ClosingofSequence.t|Time_wait|Resettypeclose_cb=unit->unittypet={on_close:close_cb;id:int;mutablestate:tcpstate;}lett~id~on_close={on_close;id;state=Closed}leton_closet=t.on_close()letstatet=t.stateletpf=Format.fprintfletpp_actionfmt=function|Passive_open->pffmt"Passive_open"|Recv_rst->pffmt"Recv_rst"|Recv_synackx->pffmt"Recv_synack(%a)"Sequence.ppx|Recv_ackx->pffmt"Recv_ack(%a)"Sequence.ppx|Recv_fin->pffmt"Recv_fin"(* | Recv_finack x -> pf fmt "Recv_finack(%a)" Sequence.pp x *)|Send_synx->pffmt"Send_syn(%a)"Sequence.ppx|Send_synackx->pffmt"Send_synack(%a)"Sequence.ppx|Send_rst->pffmt"Send_rst"|Send_finx->pffmt"Send_fin(%a)"Sequence.ppx|Timeout->pffmt"Timeout"letpp_tcpstatefmt=function|Closed->pffmt"Closed"|Listen->pffmt"Listen"|Syn_rcvdx->pffmt"Syn_rcvd(%a)"Sequence.ppx|Syn_sentx->pffmt"Syn_sent(%a)"Sequence.ppx|Established->pffmt"Established"|Close_wait->pffmt"Close_wait"|Last_ackx->pffmt"Last_ack(%a)"Sequence.ppx|Fin_wait_1x->pffmt"Fin_wait_1(%a)"Sequence.ppx|Fin_wait_2i->pffmt"Fin_wait_2(%d)"i|Closingx->pffmt"Closing(%a)"Sequence.ppx|Time_wait->pffmt"Time_wait"|Reset->pffmt"Reset"letppfmtt=pffmt"{ %a }"pp_tcpstatet.stateletfin_wait_2_time=(* 60 *)Duration.of_sec10lettime_wait_time=(* 30 *)Duration.of_sec2letrecfinwait2timertcounttimeout=Log.debug(funfmt->fmt"finwait2timer %Lu"timeout);Mirage_sleep.nstimeout>>=fun()->matcht.statewith|Fin_wait_2i->Log.debug(funf->f"finwait2timer: Fin_wait_2");ifi=countthenbegint.state<-Closed;t.on_close();Lwt.return_unitendelsebeginfinwait2timertitimeoutend|s->Log.debug(funfmt->fmt"finwait2timer: %a"pp_tcpstates);Lwt.return_unitlettimewaitttwomsl=Log.debug(funfmt->fmt"timewait %Lu"twomsl);Mirage_sleep.nstwomsl>>=fun()->t.state<-Closed;Log.debug(funfmt->fmt"timewait on_close");t.on_close();Lwt.return_unitlettransition_to_timewaitt=Lwt.async(fun()->timewaitttime_wait_time);Time_waitlettickt(i:action)=letdiffonexy=Sequence.succy=xinlettstrs(i:action)=matchs,iwith|Closed,Passive_open->Listen|Closed,Send_syna->Syn_senta|Listen,Send_synacka->Syn_rcvda|Syn_rcvd_,Timeout->t.on_close();Closed|Syn_rcvd_,Recv_rst->Closed|Syn_sent_,Timeout->t.on_close();Closed|Syn_senta,Recv_synackb->ifdiffonebathenEstablishedelseSyn_senta|Syn_rcvda,Recv_ackb->ifdiffonebathenEstablishedelseSyn_rcvda|Established,Recv_ack_->Established|Established,Send_fina->Fin_wait_1a|Established,Recv_fin->Close_wait|Established,Timeout->t.on_close();Closed|Established,Recv_rst->t.on_close();Reset|Fin_wait_1a,Recv_ackb->ifdiffonebathenletcount=0inLwt.async(fun()->finwait2timertcountfin_wait_2_time);Fin_wait_2countelseFin_wait_1a|Fin_wait_1a,Recv_fin->Closinga|Fin_wait_1_,Timeout->t.on_close();Closed|Fin_wait_1_,Recv_rst->t.on_close();Reset|Fin_wait_2i,Recv_ack_->Fin_wait_2(i+1)|Fin_wait_2_,Recv_rst->t.on_close();Reset|Fin_wait_2_,Recv_fin->transition_to_timewaitt|Closinga,Recv_ackb->ifdiffonebathentransition_to_timewaittelseClosinga|Closing_,Timeout->t.on_close();Closed|Closing_,Recv_rst->t.on_close();Reset|Time_wait,Timeout->t.on_close();Closed|Close_wait,Send_fina->Last_acka|Close_wait,Timeout->t.on_close();Closed|Close_wait,Recv_rst->t.on_close();Reset|Last_acka,Recv_ackb->ifdiffonebathen(t.on_close();Closed)elseLast_acka|Last_ack_,Timeout->t.on_close();Closed|Last_ack_,Recv_rst->t.on_close();Reset|x,_->xinletold_state=t.stateinletnew_state=tstrt.stateiinLog.debug(funfmt->fmt"%d %a - %a -> %a"t.idpp_tcpstateold_statepp_actionipp_tcpstatenew_state);t.state<-new_state;