package sendmail
Implementation of the sendmail command
Install
Dune Dependency
Authors
Maintainers
Sources
colombe-0.8.0.tbz
sha256=9d3ad39d5b7af765947ff9ff01cec15e4226924d816827fc15c7ec1e5be7fff3
sha512=8f9a8aefd33426064fead137374b134ad30f90d653afcf4f30043c3e82764edaa17e9b5323c040da3d60a9c1f491d9d265a069ae4ac887685719ecc47c812308
doc/src/sendmail.starttls/tls_io.ml.html
Source file tls_io.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
open Rresult let ( <.> ) f g x = f (g x) (* XXX(dinosaure): (c) Hannes Menhert, this code is [tls_mirage.ml] * with the possibility to define your [+'a io]. *) module type FLOW = sig type t type error type +'a io val read : t -> bytes -> int -> int -> ([ `End | `Len of int ], error) result io val fully_write : t -> string -> int -> int -> (unit, error) result io val close : t -> unit io val bind : 'a io -> ('a -> 'b io) -> 'b io val map : ('a -> 'b) -> 'a io -> 'b io val return : 'a -> 'a io end module Make (Flow : FLOW) = struct type error = | Alert of Tls.Packet.alert_type | Failure of Tls.Engine.failure | Flow_error of Flow.error | Closed let ( >>= ) = Flow.bind let ( >>| ) x f = Flow.map f x let return = Flow.return type t = { socket : Flow.t; mutable state : [ `Active of Tls.Engine.state | `Eof | `Error of error ]; mutable linger : Cstruct.t list; } let fully_write socket ({ Cstruct.len; _ } as cs) = Flow.fully_write socket (Cstruct.to_string cs) 0 len >>| R.reword_error (fun err -> Flow_error err) let read socket = let buf = Bytes.create 0x1000 in Flow.read socket buf 0 (Bytes.length buf) >>= function | Ok `End -> return `Eof | Ok (`Len len) -> return (`Data (Cstruct.of_bytes ~off:0 ~len buf)) | Error err -> return (`Error (Flow_error err)) let check_write flow f_res = ( match flow.state, f_res with | `Active _, Error err -> flow.state <- `Error err ; Flow.close flow.socket | _ -> return () ) >>| fun () -> match f_res with | Ok () -> Ok () | Error e -> Error e let read_react flow = let handle tls buf = match Tls.Engine.handle_tls tls buf with | Ok (res, `Response resp, `Data data) -> flow.state <- ( match res with | `Ok tls -> `Active tls | `Eof -> `Eof | `Alert alert -> `Error (Alert alert)) ; ( match resp with | None -> return (Ok ()) | Some buf -> fully_write flow.socket buf >>= check_write flow) >>= fun _ -> ( match res with | `Ok _ -> return () | _ -> Flow.close flow.socket) >>= fun () -> return @@ `Ok data | Error (fail, `Response resp) -> let r = `Error (Failure fail) in flow.state <- r ; fully_write flow.socket resp |> fun _ -> Flow.close flow.socket >>= fun () -> return r in match flow.state with | `Eof | `Error _ as e -> return e | `Active _ -> read flow.socket >>= function | `Eof | `Error _ as e -> flow.state <- e ; return e | `Data buf -> match flow.state with | `Active tls -> handle tls buf | `Eof | `Error _ as e -> return e let rec read flow = match flow.linger with | [] -> ( read_react flow >>= function | `Ok None -> read flow | `Ok (Some buf) -> return (Result.Ok (`Data buf)) | `Eof -> return (Result.Ok `Eof) | `Error e -> return (Result.Error e)) | bufs -> flow.linger <- [] ; return @@ Ok (`Data (Cstruct.concat @@ List.rev bufs)) let writev flow bufs = match flow.state with | `Eof -> return (Result.Error Closed) | `Error err -> return (Result.Error err) | `Active tls -> match Tls.Engine.send_application_data tls bufs with | Some (tls, answer) -> flow.state <- `Active tls ; fully_write flow.socket answer >>= check_write flow | None -> (* "Impossible" due to handshake draining. *) assert false let write flow cs = writev flow [ cs ] let close flow = match flow.state with | `Active tls -> flow.state <- `Eof ; let _, buf = Tls.Engine.send_close_notify tls in fully_write flow.socket buf >>= fun _ -> return () | _ -> return () let rec drain_handshake flow = match flow.state with | `Active tls when not (Tls.Engine.handshake_in_progress tls) -> return (Ok flow) | _ -> ( read_react flow >>= function | `Ok (Some mbuf) -> flow.linger <- mbuf :: flow.linger ; drain_handshake flow | `Ok None -> drain_handshake flow | `Error err -> return (Result.Error err) | `Eof -> return (Result.Error Closed)) let init_client cfg socket = let tls, init = Tls.Engine.client cfg in let flow = { socket; state = `Active tls; linger = [] } in fully_write socket init >>= fun _ -> drain_handshake flow let init_server cfg socket = let flow = { socket; state = `Active (Tls.Engine.server cfg); linger = [] } in drain_handshake flow end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>