summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 52c1b78)
raw | patch | inline | side by side (parent: 52c1b78)
author | Sebastian Harl <sh@tokkee.org> | |
Sat, 21 Feb 2015 23:16:49 +0000 (00:16 +0100) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sat, 21 Feb 2015 23:16:49 +0000 (00:16 +0100) |
client/client.go | patch | blob | history |
diff --git a/client/client.go b/client/client.go
index 34a0434a1eeda23886d00ad34565b97c1226c22f..fcb5d8de2f6c2d88fec581d868550c0c84e2d684 100644 (file)
--- a/client/client.go
+++ b/client/client.go
// messages, the communication with the server will usually happen
// sequentially.
type Conn struct {
// messages, the communication with the server will usually happen
// sequentially.
type Conn struct {
- c net.Conn
+ c net.Conn
+ network, addr, user string
+}
+
+func (c *Conn) connect() (err error) {
+ if c.c, err = net.Dial(c.network, c.addr); err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ c.Close()
+ }
+ }()
+
+ m := &proto.Message{
+ Type: proto.ConnectionStartup,
+ Raw: []byte(c.user),
+ }
+ if err := c.Send(m); err != nil {
+ return err
+ }
+
+ m, err = c.Receive()
+ if err != nil {
+ return err
+ }
+ if m.Type == proto.ConnectionError {
+ return fmt.Errorf("failed to startup session: %s", string(m.Raw))
+ }
+ if m.Type != proto.ConnectionOK {
+ return fmt.Errorf("failed to startup session: unsupported")
+ }
+ return nil
}
// Connect sets up a client connection to a SysDB server instance at the
}
// Connect sets up a client connection to a SysDB server instance at the
network = "unix"
}
network = "unix"
}
- c := &Conn{}
- var err error
- if c.c, err = net.Dial(network, addr); err != nil {
- return nil, err
- }
-
- m := &proto.Message{
- Type: proto.ConnectionStartup,
- Raw: []byte(user),
- }
- if err := c.Send(m); err != nil {
- return nil, err
- }
-
- m, err = c.Receive()
- if err != nil {
+ c := &Conn{network: network, addr: addr, user: user}
+ if err := c.connect(); err != nil {
return nil, err
}
return nil, err
}
- if m.Type == proto.ConnectionError {
- return nil, fmt.Errorf("failed to startup session: %s", string(m.Raw))
- }
- if m.Type != proto.ConnectionOK {
- return nil, fmt.Errorf("failed to startup session: unsupported")
- }
return c, nil
}
// Close closes the client connection.
//
// Any blocked Send or Receive operations will be unblocked and return errors.
return c, nil
}
// Close closes the client connection.
//
// Any blocked Send or Receive operations will be unblocked and return errors.
-func (c Conn) Close() { c.c.Close() }
+func (c *Conn) Close() {
+ if c.c == nil {
+ return
+ }
+ c.c.Close()
+ c.c = nil
+}
// Send sends the specified raw message to the server.
//
// Send operations block until the full message could be written to the
// underlying sockets. This ensures that server and client don't get out of
// sync.
// Send sends the specified raw message to the server.
//
// Send operations block until the full message could be written to the
// underlying sockets. This ensures that server and client don't get out of
// sync.
-func (c Conn) Send(m *proto.Message) error {
- return proto.Write(c.c, m)
+func (c *Conn) Send(m *proto.Message) error {
+ var err error
+ if c.c != nil {
+ err = proto.Write(c.c, m)
+ if err == nil {
+ return nil
+ }
+ c.Close()
+ }
+
+ // Try to reconnect.
+ if e := c.connect(); e == nil {
+ return proto.Write(c.c, m)
+ } else if err == nil {
+ err = e
+ }
+ return err
}
// Receive waits for a reply from the server and returns the raw message.
}
// Receive waits for a reply from the server and returns the raw message.
// Receive operations block until a full message could be read from the
// underlying socket. This ensures that server and client don't get out of
// sync.
// Receive operations block until a full message could be read from the
// underlying socket. This ensures that server and client don't get out of
// sync.
-func (c Conn) Receive() (*proto.Message, error) {
- return proto.Read(c.c)
+func (c *Conn) Receive() (*proto.Message, error) {
+ var err error
+ if c.c != nil {
+ var m *proto.Message
+ m, err = proto.Read(c.c)
+ if err == nil {
+ return m, err
+ }
+ c.Close()
+ }
+
+ // Try to reconnect.
+ if e := c.connect(); e == nil {
+ return proto.Read(c.c)
+ } else if err == nil {
+ err = e
+ }
+ return nil, err
}
// vim: set tw=78 sw=4 sw=4 noexpandtab :
}
// vim: set tw=78 sw=4 sw=4 noexpandtab :