aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/flesh.ml15
-rw-r--r--lib/stream.ml77
2 files changed, 48 insertions, 44 deletions
diff --git a/lib/flesh.ml b/lib/flesh.ml
index 55eeefc..03882b4 100644
--- a/lib/flesh.ml
+++ b/lib/flesh.ml
@@ -15,21 +15,22 @@ open Lwt.Infix
Portal in a "ready" state. *)
let connect (domain : string) (config : Stream.config) : (Portal.t * Stream.features) Lwt.t =
let open Portal in
+ let open Stream in
let* portal = connect domain
in
let needs_restart = function
- | Stream.Mechanisms _ | STARTTLS -> true
+ | Feature.Mechanisms _ | STARTTLS -> true
| _ -> false
in
let+ features =
let rec handle_features (features : Stream.features) : Stream.features Lwt.t =
match features with
- | feature :: mandatory, optional ->
- let* () = Stream.negotiate true feature portal config
- in if needs_restart feature
- then Stream.start domain portal >>= handle_features
- else handle_features (mandatory, optional)
+ | feature :: rest ->
+ let* () = negotiate feature portal config
+ in if needs_restart (Feature.unwrap feature)
+ then start domain portal >>= handle_features
+ else handle_features rest
| features -> Lwt.return features
- in Stream.start domain portal >>= handle_features
+ in start domain portal >>= handle_features
in (portal, features)
diff --git a/lib/stream.ml b/lib/stream.ml
index 01b4930..ecfd31b 100644
--- a/lib/stream.ml
+++ b/lib/stream.ml
@@ -4,22 +4,40 @@ open Lwt.Infix
exception ClosedStream
exception InsufficientEncryption
-type feature =
- | STARTTLS
- | Mechanisms of Sasl.mechanism list
- | Other of Xml.element
+module Feature = struct
+ open Either
+ open Xml
-type 'a requirement =
- | Mandatory of 'a
- | Optional of 'a
+ type t =
+ | STARTTLS
+ | Mechanisms of Sasl.mechanism list
+ | Other of Xml.element
-let unwrap = function
- | Mandatory f -> f
- | Optional f -> f
+ type requirement =
+ | Mandatory of t
+ | Optional of t
-let to_either = function
- | Mandatory f -> Either.Left f
- | Optional f -> Either.Right f
+ let unwrap = function
+ | Mandatory f -> f
+ | Optional f -> f
+
+ let to_either = function
+ | Mandatory f -> Left f
+ | Optional f -> Right f
+
+ let parse (stanza : element) : requirement =
+ let parse_single_mechanism = function
+ | Left {local_name = "mechanism"; children = [Right mechanism]; _} ->
+ Sasl.parse_mechanism mechanism
+ | _ -> raise (InvalidStanza (element_to_string stanza))
+ in
+ let parse_mechanisms mech_stanza = List.map parse_single_mechanism mech_stanza
+ in match stanza with
+ | {local_name="mechanisms"; _} -> Mandatory (Mechanisms (parse_mechanisms stanza.children))
+ | {local_name="starttls"; children=[Left {local_name="required"; _}]; _} -> Mandatory STARTTLS
+ | {local_name="starttls"; children=[]; _} -> Optional STARTTLS
+ | _ -> Optional (Other stanza)
+end
type config = {
starttls : Starttls.config;
@@ -27,34 +45,18 @@ type config = {
other : (Markup.signal, Markup.sync) Markup.stream list;
}
-type features = feature requirement list
+type feature = Feature.t
+type features = Feature.requirement list
(** [parse_features stanza] is a tuple of the list of all mandatory features and all
optional features described in the <features> [stanza]. *)
let parse_features (stanza : Xml.element) : features =
let open Xml in
- let open Either in
-
let children =
- if not (List.for_all is_left stanza.children)
+ if not (List.for_all Either.is_left stanza.children)
then raise (InvalidStanza (element_to_string stanza))
- else List.filter_map find_left stanza.children
- in
-
- let parse_single_mechanism = function
- | Left {local_name = "mechanism"; children = [Right mechanism]; _} ->
- Sasl.parse_mechanism mechanism
- | _ -> raise (InvalidStanza (element_to_string stanza))
- in
-
- let parse_feature (stanza : Xml.element) : feature requirement =
- let parse_mechanisms mech_stanza = List.map parse_single_mechanism mech_stanza
- in match stanza with
- | {local_name="mechanisms"; _} -> Mandatory (Mechanisms (parse_mechanisms stanza.children))
- | {local_name="starttls"; children=[Left {local_name="required"; _}]; _} -> Mandatory STARTTLS
- | {local_name="starttls"; children=[]; _} -> Optional STARTTLS
- | _ -> Optional (Other stanza)
- in let features = List.map parse_feature children
+ else List.filter_map Either.find_left stanza.children
+ in let features = List.map Feature.parse children
(* The XMPP spec mandates that sending a features element that contains only a
<starttls/> means the STARTTLS negotiation is required. *)
in match features with
@@ -89,11 +91,12 @@ let negotiate feature portal {starttls; sasl; _} : unit Lwt.t =
| Error err -> Lwt.fail_with (parse_auth_error err)
| Ok _ -> print_endline "Success!"; Lwt.return_unit
else Lwt.fail InsufficientEncryption
- in match feature with
+ in let open Feature in
+ match feature with
| Mandatory STARTTLS -> Starttls.upgrade portal
| Optional STARTTLS -> if starttls.prefer_starttls
- then Starttls.upgrade portal
- else Lwt.return_unit
+ then Starttls.upgrade portal
+ else Lwt.return_unit
| f ->
match unwrap f with
| Mechanisms mechs -> authenticate mechs