diff --git a/proto/proto.go b/proto/proto.go
index 5aadf9aee1885e45f8cc9157545683f6292d57f4..a58725d6f81a6c7ad451390974e311b63a08b0f7 100644 (file)
--- a/proto/proto.go
+++ b/proto/proto.go
import (
"encoding/binary"
+ "encoding/json"
+ "fmt"
"io"
+ "strings"
)
// Network byte order.
// 'TIMESERIES' command in the server.
ConnectionTimeseries = Status(7)
- // ConnectionExpr is the internal state for expression parsing.
- ConnectionExpr = Status(100)
+ // ConnectionMatcher is the internal state for parsing matchers.
+ ConnectionMatcher = Status(100)
+ // ConnectionExpr is the internal state for parsing expressions.
+ ConnectionExpr = Status(101)
+
+ // ConnectionServerVersion is the state requesting the server version.
+ ConnectionServerVersion = Status(1000)
+)
+
+// The DataType describes the type of data in a ConnectionData message.
+type DataType int
+
+const (
+ // A HostList can be unmarshaled to []sysdb.Host.
+ HostList DataType = iota
+ // A Host can be unmarshaled to sysdb.Host.
+ Host
+ // A Timeseries can be unmarshaled to sysdb.Timeseries.
+ Timeseries
)
// A Message represents a raw message of the SysDB front-end protocol.
Raw []byte
}
-// Decodes reads a raw message encoded in the SysDB wire format from r. The
-// raw body of the message will still be encoded in the wire format.
+// Read reads a raw message encoded in the SysDB wire format from r. The
+// function parses the header but the raw body of the message will still be
+// encoded in the wire format.
//
// The reader has to be in blocking mode. Otherwise, the client and server
// will be out of sync after reading a partial message and cannot recover from
// that.
-func Decode(r io.Reader) (*Message, error) {
+func Read(r io.Reader) (*Message, error) {
var header [8]byte
if _, err := io.ReadFull(r, header[:]); err != nil {
return nil, err
return &Message{Status(typ), msg}, nil
}
-// Encode writes a raw message to w. The raw body of m has to be encoded in
-// the SysDB wire format.
+// Write writes a raw message to w. The raw body of m has to be encoded in the
+// SysDB wire format. The function adds the right header to the message.
//
// The writer has to be in blocking mode. Otherwise, the client and server
// will be out of sync after writing a partial message and cannot recover from
// that.
-func Encode(w io.Writer, m *Message) error {
+func Write(w io.Writer, m *Message) error {
var header [8]byte
nbo.PutUint32(header[:4], uint32(m.Type))
nbo.PutUint32(header[4:], uint32(len(m.Raw)))
return nil
}
+// DataType determines the type of data in a ConnectionData message.
+func (m Message) DataType() (DataType, error) {
+ if m.Type != ConnectionData {
+ return 0, fmt.Errorf("message is not of type DATA")
+ }
+
+ typ := nbo.Uint32(m.Raw[:4])
+ switch Status(typ) {
+ case ConnectionList, ConnectionLookup:
+ return HostList, nil
+ case ConnectionFetch:
+ return Host, nil
+ case ConnectionTimeseries:
+ return Timeseries, nil
+ }
+ return 0, fmt.Errorf("unknown DATA type %d", typ)
+}
+
+// Unmarshal parses the raw body of m and stores the result in the value
+// pointed to by v which has to match the type of the message and its data.
+func Unmarshal(m *Message, v interface{}) error {
+ if m.Type != ConnectionData {
+ return fmt.Errorf("unmarshaling message of type %d not supported", m.Type)
+ }
+ if len(m.Raw) == 0 { // empty command
+ return nil
+ } else if len(m.Raw) < 4 {
+ return fmt.Errorf("DATA message body too short")
+ }
+ return json.Unmarshal(m.Raw[4:], v)
+}
+
+// EscapeString returns the quoted and escaped string s suitable for use
+// in a query.
+func EscapeString(s string) string {
+ // Currently, the server only handles double-quotes.
+ // Backslashes do not serve any special purpose.
+ return "'" + strings.Replace(s, "'", "''", -1) + "'"
+}
+
// vim: set tw=78 sw=4 sw=4 noexpandtab :