|
|
- package ber
-
- import (
- "bytes"
- "fmt"
- "io"
- "reflect"
- "errors"
- )
-
- 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 = false
-
- func 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)
-
- if reader == nil {
- return errors.New("reader was nil, aborting")
- }
-
- 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 string(data)
- }
-
- 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
- }
|