| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 | package berimport (	"bytes"	"fmt"	"io"	"reflect")type Packet struct {	ClassType   uint8	TagType     uint8	Tag         uint8	Value       interface{}	ByteValue   []byte	Data        *bytes.Buffer	Children    []*Packet	Description string}const (	TagEOC              = 0x00	TagBoolean          = 0x01	TagInteger          = 0x02	TagBitString        = 0x03	TagOctetString      = 0x04	TagNULL             = 0x05	TagObjectIdentifier = 0x06	TagObjectDescriptor = 0x07	TagExternal         = 0x08	TagRealFloat        = 0x09	TagEnumerated       = 0x0a	TagEmbeddedPDV      = 0x0b	TagUTF8String       = 0x0c	TagRelativeOID      = 0x0d	TagSequence         = 0x10	TagSet              = 0x11	TagNumericString    = 0x12	TagPrintableString  = 0x13	TagT61String        = 0x14	TagVideotexString   = 0x15	TagIA5String        = 0x16	TagUTCTime          = 0x17	TagGeneralizedTime  = 0x18	TagGraphicString    = 0x19	TagVisibleString    = 0x1a	TagGeneralString    = 0x1b	TagUniversalString  = 0x1c	TagCharacterString  = 0x1d	TagBMPString        = 0x1e	TagBitmask          = 0x1f // xxx11111b)var TagMap = map[uint8]string{	TagEOC:              "EOC (End-of-Content)",	TagBoolean:          "Boolean",	TagInteger:          "Integer",	TagBitString:        "Bit String",	TagOctetString:      "Octet String",	TagNULL:             "NULL",	TagObjectIdentifier: "Object Identifier",	TagObjectDescriptor: "Object Descriptor",	TagExternal:         "External",	TagRealFloat:        "Real (float)",	TagEnumerated:       "Enumerated",	TagEmbeddedPDV:      "Embedded PDV",	TagUTF8String:       "UTF8 String",	TagRelativeOID:      "Relative-OID",	TagSequence:         "Sequence and Sequence of",	TagSet:              "Set and Set OF",	TagNumericString:    "Numeric String",	TagPrintableString:  "Printable String",	TagT61String:        "T61 String",	TagVideotexString:   "Videotex String",	TagIA5String:        "IA5 String",	TagUTCTime:          "UTC Time",	TagGeneralizedTime:  "Generalized Time",	TagGraphicString:    "Graphic String",	TagVisibleString:    "Visible String",	TagGeneralString:    "General String",	TagUniversalString:  "Universal String",	TagCharacterString:  "Character String",	TagBMPString:        "BMP String",}const (	ClassUniversal   = 0   // 00xxxxxxb	ClassApplication = 64  // 01xxxxxxb	ClassContext     = 128 // 10xxxxxxb	ClassPrivate     = 192 // 11xxxxxxb	ClassBitmask     = 192 // 11xxxxxxb)var ClassMap = map[uint8]string{	ClassUniversal:   "Universal",	ClassApplication: "Application",	ClassContext:     "Context",	ClassPrivate:     "Private",}const (	TypePrimitive   = 0  // xx0xxxxxb	TypeConstructed = 32 // xx1xxxxxb	TypeBitmask     = 32 // xx1xxxxxb)var TypeMap = map[uint8]string{	TypePrimitive:   "Primative",	TypeConstructed: "Constructed",}var Debug bool = falsefunc PrintBytes(buf []byte, indent string) {	data_lines := make([]string, (len(buf)/30)+1)	num_lines := make([]string, (len(buf)/30)+1)	for i, b := range buf {		data_lines[i/30] += fmt.Sprintf("%02x ", b)		num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)	}	for i := 0; i < len(data_lines); i++ {		fmt.Print(indent + data_lines[i] + "\n")		fmt.Print(indent + num_lines[i] + "\n\n")	}}func PrintPacket(p *Packet) {	printPacket(p, 0, false)}func printPacket(p *Packet, indent int, printBytes bool) {	indent_str := ""	for len(indent_str) != indent {		indent_str += " "	}	class_str := ClassMap[p.ClassType]	tagtype_str := TypeMap[p.TagType]	tag_str := fmt.Sprintf("0x%02X", p.Tag)	if p.ClassType == ClassUniversal {		tag_str = TagMap[p.Tag]	}	value := fmt.Sprint(p.Value)	description := ""	if p.Description != "" {		description = p.Description + ": "	}	fmt.Printf("%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value)	if printBytes {		PrintBytes(p.Bytes(), indent_str)	}	for _, child := range p.Children {		printPacket(child, indent+1, printBytes)	}}func resizeBuffer(in []byte, new_size uint64) (out []byte) {	out = make([]byte, new_size)	copy(out, in)	return}func readBytes(reader io.Reader, buf []byte) error {	idx := 0	buflen := len(buf)	for idx < buflen {		n, err := reader.Read(buf[idx:])		if err != nil {			return err		}		idx += n	}	return nil}func ReadPacket(reader io.Reader) (*Packet, error) {	buf := make([]byte, 2)	err := readBytes(reader, buf)	if err != nil {		return nil, err	}	idx := uint64(2)	datalen := uint64(buf[1])	if Debug {		fmt.Printf("Read: datalen = %d len(buf) = %d ", datalen, len(buf))		for _, b := range buf {			fmt.Printf("%02X ", b)		}		fmt.Printf("\n")	}	if datalen&128 != 0 {		a := datalen - 128		idx += a		buf = resizeBuffer(buf, 2+a)		err := readBytes(reader, buf[2:])		if err != nil {			return nil, err		}		datalen = DecodeInteger(buf[2 : 2+a])		if Debug {			fmt.Printf("Read: a = %d  idx = %d  datalen = %d  len(buf) = %d", a, idx, datalen, len(buf))			for _, b := range buf {				fmt.Printf("%02X ", b)			}			fmt.Printf("\n")		}	}	buf = resizeBuffer(buf, idx+datalen)	err = readBytes(reader, buf[idx:])	if err != nil {		return nil, err	}	if Debug {		fmt.Printf("Read: len( buf ) = %d  idx=%d datalen=%d idx+datalen=%d\n", len(buf), idx, datalen, idx+datalen)		for _, b := range buf {			fmt.Printf("%02X ", b)		}	}	p := DecodePacket(buf)	return p, nil}func DecodeString(data []byte) (ret string) {	for _, c := range data {		ret += fmt.Sprintf("%c", c)	}	return}func DecodeInteger(data []byte) (ret uint64) {	for _, i := range data {		ret = ret * 256		ret = ret + uint64(i)	}	return}func EncodeInteger(val uint64) []byte {	var out bytes.Buffer	found := false	shift := uint(56)	mask := uint64(0xFF00000000000000)	for mask > 0 {		if !found && (val&mask != 0) {			found = true		}		if found || (shift == 0) {			out.Write([]byte{byte((val & mask) >> shift)})		}		shift -= 8		mask = mask >> 8	}	return out.Bytes()}func DecodePacket(data []byte) *Packet {	p, _ := decodePacket(data)	return p}func decodePacket(data []byte) (*Packet, []byte) {	if Debug {		fmt.Printf("decodePacket: enter %d\n", len(data))	}	p := new(Packet)	p.ClassType = data[0] & ClassBitmask	p.TagType = data[0] & TypeBitmask	p.Tag = data[0] & TagBitmask	datalen := DecodeInteger(data[1:2])	datapos := uint64(2)	if datalen&128 != 0 {		datalen -= 128		datapos += datalen		datalen = DecodeInteger(data[2 : 2+datalen])	}	p.Data = new(bytes.Buffer)	p.Children = make([]*Packet, 0, 2)	p.Value = nil	value_data := data[datapos : datapos+datalen]	if p.TagType == TypeConstructed {		for len(value_data) != 0 {			var child *Packet			child, value_data = decodePacket(value_data)			p.AppendChild(child)		}	} else if p.ClassType == ClassUniversal {		p.Data.Write(data[datapos : datapos+datalen])		p.ByteValue = value_data		switch p.Tag {		case TagEOC:		case TagBoolean:			val := DecodeInteger(value_data)			p.Value = val != 0		case TagInteger:			p.Value = DecodeInteger(value_data)		case TagBitString:		case TagOctetString:			p.Value = DecodeString(value_data)		case TagNULL:		case TagObjectIdentifier:		case TagObjectDescriptor:		case TagExternal:		case TagRealFloat:		case TagEnumerated:			p.Value = DecodeInteger(value_data)		case TagEmbeddedPDV:		case TagUTF8String:		case TagRelativeOID:		case TagSequence:		case TagSet:		case TagNumericString:		case TagPrintableString:			p.Value = DecodeString(value_data)		case TagT61String:		case TagVideotexString:		case TagIA5String:		case TagUTCTime:		case TagGeneralizedTime:		case TagGraphicString:		case TagVisibleString:		case TagGeneralString:		case TagUniversalString:		case TagCharacterString:		case TagBMPString:		}	} else {		p.Data.Write(data[datapos : datapos+datalen])	}	return p, data[datapos+datalen:]}func (p *Packet) DataLength() uint64 {	return uint64(p.Data.Len())}func (p *Packet) Bytes() []byte {	var out bytes.Buffer	out.Write([]byte{p.ClassType | p.TagType | p.Tag})	packet_length := EncodeInteger(p.DataLength())	if p.DataLength() > 127 || len(packet_length) > 1 {		out.Write([]byte{byte(len(packet_length) | 128)})		out.Write(packet_length)	} else {		out.Write(packet_length)	}	out.Write(p.Data.Bytes())	return out.Bytes()}func (p *Packet) AppendChild(child *Packet) {	p.Data.Write(child.Bytes())	if len(p.Children) == cap(p.Children) {		newChildren := make([]*Packet, cap(p.Children)*2)		copy(newChildren, p.Children)		p.Children = newChildren[0:len(p.Children)]	}	p.Children = p.Children[0 : len(p.Children)+1]	p.Children[len(p.Children)-1] = child}func Encode(ClassType, TagType, Tag uint8, Value interface{}, Description string) *Packet {	p := new(Packet)	p.ClassType = ClassType	p.TagType = TagType	p.Tag = Tag	p.Data = new(bytes.Buffer)	p.Children = make([]*Packet, 0, 2)	p.Value = Value	p.Description = Description	if Value != nil {		v := reflect.ValueOf(Value)		if ClassType == ClassUniversal {			switch Tag {			case TagOctetString:				sv, ok := v.Interface().(string)				if ok {					p.Data.Write([]byte(sv))				}			}		}	}	return p}func NewSequence(Description string) *Packet {	return Encode(ClassUniversal, TypePrimitive, TagSequence, nil, Description)}func NewBoolean(ClassType, TagType, Tag uint8, Value bool, Description string) *Packet {	intValue := 0	if Value {		intValue = 1	}	p := Encode(ClassType, TagType, Tag, nil, Description)	p.Value = Value	p.Data.Write(EncodeInteger(uint64(intValue)))	return p}func NewInteger(ClassType, TagType, Tag uint8, Value uint64, Description string) *Packet {	p := Encode(ClassType, TagType, Tag, nil, Description)	p.Value = Value	p.Data.Write(EncodeInteger(Value))	return p}func NewString(ClassType, TagType, Tag uint8, Value, Description string) *Packet {	p := Encode(ClassType, TagType, Tag, nil, Description)	p.Value = Value	p.Data.Write([]byte(Value))	return p}
 |