Implement reception of Close message

This commit is contained in:
Jakob Borg 2014-07-26 21:27:55 +02:00
parent 5bf7d372f6
commit b7176d2204
4 changed files with 107 additions and 0 deletions

View File

@ -594,6 +594,33 @@ firewalls and NAT gateways. The Ping message has no contents.
The Pong message is sent in response to a Ping. The Pong message has no
contents, but copies the Message ID from the Ping.
### Close (Type = 7)
The Close message MAY be sent to indicate that the connection will be
torn down due to an error condition. A Close message MUST NOT be
followed by further messages.
#### Graphical Representation
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length of Reason |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ Reason (variable length) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#### Fields
The Reason field contains a human description of the error condition,
suitable for consumption by a human.
struct CloseMessage {
string Reason<1024>;
}
Sharing Modes
-------------

View File

@ -71,3 +71,7 @@ type Option struct {
Key string // max:64
Value string // max:1024
}
type CloseMessage struct {
Reason string // max:1024
}

View File

@ -691,3 +691,64 @@ func (o *Option) decodeXDR(xr *xdr.Reader) error {
o.Value = xr.ReadStringMax(1024)
return xr.Error()
}
/*
CloseMessage Structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length of Reason |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ Reason (variable length) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct CloseMessage {
string Reason<1024>;
}
*/
func (o CloseMessage) EncodeXDR(w io.Writer) (int, error) {
var xw = xdr.NewWriter(w)
return o.encodeXDR(xw)
}
func (o CloseMessage) MarshalXDR() []byte {
return o.AppendXDR(make([]byte, 0, 128))
}
func (o CloseMessage) AppendXDR(bs []byte) []byte {
var aw = xdr.AppendWriter(bs)
var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw)
return []byte(aw)
}
func (o CloseMessage) encodeXDR(xw *xdr.Writer) (int, error) {
if len(o.Reason) > 1024 {
return xw.Tot(), xdr.ErrElementSizeExceeded
}
xw.WriteString(o.Reason)
return xw.Tot(), xw.Error()
}
func (o *CloseMessage) DecodeXDR(r io.Reader) error {
xr := xdr.NewReader(r)
return o.decodeXDR(xr)
}
func (o *CloseMessage) UnmarshalXDR(bs []byte) error {
var br = bytes.NewReader(bs)
var xr = xdr.NewReader(br)
return o.decodeXDR(xr)
}
func (o *CloseMessage) decodeXDR(xr *xdr.Reader) error {
o.Reason = xr.ReadStringMax(1024)
return xr.Error()
}

View File

@ -25,6 +25,7 @@ const (
messageTypePing = 4
messageTypePong = 5
messageTypeIndexUpdate = 6
messageTypeClose = 7
)
const (
@ -306,6 +307,11 @@ func (c *rawConnection) readerLoop() (err error) {
}
c.state = stateCCRcvd
case messageTypeClose:
if err := c.handleClose(); err != nil {
return err
}
default:
return fmt.Errorf("protocol error: %s: unknown message type %#x", c.id, hdr.msgType)
}
@ -389,6 +395,15 @@ func (c *rawConnection) handleClusterConfig() error {
return nil
}
func (c *rawConnection) handleClose() error {
var cm CloseMessage
cm.decodeXDR(c.xr)
if err := c.xr.Error(); err != nil {
return err
}
return errors.New(cm.Reason)
}
type encodable interface {
encodeXDR(*xdr.Writer) (int, error)
}