1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 import "golang.org/x/net/internal/iana"
9 // multipartMessageBodyDataLen takes b as an original datagram and
10 // exts as extensions, and returns a required length for message body
11 // and a required length for a padded original datagram in wire
13 func multipartMessageBodyDataLen(proto int, withOrigDgram bool, b []byte, exts []Extension) (bodyLen, dataLen int) {
14 for _, ext := range exts {
15 bodyLen += ext.Len(proto)
19 dataLen = multipartMessageOrigDatagramLen(proto, b)
21 bodyLen += 4 // length of extension header
26 return bodyLen, dataLen
29 // multipartMessageOrigDatagramLen takes b as an original datagram,
30 // and returns a required length for a padded orignal datagram in wire
32 func multipartMessageOrigDatagramLen(proto int, b []byte) int {
33 roundup := func(b []byte, align int) int {
34 // According to RFC 4884, the padded original datagram
35 // field must contain at least 128 octets.
40 return (r + align - 1) & ^(align - 1)
43 case iana.ProtocolICMP:
45 case iana.ProtocolIPv6ICMP:
52 // marshalMultipartMessageBody takes data as an original datagram and
53 // exts as extesnsions, and returns a binary encoding of message body.
54 // It can be used for non-multipart message bodies when exts is nil.
55 func marshalMultipartMessageBody(proto int, withOrigDgram bool, data []byte, exts []Extension) ([]byte, error) {
56 bodyLen, dataLen := multipartMessageBodyDataLen(proto, withOrigDgram, data, exts)
57 b := make([]byte, 4+bodyLen)
61 b[dataLen+4] = byte(extensionVersion << 4)
62 off += 4 // length of object header
63 for _, ext := range exts {
64 switch ext := ext.(type) {
66 if err := ext.marshal(proto, b[off:]); err != nil {
71 attrs, l := ext.attrsAndLen(proto)
72 if err := ext.marshal(proto, b[off:], attrs, l); err != nil {
77 if err := ext.marshal(proto, b[off:]); err != nil {
83 s := checksum(b[dataLen+4:])
84 b[dataLen+4+2] ^= byte(s)
85 b[dataLen+4+3] ^= byte(s >> 8)
88 case iana.ProtocolICMP:
89 b[1] = byte(dataLen / 4)
90 case iana.ProtocolIPv6ICMP:
91 b[0] = byte(dataLen / 8)
98 // parseMultipartMessageBody parses b as either a non-multipart
99 // message body or a multipart message body.
100 func parseMultipartMessageBody(proto int, typ Type, b []byte) ([]byte, []Extension, error) {
103 case iana.ProtocolICMP:
105 case iana.ProtocolIPv6ICMP:
111 exts, l, err := parseExtensions(typ, b[4:], l)
117 data = make([]byte, l)
120 return data, exts, nil