Source file pgx_lwt_mirage.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
open Lwt.Infix
module Channel = Mirage_channel.Make (Conduit_mirage.Flow)
let ( let* ) = Lwt.bind
let ( let+ ) t f = Lwt.map f t
module Thread = struct
type sockaddr =
| Unix of string
| Inet of string * int
type in_channel = Channel.t
type out_channel = Channel.t
let output_char oc c =
Channel.write_char oc c;
Lwt.return_unit
;;
let output_string oc s =
Channel.write_string oc s 0 (String.length s);
Lwt.return_unit
;;
let flush oc =
Channel.flush oc
>>= function
| Ok () -> Lwt.return_unit
| Error err -> Lwt.fail_with (Format.asprintf "%a" Channel.pp_write_error err)
;;
let input_char ic =
Channel.read_char ic
>>= function
| Ok (`Data c) -> Lwt.return c
| Ok `Eof -> Lwt.fail End_of_file
| Error err -> Lwt.fail_with (Format.asprintf "%a" Channel.pp_error err)
;;
let really_input ic buf off len =
Channel.read_exactly ~len ic
>>= function
| Ok (`Data bufs) ->
let content = Cstruct.copyv bufs in
Bytes.blit_string content 0 buf off len;
Lwt.return_unit
| Ok `Eof -> Lwt.fail End_of_file
| Error err -> Lwt.fail_with (Format.asprintf "%a" Channel.pp_error err)
;;
let close_in oc =
Channel.close oc
>>= function
| Ok () -> Lwt.return_unit
| Error err -> Lwt.fail_with (Format.asprintf "%a" Channel.pp_write_error err)
;;
let getlogin () = Lwt.fail_with "Running under MirageOS. getlogin not available."
end
module Make
(RANDOM : Mirage_random.S)
(MCLOCK : Mirage_clock.MCLOCK)
(STACK : Mirage_stack.V4) =
struct
module Dns = Dns_client_mirage.Make (RANDOM) (MCLOCK) (STACK)
type sockaddr = Thread.sockaddr =
| Unix of string
| Inet of string * int
let connect_stack stack sockaddr =
let dns = Dns.create stack in
let* conduit = Conduit_mirage.(with_tcp empty (stackv4 (module STACK)) stack) in
let* client =
match sockaddr with
| Unix _ -> Lwt.fail_with "Running under MirageOS. Unix sockets are not available."
| Inet (host, port) ->
(match Ipaddr.of_string host with
| Ok ipaddr -> Lwt.return (`TCP (ipaddr, port))
| Error _ ->
let host' = host |> Domain_name.of_string_exn |> Domain_name.host_exn in
Dns.gethostbyname dns host'
>>= (function
| Ok ipaddr -> Lwt.return (`TCP (Ipaddr.V4 ipaddr, port))
| Error (`Msg msg) -> Lwt.fail_with msg))
in
let+ flow = Conduit_mirage.connect conduit client in
let ch = Channel.create flow in
ch, ch
;;
let connect stack =
let open_connection = connect_stack stack in
(module struct
module T : Pgx_lwt.Io_intf.S = struct
include Thread
let open_connection = open_connection
end
include Pgx_lwt.Make (T)
end : Pgx_lwt.S)
;;
end