(* HCoop Domtool (http://hcoop.sourceforge.net/) * Copyright (c) 2006, Adam Chlipala * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) (* Network messages *) structure Msg :> MSG = struct open OpenSSL MsgTypes Slave val a2i = fn Add => 0 | Delete => 1 | Modify => 2 val i2a = fn 0 => Add | 1 => Delete | 2 => Modify | _ => raise OpenSSL.OpenSSL "Bad action number to deserialize" fun sendAcl (bio, {user, class, value}) = (OpenSSL.writeString (bio, user); OpenSSL.writeString (bio, class); OpenSSL.writeString (bio, value)) fun recvAcl bio = case (OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of (SOME user, SOME class, SOME value) => SOME {user = user, class = class, value = value} | _ => NONE fun sendList f (bio, ls) = (app (fn x => (OpenSSL.writeInt (bio, 1); f (bio, x))) ls; OpenSSL.writeInt (bio, 0)) fun recvList f bio = let fun loop ls = case OpenSSL.readInt bio of SOME 0 => SOME (rev ls) | SOME 1 => (case f bio of SOME x => loop (x :: ls) | NONE => NONE) | _ => NONE in loop [] end fun send (bio, m) = case m of MsgOk => OpenSSL.writeInt (bio, 1) | MsgError s => (OpenSSL.writeInt (bio, 2); OpenSSL.writeString (bio, s)) | MsgConfig s => (OpenSSL.writeInt (bio, 3); OpenSSL.writeString (bio, s)) | MsgFile {action, domain, dir, file} => (OpenSSL.writeInt (bio, 4); OpenSSL.writeInt (bio, a2i action); OpenSSL.writeString (bio, domain); OpenSSL.writeString (bio, dir); OpenSSL.writeString (bio, file)) | MsgDoFiles => OpenSSL.writeInt (bio, 5) | MsgGrant acl => (OpenSSL.writeInt (bio, 6); sendAcl (bio, acl)) | MsgRevoke acl => (OpenSSL.writeInt (bio, 7); sendAcl (bio, acl)) | MsgListPerms user => (OpenSSL.writeInt (bio, 8); OpenSSL.writeString (bio, user)) | MsgPerms classes => (OpenSSL.writeInt (bio, 9); sendList (fn (bio, (class, values)) => (OpenSSL.writeString (bio, class); sendList OpenSSL.writeString (bio, values))) (bio, classes)) | MsgWhoHas {class, value} => (OpenSSL.writeInt (bio, 10); OpenSSL.writeString (bio, class); OpenSSL.writeString (bio, value)) | MsgWhoHasResponse users => (OpenSSL.writeInt (bio, 11); sendList OpenSSL.writeString (bio, users)) | MsgMultiConfig codes => (OpenSSL.writeInt (bio, 12); sendList OpenSSL.writeString (bio, codes)) | MsgRmdom dom => (OpenSSL.writeInt (bio, 13); OpenSSL.writeString (bio, dom)) | MsgRegenerate => OpenSSL.writeInt (bio, 14) fun checkIt v = case v of NONE => raise OpenSSL.OpenSSL "Bad Msg format" | _ => v fun recv bio = case OpenSSL.readInt bio of NONE => NONE | SOME n => checkIt (case n of 1 => SOME MsgOk | 2 => Option.map MsgError (OpenSSL.readString bio) | 3 => Option.map MsgConfig (OpenSSL.readString bio) | 4 => (case (OpenSSL.readInt bio, OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of (SOME action, SOME domain, SOME dir, SOME file) => SOME (MsgFile {action = i2a action, domain = domain, dir = dir, file = file}) | _ => NONE) | 5 => SOME MsgDoFiles | 6 => (case recvAcl bio of SOME acl => SOME (MsgGrant acl) | _ => NONE) | 7 => (case recvAcl bio of SOME acl => SOME (MsgRevoke acl) | _ => NONE) | 8 => (case OpenSSL.readString bio of SOME user => SOME (MsgListPerms user) | _ => NONE) | 9 => Option.map MsgPerms (recvList (fn bio => case (OpenSSL.readString bio, recvList OpenSSL.readString bio) of (SOME class, SOME values) => SOME (class, values) | _ => NONE) bio) | 10 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of (SOME class, SOME value) => SOME (MsgWhoHas {class = class, value = value}) | _ => NONE) | 11 => Option.map MsgWhoHasResponse (recvList OpenSSL.readString bio) | 12 => Option.map MsgMultiConfig (recvList OpenSSL.readString bio) | 13 => Option.map MsgRmdom (OpenSSL.readString bio) | 14 => SOME MsgRegenerate | _ => NONE) end