diff --git a/lib/authentication.ml b/lib/authentication.ml index 54a8df0..9f61f33 100644 --- a/lib/authentication.ml +++ b/lib/authentication.ml @@ -24,22 +24,20 @@ let decode_plain_authentication hash ?stamp t v = take_till is_zero >>= fun v0 -> char '\000' *> take_till is_zero >>= fun v1 -> char '\000' *> available >>= take >>= fun v2 -> return (v0, v1, v2) in - match - ( stamp - , Base64.decode ~pad:false (* XXX(dinosaure): not really sure. *) v - >>= (R.reword_error (fun _ -> `Msg "Invalid input") - <.> Angstrom.parse_string ~consume:All parser) ) - with + let payload = + Base64.decode ~pad:false (* XXX(dinosaure): not really sure. *) v + >>= (R.reword_error (fun _ -> `Msg "Invalid input") <.> Angstrom.parse_string ~consume:All parser) in + match stamp, payload with | Some stamp, Ok (v0, v1, v2) -> if Eqaf.equal stamp v0 then match Angstrom.parse_string ~consume:All Emile.Parser.local_part v1 with | Ok username -> authenticate hash username v2 t | Error _ -> Lwt.return (R.error_msgf "Invalid username: %S" v1) else Lwt.return (R.error_msgf "Invalid stamp") - | None, Ok ("", v1, v2) -> ( - match Angstrom.parse_string ~consume:All Emile.Parser.local_part v1 with + | None, Ok ("", v1, v2) -> + begin match Angstrom.parse_string ~consume:All Emile.Parser.local_part v1 with | Ok username -> authenticate hash username v2 t - | Error _ -> Lwt.return (R.error_msgf "Invalid username: %S" v1)) + | Error _ -> Lwt.return (R.error_msgf "Invalid username: %S" v1) end | None, Ok (_, _, _) -> Lwt.return (R.error_msgf "Unexpected stamp") | _, (Error _ as err) -> Lwt.return err diff --git a/lib/dune b/lib/dune index 0998e64..31ad503 100644 --- a/lib/dune +++ b/lib/dune @@ -31,8 +31,7 @@ (library (name ptt) (public_name ptt) - (modules ptt authentication logic mechanism messaged - relay sigs sMTP sSMTP submission) + (modules ptt authentication logic mechanism messaged relay sMTP sSMTP submission) (libraries ptt.common ptt.flow ptt.aggregate digestif mrmime colombe.emile domain-name dns sendmail.starttls logs ipaddr) (preprocess future_syntax)) @@ -41,14 +40,7 @@ (name ptt_server) (public_name ptt.server) (modules ptt_server) - (libraries lwt tls-mirage bigstringaf mirage-time mirage-flow tcpip mimic - ptt.rdwr ptt)) - -; (library -; (name ptt_transmit) -; (public_name ptt.transmit) -; (modules ptt_transmit) -; (libraries hxd.core hxd.string ptt.tuyau mirage-clock received)) + (libraries lwt tls-mirage bigstringaf mirage-time mirage-flow tcpip mimic ptt)) (library (name lipap) @@ -85,9 +77,3 @@ (public_name ptt.spartacus) (modules spartacus) (libraries mirage-time mirage-clock mirage-random ptt ptt.map ptt.server spamtacus-mirage dns-client-mirage)) - -(library - (name rdwr) - (public_name ptt.rdwr) - (modules rdwr) - (libraries cstruct bigstringaf lwt rresult ke mirage-flow ptt)) diff --git a/lib/lexicon.ml b/lib/lexicon.ml deleted file mode 100644 index 2c6634a..0000000 --- a/lib/lexicon.ml +++ /dev/null @@ -1,24 +0,0 @@ -let pp_recipients ppf { Sendmail.domain; locals; } = - let pp_domain ppf = function - | `Ipaddr (Ipaddr.V4 v4) -> Fmt.pf ppf "[%a]" Ipaddr.V4.pp v4 - | `Ipaddr (Ipaddr.V6 v6) -> Fmt.pf ppf "[IPv6:%a]" Ipaddr.V6.pp v6 - | `Domain domain -> Domain_name.pp ppf domain in - let pp_local ppf local = - let pp_elt ppf = function - | `Atom x -> Fmt.string ppf x - | `String x -> Fmt.pf ppf "%S" x in - Fmt.(list ~sep:(any ".") pp_elt) ppf local in - match locals with - | `All -> Fmt.pf ppf "- <%a>\n" pp_domain domain - | `Some locals -> - let pp_elt local = Fmt.pf ppf "- %a@%a\n" pp_local local pp_domain domain in - List.iter pp_elt locals - -let impossible_to_send_an_email_to ~recipients mxs = - Fmt.str {text|It's impossible to send an email to: - %a - - We tried to send the email %a at %a to: - %a - - All of them are unavailable.|text} diff --git a/lib/ptt.ml b/lib/ptt.ml index fb04bfb..9c994b8 100644 --- a/lib/ptt.ml +++ b/lib/ptt.ml @@ -5,5 +5,4 @@ module Relay = Relay module Messaged = Messaged module Authentication = Authentication module Mechanism = Mechanism -module Sigs = Sigs module Logic = Logic diff --git a/lib/ptt_transmit.ml b/lib/ptt_transmit.ml deleted file mode 100644 index 9751581..0000000 --- a/lib/ptt_transmit.ml +++ /dev/null @@ -1,171 +0,0 @@ -let ( <.> ) f g x = f (g x) -let icompare : int -> int -> int = fun a b -> compare a b -let src = Logs.Src.create "ptt.transmit" - -module Log = (val Logs.src_log src) - -module Make - (Pclock : Mirage_clock.PCLOCK) - (Stack : Tcpip.Stack.V4V6) - (Md : Ptt.Messaged.S with type 'a s = 'a Lwt.t) = -struct - open Lwt.Infix - open Ptt_tuyau.Lwt_backend - include Ptt_tuyau.Client (Stack) - - let local_to_forward_path ~domain:mx_domain local = - let local = - `Dot_string (List.map (function `Atom x -> x | `String x -> x) local) - in - Colombe.Forward_path.Forward_path - { - Colombe.Path.local - ; Colombe.Path.domain= mx_domain - ; Colombe.Path.rest= [] - } - - let plug_consumer_to_producers consumer producers = - let rec go () = - consumer () >>= function - | Some ((str, off, len) as v) -> - Log.debug (fun m -> m "Send to %d recipient(s)" (List.length producers)); - Log.debug (fun m -> - m "@[%a@]" (Hxd_string.pp Hxd.default) (String.sub str off len)); - List.iter (fun producer -> producer (Some v)) producers; - Lwt.pause () >>= go - | None -> - Log.debug (fun m -> - m "Send to %d recipient(s)." (List.length producers)); - List.iter (fun producer -> producer None) producers; - Lwt.return () in - go - - let ( <+> ) s0 s1 = - let current = ref s0 in - let rec next () = - let tmp = Lwt_scheduler.prj (!current ()) in - let res = - tmp >>= function - | Some _ -> tmp - | None -> - if !current == s1 then Lwt.return None - else ( - current := s1; - Lwt_scheduler.prj (next ())) in - Lwt_scheduler.inj res in - next - - type pool = - (bytes * bytes * (char, Bigarray.int8_unsigned_elt) Ke.Rke.t) Lwt_pool.t - - let received ~info ~key recipient = - let id = Ptt.Messaged.id key in - let by = Domain_name.to_strings info.Ptt.Logic.domain in - let id = - let open Mrmime.Mailbox in - Local.(v [w (Fmt.str "%08LX" id)]), `Domain by in - let received = - Received.make - ~from:(Received.Only (Ptt.Messaged.domain_from key)) - ~by:(Received.Only (Colombe.Domain.Domain by)) ~via:Received.tcp - ~protocol:Received.esmtp ~id ~zone:info.Ptt.Logic.zone recipient - (Ptime.v (Pclock.now_d_ps ())) in - let stream = Prettym.to_stream Received.Encoder.as_field received in - let stream = - Lwt_stream.from (Lwt.return <.> stream) - |> Lwt_stream.map (fun s -> s, 0, String.length s) in - (* XXX(dinosaure): don't use [Fun.const] here, we need to keep - the side-effect of the consommation. *) - Lwt_scheduler.inj <.> fun () -> Lwt_stream.get stream - - let pp_key ppf = function - | `Ipaddr ipaddr -> Ipaddr.pp ppf ipaddr - | `Domain (domain, _) -> Domain_name.pp ppf domain - - (* XXX(dinosaure): this function tries to send an email to a recipient. - It tries multiple MX targets given by the recipient's domain. *) - let sendmail_to_a_target ~pool ~info ~tls ~key stack emitter (stream, (k, vs)) - = - let open Colombe in - let open Forward_path in - let mx_domain, mxs = - match k with - | `Ipaddr (Ipaddr.V4 v4 as mx_ipaddr) -> - Domain.IPv4 v4, Ptt.Mxs.(singleton (v ~preference:0 mx_ipaddr)) - | `Ipaddr (Ipaddr.V6 v6 as mx_ipaddr) -> - Domain.IPv6 v6, Ptt.Mxs.(singleton (v ~preference:0 mx_ipaddr)) - | `Domain (mx_domain, mxs) -> - Domain.Domain (Domain_name.to_strings mx_domain), mxs in - let recipients = - match vs with - | `All -> [Domain mx_domain] - | `Local vs -> List.map (local_to_forward_path ~domain:mx_domain) vs in - let received = - match recipients with - | [Forward_path path] -> received ~info ~key (Some path) - | _ -> received ~info ~key None in - let stream = received <+> stream in - (* TODO(dinosaure): [sendmail] and [sendmail_without_tls] can consume - the stream and fail. In that case, all sub-sequent call to these - functions will try to send an empty email. We must copy the stream - for each call of [sendmail] and [sendmail_without_tls]. *) - let rec go = function - | [] -> - Log.err (fun m -> - m "Impossible to send an email to %a (no solution found)." pp_key k); - Lwt.return () - | {Ptt.Mxs.mx_ipaddr; _} :: rest -> ( - Log.debug (fun m -> - m "Transmit the incoming email to %a (%a)." Ipaddr.pp mx_ipaddr - Domain.pp mx_domain); - Lwt_pool.use pool (fun (encoder, decoder, queue) -> - sendmail ~encoder:(Fun.const encoder) ~decoder:(Fun.const decoder) - ~queue:(Fun.const queue) ~info ~tls stack mx_ipaddr emitter stream - recipients - >>= function - | Ok () -> Lwt.return_ok () - | Error `STARTTLS_unavailable - (* TODO(dinosaure): when [insecure]. *) -> - Log.warn (fun m -> - m - "The SMTP receiver %a does not implement STARTTLS, restart \ - in clear." - Domain.pp mx_domain); - sendmail_without_tls ~encoder:(Fun.const encoder) - ~decoder:(Fun.const decoder) ~info stack mx_ipaddr emitter - stream recipients - | Error err -> Lwt.return_error err) - >>= function - | Ok () -> Lwt.return_unit - | Error err -> - Log.err (fun m -> - m "Impossible to send the given email to %a: %a." Domain.pp - mx_domain pp_error err); - go rest) in - let sort = - List.sort (fun {Ptt.Mxs.preference= a; _} {Ptt.Mxs.preference= b; _} -> - icompare a b) in - let mx_ipaddrs = Ptt.Mxs.elements mxs |> sort in - go mx_ipaddrs - - let transmit ~pool ~info ~tls stack ?emitter (key, queue, consumer) resolved = - let producers, targets = - List.fold_left - (fun (producers, targets) target -> - let stream, producer = Lwt_stream.create () in - let stream () = Lwt_scheduler.inj (Lwt_stream.get stream) in - producer :: producers, (stream, target) :: targets) - ([], []) resolved in - let emitter = Option.value ~default:(fst (Ptt.Messaged.from key)) emitter in - let transmit = plug_consumer_to_producers consumer producers in - Log.debug (fun m -> - m "Start to send the incoming email to %d recipient(s)." - (List.length targets)); - Lwt.both (transmit ()) - (Lwt_list.iter_s - (sendmail_to_a_target ~pool ~info ~tls ~key stack emitter) - targets) - >>= fun ((), ()) -> - Log.debug (fun m -> m "Email sended!"); - Md.close queue -end diff --git a/lib/ptt_transmit.mli b/lib/ptt_transmit.mli deleted file mode 100644 index 5d6695b..0000000 --- a/lib/ptt_transmit.mli +++ /dev/null @@ -1,21 +0,0 @@ -module Make - (Pclock : Mirage_clock.PCLOCK) - (Stack : Tcpip.Stack.V4V6) - (Md : Ptt.Messaged.S with type 'a s = 'a Lwt.t) : sig - type pool = - (bytes * bytes * (char, Bigarray.int8_unsigned_elt) Ke.Rke.t) Lwt_pool.t - - val transmit : - pool:pool - -> info:Ptt.Logic.info - -> tls:Tls.Config.client - -> Stack.TCP.t - -> ?emitter:Colombe.Reverse_path.t - -> Ptt.Messaged.key * Md.queue * Md.chunk Md.consumer - -> ([ `Domain of [ `host ] Domain_name.t * Ptt.Mxs.t | `Ipaddr of Ipaddr.t ] - * Ptt.Aggregate.resolved_elt) - list - -> unit Lwt.t - (** [transmit ~pool ~info ~tls tcpv4v6 (key, queue, consumer) recipients] tries - to send an email to [recipients]. *) -end diff --git a/lib/rdwr.ml b/lib/rdwr.ml deleted file mode 100644 index 2249583..0000000 --- a/lib/rdwr.ml +++ /dev/null @@ -1,47 +0,0 @@ -let blit0 src src_off dst dst_off len = - let dst = Cstruct.of_bigarray ~off:dst_off ~len dst in - Cstruct.blit src src_off dst 0 len - -let blit1 src src_off dst dst_off len = - Bigstringaf.blit_to_bytes src ~src_off dst ~dst_off ~len - -open Rresult -open Lwt.Infix - -module Make (Flow : Mirage_flow.S) = struct - type +'a io = 'a Lwt.t - type t = {queue: (char, Bigarray.int8_unsigned_elt) Ke.Rke.t; flow: Flow.flow} - type flow = t - - let make flow = {flow; queue= Ke.Rke.create ~capacity:0x1000 Bigarray.char} - - let failwith pp = function - | Ok v -> Lwt.return v - | Error err -> Lwt.fail (Failure (Fmt.str "%a" pp err)) - - let recv flow payload p_off p_len = - if Ke.Rke.is_empty flow.queue then ( - Flow.read flow.flow >>= failwith Flow.pp_error >>= function - | `Eof -> Lwt.return 0 - | `Data res -> - Ke.Rke.N.push flow.queue ~blit:blit0 ~length:Cstruct.length res; - let len = min p_len (Ke.Rke.length flow.queue) in - Ke.Rke.N.keep_exn flow.queue ~blit:blit1 ~length:Bytes.length ~off:p_off - ~len payload; - Ke.Rke.N.shift_exn flow.queue len; - Lwt.return len) - else - let len = min p_len (Ke.Rke.length flow.queue) in - Ke.Rke.N.keep_exn flow.queue ~blit:blit1 ~length:Bytes.length ~off:p_off - ~len payload; - Ke.Rke.N.shift_exn flow.queue len; - Lwt.return len - - let input flow payload p_off p_len = recv flow payload p_off p_len - - let send flow payload p_off p_len = - let cs = Cstruct.of_string payload ~off:p_off ~len:p_len in - Flow.write flow.flow cs >>= failwith Flow.pp_write_error - - let close {flow; _} = Flow.close flow -end diff --git a/lib/sigs.ml b/lib/sigs.ml deleted file mode 100644 index 971a208..0000000 --- a/lib/sigs.ml +++ /dev/null @@ -1,60 +0,0 @@ -open Colombe.Sigs - -module type SCHEDULER = X - -module type MUTEX = sig - type +'a fiber - type t - - val create : unit -> t - val lock : t -> unit fiber - val unlock : t -> unit -end - -module type CONDITION = sig - type +'a fiber - type mutex - type t - - val create : unit -> t - val wait : t -> mutex -> unit fiber - val signal : t -> unit - val broadcast : t -> unit -end - -module type IO = sig - type +'a t - - module Mutex : MUTEX with type 'a fiber = 'a t - - module Condition : - CONDITION with type 'a fiber = 'a t and type mutex = Mutex.t - - val bind : 'a t -> ('a -> 'b t) -> 'b t - val return : 'a -> 'a t - val pause : unit -> unit t -end - -module type RESOLVER = sig - type t - type +'a io - - val gethostbyname : - t -> [ `host ] Domain_name.t -> (Ipaddr.t, [> Rresult.R.msg ]) result io - - val getmxbyname : - t - -> [ `host ] Domain_name.t - -> (Dns.Rr_map.Mx_set.t, [> Rresult.R.msg ]) result io - - val extension : - t -> string -> string -> (Ipaddr.t, [> Rresult.R.msg ]) result io -end - -module type FLOW = sig - type t - type +'a io - - val recv : t -> bytes -> int -> int -> int io - val send : t -> string -> int -> int -> unit io -end diff --git a/lib/sigs.mli b/lib/sigs.mli deleted file mode 100644 index 971a208..0000000 --- a/lib/sigs.mli +++ /dev/null @@ -1,60 +0,0 @@ -open Colombe.Sigs - -module type SCHEDULER = X - -module type MUTEX = sig - type +'a fiber - type t - - val create : unit -> t - val lock : t -> unit fiber - val unlock : t -> unit -end - -module type CONDITION = sig - type +'a fiber - type mutex - type t - - val create : unit -> t - val wait : t -> mutex -> unit fiber - val signal : t -> unit - val broadcast : t -> unit -end - -module type IO = sig - type +'a t - - module Mutex : MUTEX with type 'a fiber = 'a t - - module Condition : - CONDITION with type 'a fiber = 'a t and type mutex = Mutex.t - - val bind : 'a t -> ('a -> 'b t) -> 'b t - val return : 'a -> 'a t - val pause : unit -> unit t -end - -module type RESOLVER = sig - type t - type +'a io - - val gethostbyname : - t -> [ `host ] Domain_name.t -> (Ipaddr.t, [> Rresult.R.msg ]) result io - - val getmxbyname : - t - -> [ `host ] Domain_name.t - -> (Dns.Rr_map.Mx_set.t, [> Rresult.R.msg ]) result io - - val extension : - t -> string -> string -> (Ipaddr.t, [> Rresult.R.msg ]) result io -end - -module type FLOW = sig - type t - type +'a io - - val recv : t -> bytes -> int -> int -> int io - val send : t -> string -> int -> int -> unit io -end diff --git a/lib/unixiz.mli b/lib/unixiz.mli deleted file mode 100644 index 46a020a..0000000 --- a/lib/unixiz.mli +++ /dev/null @@ -1,10 +0,0 @@ -module Make (Flow : Mirage_flow.S) : sig - include Ptt.Sigs.FLOW with type +'a io = 'a Lwt.t - - val make : Flow.flow -> t - val close : t -> unit Lwt.t - - type flow = t - - val input : flow -> bytes -> int -> int -> int Lwt.t -end diff --git a/test/test.ml b/test/test.ml index bc793b9..7918696 100644 --- a/test/test.ml +++ b/test/test.ml @@ -132,217 +132,6 @@ let recoil = Domain_name.(host_exn <.> of_string_exn) "recoil.org" let nqsb = Domain_name.(host_exn <.> of_string_exn) "nqsb.io" let gazagnaire = Domain_name.(host_exn <.> of_string_exn) "gazagnaire.org" -(* -let pp_unresolved ppf = function - | `All -> Fmt.string ppf "" - | `Postmaster -> Fmt.string ppf "" - | `Local vs -> Fmt.Dump.list Emile.pp_local ppf vs - -let equal_unresolved a b = - match a, b with - | `All, `All -> true - | `Postmaster, `Postmaster -> true - | `Local a, `Local b -> ( - let a = List.sort (Emile.compare_local ~case_sensitive:true) a in - let b = List.sort (Emile.compare_local ~case_sensitive:true) b in - try List.for_all2 (Emile.equal_local ~case_sensitive:true) a b - with _ -> false) - | _, _ -> false - -let unresolved = Alcotest.testable pp_unresolved equal_unresolved - -let aggregate_test_0 = - Alcotest_lwt.test_case "aggregate 0" `Quick @@ fun _sw () -> - let open Mrmime.Mailbox in - let m0 = Local.[w "romain"; w "calascibetta"] @ Domain.(domain, [a "gmail"; a "com"]) in - let m1 = Local.[w "thomas"] @ Domain.(domain, [a "gazagnaire"; a "org"]) in - let m2 = Local.[w "anil"] @ Domain.(domain, [a "recoil"; a "org"]) in - let m3 = Local.[w "gemma"; w "d"; w "gordon"] @ Domain.(domain, [a "gmail"; a "com"]) in - let ms = - List.map - (Rresult.R.get_ok <.> Colombe_emile.to_forward_path) - [m0; m1; m2; m3] in - let ms = - Colombe.Forward_path.Domain - ((Rresult.R.get_ok <.> Colombe_emile.to_domain) - Domain.(v domain [a "nqsb"; a "io"])) - :: ms in - let u, r = Ptt.Aggregate.aggregate_by_domains ~domain:x25519 ms in - Alcotest.(check bool) - "resolved is empty" true - (Ptt.Aggregate.By_ipaddr.is_empty r); - Alcotest.(check unresolved) - "unresolved gmail.com" - (`Local - [ - Local.(v [w "romain"; w "calascibetta"]) - ; Local.(v [w "gemma"; w "d"; w "gordon"]) - ]) - (Ptt.Aggregate.By_domain.find gmail u); - Alcotest.(check unresolved) - "unresolved recoil.org" - (`Local [Local.(v [w "anil"])]) - (Ptt.Aggregate.By_domain.find recoil u); - Alcotest.(check unresolved) - "unresolved gazagnaire.org" - (`Local [Local.(v [w "thomas"])]) - (Ptt.Aggregate.By_domain.find gazagnaire u); - Alcotest.(check unresolved) - "unresolved nqsb.io" `All - (Ptt.Aggregate.By_domain.find nqsb u); - Lwt.return_unit - -module Lwt_io = struct - include Lwt - - module Condition = struct - type +'a fiber = 'a Lwt.t - type mutex = Lwt_mutex.t - type t = unit Lwt_condition.t - - let wait (t : t) mutex = Lwt_condition.wait ~mutex t - let signal t = Lwt_condition.signal t () - let broadcast t = Lwt_condition.broadcast t () - let create () = Lwt_condition.create () - end - - module Mutex = struct - type +'a fiber = 'a Lwt.t - - include Lwt_mutex - end -end - -module Md = Ptt.Messaged.Make (Scheduler) (Lwt_io) - -let stream_of_string_list l = - let l = ref l in - let stream () = - match !l with - | [] -> Lwt.return None - | x :: r -> - l := r; - Lwt.return (Some x) in - stream - -let stream_is_empty s = - let open Lwt.Infix in - s () >>= function Some _ -> Lwt.return false | None -> Lwt.return true - -let hello_world () = - stream_of_string_list ["Hello", 0, 5; " ", 0, 1; "World!", 0, 6] - -let hello_buddy () = - stream_of_string_list ["Hello", 0, 5; " ", 0, 1; "buddy!", 0, 6] - -let hello_guy () = - stream_of_string_list ["Hello", 0, 5; " ", 0, 1; "guy!", 0, 4] - -let messaged_test_0 = - Alcotest_lwt.test_case "messaged 0" `Quick @@ fun _sw () -> - let md = Md.create () in - let do0 ~domain_from ~from v = - let open Lwt.Infix in - let key = - Ptt.Messaged.v - ~domain_from: - ((Rresult.R.get_ok <.> Colombe_emile.to_domain) domain_from) - ~from:((Rresult.R.get_ok <.> Colombe_emile.to_reverse_path) from, []) - ~recipients:[] ~ipaddr:(Ipaddr.V4 Ipaddr.V4.localhost) 0L in - Md.push md key >>= fun producer -> - let v = v () (* XXX(dinosaure): really create the stream. *) in - let rec consume () = - v () >>= function - | Some chunk -> producer (Some chunk) >>= consume - | None -> producer None in - consume () in - let contents = ref "" in - let do1 () = - let open Lwt.Infix in - Md.await md >>= fun () -> - Md.pop md >>= function - | Some (_, _, v) -> - let buf = Buffer.create 0x100 in - let rec consume () = - v () >>= function - | Some (str, off, len) -> - Buffer.add_substring buf str off len; - consume () - | None -> - contents := Buffer.contents buf; - Lwt.return_unit in - consume () - | None -> assert false in - let domain_from = Mrmime.Mailbox.Domain.(v domain [a "x25519"; a "net"]) in - let from = - let open Mrmime.Mailbox in - Local.[w "romain"; w "calascibetta"] @ Domain.(domain, [a "gmail"; a "com"]) - in - - let open Lwt.Infix in - Lwt.both (do0 ~domain_from ~from hello_world) (do1 ()) >>= fun _ -> - Alcotest.(check string) "(random schedule) payload" !contents "Hello World!"; - Lwt.both (do1 ()) (do0 ~domain_from ~from hello_buddy) >>= fun _ -> - Alcotest.(check string) - "(consumer & producer) payload" !contents "Hello buddy!"; - Lwt.both (do0 ~domain_from ~from hello_guy) (do1 ()) >>= fun _ -> - Alcotest.(check string) "(producer & consumer) payload" !contents "Hello guy!"; - Lwt.return_unit - -let messaged_test_1 = - Alcotest_lwt.test_case "messaged 1" `Quick @@ fun _sw () -> - let md = Md.create () in - let last = ref 0 in - let do0 ~domain_from ~from v = - let open Lwt.Infix in - last := 0; - let key = - Ptt.Messaged.v - ~domain_from: - ((Rresult.R.get_ok <.> Colombe_emile.to_domain) domain_from) - ~from:((Rresult.R.get_ok <.> Colombe_emile.to_reverse_path) from, []) - ~recipients:[] ~ipaddr:(Ipaddr.V4 Ipaddr.V4.localhost) 0L in - Md.push md key >>= fun producer -> - let rec consume () = - v () >>= function - | Some chunk -> producer (Some chunk) >>= fun () -> consume () - | None -> producer None in - consume () in - let do1 () = - let open Lwt.Infix in - last := 1; - Md.await md >>= fun () -> - (* XXX(dinosaure): schedule [do1] __after__ [do0]. *) - Md.pop md >>= function - | Some (_, q, _) -> Md.close q (* XXX(dinosaure): unlock [do0]. *) - | None -> assert false in - let domain_from = Mrmime.Mailbox.Domain.(v domain [a "x25519"; a "net"]) in - let from = - let open Mrmime.Mailbox in - Local.[w "romain"; w "calascibetta"] @ Domain.(domain, [a "gmail"; a "com"]) - in - let open Lwt.Infix in - let stream = hello_world () in - Lwt.both (do0 ~domain_from ~from stream) (do1 ()) >>= fun _ -> - stream_is_empty stream >>= fun res0 -> - Alcotest.(check bool) "stream consumed" res0 true; - Alcotest.(check pass) "random schedule" () (); - let stream = hello_buddy () in - Lwt.both (do1 ()) - (Lwt_unix.sleep 0.5 >>= fun () -> do0 ~domain_from ~from stream) - >>= fun _ -> - stream_is_empty stream >>= fun res1 -> - Alcotest.(check bool) "stream consumed" res1 true; - Alcotest.(check int) "(consumer & producer)" !last 0; - let stream = hello_guy () in - Lwt.both (do0 ~domain_from ~from stream) (Lwt_unix.sleep 0.5 >>= do1) - >>= fun _ -> - stream_is_empty stream >>= fun res2 -> - Alcotest.(check bool) "stream consumed" res2 true; - Alcotest.(check int) "(producer & consumer)" !last 1; - Lwt.return_unit -*) - let put_crlf x = x ^ "\r\n" let rdwr_from_flows inputs outputs = @@ -698,48 +487,6 @@ let smtp_test_7 = Alcotest.failf "Unexpected protocol error: %a" Ptt.SSMTP.pp_error err | Error `Connection_close -> Alcotest.failf "Unexpected connection close" -(* -module Random = struct - type g = unit - type +'a io = 'a Lwt.t - - let generate ?g:_ _ = Lwt.return () -end - -let fake_dns_resolvers = Hashtbl.create 16 - -let () = - Hashtbl.add fake_dns_resolvers - (Domain_name.(host_exn <.> of_string_exn) "gmail.com") - (Ipaddr.of_string_exn "10.0.0.8") - -let fake_smtp_servers = Hashtbl.create 16 -let () = Hashtbl.add fake_smtp_servers (Ipaddr.of_string_exn "10.0.0.8") 8888 - -module Resolver = struct - type t = unit - type +'a io = 'a Lwt.t - - let gethostbyname () domain_name = - match Hashtbl.find fake_dns_resolvers domain_name with - | v -> Lwt.return (Ok v) - | exception Not_found -> - let err = Rresult.R.error_msgf "%a not found" Domain_name.pp domain_name in - Lwt.return err - - let getmxbyname () domain_name = - let mxs = - Dns.Rr_map.Mx_set.add - {Dns.Mx.preference= 0; mail_exchange= domain_name} - Dns.Rr_map.Mx_set.empty in - Lwt.return (Ok mxs) - - let extension () _ _ = - let err = Rresult.R.error_msgf "Extension are not available" in - Lwt.return err -end -*) - module Server = Ptt_server.Make (Time) (Tcpip_stack_socket.V4V6) let resolver = @@ -781,28 +528,6 @@ let make_smtp_server ?stop ~port tbl info stack = let th = th >|= close in `Initialized th, stream0 -(* - let job_logic messaged ms = - let open Lwt.Infix in - Lwt.return - (`Queue - (let th, u = Lwt.wait () in - Lwt_switch.add_hook stop (fun () -> - Lwt.wakeup_later u `Stopped; - Lwt.return_unit); - let rec loop () = - SMTP.Md.await messaged >>= fun () -> - SMTP.Md.pop messaged >>= function - | Some (key, queue, _) -> - SMTP.Md.close queue >>= fun () -> Queue.push key ms; loop () - | None -> loop () in - Lwt.pick [th; loop ()] >|= fun `Stopped -> - Queue.fold (rev List.cons) [] ms)) in - Lwt.both - (smtp_relay_server conf_server) - (smtp_logic messaged (Queue.create ())) -*) - module Happy_eyeballs_daemon = Happy_eyeballs_mirage.Make (Time) (Mclock) (Tcpip_stack_socket.V4V6) @@ -825,46 +550,6 @@ let sendmail he ipaddr port ~domain sender recipients contents = | Error (#Sendmail_with_starttls.error as err) -> Fmt.failwith "%a" Sendmail_with_starttls.pp_error err -(* - let stream = stream_of_string_list contents in - let stream () = - let open Lwt.Infix in - stream () >>= function - | Some str -> Lwt.return (Some (str ^ "\r\n", 0, String.length str + 2)) - | None -> Lwt.return None in - let stream = Scheduler.inj <.> stream in - let ctx = Colombe.State.Context.make () in - let rdwr = - { - Colombe.Sigs.rd= - (fun fd buf off len -> - let fiber = - Lwt.Infix.( - Lwt_unix.read fd buf off len >>= function - | 0 -> Lwt.return `End - | len -> Lwt.return (`Len len)) in - Scheduler.inj fiber) - ; Colombe.Sigs.wr= - (fun fd buf off len -> - let fiber = - let open Lwt.Infix in - Lwt_unix.write fd (Bytes.unsafe_of_string buf) off len >>= fun _ -> - Lwt.return_unit in - Scheduler.inj fiber) - } in - let open Lwt.Infix in - let socket = Lwt_unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in - Lwt_unix.connect socket - (Unix.ADDR_INET (Ipaddr_unix.to_inet_addr ipaddr, port)) - >>= fun () -> - let res = - Sendmail.sendmail lwt rdwr socket ctx ~domain sender recipients stream in - let open Lwt.Infix in - Scheduler.prj res >>= function - | Ok () -> Lwt_unix.close socket - | Error err -> Fmt.failwith "%a" Sendmail.pp_error err -*) - let key = Alcotest.testable Ptt.Messaged.pp Ptt.Messaged.equal let full_test_0 =