~fnux/yggdrasil-go-coap

7043ef4954eb39e75e5a5c2b4ec826e7f7c16cd1 — Jozef Kralik 2 years ago b39d71a
fix issues related to blockwise
M blockwise.go => blockwise.go +81 -56
@@ 12,31 12,46 @@ const (
	blockWiseDebug = false
)

type BlockSzx uint8
// BlockWiseSzx enum representation for szx
type BlockWiseSzx uint8

const (
	BlockSzx16   BlockSzx = 0
	BlockSzx32   BlockSzx = 1
	BlockSzx64   BlockSzx = 2
	BlockSzx128  BlockSzx = 3
	BlockSzx256  BlockSzx = 4
	BlockSzx512  BlockSzx = 5
	BlockSzx1024 BlockSzx = 6
	BlockSzxBERT BlockSzx = 7
	//BlockWiseSzx16 block of size 16bytes
	BlockWiseSzx16 BlockWiseSzx = 0
	//BlockWiseSzx32 block of size 32bytes
	BlockWiseSzx32 BlockWiseSzx = 1
	//BlockWiseSzx64 block of size 64bytes
	BlockWiseSzx64 BlockWiseSzx = 2
	//BlockWiseSzx128 block of size 128bytes
	BlockWiseSzx128 BlockWiseSzx = 3
	//BlockWiseSzx256 block of size 256bytes
	BlockWiseSzx256 BlockWiseSzx = 4
	//BlockWiseSzx512 block of size 512bytes
	BlockWiseSzx512 BlockWiseSzx = 5
	//BlockWiseSzx1024 block of size 1024bytes
	BlockWiseSzx1024 BlockWiseSzx = 6
	//BlockWiseSzxBERT block of size n*1024bytes
	BlockWiseSzxBERT BlockWiseSzx = 7

	//BlockWiseSzxCount count of block enums
	BlockWiseSzxCount BlockWiseSzx = 8
)

var SZXVal = [8]int{
	0: 16,
	1: 32,
	2: 64,
	3: 128,
	4: 256,
	5: 512,
	6: 1024,
	7: 1024,
var szxToBytes = [BlockWiseSzxCount]int{
	BlockWiseSzx16:   16,
	BlockWiseSzx32:   32,
	BlockWiseSzx64:   64,
	BlockWiseSzx128:  128,
	BlockWiseSzx256:  256,
	BlockWiseSzx512:  512,
	BlockWiseSzx1024: 1024,
	BlockWiseSzxBERT: 1024, //for calculate size of block
}

func MarshalBlockOption(szx BlockSzx, blockNumber uint, moreBlocksFollowing bool) (uint32, error) {
func MarshalBlockOption(szx BlockWiseSzx, blockNumber uint, moreBlocksFollowing bool) (uint32, error) {
	if szx >= BlockWiseSzxCount {
		return 0, ErrInvalidBlockWiseSzx
	}
	if blockNumber > maxBlockNumber {
		return 0, ErrBlockNumberExceedLimit
	}


@@ 50,13 65,13 @@ func MarshalBlockOption(szx BlockSzx, blockNumber uint, moreBlocksFollowing bool
	return blockVal, nil
}

func UnmarshalBlockOption(blockVal uint32) (szx BlockSzx, blockNumber uint, moreBlocksFollowing bool, err error) {
func UnmarshalBlockOption(blockVal uint32) (szx BlockWiseSzx, blockNumber uint, moreBlocksFollowing bool, err error) {
	if blockVal > 0xffffff {
		err = ErrBlockInvalidSize
	}

	szx = BlockSzx(blockVal & 0x7) //masking for the SZX
	if (blockVal & 0x8) != 0 {     //masking for the "M"
	szx = BlockWiseSzx(blockVal & 0x7) //masking for the SZX
	if (blockVal & 0x8) != 0 {         //masking for the "M"
		moreBlocksFollowing = true
	}
	blockNumber = uint(blockVal) >> 4 //shifting out the SZX and M vals. leaving the block number behind


@@ 110,7 125,7 @@ type blockWiseSender struct {
	origin       Message

	currentNum  uint
	currentSzx  BlockSzx
	currentSzx  BlockWiseSzx
	currentMore bool
}



@@ 128,7 143,7 @@ func (s *blockWiseSender) sizeType() OptionID {
	return Size1
}

func newSender(peerDrive bool, blockType OptionID, suggestedSzx BlockSzx, expectedCode COAPCode, origin Message) *blockWiseSender {
func newSender(peerDrive bool, blockType OptionID, suggestedSzx BlockWiseSzx, expectedCode COAPCode, origin Message) *blockWiseSender {
	return &blockWiseSender{
		peerDrive:    peerDrive,
		blockType:    blockType,


@@ 155,9 170,10 @@ func (s *blockWiseSender) createReq(b *blockWiseSession) (Message, error) {
	}

	req.SetOption(s.sizeType(), len(s.origin.Payload()))

	if s.origin.Payload() != nil && len(s.origin.Payload()) > b.blockWiseMaxPayloadSize(s.currentSzx) {
		req.SetPayload(s.origin.Payload()[:b.blockWiseMaxPayloadSize(s.currentSzx)])
	var maxPayloadSize int
	maxPayloadSize, s.currentSzx = b.blockWiseMaxPayloadSize(s.currentSzx)
	if s.origin.Payload() != nil && len(s.origin.Payload()) > maxPayloadSize {
		req.SetPayload(s.origin.Payload()[:maxPayloadSize])
		s.currentMore = true
	} else {
		req.SetPayload(s.origin.Payload())


@@ 201,7 217,7 @@ func (s *blockWiseSender) processResp(b *blockWiseSession, req Message, resp Mes
					return nil, err
				}
				if !b.blockWiseIsValid(szx) {
					return nil, ErrInvalidBlockSzx
					return nil, ErrInvalidBlockWiseSzx
				}
				if num == 0 {
					resp.RemoveOption(s.sizeType())


@@ 228,10 244,11 @@ func (s *blockWiseSender) processResp(b *blockWiseSession, req Message, resp Mes
			return nil, err
		}
		if !b.blockWiseIsValid(szx) {
			return nil, ErrInvalidBlockSzx
			return nil, ErrInvalidBlockWiseSzx
		}

		s.currentSzx = szx
		var maxPayloadSize int
		maxPayloadSize, s.currentSzx = b.blockWiseMaxPayloadSize(szx)
		if s.peerDrive {
			s.currentNum = num
			req.SetMessageID(resp.MessageID())


@@ 240,12 257,16 @@ func (s *blockWiseSender) processResp(b *blockWiseSession, req Message, resp Mes
			req.SetMessageID(GenerateMessageID())
		}
		startOffset := calcStartOffset(s.currentNum, szx)
		endOffset := startOffset + b.blockWiseMaxPayloadSize(szx)
		if endOffset > len(s.origin.Payload()) {
		endOffset := startOffset + maxPayloadSize
		if endOffset >= len(s.origin.Payload()) {
			endOffset = len(s.origin.Payload())
			s.currentMore = false
		}
		if startOffset > len(s.origin.Payload()) {
			return nil, ErrBlockInvalidSize
		}
		req.SetPayload(s.origin.Payload()[startOffset:endOffset])

		//must be unique for evey msg via UDP
		if blockWiseDebug {
			log.Printf("sendPayload szx=%v num=%v more=%v\n", s.currentSzx, s.currentNum, s.currentMore)


@@ 266,7 287,7 @@ func (s *blockWiseSender) processResp(b *blockWiseSession, req Message, resp Mes
	return nil, nil
}

func (b *blockWiseSession) sendPayload(peerDrive bool, blockType OptionID, suggestedSzx BlockSzx, expectedCode COAPCode, msg Message) (Message, error) {
func (b *blockWiseSession) sendPayload(peerDrive bool, blockType OptionID, suggestedSzx BlockWiseSzx, expectedCode COAPCode, msg Message) (Message, error) {
	s := newSender(peerDrive, blockType, suggestedSzx, expectedCode, msg)
	req, err := s.createReq(b)
	if err != nil {


@@ 319,25 340,29 @@ func (b *blockWiseSession) Write(msg Message) error {
	}
}

func calcNextNum(num uint, szx BlockSzx, payloadSize int) uint {
	val := uint(payloadSize / SZXVal[szx])
	if val > 0 && (payloadSize%SZXVal[szx] == 0) {
func calcNextNum(num uint, szx BlockWiseSzx, payloadSize int) uint {
	val := uint(payloadSize / szxToBytes[szx])
	if val > 0 && (payloadSize%szxToBytes[szx] == 0) {
		val--
	}
	return num + val + 1
}

func calcStartOffset(num uint, szx BlockSzx) int {
	return int(num) * SZXVal[szx]
func calcStartOffset(num uint, szx BlockWiseSzx) int {
	return int(num) * szxToBytes[szx]
}

func (b *blockWiseSession) sendErrorMsg(code COAPCode, typ COAPType, token []byte, MessageID uint16) {
func (b *blockWiseSession) sendErrorMsg(code COAPCode, typ COAPType, token []byte, MessageID uint16, err error) {
	req := b.NewMessage(MessageParams{
		Code:      code,
		Type:      typ,
		MessageID: MessageID,
		Token:     token,
	})
	if err != nil {
		req.SetOption(ContentFormat, TextPlain)
		req.SetPayload([]byte(err.Error()))
	}
	b.networkSession.Write(req)
}



@@ 348,7 373,7 @@ type blockWiseReceiver struct {
	typ          COAPType
	origin       Message
	blockType    OptionID
	currentSzx   BlockSzx
	currentSzx   BlockWiseSzx
	nextNum      uint
	currentMore  bool
	payloadSize  uint32


@@ 423,7 448,7 @@ func newReceiver(b *blockWiseSession, peerDrive bool, origin Message, resp Messa
				return r, nil, err
			}
			if !b.blockWiseIsValid(szx) {
				return r, nil, ErrInvalidBlockSzx
				return r, nil, ErrInvalidBlockWiseSzx
			}
			//do we need blockWise?
			if more == false {


@@ 454,7 479,7 @@ func newReceiver(b *blockWiseSession, peerDrive bool, origin Message, resp Messa
				return r, nil, err
			}
			if !b.blockWiseIsValid(szx) {
				return r, nil, ErrInvalidBlockSzx
				return r, nil, ErrInvalidBlockWiseSzx
			}
			if more == false {
				origin.RemoveOption(blockType)


@@ 497,13 522,13 @@ func (r *blockWiseReceiver) processResp(b *blockWiseSession, req Message, resp M
			return nil, err
		}
		if !b.blockWiseIsValid(szx) {
			return nil, ErrInvalidBlockSzx
			return nil, ErrInvalidBlockWiseSzx
		}
		startOffset := calcStartOffset(num, szx)
		if r.payload.Len() < startOffset {
			return nil, ErrRequestEntityIncomplete
		}
		if more == true && len(resp.Payload())%SZXVal[szx] != 0 {
		if more == true && len(resp.Payload())%szxToBytes[szx] != 0 {
			if r.peerDrive {
				return nil, ErrInvalidRequest
			}


@@ 563,7 588,7 @@ func (r *blockWiseReceiver) processResp(b *blockWiseSession, req Message, resp M
	return nil, nil
}

func (r *blockWiseReceiver) sendError(b *blockWiseSession, code COAPCode, resp Message) {
func (r *blockWiseReceiver) sendError(b *blockWiseSession, code COAPCode, resp Message, err error) {
	var MessageID uint16
	var token []byte
	var typ COAPType


@@ 580,13 605,13 @@ func (r *blockWiseReceiver) sendError(b *blockWiseSession, code COAPCode, resp M
			token = r.origin.Token()
		}
	}
	b.sendErrorMsg(code, typ, token, MessageID)
	b.sendErrorMsg(code, typ, token, MessageID, err)
}

func (b *blockWiseSession) receivePayload(peerDrive bool, msg Message, resp Message, blockType OptionID, code COAPCode) (Message, error) {
	r, resp, err := newReceiver(b, peerDrive, msg, resp, blockType, code)
	if err != nil {
		r.sendError(b, BadRequest, resp)
		r.sendError(b, BadRequest, resp, err)
		return nil, err
	}
	if resp != nil {


@@ 595,7 620,7 @@ func (b *blockWiseSession) receivePayload(peerDrive bool, msg Message, resp Mess

	req, err := r.createReq(b, resp)
	if err != nil {
		r.sendError(b, BadRequest, resp)
		r.sendError(b, BadRequest, resp, err)
		return nil, err
	}



@@ 603,7 628,7 @@ func (b *blockWiseSession) receivePayload(peerDrive bool, msg Message, resp Mess
		bwResp, err := r.exchange(b, req)

		if err != nil {
			r.sendError(b, BadRequest, resp)
			r.sendError(b, BadRequest, resp, err)
			return nil, err
		}



@@ 615,7 640,7 @@ func (b *blockWiseSession) receivePayload(peerDrive bool, msg Message, resp Mess
			case ErrRequestEntityIncomplete:
				errCode = RequestEntityIncomplete
			}
			r.sendError(b, errCode, resp)
			r.sendError(b, errCode, resp, err)
			return nil, err
		}



@@ 685,14 710,14 @@ func (w *blockWiseResponseWriter) Write(msg Message) error {
			return err
		}
		//BERT is supported only via TCP
		if szx == BlockSzxBERT && !w.req.Client.networkSession.IsTCP() {
			return ErrInvalidBlockSzx
		if szx == BlockWiseSzxBERT && !w.req.Client.networkSession.IsTCP() {
			return ErrInvalidBlockWiseSzx
		}
		suggestedSzx = szx
	}

	//resp is less them szx then just write msg without blockWise
	if len(msg.Payload()) < SZXVal[suggestedSzx] {
	if len(msg.Payload()) < szxToBytes[suggestedSzx] {
		return w.responseWriter.Write(msg)
	}



@@ 716,14 741,14 @@ func (w *blockWiseNoticeWriter) Write(msg Message) error {
			return err
		}
		//BERT is supported only via TCP
		if szx == BlockSzxBERT && !w.req.Client.networkSession.IsTCP() {
			return ErrInvalidBlockSzx
		if szx == BlockWiseSzxBERT && !w.req.Client.networkSession.IsTCP() {
			return ErrInvalidBlockWiseSzx
		}
		suggestedSzx = szx
	}

	//resp is less them szx then just write msg without blockWise
	if len(msg.Payload()) < SZXVal[suggestedSzx] {
	if len(msg.Payload()) < szxToBytes[suggestedSzx] {
		return w.responseWriter.Write(msg)
	}


M blockwise_test.go => blockwise_test.go +76 -76
@@ 5,7 5,7 @@ import (
	"testing"
)

func testMarshal(t *testing.T, szx BlockSzx, blockNumber uint, moreBlocksFollowing bool, expectedBlock uint32) {
func testMarshal(t *testing.T, szx BlockWiseSzx, blockNumber uint, moreBlocksFollowing bool, expectedBlock uint32) {
	fmt.Printf("testMarshal szx=%v, num=%v more=%v\n", szx, blockNumber, moreBlocksFollowing)
	block, err := MarshalBlockOption(szx, blockNumber, moreBlocksFollowing)
	if err != nil {


@@ 16,7 16,7 @@ func testMarshal(t *testing.T, szx BlockSzx, blockNumber uint, moreBlocksFollowi
	}
}

func testUnmarshal(t *testing.T, block uint32, expectedSzx BlockSzx, expectedNum uint, expectedMoreBlocksFollowing bool) {
func testUnmarshal(t *testing.T, block uint32, expectedSzx BlockWiseSzx, expectedNum uint, expectedMoreBlocksFollowing bool) {
	fmt.Printf("testUnmarshal %v\n", block)
	szx, num, more, err := UnmarshalBlockOption(block)
	if err != nil {


@@ 34,135 34,135 @@ func testUnmarshal(t *testing.T, block uint32, expectedSzx BlockSzx, expectedNum
}

func TestBlockWiseBlockMarshal(t *testing.T) {
	testMarshal(t, BlockSzx16, 0, false, uint32(0))
	testMarshal(t, BlockSzx16, 0, true, uint32(8))
	testMarshal(t, BlockSzx32, 0, false, uint32(1))
	testMarshal(t, BlockSzx32, 0, true, uint32(9))
	testMarshal(t, BlockSzx64, 0, false, uint32(2))
	testMarshal(t, BlockSzx64, 0, true, uint32(10))
	testMarshal(t, BlockSzx128, 0, false, uint32(3))
	testMarshal(t, BlockSzx128, 0, true, uint32(11))
	testMarshal(t, BlockSzx256, 0, false, uint32(4))
	testMarshal(t, BlockSzx256, 0, true, uint32(12))
	testMarshal(t, BlockSzx512, 0, false, uint32(5))
	testMarshal(t, BlockSzx512, 0, true, uint32(13))
	testMarshal(t, BlockSzx1024, 0, false, uint32(6))
	testMarshal(t, BlockSzx1024, 0, true, uint32(14))
	testMarshal(t, BlockSzxBERT, 0, false, uint32(7))
	testMarshal(t, BlockSzxBERT, 0, true, uint32(15))

	val, err := MarshalBlockOption(BlockSzx16, maxBlockNumber+1, false)
	testMarshal(t, BlockWiseSzx16, 0, false, uint32(0))
	testMarshal(t, BlockWiseSzx16, 0, true, uint32(8))
	testMarshal(t, BlockWiseSzx32, 0, false, uint32(1))
	testMarshal(t, BlockWiseSzx32, 0, true, uint32(9))
	testMarshal(t, BlockWiseSzx64, 0, false, uint32(2))
	testMarshal(t, BlockWiseSzx64, 0, true, uint32(10))
	testMarshal(t, BlockWiseSzx128, 0, false, uint32(3))
	testMarshal(t, BlockWiseSzx128, 0, true, uint32(11))
	testMarshal(t, BlockWiseSzx256, 0, false, uint32(4))
	testMarshal(t, BlockWiseSzx256, 0, true, uint32(12))
	testMarshal(t, BlockWiseSzx512, 0, false, uint32(5))
	testMarshal(t, BlockWiseSzx512, 0, true, uint32(13))
	testMarshal(t, BlockWiseSzx1024, 0, false, uint32(6))
	testMarshal(t, BlockWiseSzx1024, 0, true, uint32(14))
	testMarshal(t, BlockWiseSzxBERT, 0, false, uint32(7))
	testMarshal(t, BlockWiseSzxBERT, 0, true, uint32(15))

	val, err := MarshalBlockOption(BlockWiseSzx16, maxBlockNumber+1, false)
	if err == nil {
		t.Fatalf("expected error, block %v", val)
	}
}

func TestBlockWiseBlockUnmarshal(t *testing.T) {
	testUnmarshal(t, uint32(0), BlockSzx16, 0, false)
	testUnmarshal(t, uint32(8), BlockSzx16, 0, true)
	testUnmarshal(t, uint32(1), BlockSzx32, 0, false)
	testUnmarshal(t, uint32(9), BlockSzx32, 0, true)
	testUnmarshal(t, uint32(2), BlockSzx64, 0, false)
	testUnmarshal(t, uint32(10), BlockSzx64, 0, true)
	testUnmarshal(t, uint32(3), BlockSzx128, 0, false)
	testUnmarshal(t, uint32(11), BlockSzx128, 0, true)
	testUnmarshal(t, uint32(4), BlockSzx256, 0, false)
	testUnmarshal(t, uint32(12), BlockSzx256, 0, true)
	testUnmarshal(t, uint32(5), BlockSzx512, 0, false)
	testUnmarshal(t, uint32(13), BlockSzx512, 0, true)
	testUnmarshal(t, uint32(6), BlockSzx1024, 0, false)
	testUnmarshal(t, uint32(14), BlockSzx1024, 0, true)
	testUnmarshal(t, uint32(7), BlockSzxBERT, 0, false)
	testUnmarshal(t, uint32(15), BlockSzxBERT, 0, true)
	testUnmarshal(t, uint32(0), BlockWiseSzx16, 0, false)
	testUnmarshal(t, uint32(8), BlockWiseSzx16, 0, true)
	testUnmarshal(t, uint32(1), BlockWiseSzx32, 0, false)
	testUnmarshal(t, uint32(9), BlockWiseSzx32, 0, true)
	testUnmarshal(t, uint32(2), BlockWiseSzx64, 0, false)
	testUnmarshal(t, uint32(10), BlockWiseSzx64, 0, true)
	testUnmarshal(t, uint32(3), BlockWiseSzx128, 0, false)
	testUnmarshal(t, uint32(11), BlockWiseSzx128, 0, true)
	testUnmarshal(t, uint32(4), BlockWiseSzx256, 0, false)
	testUnmarshal(t, uint32(12), BlockWiseSzx256, 0, true)
	testUnmarshal(t, uint32(5), BlockWiseSzx512, 0, false)
	testUnmarshal(t, uint32(13), BlockWiseSzx512, 0, true)
	testUnmarshal(t, uint32(6), BlockWiseSzx1024, 0, false)
	testUnmarshal(t, uint32(14), BlockWiseSzx1024, 0, true)
	testUnmarshal(t, uint32(7), BlockWiseSzxBERT, 0, false)
	testUnmarshal(t, uint32(15), BlockWiseSzxBERT, 0, true)
	szx, num, m, err := UnmarshalBlockOption(0x1000000)
	if err == nil {
		t.Fatalf("expected error, szx %v, num %v, m %v", szx, num, m)
	}
}

func TestServingUDPBlockSzx16(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockSzx16, make([]byte, 128), simpleMsg)
func TestServingUDPBlockWiseSzx16(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockWiseSzx16, make([]byte, 128), simpleMsg)
}

func TestServingUDPBlockSzx32(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockSzx32, make([]byte, 128), simpleMsg)
func TestServingUDPBlockWiseSzx32(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockWiseSzx32, make([]byte, 128), simpleMsg)
}

func TestServingUDPBlockSzx64(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockSzx64, make([]byte, 128), simpleMsg)
func TestServingUDPBlockWiseSzx64(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockWiseSzx64, make([]byte, 128), simpleMsg)
}

func TestServingUDPBlockSzx128(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockSzx128, make([]byte, 128), simpleMsg)
func TestServingUDPBlockWiseSzx128(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockWiseSzx128, make([]byte, 128), simpleMsg)
}

func TestServingUDPBlockSzx256(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockSzx256, make([]byte, 128), simpleMsg)
func TestServingUDPBlockWiseSzx256(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockWiseSzx256, make([]byte, 128), simpleMsg)
}

func TestServingUDPBlockSzx512(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockSzx512, make([]byte, 128), simpleMsg)
func TestServingUDPBlockWiseSzx512(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockWiseSzx512, make([]byte, 128), simpleMsg)
}

func TestServingUDPBlockSzx1024(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockSzx1024, make([]byte, 128), simpleMsg)
func TestServingUDPBlockWiseSzx1024(t *testing.T) {
	testServingTCPWithMsg(t, "udp", true, BlockWiseSzx1024, make([]byte, 128), simpleMsg)
}

func TestServingUDPBlockSzxBERT(t *testing.T) {
	_, addr, _, err := RunLocalUDPServer("udp", ":0", true, BlockSzx1024)
func TestServingUDPBlockWiseSzxBERT(t *testing.T) {
	_, addr, _, err := RunLocalUDPServer("udp", ":0", true, BlockWiseSzx1024)
	if err != nil {
		t.Fatalf("Unexpected error '%v'", err)
	}

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzxBERT
	BlockWiseTransferSzx := BlockWiseSzxBERT
	c := Client{Net: "udp", BlockWiseTransfer: &BlockWiseTransfer, BlockWiseTransferSzx: &BlockWiseTransferSzx}
	_, err = c.Dial(addr)
	if err != nil {
		if err.Error() != ErrInvalidBlockSzx.Error() {
			t.Fatalf("Expected error '%v', got '%v'", err, ErrInvalidBlockSzx)
		if err.Error() != ErrInvalidBlockWiseSzx.Error() {
			t.Fatalf("Expected error '%v', got '%v'", err, ErrInvalidBlockWiseSzx)
		}
	} else {
		t.Fatalf("Expected error '%v'", ErrInvalidBlockSzx)
		t.Fatalf("Expected error '%v'", ErrInvalidBlockWiseSzx)
	}
}

func TestServingTCPBlockSzx16(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx16, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzx16(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx16, make([]byte, 128), simpleMsg)
}

func TestServingTCPBlockSzx32(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx32, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzx32(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx32, make([]byte, 128), simpleMsg)
}

func TestServingTCPBlockSzx64(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx64, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzx64(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx64, make([]byte, 128), simpleMsg)
}

func TestServingTCPBlockSzx128(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx128, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzx128(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx128, make([]byte, 128), simpleMsg)
}

func TestServingTCPBlockSzx256(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx256, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzx256(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx256, make([]byte, 128), simpleMsg)
}

func TestServingTCPBlockSzx512(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx512, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzx512(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx512, make([]byte, 128), simpleMsg)
}

func TestServingTCPBlockSzx1024(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx1024, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzx1024(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx1024, make([]byte, 128), simpleMsg)
}

func TestServingTCPBlockSzxBERT(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzxBERT, make([]byte, 128), simpleMsg)
func TestServingTCPBlockWiseSzxBERT(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzxBERT, make([]byte, 128), simpleMsg)
}

func TestServingTCPBigMsgBlockSzx1024(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzx1024, make([]byte, 10*1024*1024), simpleMsg)
func TestServingTCPBigMsgBlockWiseSzx1024(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzx1024, make([]byte, 1024), simpleMsg)
}

func TestServingTCPBigMsgBlockSzxBERT(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockSzxBERT, make([]byte, 10*1024*1024), simpleMsg)
func TestServingTCPBigMsgBlockWiseSzxBERT(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", true, BlockWiseSzxBERT, make([]byte, 10*1024*1024), simpleMsg)
}

M client.go => client.go +6 -6
@@ 23,7 23,7 @@ type ClientConn struct {
// A Client defines parameters for a COAP client.
type Client struct {
	Net            string        // if "tcp" or "tcp-tls" (COAP over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP) or "udp-mcast" for multicast
	MaxMessageSize uint16        // Max message size that could be received from peer. If not set it defaults to 1152 B.
	MaxMessageSize uint32        // Max message size that could be received from peer. If not set it defaults to 1152 B.
	TLSConfig      *tls.Config   // TLS connection configuration
	DialTimeout    time.Duration // set Timeout for dialer
	ReadTimeout    time.Duration // net.ClientConn.SetReadTimeout value for connections, defaults to 1 hour - overridden by Timeout when that value is non-zero


@@ 33,8 33,8 @@ type Client struct {
	Handler              HandlerFunc     // default handler for handling messages from server
	NotifySessionEndFunc func(err error) // if NotifySessionEndFunc is set it is called when TCP/UDP session was ended.

	BlockWiseTransfer    *bool     // Use blockWise transfer for transfer payload (default for UDP it's enabled, for TCP it's disable)
	BlockWiseTransferSzx *BlockSzx // Set maximal block size of payload that will be send in fragment
	BlockWiseTransfer    *bool         // Use blockWise transfer for transfer payload (default for UDP it's enabled, for TCP it's disable)
	BlockWiseTransferSzx *BlockWiseSzx // Set maximal block size of payload that will be send in fragment
}

func (c *Client) readTimeout() time.Duration {


@@ 67,7 67,7 @@ func (c *Client) Dial(address string) (clientConn *ClientConn, err error) {

	dialer := &net.Dialer{Timeout: c.DialTimeout}
	BlockWiseTransfer := false
	BlockWiseTransferSzx := BlockSzx1024
	BlockWiseTransferSzx := BlockWiseSzx1024
	multicast := false

	switch c.Net {


@@ 77,14 77,14 @@ func (c *Client) Dial(address string) (clientConn *ClientConn, err error) {
		if err != nil {
			return nil, err
		}
		BlockWiseTransferSzx = BlockSzxBERT
		BlockWiseTransferSzx = BlockWiseSzxBERT
	case "tcp", "tcp4", "tcp6":
		network = c.Net
		conn, err = dialer.Dial(c.Net, address)
		if err != nil {
			return nil, err
		}
		BlockWiseTransferSzx = BlockSzxBERT
		BlockWiseTransferSzx = BlockWiseSzxBERT
	case "udp", "udp4", "udp6", "":
		network = c.Net
		if network == "" {

M client_test.go => client_test.go +17 -17
@@ 40,7 40,7 @@ func periodicTransmitter(w ResponseWriter, r *Request) {
	}()
}

func testServingObservation(t *testing.T, net string, addrstr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx) {
func testServingObservation(t *testing.T, net string, addrstr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx) {
	sync := make(chan bool)

	client := &Client{


@@ 80,7 80,7 @@ func testServingObservation(t *testing.T, net string, addrstr string, BlockWiseT
}

func TestServingUDPObservation(t *testing.T) {
	s, addrstr, fin, err := RunLocalServerUDPWithHandler("udp", ":0", false, BlockSzx16, periodicTransmitter)
	s, addrstr, fin, err := RunLocalServerUDPWithHandler("udp", ":0", false, BlockWiseSzx16, periodicTransmitter)
	if err != nil {
		t.Fatalf("unable to run test server: %v", err)
	}


@@ 88,11 88,11 @@ func TestServingUDPObservation(t *testing.T) {
		s.Shutdown()
		<-fin
	}()
	testServingObservation(t, "udp", addrstr, false, BlockSzx16)
	testServingObservation(t, "udp", addrstr, false, BlockWiseSzx16)
}

func TestServingTCPObservation(t *testing.T) {
	s, addrstr, fin, err := RunLocalServerTCPWithHandler(":0", false, BlockSzx16, periodicTransmitter)
	s, addrstr, fin, err := RunLocalServerTCPWithHandler(":0", false, BlockWiseSzx16, periodicTransmitter)
	if err != nil {
		t.Fatalf("unable to run test server: %v", err)
	}


@@ 100,10 100,10 @@ func TestServingTCPObservation(t *testing.T) {
		s.Shutdown()
		<-fin
	}()
	testServingObservation(t, "tcp", addrstr, false, BlockSzx16)
	testServingObservation(t, "tcp", addrstr, false, BlockWiseSzx16)
}

func testServingMCastByClient(t *testing.T, lnet, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx, ifis []net.Interface) {
func testServingMCastByClient(t *testing.T, lnet, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx, ifis []net.Interface) {
	payload := []byte("mcast payload")
	addrMcast := laddr
	ansArrived := make(chan bool)


@@ 160,11 160,11 @@ func testServingMCastByClient(t *testing.T, lnet, laddr string, BlockWiseTransfe
}

func TestServingIPv4MCastByClient(t *testing.T) {
	testServingMCastByClient(t, "udp4-mcast", "225.0.1.187:11111", false, BlockSzx16, []net.Interface{})
	testServingMCastByClient(t, "udp4-mcast", "225.0.1.187:11111", false, BlockWiseSzx16, []net.Interface{})
}

func TestServingIPv6MCastByClient(t *testing.T) {
	testServingMCastByClient(t, "udp6-mcast", "[ff03::158]:11111", false, BlockSzx16, []net.Interface{})
	testServingMCastByClient(t, "udp6-mcast", "[ff03::158]:11111", false, BlockWiseSzx16, []net.Interface{})
}

func TestServingIPv4AllInterfacesMCastByClient(t *testing.T) {


@@ 172,7 172,7 @@ func TestServingIPv4AllInterfacesMCastByClient(t *testing.T) {
	if err != nil {
		t.Fatalf("unable to get interfaces: %v", err)
	}
	testServingMCastByClient(t, "udp4-mcast", "225.0.1.187:11111", false, BlockSzx16, ifis)
	testServingMCastByClient(t, "udp4-mcast", "225.0.1.187:11111", false, BlockWiseSzx16, ifis)
}

func TestServingIPv6AllInterfacesMCastByClient(t *testing.T) {


@@ 180,11 180,11 @@ func TestServingIPv6AllInterfacesMCastByClient(t *testing.T) {
	if err != nil {
		t.Fatalf("unable to get interfaces: %v", err)
	}
	testServingMCastByClient(t, "udp6-mcast", "[ff03::158]:11111", false, BlockSzx16, ifis)
	testServingMCastByClient(t, "udp6-mcast", "[ff03::158]:11111", false, BlockWiseSzx16, ifis)
}

func setupServer(t *testing.T) (string, error) {
	_, addr, _, err := RunLocalServerUDPWithHandler("udp", ":0", true, BlockSzx1024, func(w ResponseWriter, r *Request) {
	_, addr, _, err := RunLocalServerUDPWithHandler("udp", ":0", true, BlockWiseSzx1024, func(w ResponseWriter, r *Request) {
		msg := r.Client.NewMessage(MessageParams{
			Type:      Acknowledgement,
			Code:      Content,


@@ 213,7 213,7 @@ func TestServingUDPGet(t *testing.T) {
	}

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzx16
	BlockWiseTransferSzx := BlockWiseSzx16
	c := Client{Net: "udp", BlockWiseTransfer: &BlockWiseTransfer, BlockWiseTransferSzx: &BlockWiseTransferSzx}
	con, err := c.Dial(addr)
	if err != nil {


@@ 232,7 232,7 @@ func TestServingUDPPost(t *testing.T) {
	}

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzx1024
	BlockWiseTransferSzx := BlockWiseSzx1024
	c := Client{Net: "udp", BlockWiseTransfer: &BlockWiseTransfer, BlockWiseTransferSzx: &BlockWiseTransferSzx}
	con, err := c.Dial(addr)
	if err != nil {


@@ 252,7 252,7 @@ func TestServingUDPPut(t *testing.T) {
	}

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzx1024
	BlockWiseTransferSzx := BlockWiseSzx1024
	c := Client{Net: "udp", BlockWiseTransfer: &BlockWiseTransfer, BlockWiseTransferSzx: &BlockWiseTransferSzx}
	con, err := c.Dial(addr)
	if err != nil {


@@ 272,7 272,7 @@ func TestServingUDPDelete(t *testing.T) {
	}

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzx1024
	BlockWiseTransferSzx := BlockWiseSzx1024
	c := Client{Net: "udp", BlockWiseTransfer: &BlockWiseTransfer, BlockWiseTransferSzx: &BlockWiseTransferSzx}
	con, err := c.Dial(addr)
	if err != nil {


@@ 285,7 285,7 @@ func TestServingUDPDelete(t *testing.T) {
}

func TestServingUDPObserve(t *testing.T) {
	_, addr, _, err := RunLocalServerUDPWithHandler("udp", ":0", true, BlockSzx16, func(w ResponseWriter, r *Request) {
	_, addr, _, err := RunLocalServerUDPWithHandler("udp", ":0", true, BlockWiseSzx16, func(w ResponseWriter, r *Request) {
		msg := r.Client.NewMessage(MessageParams{
			Type:      Acknowledgement,
			Code:      Content,


@@ 309,7 309,7 @@ func TestServingUDPObserve(t *testing.T) {
	}

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzx1024
	BlockWiseTransferSzx := BlockWiseSzx1024
	c := Client{Net: "udp", BlockWiseTransfer: &BlockWiseTransfer, BlockWiseTransferSzx: &BlockWiseTransferSzx}
	con, err := c.Dial(addr)
	if err != nil {

M clientcommander.go => clientcommander.go +3 -2
@@ 197,6 197,7 @@ func (cc *ClientCommander) Observe(path string, observeFunc func(req *Request)) 
		client:    cc,
	}
	err = cc.networkSession.TokenHandler().Add(req.Token(), func(w ResponseWriter, r *Request) {
		var err error
		needGet := false
		resp := r.Msg
		if r.Msg.Option(Size2) != nil {


@@ 216,7 217,7 @@ func (cc *ClientCommander) Observe(path string, observeFunc func(req *Request)) 
		}

		if needGet {
			resp, err = cc.Get(path)
			resp, err = r.Client.Get(path)
			if err != nil {
				return
			}


@@ 251,7 252,7 @@ func (cc *ClientCommander) Observe(path string, observeFunc func(req *Request)) 
	if err != nil {
		return nil, err
	}
	err = cc.networkSession.Write(req)
	err = cc.Write(req)
	if err != nil {
		cc.networkSession.TokenHandler().Remove(o.token)
		return nil, err

M conn.go => conn.go +15 -24
@@ 1,6 1,7 @@
package coap

import (
	"bytes"
	"log"
	"net"
	"sync/atomic"


@@ 10,11 11,11 @@ import (
type writeReq interface {
	sendResp(err error, timeout time.Duration)
	waitResp(timeout time.Duration) error
	data() []byte
	data() Message
}

type writeReqBase struct {
	req      []byte
	req      Message
	respChan chan error // channel must have size 1 for non-blocking write to channel
}



@@ 36,7 37,7 @@ func (wreq *writeReqBase) waitResp(timeout time.Duration) error {
	}
}

func (wreq *writeReqBase) data() []byte {
func (wreq *writeReqBase) data() Message {
	return wreq.req
}



@@ 150,17 151,11 @@ func (conn *connTCP) writeHandler(srv *Server) bool {
		defer srv.releaseWriter(wr)
		writeTimeout := srv.writeTimeout()
		conn.connection.SetWriteDeadline(time.Now().Add(writeTimeout))
		dataLen := len(data)
		dataWritten := 0
		for dataLen > 0 {
			n, err := wr.Write(data[dataWritten : dataLen-dataWritten])
			if err != nil {
				return err
			}
			dataLen -= n
			dataWritten += n
			wr.Flush()
		err := data.MarshalBinary(wr)
		if err != nil {
			return err
		}
		wr.Flush()
		return nil
	})
}


@@ 196,18 191,14 @@ func (conn *connUDP) writeHandler(srv *Server) bool {
		data := wreq.data()
		wreqUDP := wreq.(*writeReqUDP)
		writeTimeout := srv.writeTimeout()
		conn.connection.SetWriteDeadline(time.Now().Add(writeTimeout))
		dataLen := len(data)
		dataWritten := 0
		for dataLen > 0 {
			n, err := WriteToSessionUDP(conn.connection, data[dataWritten:dataLen-dataWritten], wreqUDP.sessionData)
			if err != nil {
				return err
			}
			dataLen -= n
			dataWritten += n
		buf := &bytes.Buffer{}
		err := data.MarshalBinary(buf)
		if err != nil {
			return err
		}
		return nil
		conn.connection.SetWriteDeadline(time.Now().Add(writeTimeout))
		_, err = WriteToSessionUDP(conn.connection, buf.Bytes(), wreqUDP.sessionData)
		return err
	})
}


M error.go => error.go +14 -4
@@ 44,9 44,12 @@ const ErrMessageInvalidVersion = Error("invalid version of Message")
// ErrServerAlreadyStarted server already started
const ErrServerAlreadyStarted = Error("server already started")

// ErrInvalidServerNetParameter invalid .Net parameter
// ErrInvalidNetParameter invalid .Net parameter
const ErrInvalidNetParameter = Error("invalid .Net parameter")

// ErrInvalidMaxMesssageSizeParameter invalid .MaxMessageSize parameter
const ErrInvalidMaxMesssageSizeParameter = Error("invalid .MaxMessageSize parameter")

// ErrInvalidServerConnParameter invalid Server.Conn parameter
const ErrInvalidServerConnParameter = Error("invalid Server.Conn parameter")



@@ 65,22 68,29 @@ const ErrInvalidResponse = Error("invalid response")
// ErrNotSupported invalid response received for certain token
const ErrNotSupported = Error("not supported")

// ErrBlockNumberExceedLimit block number exceed limit 1,048,576
const ErrBlockNumberExceedLimit = Error("block number exceed limit 1,048,576")

// ErrBlockInvalidSize block has invalid size
const ErrBlockInvalidSize = Error("block has invalid size")

// ErrInvalidOptionBlock2 message has invalid value of Block2
const ErrInvalidOptionBlock2 = Error("message has invalid value of Block2")

// ErrInvalidOptionBlock1 message has invalid value of Block1
const ErrInvalidOptionBlock1 = Error("message has invalid value of Block1")

// ErrInvalidReponseCode response code has invalid value
const ErrInvalidReponseCode = Error("response code has invalid value")

// ErrInvalidPayloadSize invalid payload size
const ErrInvalidPayloadSize = Error("invalid payload size")

const ErrInvalidBlockSzx = Error("invalid block-wise transfer szx")
// ErrInvalidBlockWiseSzx invalid block-wise transfer szx
const ErrInvalidBlockWiseSzx = Error("invalid block-wise transfer szx")

// ErrRequestEntityIncomplete payload comes in bad order
const ErrRequestEntityIncomplete = Error("payload comes in bad order")

// ErrInvalidRequest invalid requests
const ErrInvalidRequest = Error("invalid request")

const ErrInvalidPayload = Error("invalid payload")

M iotivity_test.go => iotivity_test.go +8 -5
@@ 1,5 1,6 @@
package coap

/*
import (
	"bytes"
	"fmt"


@@ 52,7 53,7 @@ func observe(w ResponseWriter, req *Request) {
}

func TestBlockWisePostBlock16(t *testing.T) {
	szx := BlockSzx16
	szx := BlockWiseSzx16
	client := &Client{Net: "udp", Handler: observe, BlockWiseTransferSzx: &szx}
	co, err := client.Dial(udpServer)
	if err != nil {


@@ 80,7 81,7 @@ func TestBlockWisePostBlock16(t *testing.T) {
}

func TestBlockWiseGetBlock16(t *testing.T) {
	szx := BlockSzx16
	szx := BlockWiseSzx16
	client := &Client{Net: "udp", Handler: observe, BlockWiseTransferSzx: &szx}

	co, err := client.Dial(udpServer)


@@ 95,7 96,7 @@ func TestBlockWiseGetBlock16(t *testing.T) {
}

func TestBlockWiseObserveBlock16(t *testing.T) {
	szx := BlockSzx16
	szx := BlockWiseSzx16
	sync := make(chan bool)
	client := &Client{Net: "udp", Handler: func(w ResponseWriter, req *Request) {
		observe(w, req)


@@ 119,7 120,7 @@ func TestBlockWiseObserveBlock16(t *testing.T) {
}

func TestBlockWiseMulticastBlock16(t *testing.T) {
	szx := BlockSzx16
	szx := BlockWiseSzx16
	client := &MulticastClient{Net: "udp", Handler: observe, BlockWiseTransferSzx: &szx}

	co, err := client.Dial("224.0.1.187:5683")


@@ 138,7 139,7 @@ func TestBlockWiseMulticastBlock16(t *testing.T) {
}

func TestGetBlock16(t *testing.T) {
	szx := BlockSzx16
	szx := BlockWiseSzx16
	bw := false
	client := &Client{Net: "tcp", Handler: observe, BlockWiseTransfer: &bw, BlockWiseTransferSzx: &szx}



@@ 152,3 153,5 @@ func TestGetBlock16(t *testing.T) {
	}
	decodeMsg(resp)
}

*/

M message.go => message.go +165 -31
@@ 316,24 316,36 @@ type option struct {
	Value interface{}
}

func encodeInt(v uint32) []byte {
func encodeInt(buf io.Writer, v uint32) error {
	switch {
	case v == 0:
		return nil
	case v < 256:
		return []byte{byte(v)}
		buf.Write([]byte{byte(v)})
	case v < 65536:
		rv := []byte{0, 0}
		binary.BigEndian.PutUint16(rv, uint16(v))
		return rv
		return binary.Write(buf, binary.BigEndian, uint16(v))
	case v < 16777216:
		rv := []byte{0, 0, 0, 0}
		binary.BigEndian.PutUint32(rv, uint32(v))
		return rv[1:]
		_, err := buf.Write(rv[1:])
		return err
	default:
		rv := []byte{0, 0, 0, 0}
		binary.BigEndian.PutUint32(rv, uint32(v))
		return rv
		return binary.Write(buf, binary.BigEndian, uint32(v))
	}
	return nil
}

func lengthInt(v uint32) int {
	switch {
	case v == 0:
		return 0
	case v < 256:
		return 1
	case v < 65536:
		return 2
	case v < 16777216:
		return 3
	default:
		return 4
	}
}



@@ 343,14 355,16 @@ func decodeInt(b []byte) uint32 {
	return binary.BigEndian.Uint32(tmp)
}

func (o option) toBytes() ([]byte, error) {
func (o option) writeData(buf io.Writer) error {
	var v uint32

	switch i := o.Value.(type) {
	case string:
		return []byte(i), nil
		_, err := buf.Write([]byte(i))
		return err
	case []byte:
		return i, nil
		_, err := buf.Write(i)
		return err
	case MediaType:
		v = uint32(i)
	case int:


@@ 362,11 376,37 @@ func (o option) toBytes() ([]byte, error) {
	case uint32:
		v = i
	default:
		return nil, fmt.Errorf("invalid type for option %x: %T (%v)",
		return fmt.Errorf("invalid type for option %x: %T (%v)",
			o.ID, o.Value, o.Value)
	}

	return encodeInt(v), nil
	return encodeInt(buf, v)
}

func (o option) toBytesLength() (int, error) {
	var v uint32

	switch i := o.Value.(type) {
	case string:
		return len(i), nil
	case []byte:
		return len(i), nil
	case MediaType:
		v = uint32(i)
	case int:
		v = uint32(i)
	case int32:
		v = uint32(i)
	case uint:
		v = uint32(i)
	case uint32:
		v = i
	default:
		return 0, fmt.Errorf("invalid type for option %x: %T (%v)",
			o.ID, o.Value, o.Value)
	}

	return lengthInt(v), nil
}

func parseOptionValue(optionDefs map[OptionID]optionDef, optionID OptionID, valueBuf []byte) interface{} {


@@ 413,14 453,15 @@ func (o options) Swap(i, j int) {
	o[i], o[j] = o[j], o[i]
}

func (o options) Minus(oid OptionID) options {
	rv := options{}
	for _, opt := range o {
		if opt.ID != oid {
			rv = append(rv, opt)
func (o options) Remove(oid OptionID) options {
	idx := 0
	for i := 0; i < len(o); i++ {
		if o[i].ID != oid {
			o[idx] = o[i]
			idx++
		}
	}
	return rv
	return o[:idx]
}

// Message represents the COAP message


@@ 446,7 487,7 @@ type Message interface {
	RemoveOption(opID OptionID)
	AddOption(opID OptionID, val interface{})
	SetOption(opID OptionID, val interface{})
	MarshalBinary() ([]byte, error)
	MarshalBinary(buf io.Writer) error
	UnmarshalBinary(data []byte) error
	SetToken(t []byte)
	SetMessageID(messageID uint16)


@@ 577,7 618,7 @@ func (m *MessageBase) SetToken(p []byte) {

// RemoveOption removes all references to an option
func (m *MessageBase) RemoveOption(opID OptionID) {
	m.opts = m.opts.Minus(opID)
	m.opts = m.opts.Remove(opID)
}

// AddOption adds an option.


@@ 654,16 695,21 @@ func writeOpt(o option, buf io.Writer, delta int) {
		d, dx := extendOpt(delta)
		l, lx := extendOpt(length)

		buf.Write([]byte{byte(d<<4) | byte(l)})
		//buf.Write([]byte{byte(d<<4) | byte(l)})
		var h [1]byte
		h[0] = byte(d<<4) | byte(l)

		buf.Write(h[:])

		tmp := []byte{0, 0}
		var tmp [2]byte
		writeExt := func(opt, ext int) {
			switch opt {
			case extoptByteCode:
				buf.Write([]byte{byte(ext)})
				tmp[0] = byte(ext)
				buf.Write(tmp[:1])
			case extoptWordCode:
				binary.BigEndian.PutUint16(tmp, uint16(ext))
				buf.Write(tmp)
				binary.BigEndian.PutUint16(tmp[:], uint16(ext))
				buf.Write(tmp[:])
			}
		}



@@ 671,12 717,12 @@ func writeOpt(o option, buf io.Writer, delta int) {
		writeExt(l, lx)
	}

	b, err := o.toBytes()
	len, err := o.toBytesLength()
	if err != nil {
		log.Fatal(err)
	} else {
		writeOptHeader(delta, len(b))
		buf.Write(b)
		writeOptHeader(delta, len)
		o.writeData(buf)
	}
}



@@ 688,6 734,94 @@ func writeOpts(buf io.Writer, opts options) {
	}
}

func lengthOpt(o option, delta int) int {
	/*
	     0   1   2   3   4   5   6   7
	   +---------------+---------------+
	   |               |               |
	   |  Option Delta | Option Length |   1 byte
	   |               |               |
	   +---------------+---------------+
	   \                               \
	   /         Option Delta          /   0-2 bytes
	   \          (extended)           \
	   +-------------------------------+
	   \                               \
	   /         Option Length         /   0-2 bytes
	   \          (extended)           \
	   +-------------------------------+
	   \                               \
	   /                               /
	   \                               \
	   /         Option Value          /   0 or more bytes
	   \                               \
	   /                               /
	   \                               \
	   +-------------------------------+

	   See parseExtOption(), extendOption()
	   and writeOptionHeader() below for implementation details
	*/

	extendOpt := func(opt int) (int, int) {
		ext := 0
		if opt >= extoptByteAddend {
			if opt >= extoptWordAddend {
				ext = opt - extoptWordAddend
				opt = extoptWordCode
			} else {
				ext = opt - extoptByteAddend
				opt = extoptByteCode
			}
		}
		return opt, ext
	}

	lengthOptHeader := func(delta, length int) int {
		d, dx := extendOpt(delta)
		l, lx := extendOpt(length)

		//buf.Write([]byte{byte(d<<4) | byte(l)})
		res := 1

		writeExt := func(opt, ext int) int {
			switch opt {
			case extoptByteCode:
				//tmp[0] = byte(ext)
				//buf.Write(tmp[:1])
				return 1
			case extoptWordCode:
				//binary.BigEndian.PutUint16(tmp[:], uint16(ext))
				//buf.Write(tmp[:])
				return 2
			}
			return 0
		}

		res = res + writeExt(d, dx)
		res = res + writeExt(l, lx)
		return res
	}

	res, err := o.toBytesLength()
	if err != nil {
		log.Fatal(err)
	} else {
		res = res + lengthOptHeader(delta, res)
	}
	return res
}

func bytesLengthOpts(opts options) int {
	length := 0
	prev := 0
	for _, o := range opts {
		length = length + lengthOpt(o, int(o.ID)-prev)
		prev = int(o.ID)
	}
	return length
}

// parseBody extracts the options and payload from a byte slice.  The supplied
// byte slice contains everything following the message header (everything
// after the token).

M message_test.go => message_test.go +61 -44
@@ 2,17 2,11 @@ package coap

import (
	"bytes"
	"encoding"
	"fmt"
	"reflect"
	"testing"
)

var (
	_ = encoding.BinaryMarshaler(&DgramMessage{})
	_ = encoding.BinaryUnmarshaler(&DgramMessage{})
)

// assertEqualMessages compares the e(xptected) message to the a(ctual) message
// and reports any diffs with t.Errorf.
func assertEqualMessages(t *testing.T, e, a Message) {


@@ 33,11 27,11 @@ func assertEqualMessages(t *testing.T, e, a Message) {
	}

	if len(e.AllOptions()) != len(a.AllOptions()) {
		t.Errorf("Expected %v options, got %v", len(e.AllOptions()), len(a.AllOptions()))
		t.Errorf("Expected %v options, got %v", e, a)
	} else {
		for i, _ := range e.AllOptions() {
			if e.AllOptions()[i].ID != a.AllOptions()[i].ID {
				t.Errorf("Expected option ID %v, got %v", e.AllOptions()[i].ID, a.AllOptions()[i].ID)
				t.Errorf("\nExpected option %v\n got %v", e.AllOptions()[i].ID, a.AllOptions()[i].ID)
				continue
			}
			switch e.AllOptions()[i].Value.(type) {


@@ 85,7 79,9 @@ func TestOptionToBytes(t *testing.T) {

	for _, test := range tests {
		op := option{Value: test.in}
		got, err := op.toBytes()
		buf := &bytes.Buffer{}
		err := op.writeData(buf)
		got := buf.Bytes()
		if err != nil {
			t.Error(err)
		} else if !bytes.Equal(test.exp, got) {


@@ 120,7 116,8 @@ func TestMissingOption(t *testing.T) {
}

func TestOptionToBytesError(t *testing.T) {
	_, err := option{Value: 3.1415926535897}.toBytes()
	buf := &bytes.Buffer{}
	err := option{Value: 3.1415926535897}.writeData(buf)
	if err == nil {
		t.Error("Expected panic. Didn't")
	} else {


@@ 169,15 166,16 @@ func TestEncodeMessageWithoutOptionsAndPayload(t *testing.T) {
		},
	}

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}

	// Inspected by hand.
	exp := []byte{0x40, 0x1, 0x30, 0x39}
	if !bytes.Equal(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !bytes.Equal(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 193,7 191,8 @@ func TestEncodeMessageSmall(t *testing.T) {
	req.AddOption(ETag, []byte("weetag"))
	req.AddOption(MaxAge, 3)

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}


@@ 203,8 202,8 @@ func TestEncodeMessageSmall(t *testing.T) {
		0x40, 0x1, 0x30, 0x39, 0x46, 0x77,
		0x65, 0x65, 0x74, 0x61, 0x67, 0xa1, 0x3,
	}
	if !reflect.DeepEqual(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !reflect.DeepEqual(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 221,7 220,8 @@ func TestEncodeMessageSmallWithPayload(t *testing.T) {
	req.AddOption(ETag, []byte("weetag"))
	req.AddOption(MaxAge, 3)

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}


@@ 232,8 232,8 @@ func TestEncodeMessageSmallWithPayload(t *testing.T) {
		0x65, 0x65, 0x74, 0x61, 0x67, 0xa1, 0x3,
		0xff, 'h', 'i',
	}
	if !reflect.DeepEqual(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !reflect.DeepEqual(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 349,7 349,8 @@ func TestEncodeMessageVerySmall(t *testing.T) {
	}
	req.SetPathString("x")

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}


@@ 358,8 359,8 @@ func TestEncodeMessageVerySmall(t *testing.T) {
	exp := []byte{
		0x40, 0x1, 0x30, 0x39, 0xb1, 0x78,
	}
	if !reflect.DeepEqual(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !reflect.DeepEqual(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 374,7 375,8 @@ func TestEncodeMessageVerySmall2(t *testing.T) {
	}
	req.SetPathString("/x")

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}


@@ 383,8 385,8 @@ func TestEncodeMessageVerySmall2(t *testing.T) {
	exp := []byte{
		0x40, 0x1, 0x30, 0x39, 0xb1, 0x78,
	}
	if !reflect.DeepEqual(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !reflect.DeepEqual(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 404,13 406,14 @@ func TestEncodeSeveral(t *testing.T) {
			},
		}
		m.SetPathString(p)
		b, err := m.MarshalBinary()
		buf := &bytes.Buffer{}
		err := m.MarshalBinary(buf)
		if err != nil {
			t.Errorf("Error encoding %#v", p)
			t.Fail()
			continue
		}
		m2, err := ParseDgramMessage(b)
		m2, err := ParseDgramMessage(buf.Bytes())
		if err != nil {
			t.Fatalf("Can't parse my own message at %#v: %v", p, err)
		}


@@ 431,13 434,14 @@ func TestPathAsOption(t *testing.T) {
		},
	}
	m.SetOption(LocationPath, []string{"a", "b"})
	got, err := m.MarshalBinary()
	buf := &bytes.Buffer{}
	err := m.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error marshaling: %v", err)
	}
	exp := []byte{0x40, 0x1, 0x30, 0x39, 0x81, 0x61, 0x1, 0x62}
	if !bytes.Equal(got, exp) {
		t.Errorf("Got %#v, wanted %#v", got, exp)
	if !bytes.Equal(buf.Bytes(), exp) {
		t.Errorf("Got %#v, wanted %#v", buf.Bytes(), exp)
	}
}



@@ 451,7 455,8 @@ func TestEncodePath14(t *testing.T) {
	}
	req.SetPathString("123456789ABCDE")

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}


@@ 462,8 467,8 @@ func TestEncodePath14(t *testing.T) {
		'1', '2', '3', '4', '5', '6', '7', '8',
		'9', 'A', 'B', 'C', 'D', 'E',
	}
	if !reflect.DeepEqual(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !reflect.DeepEqual(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 477,7 482,8 @@ func TestEncodePath15(t *testing.T) {
	}
	req.SetPathString("123456789ABCDEF")

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}


@@ 488,8 494,8 @@ func TestEncodePath15(t *testing.T) {
		'1', '2', '3', '4', '5', '6', '7', '8',
		'9', 'A', 'B', 'C', 'D', 'E', 'F',
	}
	if !reflect.DeepEqual(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !reflect.DeepEqual(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 508,7 514,8 @@ func TestEncodeLargePath(t *testing.T) {
			req.PathString())
	}

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}


@@ 522,8 529,8 @@ func TestEncodeLargePath(t *testing.T) {
		0x68, 0x61, 0x6e, 0x5f, 0x66, 0x69, 0x66, 0x74, 0x65,
		0x65, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
	}
	if !reflect.DeepEqual(exp, data) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, data)
	if !reflect.DeepEqual(exp, buf.Bytes()) {
		t.Fatalf("Expected\n%#v\ngot\n%#v", exp, buf.Bytes())
	}
}



@@ 555,8 562,9 @@ func TestDecodeLargePath(t *testing.T) {
	exp.SetOption(URIPath, path)

	if fmt.Sprintf("%#v", exp) != fmt.Sprintf("%#v", req) {
		b, _ := exp.MarshalBinary()
		t.Fatalf("Expected\n%#v\ngot\n%#v\nfor %#v", exp, req, b)
		buf := &bytes.Buffer{}
		exp.MarshalBinary(buf)
		t.Fatalf("Expected\n%#v\ngot\n%#v\nfor %#v", exp, req, buf.Bytes())
	}
}



@@ 601,7 609,12 @@ func TestByteEncoding(t *testing.T) {
	}

	for _, v := range tests {
		got := encodeInt(v.Value)
		buf := &bytes.Buffer{}
		err := encodeInt(buf, v.Value)
		if err != nil {
			t.Error(err)
		}
		got := buf.Bytes()
		if !reflect.DeepEqual(got, v.Expected) {
			t.Fatalf("Expected %#v, got %#v for %v",
				v.Expected, got, v.Value)


@@ 801,13 814,17 @@ func TestEncodeMessageWithAllOptions(t *testing.T) {
	req.AddOption(ProxyURI, "PROXYURI")
	req.AddOption(ProxyScheme, "PROXYSCHEME")
	req.AddOption(Size1, uint32(9999))
	req.AddOption(Block1, uint32(66560))
	req.AddOption(Size2, uint32(9999))
	req.AddOption(Block2, uint32(66560))

	data, err := req.MarshalBinary()
	buf := &bytes.Buffer{}
	err := req.MarshalBinary(buf)
	if err != nil {
		t.Fatalf("Error encoding request: %v", err)
	}

	parsedMsg, err := ParseDgramMessage(data)
	parsedMsg, err := ParseDgramMessage(buf.Bytes())
	if err != nil {
		t.Fatalf("Error parsing binary packet: %v", err)
	}

M messagedgram.go => messagedgram.go +5 -6
@@ 1,8 1,8 @@
package coap

import (
	"bytes"
	"encoding/binary"
	"io"
	"sort"
)



@@ 29,7 29,7 @@ func (m *DgramMessage) SetMessageID(messageID uint16) {
}

// MarshalBinary produces the binary form of this DgramMessage.
func (m *DgramMessage) MarshalBinary() ([]byte, error) {
func (m *DgramMessage) MarshalBinary(buf io.Writer) error {
	tmpbuf := []byte{0, 0}
	binary.BigEndian.PutUint16(tmpbuf, m.MessageID())



@@ 47,7 47,6 @@ func (m *DgramMessage) MarshalBinary() ([]byte, error) {
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	*/

	buf := bytes.Buffer{}
	buf.Write([]byte{
		(1 << 6) | (uint8(m.Type()) << 4) | uint8(0xf&len(m.MessageBase.token)),
		byte(m.MessageBase.code),


@@ 55,12 54,12 @@ func (m *DgramMessage) MarshalBinary() ([]byte, error) {
	})

	if len(m.MessageBase.token) > MaxTokenSize {
		return nil, ErrInvalidTokenLen
		return ErrInvalidTokenLen
	}
	buf.Write(m.MessageBase.token)

	sort.Stable(&m.MessageBase.opts)
	writeOpts(&buf, m.MessageBase.opts)
	writeOpts(buf, m.MessageBase.opts)

	if len(m.MessageBase.payload) > 0 {
		buf.Write([]byte{0xff})


@@ 68,7 67,7 @@ func (m *DgramMessage) MarshalBinary() ([]byte, error) {

	buf.Write(m.MessageBase.payload)

	return buf.Bytes(), nil
	return nil
}

// UnmarshalBinary parses the given binary slice as a DgramMessage.

M messagetcp.go => messagetcp.go +28 -20
@@ 114,7 114,7 @@ func (m *TcpMessage) SetMessageID(messageID uint16) {
	//not used by COAP over TCP
}

func (m *TcpMessage) MarshalBinary() ([]byte, error) {
func (m *TcpMessage) MarshalBinary(buf io.Writer) error {
	/*
	   A CoAP TCP message looks like:



@@ 142,41 142,41 @@ func (m *TcpMessage) MarshalBinary() ([]byte, error) {
	*/

	if len(m.MessageBase.token) > MaxTokenSize {
		return nil, ErrInvalidTokenLen
		return ErrInvalidTokenLen
	}

	buf := bytes.Buffer{}

	sort.Stable(&m.MessageBase.opts)
	writeOpts(&buf, m.MessageBase.opts)

	if len(m.MessageBase.payload) > 0 {
		buf.Write([]byte{0xff})
		buf.Write(m.MessageBase.payload)
	payloadLen := len(m.MessageBase.payload)
	if payloadLen > 0 {
		//for separator 0xff
		payloadLen++
	}

	optionsLen := bytesLengthOpts(m.MessageBase.opts)
	bufLen := payloadLen + optionsLen
	var lenNib uint8
	var extLenBytes []byte

	if buf.Len() < TCP_MESSAGE_LEN13_BASE {
		lenNib = uint8(buf.Len())
	} else if buf.Len() < TCP_MESSAGE_LEN14_BASE {
	if bufLen < TCP_MESSAGE_LEN13_BASE {
		lenNib = uint8(bufLen)
	} else if bufLen < TCP_MESSAGE_LEN14_BASE {
		lenNib = 13
		extLen := buf.Len() - TCP_MESSAGE_LEN13_BASE
		extLen := bufLen - TCP_MESSAGE_LEN13_BASE
		extLenBytes = []byte{uint8(extLen)}
	} else if buf.Len() < TCP_MESSAGE_LEN15_BASE {
	} else if bufLen < TCP_MESSAGE_LEN15_BASE {
		lenNib = 14
		extLen := buf.Len() - TCP_MESSAGE_LEN14_BASE
		extLen := bufLen - TCP_MESSAGE_LEN14_BASE
		extLenBytes = make([]byte, 2)
		binary.BigEndian.PutUint16(extLenBytes, uint16(extLen))
	} else if buf.Len() < TCP_MESSAGE_MAX_LEN {
	} else if bufLen < TCP_MESSAGE_MAX_LEN {
		lenNib = 15
		extLen := buf.Len() - TCP_MESSAGE_LEN15_BASE
		extLen := bufLen - TCP_MESSAGE_LEN15_BASE
		extLenBytes = make([]byte, 4)
		binary.BigEndian.PutUint32(extLenBytes, uint32(extLen))
	}

	hdr := make([]byte, 1+len(extLenBytes)+len(m.MessageBase.token)+1)
	//hdr := make([]byte, 1+len(extLenBytes)+len(m.MessageBase.token)+1)
	var hdr [1 + 4 + MaxTokenSize + 1]byte
	hdrLen := 1 + len(extLenBytes) + len(m.MessageBase.token) + 1
	hdrOff := 0

	// Length and TKL nibbles.


@@ 199,7 199,15 @@ func (m *TcpMessage) MarshalBinary() ([]byte, error) {
		hdrOff += len(m.MessageBase.token)
	}

	return append(hdr, buf.Bytes()...), nil
	bufLen = bufLen + len(hdr)
	buf.Write(hdr[:hdrLen])
	writeOpts(buf, m.MessageBase.opts)
	if len(m.MessageBase.payload) > 0 {
		buf.Write([]byte{0xff})
		buf.Write(m.MessageBase.payload)
	}

	return nil
}

// msgTcpInfo describes a single TCP CoAP message.  Used during reassembly.

M multicastClient.go => multicastClient.go +3 -3
@@ 16,7 16,7 @@ type MulticastClientConn struct {
// A MulticastClient defines parameters for a COAP client.
type MulticastClient struct {
	Net            string        // "udp" / "udp4" / "udp6"
	MaxMessageSize uint16        // Max message size that could be received from peer. If not set it defaults to 1152 B.
	MaxMessageSize uint32        // Max message size that could be received from peer. If not set it defaults to 1152 B.
	DialTimeout    time.Duration // set Timeout for dialer
	ReadTimeout    time.Duration // net.ClientConn.SetReadTimeout value for connections, defaults to 1 hour - overridden by Timeout when that value is non-zero
	WriteTimeout   time.Duration // net.ClientConn.SetWriteTimeout value for connections, defaults to 1 hour - overridden by Timeout when that value is non-zero


@@ 25,8 25,8 @@ type MulticastClient struct {
	Handler              HandlerFunc     // default handler for handling messages from server
	NotifySessionEndFunc func(err error) // if NotifySessionEndFunc is set it is called when TCP/UDP session was ended.

	BlockWiseTransfer    *bool     // Use blockWise transfer for transfer payload (default for UDP it's enabled, for TCP it's disable)
	BlockWiseTransferSzx *BlockSzx // Set maximal block size of payload that will be send in fragment
	BlockWiseTransfer    *bool         // Use blockWise transfer for transfer payload (default for UDP it's enabled, for TCP it's disable)
	BlockWiseTransferSzx *BlockWiseSzx // Set maximal block size of payload that will be send in fragment

	multicastHandler *TokenHandler
}

M multicastClient_test.go => multicastClient_test.go +14 -14
@@ 4,30 4,30 @@ import (
	"testing"
)

func TestServingIPv4MCastBlockSzx16(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockSzx16, 1033)
func TestServingIPv4MCastBlockWiseSzx16(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockWiseSzx16, 1033)
}

func TestServingIPv4MCastBlockSzx32(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockSzx32, 1033)
func TestServingIPv4MCastBlockWiseSzx32(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockWiseSzx32, 1033)
}

func TestServingIPv4MCastBlockSzx64(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockSzx64, 1033)
func TestServingIPv4MCastBlockWiseSzx64(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockWiseSzx64, 1033)
}

func TestServingIPv4MCastBlockSzx128(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockSzx128, 1033)
func TestServingIPv4MCastBlockWiseSzx128(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockWiseSzx128, 1033)
}

func TestServingIPv4MCastBlockSzx256(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockSzx256, 1033)
func TestServingIPv4MCastBlockWiseSzx256(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockWiseSzx256, 1033)
}

func TestServingIPv4MCastBlockSzx512(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockSzx512, 1033)
func TestServingIPv4MCastBlockWiseSzx512(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockWiseSzx512, 1033)
}

func TestServingIPv4MCastBlockSzx1024(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockSzx1024, 1033)
func TestServingIPv4MCastBlockWiseSzx1024(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", true, BlockWiseSzx1024, 1033)
}

M networksession.go => networksession.go +45 -59
@@ 56,18 56,18 @@ type networkSession interface {
	// BlockWiseTransferEnabled
	blockWiseEnabled() bool
	// BlockWiseTransferSzx
	blockWiseSzx() BlockSzx
	blockWiseSzx() BlockWiseSzx
	// MaxPayloadSize
	blockWiseMaxPayloadSize(peer BlockSzx) int
	blockWiseMaxPayloadSize(peer BlockWiseSzx) (int, BlockWiseSzx)

	blockWiseIsValid(szx BlockSzx) bool
	blockWiseIsValid(szx BlockWiseSzx) bool
}

// NewSessionUDP create new session for UDP connection
func newSessionUDP(connection Conn, srv *Server, sessionUDPData *SessionUDPData) (networkSession, error) {

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzx1024
	BlockWiseTransferSzx := BlockWiseSzx1024
	if srv.BlockWiseTransfer != nil {
		BlockWiseTransfer = *srv.BlockWiseTransfer
	}


@@ 75,8 75,8 @@ func newSessionUDP(connection Conn, srv *Server, sessionUDPData *SessionUDPData)
		BlockWiseTransferSzx = *srv.BlockWiseTransferSzx
	}

	if BlockWiseTransfer && BlockWiseTransferSzx == BlockSzxBERT {
		return nil, ErrInvalidBlockSzx
	if BlockWiseTransfer && BlockWiseTransferSzx == BlockWiseSzxBERT {
		return nil, ErrInvalidBlockWiseSzx
	}

	s := &sessionUDP{


@@ 87,7 87,7 @@ func newSessionUDP(connection Conn, srv *Server, sessionUDPData *SessionUDPData)
			writeDeadline:        30 * time.Second,
			handler:              &TokenHandler{tokenHandlers: make(map[[MaxTokenSize]byte]HandlerFunc)},
			blockWiseTransfer:    BlockWiseTransfer,
			blockWiseTransferSzx: BlockWiseTransferSzx,
			blockWiseTransferSzx: uint32(BlockWiseTransferSzx),
		},
		sessionUDPData: sessionUDPData,
		mapPairs:       make(map[[MaxTokenSize]byte]map[uint16](*sessionResp)),


@@ 98,7 98,7 @@ func newSessionUDP(connection Conn, srv *Server, sessionUDPData *SessionUDPData)
// newSessionTCP create new session for TCP connection
func newSessionTCP(connection Conn, srv *Server) (networkSession, error) {
	BlockWiseTransfer := false
	BlockWiseTransferSzx := BlockSzxBERT
	BlockWiseTransferSzx := BlockWiseSzxBERT
	if srv.BlockWiseTransfer != nil {
		BlockWiseTransfer = *srv.BlockWiseTransfer
	}


@@ 115,7 115,7 @@ func newSessionTCP(connection Conn, srv *Server) (networkSession, error) {
			writeDeadline:        30 * time.Second,
			handler:              &TokenHandler{tokenHandlers: make(map[[MaxTokenSize]byte]HandlerFunc)},
			blockWiseTransfer:    BlockWiseTransfer,
			blockWiseTransferSzx: BlockWiseTransferSzx,
			blockWiseTransferSzx: uint32(BlockWiseTransferSzx),
		},
	}



@@ 138,7 138,7 @@ type sessionBase struct {
	handler       *TokenHandler

	blockWiseTransfer    bool
	blockWiseTransferSzx BlockSzx
	blockWiseTransferSzx uint32 //BlockWiseSzx
}

type sessionUDP struct {


@@ 204,33 204,39 @@ func (s *sessionTCP) blockWiseEnabled() bool {
	return s.blockWiseTransfer /*&& atomic.LoadUint32(&s.peerBlockWiseTransfer) != 0*/
}

func (s *sessionBase) blockWiseSzx() BlockSzx {
	return s.blockWiseTransferSzx
func (s *sessionBase) blockWiseSzx() BlockWiseSzx {
	return BlockWiseSzx(atomic.LoadUint32(&s.blockWiseTransferSzx))
}

func (s *sessionBase) blockWiseMaxPayloadSize(peer BlockSzx) int {
	if peer < s.blockWiseTransferSzx {
		return SZXVal[peer]
func (s *sessionBase) setBlockWiseSzx(szx BlockWiseSzx) {
	atomic.StoreUint32(&s.blockWiseTransferSzx, uint32(szx))
}

func (s *sessionBase) blockWiseMaxPayloadSize(peer BlockWiseSzx) (int, BlockWiseSzx) {
	szx := s.blockWiseSzx()
	if peer < szx {
		return szxToBytes[peer], peer
	}
	return SZXVal[s.blockWiseTransferSzx]
	return szxToBytes[szx], szx
}

func (s *sessionTCP) blockWiseMaxPayloadSize(peer BlockSzx) int {
	if s.blockWiseTransferSzx == BlockSzxBERT && peer == BlockSzxBERT {
func (s *sessionTCP) blockWiseMaxPayloadSize(peer BlockWiseSzx) (int, BlockWiseSzx) {
	szx := s.blockWiseSzx()
	if szx == BlockWiseSzxBERT && peer == BlockWiseSzxBERT {
		m := atomic.LoadUint32(&s.peerMaxMessageSize)
		if m == 0 {
			m = uint32(s.srv.MaxMessageSize)
		}
		return int(m - (m % 1024))
		return int(m - (m % 1024)), BlockWiseSzxBERT
	}
	return s.sessionBase.blockWiseMaxPayloadSize(peer)
}

func (s *sessionUDP) blockWiseIsValid(szx BlockSzx) bool {
	return szx <= BlockSzx1024
func (s *sessionUDP) blockWiseIsValid(szx BlockWiseSzx) bool {
	return szx <= BlockWiseSzx1024
}

func (s *sessionTCP) blockWiseIsValid(szx BlockSzx) bool {
func (s *sessionTCP) blockWiseIsValid(szx BlockWiseSzx) bool {
	return true
}



@@ 424,30 430,14 @@ func (s *sessionUDP) Write(m Message) error {
}

func (s *sessionTCP) writeTimeout(m Message, timeout time.Duration) error {
	req, err := m.MarshalBinary()
	if err != nil {
		return err
	}
	peerMaxMessageSize := int(atomic.LoadUint32(&s.peerMaxMessageSize))
	if peerMaxMessageSize != 0 && len(req) > peerMaxMessageSize {
		//TODO blockWise transfer + BERT to device
		return ErrMsgTooLarge
	}
	return s.connection.write(&writeReqTCP{writeReqBase{req: req, respChan: make(chan error, 1)}}, timeout)
	//TODO check size of m
	return s.connection.write(&writeReqTCP{writeReqBase{req: m, respChan: make(chan error, 1)}}, timeout)
}

// WriteMsg implements the networkSession.WriteMsg method.
func (s *sessionUDP) writeTimeout(m Message, timeout time.Duration) error {
	req, err := m.MarshalBinary()
	if err != nil {
		return err
	}

	//TODO blockWise transfer to device
	if len(req) > int(s.srv.MaxMessageSize) {
		return ErrMsgTooLarge
	}
	return s.connection.write(&writeReqUDP{writeReqBase{req: req, respChan: make(chan error, 1)}, s.sessionUDPData}, timeout)
	//TODO check size of m
	return s.connection.write(&writeReqUDP{writeReqBase{req: m, respChan: make(chan error, 1)}, s.sessionUDPData}, timeout)
}

func (s *sessionTCP) handlePairMsg(w ResponseWriter, r *Request) bool {


@@ 544,27 534,23 @@ func (s *sessionTCP) handleSignals(w ResponseWriter, r *Request) bool {
		}
		if r.Msg.Option(BlockWiseTransfer) != nil {
			s.setPeerBlockWiseTransfer(true)
			switch s.blockWiseSzx() {
			case BlockSzxBERT:
				if SZXVal[BlockSzx1024] < int(maxmsgsize) {
					s.sessionBase.blockWiseTransferSzx = BlockSzxBERT
				} else {
					for i := BlockSzx512; i > BlockSzx16; i-- {
						if SZXVal[i] < int(maxmsgsize) {
							s.sessionBase.blockWiseTransferSzx = i
						}
					}
					s.sessionBase.blockWiseTransferSzx = BlockSzx16
			startIter := s.blockWiseSzx()
			if startIter == BlockWiseSzxBERT {
				if szxToBytes[BlockWiseSzx1024] < int(maxmsgsize) {
					s.setBlockWiseSzx(BlockWiseSzxBERT)
					return true
				}
			default:
				for i := s.blockWiseSzx(); i > BlockSzx16; i-- {
					if SZXVal[i] < int(maxmsgsize) {
						s.sessionBase.blockWiseTransferSzx = i
					}
				startIter = BlockWiseSzx512
			}
			for i := startIter; i > BlockWiseSzx16; i-- {
				if szxToBytes[i] < int(maxmsgsize) {
					s.setBlockWiseSzx(i)
					return true
				}
				s.sessionBase.blockWiseTransferSzx = BlockSzx16
			}
			s.setBlockWiseSzx(BlockWiseSzx16)
		}

		return true
	case Ping:
		if r.Msg.Option(Custody) != nil {

M server.go => server.go +12 -7
@@ 112,9 112,9 @@ type Server struct {
	Conn net.Conn
	// Handler to invoke, COAP.DefaultServeMux if nil.
	Handler Handler
	// Max message size that could be received from peer. If not set
	// Max message size that could be received from peer. Min 16bytes. If not set
	// it defaults to 1152 B.
	MaxMessageSize uint16
	MaxMessageSize uint32
	// The net.Conn.SetReadTimeout value for new connections, defaults to 1hour.
	ReadTimeout time.Duration
	// The net.Conn.SetWriteTimeout value for new connections, defaults to 1hour.


@@ 136,7 136,7 @@ type Server struct {
	// Use blockWise transfer for transfer payload (default for UDP it's enabled, for TCP it's disable)
	BlockWiseTransfer *bool
	// Set maximal block size of payload that will be send in fragment
	BlockWiseTransferSzx *BlockSzx
	BlockWiseTransferSzx *BlockWiseSzx

	TCPReadBufferSize  int
	TCPWriteBufferSize int


@@ 275,9 275,6 @@ func (srv *Server) ListenAndServe() error {
}

func (srv *Server) initServeUDP(conn *net.UDPConn) error {
	if srv.MaxMessageSize == 0 {
		srv.MaxMessageSize = maxMessageSize
	}
	srv.lock.Lock()
	srv.started = true
	srv.lock.Unlock()


@@ 307,6 304,13 @@ func (srv *Server) ActivateAndServe() error {
	pConn := srv.Conn
	l := srv.Listener

	if srv.MaxMessageSize == 0 {
		srv.MaxMessageSize = maxMessageSize
	}
	if srv.MaxMessageSize < uint32(szxToBytes[BlockWiseSzx16]) {
		return ErrInvalidMaxMesssageSizeParameter
	}

	srv.sessionUDPMap = make(map[string]networkSession)

	srv.queue = make(chan *Request)


@@ 517,8 521,9 @@ func (srv *Server) serveUDP(conn *net.UDPConn) error {
	// deadline is not used here

	connUDP := newConnectionUDP(conn, srv).(*connUDP)
	m := make([]byte, srv.MaxMessageSize)

	for {
		m := make([]byte, ^uint16(0))
		srv.lock.RLock()
		if !srv.started {
			srv.lock.RUnlock()

M server_test.go => server_test.go +34 -33
@@ 58,7 58,7 @@ func EchoServerBadID(w ResponseWriter, r *Request) {
	}
}

func RunLocalServerUDPWithHandler(lnet, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx, handler HandlerFunc) (*Server, string, chan error, error) {
func RunLocalServerUDPWithHandler(lnet, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx, handler HandlerFunc) (*Server, string, chan error, error) {
	network := strings.TrimSuffix(lnet, "-mcast")

	a, err := net.ResolveUDPAddr(network, laddr)


@@ 104,11 104,11 @@ func RunLocalServerUDPWithHandler(lnet, laddr string, BlockWiseTransfer bool, Bl
	return server, pc.LocalAddr().String(), fin, nil
}

func RunLocalUDPServer(net, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx) (*Server, string, chan error, error) {
func RunLocalUDPServer(net, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx) (*Server, string, chan error, error) {
	return RunLocalServerUDPWithHandler(net, laddr, BlockWiseTransfer, BlockWiseTransferSzx, nil)
}

func RunLocalServerTCPWithHandler(laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx, handler HandlerFunc) (*Server, string, chan error, error) {
func RunLocalServerTCPWithHandler(laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx, handler HandlerFunc) (*Server, string, chan error, error) {
	l, err := net.Listen("tcp", laddr)
	if err != nil {
		return nil, "", nil, err


@@ 122,7 122,7 @@ func RunLocalServerTCPWithHandler(laddr string, BlockWiseTransfer bool, BlockWis
		}, Handler: handler,
		BlockWiseTransfer:    &BlockWiseTransfer,
		BlockWiseTransferSzx: &BlockWiseTransferSzx,
		MaxMessageSize:       ^uint16(0),
		MaxMessageSize:       ^uint32(0),
	}

	waitLock := sync.Mutex{}


@@ 142,7 142,7 @@ func RunLocalServerTCPWithHandler(laddr string, BlockWiseTransfer bool, BlockWis
	return server, l.Addr().String(), fin, nil
}

func RunLocalTCPServer(laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx) (*Server, string, chan error, error) {
func RunLocalTCPServer(laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx) (*Server, string, chan error, error) {
	return RunLocalServerTCPWithHandler(laddr, BlockWiseTransfer, BlockWiseTransferSzx, nil)
}



@@ 179,7 179,7 @@ func RunLocalTLSServer(laddr string, config *tls.Config) (*Server, string, chan 

type clientHandler func(t *testing.T, payload []byte, co *ClientConn)

func testServingTCPWithMsgWithObserver(t *testing.T, net string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx, payload []byte, ch clientHandler, observeFunc HandlerFunc) {
func testServingTCPWithMsgWithObserver(t *testing.T, net string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx, payload []byte, ch clientHandler, observeFunc HandlerFunc) {
	HandleFunc("/test", EchoServer)
	defer HandleRemove("/test")



@@ 191,6 191,7 @@ func testServingTCPWithMsgWithObserver(t *testing.T, net string, BlockWiseTransf
		Handler:              observeFunc,
		BlockWiseTransfer:    &BlockWiseTransfer,
		BlockWiseTransferSzx: &BlockWiseTransferSzx,
		MaxMessageSize:       ^uint32(0),
	}
	var fin chan error
	switch net {


@@ 255,41 256,41 @@ func pingMsg(t *testing.T, payload []byte, co *ClientConn) {
	}
}

func testServingTCPWithMsg(t *testing.T, net string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx, payload []byte, ch clientHandler) {
func testServingTCPWithMsg(t *testing.T, net string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx, payload []byte, ch clientHandler) {
	testServingTCPWithMsgWithObserver(t, net, BlockWiseTransfer, BlockWiseTransferSzx, payload, ch, nil)
}

func TestServingUDP(t *testing.T) {
	testServingTCPWithMsg(t, "udp", false, BlockSzx16, make([]byte, 128), simpleMsg)
	testServingTCPWithMsg(t, "udp", false, BlockWiseSzx16, make([]byte, 128), simpleMsg)
}

func TestServingUDPPing(t *testing.T) {

	testServingTCPWithMsg(t, "udp", false, BlockSzx16, nil, pingMsg)
	testServingTCPWithMsg(t, "udp", false, BlockWiseSzx16, nil, pingMsg)
}

func TestServingTCPPing(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", false, BlockSzx16, nil, pingMsg)
	testServingTCPWithMsg(t, "tcp", false, BlockWiseSzx16, nil, pingMsg)
}

func TestServingUDPBigMsg(t *testing.T) {
	testServingTCPWithMsg(t, "udp", false, BlockSzx16, make([]byte, 1024), simpleMsg)
	testServingTCPWithMsg(t, "udp", false, BlockWiseSzx16, make([]byte, 1024), simpleMsg)
}

func TestServingTCP(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", false, BlockSzx16, make([]byte, 128), simpleMsg)
	testServingTCPWithMsg(t, "tcp", false, BlockWiseSzx16, make([]byte, 128), simpleMsg)
}

func TestServingTCPBigMsg(t *testing.T) {
	testServingTCPWithMsg(t, "tcp", false, BlockSzx16, make([]byte, 10*1024*1024), simpleMsg)
	testServingTCPWithMsg(t, "tcp", false, BlockWiseSzx16, make([]byte, 10*1024*1024), simpleMsg)
}

func TestServingTLS(t *testing.T) {
	testServingTCPWithMsg(t, "tcp-tls", false, BlockSzx16, make([]byte, 128), simpleMsg)
	testServingTCPWithMsg(t, "tcp-tls", false, BlockWiseSzx16, make([]byte, 128), simpleMsg)
}

func TestServingTLSBigMsg(t *testing.T) {
	testServingTCPWithMsg(t, "tcp-tls", false, BlockSzx16, make([]byte, 10*1024*1024), simpleMsg)
	testServingTCPWithMsg(t, "tcp-tls", false, BlockWiseSzx16, make([]byte, 10*1024*1024), simpleMsg)
}

func ChallegingServer(w ResponseWriter, r *Request) {


@@ 350,25 351,25 @@ func simpleChallengingPathMsg(t *testing.T, payload []byte, co *ClientConn, path
func TestServingChallengingClient(t *testing.T) {
	HandleFunc("/challenging", ChallegingServer)
	defer HandleRemove("/challenging")
	testServingTCPWithMsg(t, "udp", false, BlockSzx16, make([]byte, 128), simpleChallengingMsg)
	testServingTCPWithMsg(t, "udp", false, BlockWiseSzx16, make([]byte, 128), simpleChallengingMsg)
}

func TestServingChallengingClientTCP(t *testing.T) {
	HandleFunc("/challenging", ChallegingServer)
	defer HandleRemove("/challenging")
	testServingTCPWithMsg(t, "tcp", false, BlockSzx16, make([]byte, 128), simpleChallengingMsg)
	testServingTCPWithMsg(t, "tcp", false, BlockWiseSzx16, make([]byte, 128), simpleChallengingMsg)
}

func TestServingChallengingClientTLS(t *testing.T) {
	HandleFunc("/challenging", ChallegingServer)
	defer HandleRemove("/challenging")
	testServingTCPWithMsg(t, "tcp-tls", false, BlockSzx16, make([]byte, 128), simpleChallengingMsg)
	testServingTCPWithMsg(t, "tcp-tls", false, BlockWiseSzx16, make([]byte, 128), simpleChallengingMsg)
}

func TestServingChallengingTimeoutClient(t *testing.T) {
	HandleFunc("/challengingTimeout", ChallegingServerTimeout)
	defer HandleRemove("/challengingTimeout")
	testServingTCPWithMsgWithObserver(t, "udp", false, BlockSzx16, make([]byte, 128), simpleChallengingTimeoutMsg, func(w ResponseWriter, r *Request) {
	testServingTCPWithMsgWithObserver(t, "udp", false, BlockWiseSzx16, make([]byte, 128), simpleChallengingTimeoutMsg, func(w ResponseWriter, r *Request) {
		//for timeout
		time.Sleep(2 * time.Second)
	})


@@ 377,7 378,7 @@ func TestServingChallengingTimeoutClient(t *testing.T) {
func TestServingChallengingTimeoutClientTCP(t *testing.T) {
	HandleFunc("/challengingTimeout", ChallegingServerTimeout)
	defer HandleRemove("/challengingTimeout")
	testServingTCPWithMsgWithObserver(t, "tcp", false, BlockSzx16, make([]byte, 128), simpleChallengingTimeoutMsg, func(w ResponseWriter, r *Request) {
	testServingTCPWithMsgWithObserver(t, "tcp", false, BlockWiseSzx16, make([]byte, 128), simpleChallengingTimeoutMsg, func(w ResponseWriter, r *Request) {
		//for timeout
		time.Sleep(2 * time.Second)
	})


@@ 386,13 387,13 @@ func TestServingChallengingTimeoutClientTCP(t *testing.T) {
func TestServingChallengingTimeoutClientTLS(t *testing.T) {
	HandleFunc("/challengingTimeout", ChallegingServerTimeout)
	defer HandleRemove("/challengingTimeout")
	testServingTCPWithMsgWithObserver(t, "tcp-tls", false, BlockSzx16, make([]byte, 128), simpleChallengingTimeoutMsg, func(w ResponseWriter, r *Request) {
	testServingTCPWithMsgWithObserver(t, "tcp-tls", false, BlockWiseSzx16, make([]byte, 128), simpleChallengingTimeoutMsg, func(w ResponseWriter, r *Request) {
		//for timeout
		time.Sleep(2 * time.Second)
	})
}

func testServingMCast(t *testing.T, lnet, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockSzx, payloadLen int) {
func testServingMCast(t *testing.T, lnet, laddr string, BlockWiseTransfer bool, BlockWiseTransferSzx BlockWiseSzx, payloadLen int) {
	addrMcast := laddr
	ansArrived := make(chan bool)



@@ 464,11 465,11 @@ func testServingMCast(t *testing.T, lnet, laddr string, BlockWiseTransfer bool, 
}

func TestServingIPv4MCast(t *testing.T) {
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", false, BlockSzx16, 16)
	testServingMCast(t, "udp4-mcast", "225.0.1.187:11111", false, BlockWiseSzx16, 16)
}

func TestServingIPv6MCast(t *testing.T) {
	testServingMCast(t, "udp6-mcast", "[ff03::158]:11111", false, BlockSzx16, 16)
	testServingMCast(t, "udp6-mcast", "[ff03::158]:11111", false, BlockWiseSzx16, 16)
}

type dataReader struct {


@@ 495,7 496,7 @@ func BenchmarkServe(b *testing.B) {
	HandleFunc("/test", EchoServer)
	defer HandleRemove("/test")

	s, addrstr, fin, err := RunLocalUDPServer("udp", ":0", false, BlockSzx16)
	s, addrstr, fin, err := RunLocalUDPServer("udp", ":0", false, BlockWiseSzx16)
	if err != nil {
		b.Fatalf("unable to run test server: %v", err)
	}


@@ 525,7 526,7 @@ func BenchmarkServeBlockWise(b *testing.B) {
	HandleFunc("/test", EchoServer)
	defer HandleRemove("/test")

	s, addrstr, fin, err := RunLocalUDPServer("udp", ":0", true, BlockSzx1024)
	s, addrstr, fin, err := RunLocalUDPServer("udp", ":0", true, BlockWiseSzx1024)
	if err != nil {
		b.Fatalf("unable to run test server: %v", err)
	}


@@ 540,7 541,7 @@ func BenchmarkServeBlockWise(b *testing.B) {
	}
	defer co.Close()

	data := make([]byte, 65000)
	data := make([]byte, ^uint16(0))
	b.StartTimer()
	for i := uint32(0); i < uint32(b.N); i++ {
		_, err := co.Post("/test", TextPlain, &dataReader{data: data})


@@ 555,7 556,7 @@ func BenchmarkServeTCP(b *testing.B) {
	HandleFunc("/test", EchoServer)
	defer HandleRemove("/test")

	s, addrstr, fin, err := RunLocalTCPServer(":0", false, BlockSzx16)
	s, addrstr, fin, err := RunLocalTCPServer(":0", false, BlockWiseSzx16)
	if err != nil {
		b.Fatalf("unable to run test server: %v", err)
	}


@@ 570,7 571,7 @@ func BenchmarkServeTCP(b *testing.B) {
	}
	defer co.Close()

	data := make([]byte, 128)
	data := make([]byte, ^uint16(0))
	b.StartTimer()
	for i := uint32(0); i < uint32(b.N); i++ {
		_, err := co.Post("/test", TextPlain, &dataReader{data: data})


@@ 586,7 587,7 @@ func BenchmarkServeTCPBlockwise(b *testing.B) {
	defer HandleRemove("/test")

	BlockWiseTransfer := true
	BlockWiseTransferSzx := BlockSzx1024
	BlockWiseTransferSzx := BlockWiseSzxBERT

	s, addrstr, fin, err := RunLocalTCPServer(":0", BlockWiseTransfer, BlockWiseTransferSzx)
	if err != nil {


@@ 601,7 602,7 @@ func BenchmarkServeTCPBlockwise(b *testing.B) {
		Net:                  "tcp",
		BlockWiseTransfer:    &BlockWiseTransfer,
		BlockWiseTransferSzx: &BlockWiseTransferSzx,
		MaxMessageSize:       65000,
		MaxMessageSize:       ^uint32(0),
	}
	co, err := client.Dial(addrstr)
	if err != nil {


@@ 609,7 610,7 @@ func BenchmarkServeTCPBlockwise(b *testing.B) {
	}
	defer co.Close()

	data := make([]byte, 128)
	data := make([]byte, ^uint16(0))
	b.StartTimer()
	for i := uint32(0); i < uint32(b.N); i++ {
		_, err := co.Post("/test", TextPlain, &dataReader{data: data})


@@ 624,7 625,7 @@ func benchmarkServeTCPStreamWithMsg(b *testing.B, req *TcpMessage) {
	HandleFunc("/test", EchoServer)
	defer HandleRemove("/test")

	s, addrstr, fin, err := RunLocalTCPServer(":0", false, BlockSzx16)
	s, addrstr, fin, err := RunLocalTCPServer(":0", false, BlockWiseSzx16)
	if err != nil {
		b.Fatalf("unable to run test server: %v", err)
	}