Blob


1 package mailmux
3 import (
4 "encoding/json"
5 "errors"
6 "io"
7 "time"
8 )
10 const (
11 Tregister = 1 + iota
12 Rregister
13 Rerror
14 Tcreate
15 Rcreate
16 Tlist
17 Rlist
18 Tremove
19 Rremove
20 Tauth
21 Rauth
22 )
24 // Mcall represents a message passed between mailmux clients and servers.
25 // Operations requested by clients are T-messages (such as Tregister).
26 // Servers respond with the corresponding R-message (such as Rregister).
27 // Servers may instead respond with Rerror to inform the client, with a diagnostic message,
28 // that the request was not completed successfully.
29 // This design is loosely based on the Plan 9 network file protocol 9P.
30 type Mcall struct {
31 Type uint
32 Username string `json:",omitempty"` // Tregister, Rregister
33 Password string `json:",omitempty"` // Tregister
34 Error string `json:",omitempty"` // Rerror
35 Aliases []Alias `json:",omitempty"` // Rnew, Rlist, Tremove
36 Expiry time.Time `json:",omitempty"` // Tcreate, Rnew
37 }
39 // ParseMcall parses and validates a JSON-encoded Mcall from r.
40 func ParseMcall(r io.Reader) (*Mcall, error) {
41 var mc Mcall
42 if err := json.NewDecoder(r).Decode(&mc); err != nil {
43 return nil, err
44 }
45 switch mc.Type {
46 case Rerror:
47 if mc.Error == "" {
48 return nil, errors.New("empty error message")
49 }
50 case Tauth:
51 if mc.Username == "" {
52 return nil, errors.New("empty username")
53 }
54 if mc.Password == "" {
55 return nil, errors.New("empty password")
56 }
57 case Tregister, Tcreate, Tlist, Tremove:
58 // check required params
59 }
60 return &mc, nil
61 }
63 func writeMcall(w io.Writer, mcall *Mcall) error {
64 return json.NewEncoder(w).Encode(mcall)
65 }
67 // rerror writes a JSON-encoded Rerror message to the underlying writer
68 // with its Error field set to errormsg.
69 func rerror(w io.Writer, errormsg string) error {
70 rmsg := &Mcall{Type: Rerror, Error: errormsg}
71 return writeMcall(w, rmsg)
72 }