Don't generate BIND data for localhost
[hcoop/domtool2.git] / src / msg.sml
1 (* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006, Adam Chlipala
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *)
18
19 (* Network messages *)
20
21 structure Msg :> MSG = struct
22
23 open OpenSSL MsgTypes Slave
24
25 val a2i = fn Add => 0
26 | Delete => 1
27 | Modify => 2
28
29 val i2a = fn 0 => Add
30 | 1 => Delete
31 | 2 => Modify
32 | _ => raise OpenSSL.OpenSSL "Bad action number to deserialize"
33
34 fun sendAcl (bio, {user, class, value}) =
35 (OpenSSL.writeString (bio, user);
36 OpenSSL.writeString (bio, class);
37 OpenSSL.writeString (bio, value))
38
39 fun recvAcl bio =
40 case (OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of
41 (SOME user, SOME class, SOME value) => SOME {user = user, class = class, value = value}
42 | _ => NONE
43
44 fun sendList f (bio, ls) =
45 (app (fn x =>
46 (OpenSSL.writeInt (bio, 1);
47 f (bio, x))) ls;
48 OpenSSL.writeInt (bio, 0))
49
50 fun recvList f bio =
51 let
52 fun loop ls =
53 case OpenSSL.readInt bio of
54 SOME 0 => SOME (rev ls)
55 | SOME 1 =>
56 (case f bio of
57 SOME x => loop (x :: ls)
58 | NONE => NONE)
59 | _ => NONE
60 in
61 loop []
62 end
63
64 fun sendOption f (bio, opt) =
65 case opt of
66 NONE => OpenSSL.writeInt (bio, 0)
67 | SOME x => (OpenSSL.writeInt (bio, 1);
68 f (bio, x))
69
70 fun recvOption f bio =
71 case OpenSSL.readInt bio of
72 SOME 0 => SOME NONE
73 | SOME 1 =>
74 (case f bio of
75 SOME x => SOME (SOME x)
76 | NONE => NONE)
77 | _ => NONE
78
79 fun sendBool (bio, b) =
80 if b then
81 OpenSSL.writeInt (bio, 1)
82 else
83 OpenSSL.writeInt (bio, 0)
84
85 fun recvBool bio =
86 case OpenSSL.readInt bio of
87 SOME 0 => SOME false
88 | SOME 1 => SOME true
89 | _ => NONE
90
91 fun send (bio, m) =
92 case m of
93 MsgOk => OpenSSL.writeInt (bio, 1)
94 | MsgError s => (OpenSSL.writeInt (bio, 2);
95 OpenSSL.writeString (bio, s))
96 | MsgConfig s => (OpenSSL.writeInt (bio, 3);
97 OpenSSL.writeString (bio, s))
98 | MsgFile {action, domain, dir, file} =>
99 (OpenSSL.writeInt (bio, 4);
100 OpenSSL.writeInt (bio, a2i action);
101 OpenSSL.writeString (bio, domain);
102 OpenSSL.writeString (bio, dir);
103 OpenSSL.writeString (bio, file))
104 | MsgDoFiles => OpenSSL.writeInt (bio, 5)
105 | MsgGrant acl => (OpenSSL.writeInt (bio, 6);
106 sendAcl (bio, acl))
107 | MsgRevoke acl => (OpenSSL.writeInt (bio, 7);
108 sendAcl (bio, acl))
109 | MsgListPerms user => (OpenSSL.writeInt (bio, 8);
110 OpenSSL.writeString (bio, user))
111 | MsgPerms classes => (OpenSSL.writeInt (bio, 9);
112 sendList (fn (bio, (class, values)) =>
113 (OpenSSL.writeString (bio, class);
114 sendList OpenSSL.writeString (bio, values)))
115 (bio, classes))
116 | MsgWhoHas {class, value} => (OpenSSL.writeInt (bio, 10);
117 OpenSSL.writeString (bio, class);
118 OpenSSL.writeString (bio, value))
119 | MsgWhoHasResponse users => (OpenSSL.writeInt (bio, 11);
120 sendList OpenSSL.writeString (bio, users))
121 | MsgMultiConfig codes => (OpenSSL.writeInt (bio, 12);
122 sendList OpenSSL.writeString (bio, codes))
123 | MsgRmdom doms => (OpenSSL.writeInt (bio, 13);
124 sendList OpenSSL.writeString (bio, doms))
125 | MsgRegenerate => OpenSSL.writeInt (bio, 14)
126 | MsgRmuser dom => (OpenSSL.writeInt (bio, 15);
127 OpenSSL.writeString (bio, dom))
128 | MsgCreateDbUser {dbtype, passwd} => (OpenSSL.writeInt (bio, 16);
129 OpenSSL.writeString (bio, dbtype);
130 sendOption OpenSSL.writeString (bio, passwd))
131 | MsgCreateDbTable {dbtype, dbname} => (OpenSSL.writeInt (bio, 17);
132 OpenSSL.writeString (bio, dbtype);
133 OpenSSL.writeString (bio, dbname))
134 | MsgNewMailbox {domain, user, passwd, mailbox} =>
135 (OpenSSL.writeInt (bio, 18);
136 OpenSSL.writeString (bio, domain);
137 OpenSSL.writeString (bio, user);
138 OpenSSL.writeString (bio, passwd);
139 OpenSSL.writeString (bio, mailbox))
140 | MsgPasswdMailbox {domain, user, passwd} =>
141 (OpenSSL.writeInt (bio, 19);
142 OpenSSL.writeString (bio, domain);
143 OpenSSL.writeString (bio, user);
144 OpenSSL.writeString (bio, passwd))
145 | MsgRmMailbox {domain, user} =>
146 (OpenSSL.writeInt (bio, 20);
147 OpenSSL.writeString (bio, domain);
148 OpenSSL.writeString (bio, user))
149 | MsgListMailboxes domain =>
150 (OpenSSL.writeInt (bio, 21);
151 OpenSSL.writeString (bio, domain))
152 | MsgMailboxes users =>
153 (OpenSSL.writeInt (bio, 22);
154 sendList (fn (bio, {user, mailbox}) =>
155 (OpenSSL.writeString (bio, user);
156 OpenSSL.writeString (bio, mailbox)))
157 (bio, users))
158 | MsgSaQuery addr => (OpenSSL.writeInt (bio, 23);
159 OpenSSL.writeString (bio, addr))
160 | MsgSaStatus b => (OpenSSL.writeInt (bio, 24);
161 sendBool (bio, b))
162 | MsgSaSet (addr, b) => (OpenSSL.writeInt (bio, 25);
163 OpenSSL.writeString (bio, addr);
164 sendBool (bio, b))
165 | MsgSmtpLogReq domain => (OpenSSL.writeInt (bio, 26);
166 OpenSSL.writeString (bio, domain))
167 | MsgSmtpLogRes domain => (OpenSSL.writeInt (bio, 27);
168 OpenSSL.writeString (bio, domain))
169 | MsgDbPasswd {dbtype, passwd} => (OpenSSL.writeInt (bio, 28);
170 OpenSSL.writeString (bio, dbtype);
171 OpenSSL.writeString (bio, passwd))
172 | MsgShutdown => OpenSSL.writeInt (bio, 29)
173
174 fun checkIt v =
175 case v of
176 NONE => raise OpenSSL.OpenSSL "Bad Msg format"
177 | _ => v
178
179 fun recv bio =
180 case OpenSSL.readInt bio of
181 NONE => NONE
182 | SOME n =>
183 checkIt (case n of
184 1 => SOME MsgOk
185 | 2 => Option.map MsgError (OpenSSL.readString bio)
186 | 3 => Option.map MsgConfig (OpenSSL.readString bio)
187 | 4 => (case (OpenSSL.readInt bio,
188 OpenSSL.readString bio,
189 OpenSSL.readString bio,
190 OpenSSL.readString bio) of
191 (SOME action, SOME domain, SOME dir, SOME file) =>
192 SOME (MsgFile {action = i2a action,
193 domain = domain,
194 dir = dir,
195 file = file})
196 | _ => NONE)
197 | 5 => SOME MsgDoFiles
198 | 6 => (case recvAcl bio of
199 SOME acl => SOME (MsgGrant acl)
200 | _ => NONE)
201 | 7 => (case recvAcl bio of
202 SOME acl => SOME (MsgRevoke acl)
203 | _ => NONE)
204 | 8 => (case OpenSSL.readString bio of
205 SOME user => SOME (MsgListPerms user)
206 | _ => NONE)
207 | 9 => Option.map MsgPerms
208 (recvList (fn bio =>
209 case (OpenSSL.readString bio,
210 recvList OpenSSL.readString bio) of
211 (SOME class, SOME values) => SOME (class, values)
212 | _ => NONE) bio)
213 | 10 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
214 (SOME class, SOME value) => SOME (MsgWhoHas {class = class, value = value})
215 | _ => NONE)
216 | 11 => Option.map MsgWhoHasResponse
217 (recvList OpenSSL.readString bio)
218 | 12 => Option.map MsgMultiConfig
219 (recvList OpenSSL.readString bio)
220 | 13 => Option.map MsgRmdom (recvList OpenSSL.readString bio)
221 | 14 => SOME MsgRegenerate
222 | 15 => Option.map MsgRmuser (OpenSSL.readString bio)
223 | 16 => (case (OpenSSL.readString bio, recvOption OpenSSL.readString bio) of
224 (SOME dbtype, SOME passwd) =>
225 SOME (MsgCreateDbUser {dbtype = dbtype, passwd = passwd})
226 | _ => NONE)
227 | 17 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
228 (SOME dbtype, SOME dbname) =>
229 SOME (MsgCreateDbTable {dbtype = dbtype, dbname = dbname})
230 | _ => NONE)
231 | 18 => (case (OpenSSL.readString bio, OpenSSL.readString bio,
232 OpenSSL.readString bio, OpenSSL.readString bio) of
233 (SOME domain, SOME user, SOME passwd, SOME mailbox) =>
234 SOME (MsgNewMailbox {domain = domain, user = user,
235 passwd = passwd, mailbox = mailbox})
236 | _ => NONE)
237 | 19 => (case (OpenSSL.readString bio, OpenSSL.readString bio,
238 OpenSSL.readString bio) of
239 (SOME domain, SOME user, SOME passwd) =>
240 SOME (MsgPasswdMailbox {domain = domain, user = user,
241 passwd = passwd})
242 | _ => NONE)
243 | 20 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
244 (SOME domain, SOME user) =>
245 SOME (MsgRmMailbox {domain = domain, user = user})
246 | _ => NONE)
247 | 21 => Option.map MsgListMailboxes (OpenSSL.readString bio)
248 | 22 => Option.map MsgMailboxes (recvList
249 (fn bio =>
250 case (OpenSSL.readString bio,
251 OpenSSL.readString bio) of
252 (SOME user, SOME mailbox) =>
253 SOME {user = user, mailbox = mailbox}
254 | _ => NONE)
255 bio)
256 | 23 => Option.map MsgSaQuery (OpenSSL.readString bio)
257 | 24 => Option.map MsgSaStatus (recvBool bio)
258 | 25 => (case (OpenSSL.readString bio, recvBool bio) of
259 (SOME user, SOME b) => SOME (MsgSaSet (user, b))
260 | _ => NONE)
261 | 26 => Option.map MsgSmtpLogReq (OpenSSL.readString bio)
262 | 27 => Option.map MsgSmtpLogRes (OpenSSL.readString bio)
263 | 28 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of
264 (SOME dbtype, SOME passwd) =>
265 SOME (MsgDbPasswd {dbtype = dbtype, passwd = passwd})
266 | _ => NONE)
267 | 29 => SOME MsgShutdown
268 | _ => NONE)
269
270 end