Skip to content

Commit

Permalink
[wip] implement capability advertisement decoding
Browse files Browse the repository at this point in the history
that is sent by the server on initial contact with client
  • Loading branch information
ulugbekna committed Nov 27, 2020
1 parent a0ceff2 commit 8b9ec8b
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/not-so-smart/capability_v2.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
open Astring

type t =
[ `Shallow
| `Filter
| `Ref_in_want
| `Sideband_all
| `Packfile_uris
| `Unknown of string
| `Unknown_with_param of string * string ]

let to_string = function
| `Shallow -> "shallow"
| `Ref_in_want -> "ref-in-want"
| `Sideband_all -> "sideband-all"
| `Filter -> "filter"
| `Packfile_uris -> "packfile-uris"
| `Unknown s -> s
| `Unknown_with_param (k, v) -> Fmt.str "%s=%s" k v

let of_string ?value = function
| "shallow" -> `Shallow
| "ref-in-want" -> `Ref_in_want
| "sideband-all" -> `Sideband_all
| "filter" -> `Filter
| "packfile-uris" -> `Packfile_uris
| c -> (
assert (not (String.is_empty c));
match value with
| None -> `Unknown c
| Some "" -> assert false
| Some v -> `Unknown_with_param (c, v) )

let pp = Fmt.of_to_string to_string

let equal t1 t2 =
match t1, t2 with
| `Shallow, `Shallow
| `Filter, `Filter
| `Ref_in_want, `Ref_in_want
| `Sideband_all, `Sideband_all
| `Packfile_uris, `Packfile_uris ->
true
| _, _ -> false
13 changes: 13 additions & 0 deletions src/not-so-smart/capability_v2.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type t =
[ `Shallow
| `Filter
| `Ref_in_want
| `Sideband_all
| `Packfile_uris
| `Unknown of string
| `Unknown_with_param of string * string ]

val to_string : t -> string
val of_string : ?value:string -> string -> t
val pp : t Fmt.t
val equal : t -> t -> bool
6 changes: 6 additions & 0 deletions src/not-so-smart/dune
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@
(libraries ipaddr decompress.de decompress.zl cstruct logs astring result
rresult bigstringaf fmt emile conduit lwt domain-name uri sigs smart pck
nss digestif carton carton-lwt))

(library
(name git_proto_v2)
(public_name git-nss.git-wire-proto-v2)
(modules capability_v2 protocol_v2)
(libraries astring git-nss.pkt-line fmt))
60 changes: 60 additions & 0 deletions src/not-so-smart/protocol_v2.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
open Astring

module Decoder = struct
open Pkt_line.Decoder

type nonrec error = [ error | `Expected_protocol_version ]
type 'a t = decoder -> ('a, error) state

(* let v_space = String.Sub.of_string " " *)
let v_version2 = String.Sub.of_string "version 2"
let v_flush_pkt = String.Sub.of_string "0000"
let is_flush_pkt = String.Sub.equal v_flush_pkt
let is_new_line = function '\n' -> true | _ -> false

let peek_pkt ?(trim = true) decoder =
let buf, off, len = peek_pkt decoder in
let buf = Bytes.to_string buf in
let res = String.Sub.v buf ~start:off ~stop:(off + len) in
if trim then String.Sub.trim ~drop:is_new_line res else res

let rec prompt_pkt ?strict k decoder =
if at_least_one_pkt decoder then k decoder
else prompt ?strict (prompt_pkt ?strict k) decoder

(*
capability-advertisement = protocol-version
capability-list
flush-pkt
*)
let decode_capability_ad decoder =
(* capability = PKT-LINE(key[=value] LF)
key = 1*(ALPHA | DIGIT | "-")
value = 1*(ALPHA | DIGIT | " -_.,?\/{}[]()<>!@#$%^&*+=:;") *)
let parse_capability s =
let s = String.Sub.to_string s in
match String.cut s ~sep:"=" with
| None -> Capability_v2.of_string s
| Some (key, value) -> Capability_v2.of_string key ~value
in

(* capability-list = *capability *)
let rec decode_capability_list capabilities decoder =
let v = peek_pkt decoder in
if is_flush_pkt v then return capabilities decoder
else
let cap = parse_capability v in
prompt_pkt (decode_capability_list (cap :: capabilities)) decoder
in

(* protocol-version = PKT-LINE("version 2" LF) *)
let decode_protocol_version decoder =
let v = peek_pkt decoder in
if String.Sub.equal v v_version2 then
prompt_pkt (decode_capability_list []) decoder
else fail decoder `Expected_protocol_version
in

decode_protocol_version decoder
end
8 changes: 8 additions & 0 deletions src/not-so-smart/protocol_v2.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Decoder : sig
open Pkt_line.Decoder

type nonrec error = [ error | `Expected_protocol_version ]
type 'a t = decoder -> ('a, error) state

val decode_capability_ad : Capability_v2.t list t
end

0 comments on commit 8b9ec8b

Please sign in to comment.