/frame.ml

http://github.com/djs55/ocaml-spdy · OCaml · 293 lines · 278 code · 13 blank · 2 comment · 5 complexity · b9d0c7591e76f8d97774fcf00edc1631 MD5 · raw file

  1. let rec really_read fd string off n =
  2. if n=0 then () else
  3. let m = Unix.read fd string off n in
  4. if m = 0 then raise End_of_file;
  5. really_read fd string (off+m) (n-m)
  6. let really_read_string fd length =
  7. let buf = String.make length '\000' in
  8. really_read fd buf 0 length;
  9. buf
  10. module Message = struct
  11. type t = {
  12. control: bool;
  13. version: int;
  14. ty: int;
  15. flags: int;
  16. length: int;
  17. data: Bitstring.t;
  18. }
  19. let unmarshal fd =
  20. (* The first 8 bytes contain the length of the message *)
  21. let hdr = really_read_string fd 8 in
  22. let bs = Bitstring.bitstring_of_string hdr in
  23. bitmatch bs with
  24. | { control: 1;
  25. version: 15: int;
  26. ty: 16: int;
  27. flags: 8: int;
  28. length: 24: int } ->
  29. let data = really_read_string fd length in
  30. let data = Bitstring.bitstring_of_string data in {
  31. control = control; version = version; ty = ty;
  32. flags = flags; length = length; data = data
  33. }
  34. | { _ } -> failwith "Failed to parse header"
  35. end
  36. let take num one bits =
  37. let rec loop acc bits = function
  38. | 0l -> List.rev acc
  39. | n ->
  40. let nv, rest = one bits in
  41. loop (nv :: acc) rest (Int32.sub n 1l) in
  42. loop [] bits num
  43. module NVPairs = struct
  44. let unmarshal bits =
  45. let num, rest = bitmatch bits with
  46. | { num: 16;
  47. rest: -1: bitstring
  48. } -> Int32.of_int num, rest
  49. | { _ } -> failwith "Failed to parse NVPairs len" in
  50. let one bits = bitmatch bits with
  51. | { name_len: 16;
  52. name: name_len * 8: string;
  53. v_len: 16;
  54. v: v_len * 8: string;
  55. rest: -1: bitstring
  56. } -> (name, v), rest
  57. | { _ } -> failwith "Failed to parse NVPair" in
  58. take num one rest
  59. end
  60. module IdVPairs = struct
  61. let unmarshal bits =
  62. let num, rest = bitmatch bits with
  63. | { num: 32;
  64. rest: -1: bitstring
  65. } -> num, rest in
  66. let one bits = bitmatch bits with
  67. | { id: 24;
  68. flags: 8;
  69. v: 32
  70. } -> (id, flags, v), rest
  71. | { _ } -> failwith "Failed to parse NVPair" in
  72. take num one rest
  73. end
  74. let parse_flags table x =
  75. List.map snd (List.filter (fun (mask, flag) -> x.Message.flags land mask <> 0) table)
  76. module Control = struct
  77. module Syn = struct
  78. type flag =
  79. | Fin
  80. | Unidirectional
  81. let flags = [
  82. 0x01, Fin;
  83. 0x02, Unidirectional
  84. ]
  85. type t = {
  86. stream_id: int; (* 31 bits *)
  87. associated_to_stream_id: int; (* 31 bits *)
  88. pri: int; (* 2 bits *)
  89. flags: flag list;
  90. headers: (string * string) list;
  91. }
  92. let unmarshal (x: Message.t) =
  93. let flags = parse_flags flags x in
  94. bitmatch x.Message.data with
  95. | { _: 1;
  96. stream_id: 31;
  97. _: 1;
  98. associated_to_stream_id: 31;
  99. pri: 2;
  100. _: 14;
  101. rest: -1: bitstring
  102. } ->
  103. let headers = NVPairs.unmarshal rest in {
  104. stream_id = stream_id;
  105. associated_to_stream_id = associated_to_stream_id;
  106. pri = pri;
  107. flags = flags;
  108. headers = headers
  109. }
  110. | { _ } -> failwith "Failed to parse SYN"
  111. end
  112. module Reply = struct
  113. type flag =
  114. | Fin
  115. let flags = [
  116. 0x1, Fin
  117. ]
  118. type t = {
  119. stream_id: int; (* 31 bits *)
  120. flags: flag list;
  121. headers: (string * string) list;
  122. }
  123. let unmarshal (x: Message.t) =
  124. bitmatch x.Message.data with
  125. | { _: 1;
  126. stream_id: 31;
  127. _: 16;
  128. rest: -1: bitstring } ->
  129. let flags = parse_flags flags x in
  130. let headers = NVPairs.unmarshal rest in {
  131. stream_id = stream_id;
  132. flags = flags;
  133. headers = headers
  134. }
  135. | { _ } -> failwith "Failed to parse REPLY"
  136. end
  137. module Rst = struct
  138. type status_code =
  139. | Protocol_error
  140. | Invalid_stream
  141. | Refused_stream
  142. | Unsupported_version
  143. | Cancel
  144. | Internal_error
  145. | Flow_control_error
  146. let status_codes = [
  147. 1l, Protocol_error;
  148. 2l, Invalid_stream;
  149. 3l, Refused_stream;
  150. 4l, Unsupported_version;
  151. 5l, Cancel;
  152. 6l, Internal_error;
  153. 7l, Flow_control_error
  154. ]
  155. type t = {
  156. stream_id: int; (* 31 bits *)
  157. status_code: status_code;
  158. }
  159. let unmarshal (x: Message.t) =
  160. bitmatch x.Message.data with
  161. | { _: 1;
  162. stream_id: 31;
  163. status_code: 32
  164. } ->
  165. if not (List.mem_assoc status_code status_codes)
  166. then failwith (Printf.sprintf "Unknown RST status code: %ld" status_code);
  167. { stream_id = stream_id;
  168. status_code = List.assoc status_code status_codes }
  169. | { _ } -> failwith "Failed to parse RST"
  170. end
  171. module Settings = struct
  172. type flag =
  173. | Clear_previously_persisted_settings
  174. let flags = [
  175. 0x1, Clear_previously_persisted_settings
  176. ]
  177. type id_flag =
  178. | Persist_value
  179. | Persisted
  180. let id_flags = [
  181. 0x1, Persist_value;
  182. 0x2, Persisted;
  183. ]
  184. type id =
  185. | Upload_bandwidth
  186. | Download_bandwidth
  187. | Round_trip_time
  188. | Max_concurrent_streams
  189. | Current_cwnd
  190. | Download_retrans_rate
  191. | Initial_window_size
  192. let ids = [
  193. 1, Upload_bandwidth;
  194. 2, Download_bandwidth;
  195. 3, Round_trip_time;
  196. 4, Max_concurrent_streams;
  197. 5, Current_cwnd;
  198. 6, Download_retrans_rate;
  199. 7, Initial_window_size;
  200. ]
  201. type t = {
  202. flags: flag list;
  203. settings: (id * id_flag * Int32.t) list;
  204. }
  205. let unmarshal (x: Message.t) =
  206. let flags = parse_flags flags x in
  207. let raw_settings = IdVPairs.unmarshal x.Message.data in
  208. let settings =
  209. List.map (fun (id, id_flag, v) ->
  210. if not(List.mem_assoc id ids)
  211. then failwith (Printf.sprintf "Unknown SETTINGS id %d" id);
  212. if not(List.mem_assoc id_flag id_flags)
  213. then failwith (Printf.sprintf "Unknown SETTINGS id_flag %d" id_flag);
  214. List.assoc id ids, List.assoc id_flag id_flags, v
  215. ) raw_settings in
  216. { flags = flags;
  217. settings = settings }
  218. end
  219. module Noop = struct
  220. type t = unit
  221. let unmarshal (x: Message.t) = ()
  222. end
  223. module Ping = struct
  224. type t = int32
  225. let unmarshal (x: Message.t) =
  226. bitmatch x.Message.data with
  227. | { id: 32 } -> id
  228. | { _ } -> failwith "Failed to parse PING"
  229. end
  230. module Goaway = struct
  231. type t = {
  232. last_good_stream_id: int; (* 31 bits *)
  233. }
  234. let unmarshal (x: Message.t) =
  235. bitmatch x.Message.data with
  236. | { _: 1;
  237. last_good_stream_id: 31 } -> {
  238. last_good_stream_id = last_good_stream_id
  239. }
  240. | { _ } -> failwith "Failed to parse GOAWAY"
  241. end
  242. module Headers = struct
  243. type t = {
  244. stream_id: int; (* 31 bits *)
  245. headers: (string * string) list;
  246. }
  247. let unmarshal (x: Message.t) =
  248. bitmatch x.Message.data with
  249. | { _: 1;
  250. stream_id: 31;
  251. _: 16;
  252. rest: -1: bitstring } ->
  253. let headers = NVPairs.unmarshal rest in {
  254. stream_id = stream_id;
  255. headers = headers
  256. }
  257. | { _ } -> failwith "Failed to parse HEADERS"
  258. end
  259. type t =
  260. | Syn of Syn.t
  261. | Reply of Reply.t
  262. | Rst of Rst.t
  263. | Settings of Settings.t
  264. | Noop of Noop.t
  265. | Ping of Ping.t
  266. | Goaway of Goaway.t
  267. | Headers of Headers.t
  268. let unmarshal (x: Message.t) =
  269. (* assume control and version have values we recognise *)
  270. match x.Message.ty with
  271. | 1 -> Syn (Syn.unmarshal x)
  272. | 2 -> Reply (Reply.unmarshal x)
  273. | 3 -> Rst (Rst.unmarshal x)
  274. | 4 -> Settings (Settings.unmarshal x)
  275. | 5 -> Noop (Noop.unmarshal x)
  276. | 6 -> Ping (Ping.unmarshal x)
  277. | 7 -> Goaway (Goaway.unmarshal x)
  278. | 8 -> Headers (Headers.unmarshal x)
  279. | x -> failwith (Printf.sprintf "Unknown CONTROL message type: %d" x)
  280. end