diff options
-rw-r--r-- | ber.go | 566 |
1 files changed, 282 insertions, 284 deletions
@@ -3,19 +3,18 @@ package ber import ( "bytes" "fmt" - "io" - "os" + "io" "reflect" ) type Packet struct { - ClassType uint8 - TagType uint8 - Tag uint8 - Value interface{} - Data *bytes.Buffer - Children []*Packet - Description string + ClassType uint8 + TagType uint8 + Tag uint8 + Value interface{} + Data *bytes.Buffer + Children []*Packet + Description string } const ( @@ -51,211 +50,211 @@ const ( 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", +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 + 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", +var ClassMap = map[uint8]string{ + ClassUniversal: "Universal", + ClassApplication: "Application", + ClassContext: "Context", + ClassPrivate: "Private", } const ( - TypePrimative = 0 // xx0xxxxxb - TypeConstructed = 32 // xx1xxxxxb - TypeBitmask = 32 // xx1xxxxxb + TypePrimative = 0 // xx0xxxxxb + TypeConstructed = 32 // xx1xxxxxb + TypeBitmask = 32 // xx1xxxxxb ) -var TypeMap = map[uint8] string { - TypePrimative : "Primative", - TypeConstructed : "Constructed", +var TypeMap = map[uint8]string{ + TypePrimative: "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 ) +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, 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" ) - } + 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) { + printPacket(p, 0, false) } -func printPacket( p *Packet, indent int, printBytes bool ) { +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 ) + 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 ] - } + if p.ClassType == ClassUniversal { + tag_str = TagMap[p.Tag] + } - value := fmt.Sprint( p.Value ) - description := "" - if p.Description != "" { - description = p.Description + ": " - } + 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 ) + 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 ) - } + if printBytes { + PrintBytes(p.Bytes(), indent_str) + } - for _, child := range p.Children { - printPacket( child, indent + 1, printBytes ) - } + 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 resizeBuffer(in []byte, new_size uint64) (out []byte) { + out = make([]byte, new_size) + copy(out, in) + return } -func readBytes( reader io.Reader, buf []byte ) os.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 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, os.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 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 ) +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 { +func DecodeInteger(data []byte) (ret uint64) { + for _, i := range data { ret = ret * 256 ret = ret + uint64(i) } return } -func EncodeInteger( val uint64 ) []byte { +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 ) { + if !found && (val&mask != 0) { found = true } - if found || ( shift == 0 ) { - out.Write( []byte { byte( ( val & mask ) >> shift ) } ) + if found || (shift == 0) { + out.Write([]byte{byte((val & mask) >> shift)}) } shift -= 8 mask = mask >> 8 @@ -263,135 +262,135 @@ func EncodeInteger( val uint64 ) []byte { return out.Bytes() } -func DecodePacket( data []byte ) *Packet { - p, _ := decodePacket( data ) - return p +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] ) +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]) 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: + 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] ) - } + } else { + p.Data.Write(data[datapos : datapos+datalen]) + } - return p, data[ datapos + datalen: ] + return p, data[datapos+datalen:] } func (p *Packet) DataLength() uint64 { - return uint64( p.Data.Len() ) + 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 ) + 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(packet_length) } - out.Write( p.Data.Bytes() ) + 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 (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 ) +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 + p.Data = new(bytes.Buffer) + p.Children = make([]*Packet, 0, 2) + p.Value = Value + p.Description = Description if Value != nil { - v := reflect.NewValue(Value) + v := reflect.ValueOf(Value) - if ( ClassType == ClassUniversal ) { + if ClassType == ClassUniversal { switch Tag { - case TagOctetString: - sv, ok := v.Interface().(string) - if ok { - p.Data.Write( []byte(sv) ) - } + case TagOctetString: + sv, ok := v.Interface().(string) + if ok { + p.Data.Write([]byte(sv)) + } } } } @@ -399,33 +398,32 @@ func Encode( ClassType, TagType, Tag uint8, Value interface{}, Description strin return p } -func NewSequence( Description string) *Packet { - return Encode( ClassUniversal, TypePrimative, TagSequence, nil, Description ) +func NewSequence(Description string) *Packet { + return Encode(ClassUniversal, TypePrimative, TagSequence, nil, Description) } -func NewBoolean( ClassType, TagType, Tag uint8, Value bool, Description string ) *Packet { - intValue := 0 - if Value { - intValue = 1 - } +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 + 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 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 +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 } - |