Skip to content
This repository has been archived by the owner on Apr 5, 2024. It is now read-only.

Commit

Permalink
TCPCL: Message Rejection Message
Browse files Browse the repository at this point in the history
  • Loading branch information
oxzi committed Sep 5, 2019
1 parent c9fd2e6 commit a899a61
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
107 changes: 107 additions & 0 deletions cla/tcpcl/message_reject.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package tcpcl

import (
"bytes"
"encoding/binary"
"fmt"
)

// MessageRejectionReason is the one-octet refusal code from a MessageRejectionMessage.
type MessageRejectionReason uint8

const (
// RejectionTypeUnknown indicates an unknown Message Type Code.
RejectionTypeUnknown MessageRejectionReason = 0x01

// RejectionUnsupported indicates that this TCPCL node cannot comply with
// the message content.
RejectionUnsupported MessageRejectionReason = 0x02

// RejectionUnexptected indicates that this TCPCL node received a message
// while the session is in a state in which the message is not expected.
RejectionUnexptected MessageRejectionReason = 0x03

// messageRejectionReason_INVALID is a bit field of all invalid MessageRejectionMessages.
messageRejectionReason_INVALID = 0xFC
)

func (mrr MessageRejectionReason) String() string {
switch mrr {
case RejectionTypeUnknown:
return "Message Type Unknown"
case RejectionUnsupported:
return "Message Unsupported"
case RejectionUnexptected:
return "Message Unexpected"
default:
return "INVALID"
}
}

// MSG_REJECT is the Message Header code for a Message Rejection Message.
const MSG_REJECT uint8 = 0x06

// MessageRejectionMessage is the MSG_REJECT message for message rejection.
type MessageRejectionMessage struct {
ReasonCode MessageRejectionReason
MessageHeader uint8
}

// NewMessageRejectionMessage creates a new MessageRejectionMessage with given fields.
func NewMessageRejectionMessage(reasonCode MessageRejectionReason, messageHeader uint8) MessageRejectionMessage {
return MessageRejectionMessage{
ReasonCode: reasonCode,
MessageHeader: messageHeader,
}
}

func (mrm MessageRejectionMessage) String() string {
return fmt.Sprintf(
"MSG_REJECT(Reason Code=%v, Rejected Message Header=%d)",
mrm.ReasonCode, mrm.MessageHeader)
}

// MarshalBinary encodes this MessageRejectionMessage into its binary form.
func (mrm MessageRejectionMessage) MarshalBinary() (data []byte, err error) {
var buf = new(bytes.Buffer)
var fields = []interface{}{
MSG_REJECT,
mrm.ReasonCode,
mrm.MessageHeader}

for _, field := range fields {
if binErr := binary.Write(buf, binary.BigEndian, field); binErr != nil {
err = binErr
return
}
}

data = buf.Bytes()
return
}

// UnmarshalBinary decodes a MessageRejectionMessage from its binary form.
func (mrm *MessageRejectionMessage) UnmarshalBinary(data []byte) error {
var buf = bytes.NewReader(data)

var messageHeader uint8
if err := binary.Read(buf, binary.BigEndian, &messageHeader); err != nil {
return err
} else if messageHeader != MSG_REJECT {
return fmt.Errorf("MSG_REJECT's Message Header is wrong: %d instead of %d", messageHeader, MSG_REJECT)
}

var fields = []interface{}{&mrm.ReasonCode, &mrm.MessageHeader}

for _, field := range fields {
if err := binary.Read(buf, binary.BigEndian, field); err != nil {
return err
}
}

if mrm.ReasonCode&messageRejectionReason_INVALID != 0 {
return fmt.Errorf("MSG_REJECT's Reason Code %x is invalid", mrm.ReasonCode)
}

return nil
}
38 changes: 38 additions & 0 deletions cla/tcpcl/message_reject_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package tcpcl

import (
"bytes"
"reflect"
"testing"
)

func TestMessageRejectionMessage(t *testing.T) {
tests := []struct {
valid bool
data []byte
mrm MessageRejectionMessage
}{
{true, []byte{0x06, 0x01, 0x01}, NewMessageRejectionMessage(RejectionTypeUnknown, 0x01)},
{true, []byte{0x06, 0x03, 0x01}, NewMessageRejectionMessage(RejectionUnexptected, 0x01)},
{false, []byte{0x07, 0x00, 0x00}, MessageRejectionMessage{}},
{false, []byte{0x06, 0xF0, 0x00}, MessageRejectionMessage{}},
}

for _, test := range tests {
var mrm MessageRejectionMessage

if err := mrm.UnmarshalBinary(test.data); (err == nil) != test.valid {
t.Fatalf("Error state was not expected; valid := %t, got := %v", test.valid, err)
} else if !test.valid {
continue
} else if !reflect.DeepEqual(test.mrm, mrm) {
t.Fatalf("MessageRejectionMessage does not match, expected %v and got %v", test.mrm, mrm)
}

if data, err := test.mrm.MarshalBinary(); err != nil {
t.Fatal(err)
} else if !bytes.Equal(data, test.data) {
t.Fatalf("Data does not match, expected %x and got %x", test.data, data)
}
}
}

0 comments on commit a899a61

Please sign in to comment.