Code

5aadf9aee1885e45f8cc9157545683f6292d57f4
[sysdb/go.git] / proto / proto.go
1 //
2 // Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 // 1. Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the distribution.
13 //
14 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 // ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
18 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // Package proto provides helper functions for using the SysDB front-end
27 // protocol. That's the protocol used for communication between a client and a
28 // SysDB server instance.
29 package proto
31 import (
32         "encoding/binary"
33         "io"
34 )
36 // Network byte order.
37 var nbo = binary.BigEndian
39 // A Status represents the type of a message. The message type describes the
40 // current status or state of a connection depending on the context.
41 type Status uint32
43 const (
44         // ConnectionOK indicates that a command was successful.
45         ConnectionOK = Status(0)
46         // ConnectionError indicates that a command has failed.
47         ConnectionError = Status(1)
48         // ConnectionLog indicates an (asynchronous) log message.
49         ConnectionLog = Status(2)
51         // ConnectionData indicates a successful query returning data.
52         ConnectionData = Status(100)
53 )
55 const (
56         // ConnectionIdle is the internal state for idle connections.
57         ConnectionIdle = Status(0)
58         // ConnectionPing is the state requesting a connection check.
59         ConnectionPing = Status(1)
60         // ConnectionStartup is the state requesting the setup of a client
61         // connection.
62         ConnectionStartup = Status(2)
64         // ConnectionQuery is the state requesting the execution of a query in the
65         // server.
66         ConnectionQuery = Status(3)
67         // ConnectionFetch is the state requesting the execution of the 'FETCH'
68         // command in the server.
69         ConnectionFetch = Status(4)
70         // ConnectionList is the state requesting the execution of the 'LIST'
71         // command in the server.
72         ConnectionList = Status(5)
73         // ConnectionLookup is the state requesting the execution of the 'LOOKUP'
74         // command in the server.
75         ConnectionLookup = Status(6)
76         // ConnectionTimeseries is the state requesting the execution of the
77         // 'TIMESERIES' command in the server.
78         ConnectionTimeseries = Status(7)
80         // ConnectionExpr is the internal state for expression parsing.
81         ConnectionExpr = Status(100)
82 )
84 // A Message represents a raw message of the SysDB front-end protocol.
85 type Message struct {
86         Type Status
87         Raw  []byte
88 }
90 // Decodes reads a raw message encoded in the SysDB wire format from r. The
91 // raw body of the message will still be encoded in the wire format.
92 //
93 // The reader has to be in blocking mode. Otherwise, the client and server
94 // will be out of sync after reading a partial message and cannot recover from
95 // that.
96 func Decode(r io.Reader) (*Message, error) {
97         var header [8]byte
98         if _, err := io.ReadFull(r, header[:]); err != nil {
99                 return nil, err
100         }
102         typ := nbo.Uint32(header[:4])
103         l := nbo.Uint32(header[4:])
104         msg := make([]byte, l)
105         if _, err := io.ReadFull(r, msg); err != nil {
106                 return nil, err
107         }
109         return &Message{Status(typ), msg}, nil
112 // Encode writes a raw message to w. The raw body of m has to be encoded in
113 // the SysDB wire format.
114 //
115 // The writer has to be in blocking mode. Otherwise, the client and server
116 // will be out of sync after writing a partial message and cannot recover from
117 // that.
118 func Encode(w io.Writer, m *Message) error {
119         var header [8]byte
120         nbo.PutUint32(header[:4], uint32(m.Type))
121         nbo.PutUint32(header[4:], uint32(len(m.Raw)))
123         if _, err := io.WriteString(w, string(header[:])); err != nil {
124                 return err
125         }
126         if _, err := io.WriteString(w, string(m.Raw)); err != nil {
127                 return err
128         }
129         return nil
132 // vim: set tw=78 sw=4 sw=4 noexpandtab :