package utp import ( "encoding/binary" "errors" "fmt" ) const ( extensionTypeSelectiveAck = 1 ) type extensionField struct { Type byte Bytes []byte } type header struct { Type st Version int ConnID uint16 Timestamp uint32 TimestampDiff uint32 WndSize uint32 SeqNr uint16 AckNr uint16 Extensions []extensionField } func unmarshalExtensions(_type byte, b []byte) (n int, ef []extensionField, err error) { for _type != 0 { if _type != extensionTypeSelectiveAck { // An extension type that is not known to us. Generally we're // unmarshalling an packet that isn't actually uTP but we don't // yet know for sure until we try to deliver it. // logonce.Stderr.Printf("utp extension %d", _type) } if len(b) < 2 || len(b) < int(b[1])+2 { err = fmt.Errorf("buffer ends prematurely: %x", b) return } ef = append(ef, extensionField{ Type: _type, Bytes: append([]byte(nil), b[2:int(b[1])+2]...), }) _type = b[0] n += 2 + int(b[1]) b = b[2+int(b[1]):] } return } var errInvalidHeader = errors.New("invalid header") func (h *header) Unmarshal(b []byte) (n int, err error) { h.Type = st(b[0] >> 4) h.Version = int(b[0] & 0xf) if h.Type > stMax || h.Version != 1 { err = errInvalidHeader return } n, h.Extensions, err = unmarshalExtensions(b[1], b[20:]) if err != nil { return } h.ConnID = binary.BigEndian.Uint16(b[2:4]) h.Timestamp = binary.BigEndian.Uint32(b[4:8]) h.TimestampDiff = binary.BigEndian.Uint32(b[8:12]) h.WndSize = binary.BigEndian.Uint32(b[12:16]) h.SeqNr = binary.BigEndian.Uint16(b[16:18]) h.AckNr = binary.BigEndian.Uint16(b[18:20]) n += 20 return } func (h *header) Marshal(p []byte) (n int) { n = 20 + func() (ret int) { for _, ext := range h.Extensions { ret += 2 + len(ext.Bytes) } return }() p = p[:n] p[0] = byte(h.Type<<4 | 1) binary.BigEndian.PutUint16(p[2:4], h.ConnID) binary.BigEndian.PutUint32(p[4:8], h.Timestamp) binary.BigEndian.PutUint32(p[8:12], h.TimestampDiff) binary.BigEndian.PutUint32(p[12:16], h.WndSize) binary.BigEndian.PutUint16(p[16:18], h.SeqNr) binary.BigEndian.PutUint16(p[18:20], h.AckNr) // Pointer to the last type field so the next extension can set it. _type := &p[1] // We're done with the basic header. p = p[20:] for _, ext := range h.Extensions { *_type = ext.Type // The next extension's type will go here. _type = &p[0] p[1] = uint8(len(ext.Bytes)) if int(p[1]) != copy(p[2:], ext.Bytes) { panic("unexpected extension length") } p = p[2+len(ext.Bytes):] } *_type = 0 if len(p) != 0 { panic("header length changed") } return } type selectiveAckBitmask struct { Bytes []byte } func (me *selectiveAckBitmask) expandBytesForBit(index int) { minLen := (3 + (index / 8) + 1) / 4 * 4 for len(me.Bytes) < minLen { me.Bytes = append(me.Bytes, 0) } } func (me *selectiveAckBitmask) NumBits() int { return len(me.Bytes) * 8 } func (me *selectiveAckBitmask) SetBit(index int) { me.expandBytesForBit(index) me.Bytes[index/8] |= 1 << uint(index%8) } func (me *selectiveAckBitmask) BitIsSet(index int) bool { return me.Bytes[index/8]>>uint(index%8)&1 == 1 }