This repository has been archived by the owner on Apr 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package tcpcl | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
) | ||
|
||
// ContactFlags are single-bit flags used in the ContactHeader. | ||
type ContactFlags uint8 | ||
|
||
const ( | ||
// ContactFlags_NONE is a default for no flags | ||
ContactFlags_NONE ContactFlags = 0x00 | ||
|
||
// ContactFlags_CAN_TLS indicates that the sending peer is capable of TLS security. | ||
ContactFlags_CAN_TLS ContactFlags = 0x01 | ||
|
||
// contactFlags_INVALID is a bit field of all invalid ContactFlags. | ||
contactFlags_INVALID ContactFlags = 0xFE | ||
) | ||
|
||
func (cf ContactFlags) String() string { | ||
switch cf { | ||
case ContactFlags_NONE: | ||
return "NONE" | ||
case ContactFlags_CAN_TLS: | ||
return "CAN_TLS" | ||
default: | ||
return "INVALID" | ||
} | ||
} | ||
|
||
// ContactHeader will be exchanged at first after a TCP connection was | ||
// established. Both entities are sending a ContactHeader and are validating | ||
// the peer's one. | ||
type ContactHeader struct { | ||
Flags ContactFlags | ||
} | ||
|
||
// NewContactHeader creates a new ContactHeader with given ContactFlags. | ||
func NewContactHeader(flags ContactFlags) ContactHeader { | ||
return ContactHeader{ | ||
Flags: flags, | ||
} | ||
} | ||
|
||
func (ch ContactHeader) String() string { | ||
return fmt.Sprintf("ContactHeader(Version=4, Flags=%v)", ch.Flags) | ||
} | ||
|
||
// MarshalBinary encodes this ContactHeader into its binary form. | ||
func (ch ContactHeader) MarshalBinary() (data []byte, _ error) { | ||
// magic='dtn!', version=4, flags=flags | ||
data = []byte{0x64, 0x74, 0x6E, 0x21, 0x04, byte(ch.Flags)} | ||
return | ||
} | ||
|
||
// UnmarshalBinary decodes a ContactHeader from its binary form. | ||
func (ch *ContactHeader) UnmarshalBinary(data []byte) error { | ||
if len(data) != 6 { | ||
return fmt.Errorf("ContactHeader's length is wrong: %d instead of 6", len(data)) | ||
} | ||
|
||
if !bytes.Equal(data[:4], []byte("dtn!")) { | ||
return fmt.Errorf("ContactHeader's magic does not match: %x != 'dtn!'", data[:4]) | ||
} | ||
|
||
if uint8(data[4]) != 4 { | ||
return fmt.Errorf("ContactHeader's version is wrong: %d instead of 4", uint8(data[4])) | ||
} | ||
|
||
if cf := ContactFlags(data[5]); cf&contactFlags_INVALID != 0 { | ||
return fmt.Errorf("ContactHeader's flags %x contain invalid flags", cf) | ||
} else { | ||
ch.Flags = cf | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package tcpcl | ||
|
||
import ( | ||
"bytes" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestContactHeaderMarshal(t *testing.T) { | ||
tests := []struct { | ||
contactHeader ContactHeader | ||
expectedData []byte | ||
}{ | ||
{NewContactHeader(ContactFlags_NONE), []byte{0x64, 0x74, 0x6E, 0x21, 0x04, 0x00}}, | ||
{NewContactHeader(ContactFlags_CAN_TLS), []byte{0x64, 0x74, 0x6E, 0x21, 0x04, 0x01}}, | ||
} | ||
|
||
for _, test := range tests { | ||
if data, err := test.contactHeader.MarshalBinary(); err != nil { | ||
t.Fatal(err) | ||
} else if !bytes.Equal(data, test.expectedData) { | ||
t.Fatalf("Data does not match, expected %x and got %x", test.expectedData, data) | ||
} | ||
} | ||
} | ||
|
||
func TestContactHeaderUnmarshal(t *testing.T) { | ||
tests := []struct { | ||
data []byte | ||
valid bool | ||
contactHeader ContactHeader | ||
}{ | ||
{[]byte{0x64, 0x74, 0x6E, 0x21, 0x04, 0x00}, true, ContactHeader{Flags: ContactFlags_NONE}}, | ||
{[]byte{0x64, 0x74, 0x6E, 0x21, 0x04, 0x01}, true, ContactHeader{Flags: ContactFlags_CAN_TLS}}, | ||
{[]byte{0x64, 0x74, 0x6E, 0x21, 0x04}, false, ContactHeader{}}, | ||
{[]byte{0x64, 0x74, 0x6E, 0x21, 0x04, 0x00, 0x00}, false, ContactHeader{}}, | ||
{[]byte{0x64, 0x74, 0x6E, 0x3F, 0x04, 0x00}, false, ContactHeader{}}, | ||
{[]byte{0x64, 0x74, 0x6E, 0x21, 0x23, 0x00}, false, ContactHeader{}}, | ||
{[]byte{0x64, 0x74, 0x6E, 0x21, 0x04, 0x23}, false, ContactHeader{}}, | ||
} | ||
|
||
for _, test := range tests { | ||
var ch ContactHeader | ||
if err := ch.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.contactHeader, ch) { | ||
t.Fatalf("ContactHeader does not match, expected %v and got %v", test.contactHeader, ch) | ||
} | ||
} | ||
} |