Add init ack sending, added cookie state

This commit is contained in:
John R. Bradley
2018-07-11 23:28:17 -05:00
committed by Sean DuBois
parent 04f049fb4c
commit 0e43088e58
9 changed files with 125 additions and 11 deletions

View File

@@ -213,10 +213,11 @@ func (p *Port) networkLoop(remoteKey []byte, tlscfg *dtls.TLSCfg, b BufferTransp
p.sctpAssocations[in.srcAddr.String()] = sctp.NewAssocation(func(pkt *sctp.Packet) {
raw, err := pkt.Marshal()
if err != nil {
fmt.Println(errors.Wrap(err, "Failed to Unmarshal SCTP packet"))
fmt.Println(errors.Wrap(err, "Failed to Marshal SCTP packet"))
return
}
fmt.Println(raw)
fmt.Printf("Out: %v\n", raw)
d.Send(raw)
}, func(data []byte) {
fmt.Printf("Handle data %v \n", data)
})

View File

@@ -210,8 +210,9 @@ func (a *Association) handleInit(p *Packet, i *Init) (*Packet, error) {
initAck.initiateTag = a.myVerificationTag
initAck.advertisedReceiverWindowCredit = a.myRreceiverWindowCredit
//initAck.params = append(initAck.params, )
outbound.Chunks = []Chunk{}
initAck.params = []Param{NewRandomStateCookie(), NewEmptySupportedExtensions()}
outbound.Chunks = []Chunk{initAck}
return outbound, nil

View File

@@ -57,6 +57,7 @@ func (i *InitAck) Marshal() ([]byte, error) {
return nil, errors.Wrap(err, "Failed marshalling INIT common data")
}
i.ChunkHeader.typ = INITACK
chunkHeader, err := i.ChunkHeader.Marshal(len(initShared))
if err != nil {
return nil, errors.Wrap(err, "Failed marshalling InitAck Chunk Header")

View File

@@ -111,6 +111,13 @@ func (i *InitCommon) Marshal() ([]byte, error) {
binary.BigEndian.PutUint16(out[8:], i.numOutboundStreams)
binary.BigEndian.PutUint16(out[10:], i.numInboundStreams)
binary.BigEndian.PutUint32(out[12:], i.initialTSN)
for _, p := range i.params {
pp, err := p.Marshal()
if err != nil {
return nil, errors.Wrap(err, "Unable to marshal parameter for INIT/INITACK")
}
out = append(out, pp...)
}
return out, nil
}

View File

@@ -3,6 +3,7 @@ package sctp
import (
"testing"
"fmt"
"github.com/pkg/errors"
)
@@ -37,3 +38,68 @@ func TestInitChunk(t *testing.T) {
t.Error(errors.Errorf("Unmarshal passed for SCTP packet, but got incorrect initialTSN exp: %d act: %d", 3899461680, i.initialTSN))
}
}
func TestInitAck(t *testing.T) {
pkt := &Packet{}
rawPkt := []byte{0x13, 0x88, 0x13, 0x88, 0xce, 0x15, 0x79, 0xa2, 0x96, 0x19, 0xe8, 0xb2, 0x02, 0x00, 0x00, 0x1c, 0xeb, 0x81, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x50, 0xdf, 0x90, 0xd9, 0x00, 0x07, 0x00, 0x08, 0x94, 0x06, 0x2f, 0x93}
err := pkt.Unmarshal(rawPkt)
if err != nil {
t.Error(errors.Wrap(err, "Unmarshal failed, has chunk"))
}
i, ok := pkt.Chunks[0].(*InitAck)
if !ok {
t.Error("Failed to cast Chunk -> Init")
}
fmt.Printf("Init ack: %v\n", i)
if err != nil {
t.Error(errors.Wrap(err, "Unmarshal init Chunk failed"))
}
}
func TestInitMarshalUnmarshal(t *testing.T) {
p := &Packet{}
p.DestinationPort = 1
p.SourcePort = 1
p.VerificationTag = 123
initAck := &InitAck{}
initAck.initialTSN = 123
initAck.numOutboundStreams = 1
initAck.numInboundStreams = 1
initAck.initiateTag = 123
initAck.advertisedReceiverWindowCredit = 1024
initAck.params = []Param{NewRandomStateCookie()}
p.Chunks = []Chunk{initAck}
rawPkt, err := p.Marshal()
if err != nil {
t.Error(errors.Wrap(err, "Failed to marshal packet"))
}
pkt := &Packet{}
err = pkt.Unmarshal(rawPkt)
if err != nil {
t.Error(errors.Wrap(err, "Unmarshal failed, has chunk"))
}
i, ok := pkt.Chunks[0].(*InitAck)
if !ok {
t.Error("Failed to cast Chunk -> InitAck")
}
if err != nil {
t.Error(errors.Wrap(err, "Unmarshal init ack Chunk failed"))
} else if i.initiateTag != 123 {
t.Error(errors.Errorf("Unmarshal passed for SCTP packet, but got incorrect initiate tag exp: %d act: %d", 123, i.initiateTag))
} else if i.advertisedReceiverWindowCredit != 1024 {
t.Error(errors.Errorf("Unmarshal passed for SCTP packet, but got incorrect advertisedReceiverWindowCredit exp: %d act: %d", 1024, i.advertisedReceiverWindowCredit))
} else if i.numOutboundStreams != 1 {
t.Error(errors.Errorf("Unmarshal passed for SCTP packet, but got incorrect numOutboundStreams tag exp: %d act: %d", 1, i.numOutboundStreams))
} else if i.numInboundStreams != 1 {
t.Error(errors.Errorf("Unmarshal passed for SCTP packet, but got incorrect numInboundStreams exp: %d act: %d", 1, i.numInboundStreams))
} else if i.initialTSN != 123 {
t.Error(errors.Errorf("Unmarshal passed for SCTP packet, but got incorrect initialTSN exp: %d act: %d", 123, i.initialTSN))
}
}

View File

@@ -75,6 +75,8 @@ func (p *Packet) Unmarshal(raw []byte) error {
switch ChunkType(raw[offset]) {
case INIT:
c = &Init{}
case INITACK:
c = &InitAck{}
default:
return errors.Errorf("Failed to unmarshal, contains unknown chunk type %s", ChunkType(raw[offset]).String())
}
@@ -82,6 +84,7 @@ func (p *Packet) Unmarshal(raw []byte) error {
if err := c.Unmarshal(raw[offset:]); err != nil {
return err
}
p.Chunks = append(p.Chunks, c)
chunkValuePadding := c.valueLength() % 4
offset += chunkHeaderSize + c.valueLength() + chunkValuePadding
@@ -113,7 +116,7 @@ func (p *Packet) Marshal() ([]byte, error) {
raw = append(raw, chunkRaw...)
}
paddingNeeded := len(raw) % 4
paddingNeeded := getPadding(len(raw), 4)
if paddingNeeded != 0 {
raw = append(raw, make([]byte, paddingNeeded)...)
}

View File

@@ -10,6 +10,7 @@ type ParamType uint16
// Param interface
type Param interface {
Marshal() ([]byte, error)
Length() int
}
@@ -26,6 +27,8 @@ func BuildParam(t ParamType, rawParam []byte) (Param, error) {
return (&ParamRequestedHMACAlgorithm{}).Unmarshal(rawParam)
case ChunkList:
return (&ParamChunkList{}).Unmarshal(rawParam)
case StateCookie:
return (&ParamStateCookie{}).Unmarshal(rawParam)
}
return nil, errors.Errorf("Unhandled ParamType %v", t)

View File

@@ -0,0 +1,34 @@
package sctp
import (
"encoding/binary"
"math/rand"
"time"
)
type ParamStateCookie struct {
ParamHeader
Cookie []byte
}
func NewRandomStateCookie() *ParamStateCookie {
rs := rand.NewSource(time.Now().UnixNano())
r := rand.New(rs)
randCookie := make([]byte, 4)
binary.BigEndian.PutUint32(randCookie, r.Uint32())
s := &ParamStateCookie{
Cookie: randCookie,
}
return s
}
func (s *ParamStateCookie) Marshal() ([]byte, error) {
return s.ParamHeader.Marshal(StateCookie, s.Cookie)
}
func (s *ParamStateCookie) Unmarshal(raw []byte) (Param, error) {
s.ParamHeader.Unmarshal(raw)
s.Cookie = s.raw
return s, nil
}

View File

@@ -1,9 +1,5 @@
package sctp
import (
"fmt"
)
func chunkTypeIntersect(l, r []ChunkType) (c []ChunkType) {
m := make(map[ChunkType]bool)
@@ -19,9 +15,12 @@ func chunkTypeIntersect(l, r []ChunkType) (c []ChunkType) {
return
}
func NewEmptySupportedExtensions() *ParamSupportedExtensions {
return &ParamSupportedExtensions{}
}
type ParamSupportedExtensions struct {
ParamHeader
Raw []byte
ChunkTypes []ChunkType
}
@@ -40,7 +39,6 @@ func (s *ParamSupportedExtensions) Unmarshal(raw []byte) (Param, error) {
for t := range s.raw {
s.ChunkTypes = append(s.ChunkTypes, ChunkType(t))
}
fmt.Print(s.ChunkTypes)
return s, nil
}