From 497c919b06b6fc4adf780702d5ec4aab69d26184 Mon Sep 17 00:00:00 2001 From: free5gc-org Date: Tue, 28 Apr 2020 00:03:30 +0800 Subject: [PATCH 1/5] Init commit --- .gitignore | 15 + CHANGELOG.md | 9 + aper.go | 884 +++++++++++++++++++++++++++++++++++++++ aper_test.go | 1000 ++++++++++++++++++++++++++++++++++++++++++++ asn_type.go | 35 ++ common.go | 78 ++++ logger/logger.go | 49 +++ marshal.go | 774 ++++++++++++++++++++++++++++++++++ marshal_test.go | 254 +++++++++++ version/version.go | 7 + 10 files changed, 3105 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 aper.go create mode 100644 aper_test.go create mode 100644 asn_type.go create mode 100644 common.go create mode 100644 logger/logger.go create mode 100644 marshal.go create mode 100644 marshal_test.go create mode 100644 version/version.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05fa7d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Toolchain +# Goland project folder +.idea/ +# Visual Studio Code +.vscode/ +# emacs/vim +GPATH +GRTAGS +GTAGS +TAGS +tags +cscope.* +# mac +.DS_Store + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f465a20 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log +--- +2020-03-xx-xx +--- +- Implemented enchacements: + +- Fixed bugs: + +- Closed issues: diff --git a/aper.go b/aper.go new file mode 100644 index 0000000..3f2a18c --- /dev/null +++ b/aper.go @@ -0,0 +1,884 @@ +package aper + +import ( + "fmt" + "free5gc/lib/aper/logger" + "path" + "reflect" + "runtime" +) + +type perBitData struct { + bytes []byte + byteOffset uint64 + bitsOffset uint +} + +func perTrace(level int, s string) { + + _, file, line, ok := runtime.Caller(1) + if !ok { + logger.AperLog.Debugln(s) + } else { + logger.AperLog.Debugf("%s (%s:%d)\n", s, path.Base(file), line) + } +} + +func perBitLog(numBits uint64, byteOffset uint64, bitsOffset uint, value interface{}) string { + if reflect.TypeOf(value).Kind() == reflect.Uint64 { + return fmt.Sprintf(" [PER got %2d bits, byteOffset(after): %d, bitsOffset(after): %d, value: 0x%0x]", + numBits, byteOffset, bitsOffset, reflect.ValueOf(value).Uint()) + } + return fmt.Sprintf(" [PER got %2d bits, byteOffset(after): %d, bitsOffset(after): %d, value: 0x%0x]", + numBits, byteOffset, bitsOffset, reflect.ValueOf(value).Bytes()) + +} + +// GetBitString is to get BitString with desire size from source byte array with bit offset +func GetBitString(srcBytes []byte, bitsOffset uint, numBits uint) (dstBytes []byte, err error) { + bitsLeft := uint(len(srcBytes))*8 - bitsOffset + if numBits > bitsLeft { + err = fmt.Errorf("Get bits overflow, requireBits: %d, leftBits: %d", numBits, bitsLeft) + return + } + byteLen := (bitsOffset + numBits + 7) >> 3 + numBitsByteLen := (numBits + 7) >> 3 + dstBytes = make([]byte, numBitsByteLen) + numBitsMask := byte(0xff) + if modEight := numBits & 0x7; modEight != 0 { + numBitsMask <<= uint8(8 - (modEight)) + } + for i := 1; i < int(byteLen); i++ { + dstBytes[i-1] = srcBytes[i-1]<>(8-bitsOffset) + } + if byteLen == numBitsByteLen { + dstBytes[byteLen-1] = srcBytes[byteLen-1] << bitsOffset + } + dstBytes[numBitsByteLen-1] &= numBitsMask + return +} + +// GetFewBits is to get Value with desire few bits from source byte with bit offset +// func GetFewBits(srcByte byte, bitsOffset uint, numBits uint) (value uint64, err error) { + +// if numBits == 0 { +// value = 0 +// return +// } +// bitsLeft := 8 - bitsOffset +// if bitsLeft < numBits { +// err = fmt.Errorf("Get bits overflow, requireBits: %d, leftBits: %d", numBits, bitsLeft) +// return +// } +// if bitsOffset == 0 { +// value = uint64(srcByte >> (8 - numBits)) +// } else { +// value = uint64((srcByte << bitsOffset) >> (8 - numBits)) +// } +// return +// } + +// GetBitsValue is to get Value with desire bits from source byte array with bit offset +func GetBitsValue(srcBytes []byte, bitsOffset uint, numBits uint) (value uint64, err error) { + var dstBytes []byte + dstBytes, err = GetBitString(srcBytes, bitsOffset, numBits) + if err != nil { + return + } + for i, j := 0, numBits; j >= 8; i, j = i+1, j-8 { + value <<= 8 + value |= uint64(uint(dstBytes[i])) + } + if numBitsOff := uint(numBits & 0x7); numBitsOff != 0 { + var mask uint = (1 << numBitsOff) - 1 + value <<= numBitsOff + value |= uint64(uint(dstBytes[len(dstBytes)-1]>>(8-numBitsOff)) & mask) + } + return +} + +func (pd *perBitData) bitCarry() { + pd.byteOffset += uint64(pd.bitsOffset >> 3) + pd.bitsOffset = pd.bitsOffset & 0x07 +} + +func (pd *perBitData) getBitString(numBits uint) (dstBytes []byte, err error) { + + dstBytes, err = GetBitString(pd.bytes[pd.byteOffset:], pd.bitsOffset, numBits) + if err != nil { + return + } + pd.bitsOffset += uint(numBits) + + pd.bitCarry() + perTrace(1, perBitLog(uint64(numBits), pd.byteOffset, pd.bitsOffset, dstBytes)) + return +} + +func (pd *perBitData) getBitsValue(numBits uint) (value uint64, err error) { + value, err = GetBitsValue(pd.bytes[pd.byteOffset:], pd.bitsOffset, numBits) + if err != nil { + return + } + pd.bitsOffset += numBits + pd.bitCarry() + perTrace(1, perBitLog(uint64(numBits), pd.byteOffset, pd.bitsOffset, value)) + return +} + +func (pd *perBitData) parseAlignBits() error { + + if (pd.bitsOffset & 0x7) > 0 { + alignBits := 8 - ((pd.bitsOffset) & 0x7) + perTrace(2, fmt.Sprintf("Aligning %d bits", alignBits)) + if val, err := pd.getBitsValue(alignBits); err != nil { + return err + } else if val != 0 { + return fmt.Errorf("Align Bit is not zero") + } + } else if pd.bitsOffset != 0 { + pd.bitCarry() + } + return nil +} + +func (pd *perBitData) parseConstraintValue(valueRange int64) (value uint64, err error) { + perTrace(3, fmt.Sprintf("Getting Constraint Value with range %d", valueRange)) + + var bytes uint + if valueRange <= 255 { + if valueRange < 0 { + err = fmt.Errorf("Value range is negative") + return + } + var i uint + // 1 ~ 8 bits + for i = 1; i <= 8; i++ { + upper := 1 << i + if int64(upper) >= valueRange { + break + } + } + value, err = pd.getBitsValue(i) + return + } else if valueRange == 256 { + bytes = 1 + } else if valueRange <= 65536 { + bytes = 2 + } else { + err = fmt.Errorf("Constraint Value is large than 65536") + return + } + if err = pd.parseAlignBits(); err != nil { + return + } + value, err = pd.getBitsValue(bytes * 8) + return +} + +func (pd *perBitData) parseLength(sizeRange int64, repeat *bool) (value uint64, err error) { + *repeat = false + if sizeRange <= 65536 && sizeRange > 0 { + return pd.parseConstraintValue(sizeRange) + } + + if err = pd.parseAlignBits(); err != nil { + return + } + firstByte, err := pd.getBitsValue(8) + if err != nil { + return + } + if (firstByte & 128) == 0 { // #10.9.3.6 + value = firstByte & 0x7F + return + } else if (firstByte & 64) == 0 { // #10.9.3.7 + var secondByte uint64 + if secondByte, err = pd.getBitsValue(8); err != nil { + return + } + value = ((firstByte & 63) << 8) | secondByte + return + } + firstByte &= 63 + if firstByte < 1 || firstByte > 4 { + err = fmt.Errorf("Parse Length Out of Constraint") + return + } + *repeat = true + value = 16384 * firstByte + return +} + +func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (bitString BitString, err error) { + var lb, ub, sizeRange int64 = 0, -1, -1 + if !extensed { + if lowerBoundPtr != nil { + lb = *lowerBoundPtr + } + if upperBoundPtr != nil { + ub = *upperBoundPtr + sizeRange = ub - lb + 1 + } + } + if ub > 65535 { + sizeRange = -1 + } + // initailization + bitString = BitString{[]byte{}, 0} + // lowerbound == upperbound + if sizeRange == 1 { + sizes := uint64(ub+7) >> 3 + bitString.BitLength = uint64(ub) + perTrace(2, fmt.Sprintf("Decoding BIT STRING size %d", ub)) + if sizes > 2 { + if err = pd.parseAlignBits(); err != nil { + return + } + if (pd.byteOffset + sizes) > uint64(len(pd.bytes)) { + err = fmt.Errorf("PER data out of range") + return + } + bitString.Bytes = pd.bytes[pd.byteOffset : pd.byteOffset+sizes] + pd.byteOffset += sizes + pd.bitsOffset = uint(ub & 0x7) + if pd.bitsOffset > 0 { + pd.byteOffset-- + } + perTrace(1, perBitLog(uint64(ub), pd.byteOffset, pd.bitsOffset, bitString.Bytes)) + } else { + bitString.Bytes, err = pd.getBitString(uint(ub)) + } + perTrace(2, fmt.Sprintf("Decoded BIT STRING (length = %d): %0.8b", ub, bitString.Bytes)) + return + + } + repeat := false + for { + var rawLength uint64 + if rawLength, err = pd.parseLength(sizeRange, &repeat); err != nil { + return + } + rawLength += uint64(lb) + perTrace(2, fmt.Sprintf("Decoding BIT STRING size %d", rawLength)) + if rawLength == 0 { + return + } + sizes := (rawLength + 7) >> 3 + if err = pd.parseAlignBits(); err != nil { + return + } + + if (pd.byteOffset + sizes) > uint64(len(pd.bytes)) { + err = fmt.Errorf("PER data out of range") + return + } + bitString.Bytes = append(bitString.Bytes, pd.bytes[pd.byteOffset:pd.byteOffset+sizes]...) + bitString.BitLength += rawLength + pd.byteOffset += sizes + pd.bitsOffset = uint(rawLength & 0x7) + if pd.bitsOffset != 0 { + pd.byteOffset-- + } + perTrace(1, perBitLog(rawLength, pd.byteOffset, pd.bitsOffset, bitString.Bytes)) + perTrace(2, fmt.Sprintf("Decoded BIT STRING (length = %d): %0.8b", rawLength, bitString.Bytes)) + + if !repeat { + // if err = pd.parseAlignBits(); err != nil { + // return + // } + break + } + } + return +} +func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (octetString OctetString, err error) { + var lb, ub, sizeRange int64 = 0, -1, -1 + if !extensed { + if lowerBoundPtr != nil { + lb = *lowerBoundPtr + } + if upperBoundPtr != nil { + ub = *upperBoundPtr + sizeRange = ub - lb + 1 + } + } + if ub > 65535 { + sizeRange = -1 + } + // initailization + octetString = OctetString("") + // lowerbound == upperbound + if sizeRange == 1 { + perTrace(2, fmt.Sprintf("Decoding OCTET STRING size %d", ub)) + if ub > 2 { + unsignedUB := uint64(ub) + if err = pd.parseAlignBits(); err != nil { + return + } + if (int64(pd.byteOffset) + ub) > int64(len(pd.bytes)) { + err = fmt.Errorf("per data out of range") + return + } + octetString = pd.bytes[pd.byteOffset : pd.byteOffset+unsignedUB] + pd.byteOffset += uint64(ub) + perTrace(1, perBitLog(8*unsignedUB, pd.byteOffset, pd.bitsOffset, octetString)) + } else { + octetString, err = pd.getBitString(uint(ub * 8)) + } + perTrace(2, fmt.Sprintf("Decoded OCTET STRING (length = %d): 0x%0x", ub, octetString)) + return + + } + repeat := false + for { + var rawLength uint64 + if rawLength, err = pd.parseLength(sizeRange, &repeat); err != nil { + return + } + rawLength += uint64(lb) + perTrace(2, fmt.Sprintf("Decoding OCTET STRING size %d", rawLength)) + if rawLength == 0 { + return + } else if err = pd.parseAlignBits(); err != nil { + return + } + if (rawLength + pd.byteOffset) > uint64(len(pd.bytes)) { + err = fmt.Errorf("per data out of range ") + return + } + octetString = append(octetString, pd.bytes[pd.byteOffset:pd.byteOffset+rawLength]...) + pd.byteOffset += rawLength + perTrace(1, perBitLog(8*rawLength, pd.byteOffset, pd.bitsOffset, octetString)) + perTrace(2, fmt.Sprintf("Decoded OCTET STRING (length = %d): 0x%0x", rawLength, octetString)) + if !repeat { + // if err = pd.parseAlignBits(); err != nil { + // return + // } + break + } + } + return +} + +func (pd *perBitData) parseBool() (value bool, err error) { + perTrace(3, fmt.Sprintf("Decoding BOOLEAN Value")) + bit, err1 := pd.getBitsValue(1) + if err1 != nil { + err = err1 + return + } + if bit == 1 { + value = true + perTrace(2, fmt.Sprintf("Decoded BOOLEAN Value : ture")) + } else { + value = false + perTrace(2, fmt.Sprintf("Decoded BOOLEAN Value : false")) + } + return +} + +func (pd *perBitData) parseInteger(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (value int64, err error) { + var lb, ub, valueRange int64 = 0, -1, 0 + if !extensed { + if lowerBoundPtr == nil { + perTrace(3, fmt.Sprintf("Decoding INTEGER with Unconstraint Value")) + valueRange = -1 + } else { + lb = *lowerBoundPtr + if upperBoundPtr != nil { + ub = *upperBoundPtr + valueRange = ub - lb + 1 + perTrace(3, fmt.Sprintf("Decoding INTEGER with Value Range(%d..%d)", lb, ub)) + } else { + perTrace(3, fmt.Sprintf("Decoding INTEGER with Semi-Constraint Range(%d..)", lb)) + } + } + } else { + valueRange = -1 + perTrace(3, fmt.Sprintf("Decoding INTEGER with Extensive Value")) + } + var rawLength uint + if valueRange == 1 { + value = ub + return + } else if valueRange <= 0 { + // semi-constraint or unconstraint + if err = pd.parseAlignBits(); err != nil { + return + } + if pd.byteOffset >= uint64(len(pd.bytes)) { + err = fmt.Errorf("per data out of range") + return + } + rawLength = uint(pd.bytes[pd.byteOffset]) + pd.byteOffset++ + perTrace(1, perBitLog(8, pd.byteOffset, pd.bitsOffset, uint64(rawLength))) + } else if valueRange <= 65536 { + rawValue, err1 := pd.parseConstraintValue(valueRange) + if err1 != nil { + err = err1 + } else { + value = int64(rawValue) + lb + } + return + } else { + // valueRange > 65536 + var byteLen uint + unsignedValueRange := uint64(valueRange - 1) + for byteLen = 1; byteLen <= 127; byteLen++ { + unsignedValueRange >>= 8 + if unsignedValueRange == 0 { + break + } + } + var i, upper uint + // 1 ~ 8 bits + for i = 1; i <= 8; i++ { + upper = 1 << i + if upper >= byteLen { + break + } + } + if tempLength, err1 := pd.getBitsValue(i); err1 != nil { + err = err1 + return + } else { + rawLength = uint(tempLength) + } + rawLength++ + if err = pd.parseAlignBits(); err != nil { + return + } + } + perTrace(2, fmt.Sprintf("Decoding INTEGER Length with %d bytes", rawLength)) + var rawValue uint64 + if rawValue, err = pd.getBitsValue(rawLength * 8); err != nil { + return + } else if valueRange < 0 { + signedBitMask := uint64(1 << (rawLength*8 - 1)) + valueMask := signedBitMask - 1 + // negative + if rawValue&signedBitMask > 0 { + value = int64((^rawValue)&valueMask+1) * -1 + return + } + } + value = int64(rawValue) + lb + return + +} + +// parse ENUMERATED type but do not implement extensive value and different value with index +func (pd *perBitData) parseEnumerated(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (value uint64, err error) { + if extensed { + err = fmt.Errorf("Unsupport the extensive value of ENUMERATED ") + return + } + if lowerBoundPtr == nil || upperBoundPtr == nil { + err = fmt.Errorf("ENUMERATED value constraint is error ") + return + } + lb, ub := *lowerBoundPtr, *upperBoundPtr + valueRange := ub - lb + 1 + perTrace(2, fmt.Sprintf("Decoding ENUMERATED with Value Range(%d..%d)", lb, ub)) + if valueRange > 1 { + value, err = pd.parseConstraintValue(valueRange) + } + perTrace(2, fmt.Sprintf("Decoded ENUMERATED Value : %d", value)) + return + +} +func (pd *perBitData) parseSequenceOf(sizeExtensed bool, params fieldParameters, sliceType reflect.Type) (sliceContent reflect.Value, err error) { + var lb int64 = 0 + var sizeRange int64 + if params.sizeLowerBound != nil && *params.sizeLowerBound < 65536 { + lb = *params.sizeLowerBound + } + if !sizeExtensed && params.sizeUpperBound != nil && *params.sizeUpperBound < 65536 { + ub := *params.sizeUpperBound + sizeRange = ub - lb + 1 + perTrace(3, fmt.Sprintf("Decoding Length of \"SEQUENCE OF\" with Size Range(%d..%d)", lb, ub)) + } else { + sizeRange = -1 + perTrace(3, fmt.Sprintf("Decoding Length of \"SEQUENCE OF\" with Semi-Constraint Range(%d..)", lb)) + } + + var numElements uint64 + if sizeRange > 1 { + numElements, err = pd.parseConstraintValue(sizeRange) + numElements += uint64(lb) + } else if sizeRange == 1 { + numElements += uint64(lb) + } else { + if err = pd.parseAlignBits(); err != nil { + return + } + if pd.byteOffset >= uint64(len(pd.bytes)) { + err = fmt.Errorf("per data out of range") + return + } + numElements = uint64(pd.bytes[pd.byteOffset]) + pd.byteOffset++ + perTrace(1, perBitLog(8, pd.byteOffset, pd.bitsOffset, numElements)) + } + perTrace(2, fmt.Sprintf("Decoding \"SEQUENCE OF\" struct %s with len(%d)", sliceType.Elem().Name(), numElements)) + params.sizeExtensible = false + params.sizeUpperBound = nil + params.sizeLowerBound = nil + intNumElements := int(numElements) + sliceContent = reflect.MakeSlice(sliceType, intNumElements, intNumElements) + for i := 0; i < intNumElements; i++ { + err = parseField(sliceContent.Index(i), pd, params) + if err != nil { + return + } + } + return +} + +func (pd *perBitData) getChoiceIndex(extensed bool, upperBoundPtr *int64) (present int, err error) { + if extensed { + err = fmt.Errorf("Unsupport value of CHOICE type is in Extensed") + } else if upperBoundPtr == nil { + err = fmt.Errorf("The upper bound of CHIOCE is missing") + } else if ub := *upperBoundPtr; ub < 0 { + err = fmt.Errorf("The upper bound of CHIOCE is negative") + } else if rawChoice, err1 := pd.parseConstraintValue(ub + 1); err1 != nil { + err = err1 + } else { + perTrace(2, fmt.Sprintf("Decoded Present index of CHOICE is %d + 1", rawChoice)) + present = int(rawChoice) + 1 + } + return +} +func getReferenceFieldValue(v reflect.Value) (value int64, err error) { + fieldType := v.Type() + switch v.Kind() { + case reflect.Int, reflect.Int32, reflect.Int64: + value = v.Int() + case reflect.Struct: + if fieldType.Field(0).Name == "Present" { + present := int(v.Field(0).Int()) + if present == 0 { + err = fmt.Errorf("ReferenceField Value present is 0(present's field number)") + } else if present >= fieldType.NumField() { + err = fmt.Errorf("Present is bigger than number of struct field") + } else { + value, err = getReferenceFieldValue(v.Field(present)) + } + } else { + value, err = getReferenceFieldValue(v.Field(0)) + } + default: + err = fmt.Errorf("OpenType reference only support INTEGER") + } + return +} + +func (pd *perBitData) parseOpenType(v reflect.Value, params fieldParameters) (err error) { + + pdOpenType := &perBitData{[]byte(""), 0, 0} + repeat := false + for { + var rawLength uint64 + if rawLength, err = pd.parseLength(-1, &repeat); err != nil { + return + } + if rawLength == 0 { + break + } else if err = pd.parseAlignBits(); err != nil { + return + } + if (rawLength + pd.byteOffset) > uint64(len(pd.bytes)) { + err = fmt.Errorf("per data out of range ") + return + } + pdOpenType.bytes = append(pdOpenType.bytes, pd.bytes[pd.byteOffset:pd.byteOffset+rawLength]...) + pd.byteOffset += rawLength + + if !repeat { + if err = pd.parseAlignBits(); err != nil { + return + } + break + } + } + perTrace(2, fmt.Sprintf("Decoding OpenType %s with (len = %d byte)", v.Type().String(), len(pdOpenType.bytes))) + err = parseField(v, pdOpenType, params) + perTrace(2, fmt.Sprintf("Decoded OpenType %s", v.Type().String())) + return +} + +// parseField is the main parsing function. Given a byte slice and an offset +// into the array, it will try to parse a suitable ASN.1 value out and store it +// in the given Value. TODO : ObjectIdenfier, handle extension Field +func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err error) { + fieldType := v.Type() + + // If we have run out of data return error. + if pd.byteOffset == uint64(len(pd.bytes)) { + err = fmt.Errorf("sequence truncated") + return + } + if v.Kind() == reflect.Ptr { + ptr := reflect.New(fieldType.Elem()) + v.Set(ptr) + err = parseField(v.Elem(), pd, params) + return + } + sizeExtensible := false + valueExtensible := false + if params.sizeExtensible { + if bitsValue, err1 := pd.getBitsValue(1); err1 != nil { + return err1 + } else if bitsValue != 0 { + sizeExtensible = true + } + perTrace(2, fmt.Sprintf("Decoded Size Extensive Bit : %t", sizeExtensible)) + } + if params.valueExtensible && v.Kind() != reflect.Slice { + if bitsValue, err1 := pd.getBitsValue(1); err1 != nil { + return err1 + } else if bitsValue != 0 { + valueExtensible = true + } + perTrace(2, fmt.Sprintf("Decoded Value Extensive Bit : %t", valueExtensible)) + } + + // We deal with the structures defined in this package first. + switch fieldType { + case BitStringType: + bitString, err1 := pd.parseBitString(sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) + + if err1 != nil { + return err1 + } + v.Set(reflect.ValueOf(bitString)) + return + case ObjectIdentifierType: + err = fmt.Errorf("Unsupport ObjectIdenfier type") + return + case OctetStringType: + octetString, err1 := pd.parseOctetString(sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) + if err1 == nil { + v.Set(reflect.ValueOf(octetString)) + } + err = err1 + return + case EnumeratedType: + parsedEnum, err1 := pd.parseEnumerated(valueExtensible, params.valueLowerBound, params.valueUpperBound) + if err1 == nil { + v.SetUint(parsedEnum) + } + err = err1 + return + } + switch val := v; val.Kind() { + case reflect.Bool: + parsedBool, err1 := pd.parseBool() + if err1 == nil { + val.SetBool(parsedBool) + } + err = err1 + return + case reflect.Int, reflect.Int32, reflect.Int64: + parsedInt, err1 := pd.parseInteger(valueExtensible, params.valueLowerBound, params.valueUpperBound) + if err1 == nil { + val.SetInt(parsedInt) + perTrace(2, fmt.Sprintf("Decoded INTEGER Value : %d", parsedInt)) + } + err = err1 + return + + case reflect.Struct: + + structType := fieldType + var structParams []fieldParameters + var optionalCount uint + var optionalPresents uint64 + + // pass tag for optional + for i := 0; i < structType.NumField(); i++ { + if structType.Field(i).PkgPath != "" { + err = fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) + return + } + tempParams := parseFieldParameters(structType.Field(i).Tag.Get("aper")) + // for optional flag + if tempParams.optional { + optionalCount++ + } + structParams = append(structParams, tempParams) + } + + if optionalCount > 0 { + if optionalPresents, err = pd.getBitsValue(optionalCount); err != nil { + return + } + perTrace(2, fmt.Sprintf("optionalPresents is %0b", optionalPresents)) + } + + // CHOICE or OpenType + if structType.NumField() > 0 && structType.Field(0).Name == "Present" { + var present int = 0 + if params.openType { + if params.referenceFieldValue == nil { + err = fmt.Errorf("OpenType reference value is empty") + return + } + refValue := *params.referenceFieldValue + + for j, param := range structParams { + if j == 0 { + continue + } + if param.referenceFieldValue != nil && *param.referenceFieldValue == refValue { + present = j + break + } + } + if present == 0 { + err = fmt.Errorf("OpenType reference value does not match any field") + } else if present >= structType.NumField() { + err = fmt.Errorf("OpenType Present is bigger than number of struct field") + } else { + val.Field(0).SetInt(int64(present)) + perTrace(2, fmt.Sprintf("Decoded Present index of OpenType is %d ", present)) + err = pd.parseOpenType(val.Field(present), structParams[present]) + } + } else { + present, err = pd.getChoiceIndex(valueExtensible, params.valueUpperBound) + if err != nil { + logger.AperLog.Errorf("pd.getChoiceIndex Error") + } + val.Field(0).SetInt(int64(present)) + if present == 0 { + err = fmt.Errorf("CHOICE present is 0(present's field number)") + } else if present >= structType.NumField() { + err = fmt.Errorf("CHOICE Present is bigger than number of struct field") + } else { + err = parseField(val.Field(present), pd, structParams[present]) + } + } + return + + } + + for i := 0; i < structType.NumField(); i++ { + if structParams[i].optional && optionalCount > 0 { + optionalCount-- + if optionalPresents&(1<>3] + if pd.bitsOffset == 0 { + pd.bytes = append(pd.bytes, bytes...) + pd.bitsOffset = (numBits & 0x7) + perTrace(1, perRawBitLog(uint64(numBits), len(pd.bytes), pd.bitsOffset, bytes)) + return + } + bitsLeft := 8 - pd.bitsOffset + currentByte := len(pd.bytes) - 1 + if numBits <= bitsLeft { + pd.bytes[currentByte] |= (bytes[0] >> pd.bitsOffset) + } else { + bytes = append([]byte{0x00}, bytes...) + var shiftBytes []byte + if shiftBytes, err = GetBitString(bytes, bitsLeft, pd.bitsOffset+numBits); err != nil { + return + } + pd.bytes[currentByte] |= shiftBytes[0] + pd.bytes = append(pd.bytes, shiftBytes[1:]...) + bytes = bytes[1:] + } + pd.bitsOffset = (numBits & 0x7) + pd.bitsOffset + pd.bitCarry() + perTrace(1, perRawBitLog(uint64(numBits), len(pd.bytes), pd.bitsOffset, bytes)) + return +} + +func (pd *perRawBitData) putBitsValue(value uint64, numBits uint) (err error) { + if numBits == 0 { + return + } + Byteslen := (numBits + 7) >> 3 + tempBytes := make([]byte, Byteslen) + bitOff := numBits & 0x7 + if bitOff == 0 { + bitOff = 8 + } + LeftbitOff := 8 - bitOff + tempBytes[Byteslen-1] = byte((value << LeftbitOff) & 0xff) + value >>= bitOff + var i int + for i = int(Byteslen) - 2; value > 0; i-- { + if i < 0 { + err = fmt.Errorf("Bits Value is over capacity") + return + } + tempBytes[i] = byte(value & 0xff) + value >>= 8 + } + + err = pd.putBitString(tempBytes, numBits) + return +} + +func (pd *perRawBitData) appendConstraintValue(valueRange int64, value uint64) (err error) { + perTrace(3, fmt.Sprintf("Putting Constraint Value %d with range %d", value, valueRange)) + + var bytes uint + if valueRange <= 255 { + if valueRange < 0 { + err = fmt.Errorf("Value range is negative") + return + } + var i uint + // 1 ~ 8 bits + for i = 1; i <= 8; i++ { + upper := 1 << i + if int64(upper) >= valueRange { + break + } + } + err = pd.putBitsValue(value, i) + return + } else if valueRange == 256 { + bytes = 1 + } else if valueRange <= 65536 { + bytes = 2 + } else { + err = fmt.Errorf("Constraint Value is large than 65536") + return + } + pd.appendAlignBits() + err = pd.putBitsValue(value, bytes*8) + return +} + +func (pd *perRawBitData) appendLength(sizeRange int64, value uint64) (err error) { + if sizeRange <= 65536 && sizeRange > 0 { + return pd.appendConstraintValue(sizeRange, value) + } + pd.appendAlignBits() + perTrace(2, fmt.Sprintf("Putting Length of Value : %d", value)) + if value <= 127 { + err = pd.putBitsValue(value, 8) + return + } else if value <= 16383 { + value |= 0x8000 + err = pd.putBitsValue(value, 16) + return + } + + value = (value >> 14) | 0xc0 + err = pd.putBitsValue(value, 8) + return +} + +func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extensive bool, lowerBoundPtr *int64, upperBoundPtr *int64) (err error) { + var lb, ub, sizeRange int64 = 0, -1, -1 + if lowerBoundPtr != nil { + lb = *lowerBoundPtr + if upperBoundPtr != nil { + ub = *upperBoundPtr + if bitsLength <= uint64(ub) { + sizeRange = ub - lb + 1 + } else if !extensive { + err = fmt.Errorf("bitString Length is over upperbound") + return + } + if extensive { + perTrace(2, fmt.Sprintf("Putting size Extension Value")) + if sizeRange == -1 { + if err := pd.putBitsValue(1, 1); err != nil { + log.Printf("putBitsValue(1, 1) error: %v", err) + } + lb = 0 + } else { + if err := pd.putBitsValue(0, 1); err != nil { + log.Printf("putBitsValue(0, 1) error: %v", err) + } + } + } + + } + } + + if ub > 65535 { + sizeRange = -1 + } + sizes := (bitsLength + 7) >> 3 + shift := (8 - bitsLength&0x7) + if shift != 8 { + bytes[sizes-1] &= (0xff << shift) + } + + if sizeRange == 1 { + if bitsLength != uint64(ub) { + err = fmt.Errorf("bitString Length(%d) is not match fix-sized : %d", bitsLength, ub) + } + perTrace(2, fmt.Sprintf("Encoding BIT STRING size %d", ub)) + if sizes > 2 { + pd.appendAlignBits() + pd.bytes = append(pd.bytes, bytes...) + pd.bitsOffset = uint(ub & 0x7) + perTrace(1, perRawBitLog(bitsLength, len(pd.bytes), pd.bitsOffset, bytes)) + } else { + err = pd.putBitString(bytes, uint(bitsLength)) + } + perTrace(2, fmt.Sprintf("Encoded BIT STRING (length = %d): 0x%0x", bitsLength, bytes)) + return + } + rawLength := bitsLength - uint64(lb) + + var byteOffset, partOfRawLength uint64 + for { + if rawLength > 65536 { + partOfRawLength = 65536 + } else if rawLength >= 16384 { + partOfRawLength = rawLength & 0xc000 + } else { + partOfRawLength = rawLength + } + if err = pd.appendLength(sizeRange, partOfRawLength); err != nil { + return + } + partOfRawLength += uint64(lb) + sizes := (partOfRawLength + 7) >> 3 + perTrace(2, fmt.Sprintf("Encoding BIT STRING size %d", partOfRawLength)) + if partOfRawLength == 0 { + return + } + pd.appendAlignBits() + pd.bytes = append(pd.bytes, bytes[byteOffset:byteOffset+sizes]...) + perTrace(1, perRawBitLog(partOfRawLength, len(pd.bytes), pd.bitsOffset, bytes)) + perTrace(2, fmt.Sprintf("Encoded BIT STRING (length = %d): 0x%0x", partOfRawLength, bytes[byteOffset:byteOffset+sizes])) + rawLength -= (partOfRawLength - uint64(lb)) + if rawLength > 0 { + byteOffset += sizes + } else { + pd.bitsOffset += uint(partOfRawLength & 0x7) + // pd.appendAlignBits() + break + } + } + return + +} + +func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBoundPtr *int64, upperBoundPtr *int64) (err error) { + byteLen := uint64(len(bytes)) + var lb, ub, sizeRange int64 = 0, -1, -1 + if lowerBoundPtr != nil { + lb = *lowerBoundPtr + if upperBoundPtr != nil { + ub = *upperBoundPtr + if byteLen <= uint64(ub) { + sizeRange = ub - lb + 1 + } else if !extensive { + err = fmt.Errorf("OctetString Length is over upperbound") + return + } + if extensive { + perTrace(2, fmt.Sprintf("Putting size Extension Value")) + if sizeRange == -1 { + if err := pd.putBitsValue(1, 1); err != nil { + log.Printf("putBitsValue(1, 1) err: %v", err) + } + lb = 0 + } else { + if err := pd.putBitsValue(0, 1); err != nil { + log.Printf("putBitsValue(0, 1) err: %v", err) + } + } + } + + } + } + + if ub > 65535 { + sizeRange = -1 + } + + if sizeRange == 1 { + if byteLen != uint64(ub) { + err = fmt.Errorf("OctetString Length(%d) is not match fix-sized : %d", byteLen, ub) + } + perTrace(2, fmt.Sprintf("Encoding OCTET STRING size %d", ub)) + if byteLen > 2 { + pd.appendAlignBits() + pd.bytes = append(pd.bytes, bytes...) + perTrace(1, perRawBitLog(byteLen*8, len(pd.bytes), 0, bytes)) + } else { + err = pd.putBitString(bytes, uint(byteLen*8)) + } + perTrace(2, fmt.Sprintf("Encoded OCTET STRING (length = %d): 0x%0x", byteLen, bytes)) + return + } + rawLength := byteLen - uint64(lb) + + var byteOffset, partOfRawLength uint64 + for { + if rawLength > 65536 { + partOfRawLength = 65536 + } else if rawLength >= 16384 { + partOfRawLength = rawLength & 0xc000 + } else { + partOfRawLength = rawLength + } + if err = pd.appendLength(sizeRange, partOfRawLength); err != nil { + return + } + partOfRawLength += uint64(lb) + perTrace(2, fmt.Sprintf("Encoding OCTET STRING size %d", partOfRawLength)) + if partOfRawLength == 0 { + return + } + pd.appendAlignBits() + pd.bytes = append(pd.bytes, bytes[byteOffset:byteOffset+partOfRawLength]...) + perTrace(1, perRawBitLog(partOfRawLength*8, len(pd.bytes), pd.bitsOffset, bytes)) + perTrace(2, fmt.Sprintf("Encoded OCTET STRING (length = %d): 0x%0x", partOfRawLength, bytes[byteOffset:byteOffset+partOfRawLength])) + rawLength -= (partOfRawLength - uint64(lb)) + if rawLength > 0 { + byteOffset += partOfRawLength + } else { + // pd.appendAlignBits() + break + } + } + return + +} + +func (pd *perRawBitData) appendBool(value bool) (err error) { + perTrace(3, fmt.Sprintf("Encoding BOOLEAN Value %t", value)) + if value { + err = pd.putBitsValue(1, 1) + perTrace(2, fmt.Sprintf("Encoded BOOLEAN Value : 0x1")) + } else { + err = pd.putBitsValue(0, 1) + perTrace(2, fmt.Sprintf("Encoded BOOLEAN Value : 0x0")) + } + return +} + +func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPtr *int64, upperBoundPtr *int64) (err error) { + var lb, valueRange int64 = 0, 0 + if lowerBoundPtr != nil { + lb = *lowerBoundPtr + if value < lb { + err = fmt.Errorf("INTEGER value is smaller than lowerbound") + return + } + if upperBoundPtr != nil { + ub := *upperBoundPtr + if value <= ub { + valueRange = ub - lb + 1 + } else if !extensive { + err = fmt.Errorf("INTEGER value is larger than upperbound") + return + } + if extensive { + perTrace(2, fmt.Sprintf("Putting value Extension bit")) + if valueRange == 0 { + perTrace(3, fmt.Sprintf("Encoding INTEGER with Unconstraint Value")) + valueRange = -1 + if err := pd.putBitsValue(1, 1); err != nil { + fmt.Printf("pd.putBitsValue(1, 1) error: %v", err) + } + } else { + perTrace(3, fmt.Sprintf("Encoding INTEGER with Value Range(%d..%d)", lb, ub)) + if err := pd.putBitsValue(0, 1); err != nil { + fmt.Printf("pd.putBitsValue(0, 1) error: %v", err) + } + } + } + + } else { + perTrace(3, fmt.Sprintf("Encoding INTEGER with Semi-Constraint Range(%d..)", lb)) + } + } else { + perTrace(3, fmt.Sprintf("Encoding INTEGER with Unconstraint Value")) + valueRange = -1 + } + + unsignedValue := uint64(value) + var rawLength uint + if valueRange == 1 { + perTrace(2, fmt.Sprintf("Value of INTEGER is fixed")) + + return + } + if value < 0 { + y := value >> 63 + unsignedValue = uint64(((value ^ y) - y)) - 1 + } + if valueRange <= 0 { + unsignedValue >>= 7 + } else if valueRange <= 65536 { + err = pd.appendConstraintValue(valueRange, uint64(value-lb)) + return + } else { + unsignedValue >>= 8 + } + for rawLength = 1; rawLength <= 127; rawLength++ { + if unsignedValue == 0 { + break + } + unsignedValue >>= 8 + } + // putting length + if valueRange <= 0 { + // semi-constraint or unconstraint + pd.appendAlignBits() + pd.bytes = append(pd.bytes, byte(rawLength)) + perTrace(2, fmt.Sprintf("Encoding INTEGER Length %d in one byte", rawLength)) + + perTrace(1, perRawBitLog(8, len(pd.bytes), pd.bitsOffset, uint64(rawLength))) + } else { + // valueRange > 65536 + var byteLen uint + unsignedValueRange := uint64(valueRange - 1) + for byteLen = 1; byteLen <= 127; byteLen++ { + unsignedValueRange >>= 8 + if unsignedValueRange <= 1 { + break + } + } + var i, upper uint + // 1 ~ 8 bits + for i = 1; i <= 8; i++ { + upper = 1 << i + if upper >= byteLen { + break + } + } + perTrace(2, fmt.Sprintf("Encoding INTEGER Length %d-1 in %d bits", rawLength, i)) + if err = pd.putBitsValue(uint64(rawLength-1), i); err != nil { + return + } + } + perTrace(2, fmt.Sprintf("Encoding INTEGER %d with %d bytes", value, rawLength)) + + rawLength *= 8 + pd.appendAlignBits() + + if valueRange < 0 { + mask := int64(1< ub { + if extensive { + err = fmt.Errorf("Unsupport the extensive value of ENUMERATED ") + } else { + err = fmt.Errorf("ENUMERATED value is larger than upperbound") + } + return + } else if signedValue < lb { + err = fmt.Errorf("ENUMERATED value is smaller than lowerbound") + return + } + if extensive { + if err = pd.putBitsValue(0, 1); err != nil { + return + } + } + + valueRange := ub - lb + 1 + perTrace(2, fmt.Sprintf("Encoding ENUMERATED Value : %d with Value Range(%d..%d)", value, lb, ub)) + if valueRange > 1 { + err = pd.appendConstraintValue(valueRange, value) + } + return + +} + +func (pd *perRawBitData) parseSequenceOf(v reflect.Value, params fieldParameters) (err error) { + var lb, ub, sizeRange int64 = 0, -1, -1 + numElements := int64(v.Len()) + if params.sizeLowerBound != nil && *params.sizeLowerBound < 65536 { + lb = *params.sizeLowerBound + } + if params.sizeUpperBound != nil && *params.sizeUpperBound < 65536 { + ub = *params.sizeUpperBound + if params.sizeExtensible { + if numElements > ub { + err = pd.putBitsValue(1, 1) + } else { + err = pd.putBitsValue(0, 1) + sizeRange = ub - lb + 1 + } + } else if numElements > ub { + err = fmt.Errorf("SEQUENCE OF Size is larger than upperbound") + } else { + sizeRange = ub - lb + 1 + } + if err != nil { + return + } + + } else { + sizeRange = -1 + } + + if numElements < lb { + err = fmt.Errorf("SEQUENCE OF Size is lower than lowerbound") + } else if sizeRange == 1 { + perTrace(3, fmt.Sprintf("Encoding Length of \"SEQUENCE OF\" with fix-size %d", ub)) + if numElements != ub { + err = fmt.Errorf("Encoding Length %d != fix-size %d", numElements, ub) + } + } else if sizeRange > 0 { + perTrace(3, fmt.Sprintf("Encoding Length(%d) of \"SEQUENCE OF\" with Size Range(%d..%d)", numElements, lb, ub)) + err = pd.appendConstraintValue(sizeRange, uint64(numElements-lb)) + } else { + perTrace(3, fmt.Sprintf("Encoding Length(%d) of \"SEQUENCE OF\" with Semi-Constraint Range(%d..)", numElements, lb)) + pd.appendAlignBits() + pd.bytes = append(pd.bytes, byte(numElements&0xff)) + perTrace(1, perRawBitLog(8, len(pd.bytes), pd.bitsOffset, uint64(numElements))) + } + if err != nil { + return + } + perTrace(2, fmt.Sprintf("Encoding \"SEQUENCE OF\" struct %s with len(%d)", v.Type().Elem().Name(), numElements)) + params.sizeExtensible = false + params.sizeUpperBound = nil + params.sizeLowerBound = nil + for i := 0; i < v.Len(); i++ { + err = pd.makeField(v.Index(i), params) + if err != nil { + return + } + } + return +} + +func (pd *perRawBitData) appendChoiceIndex(present int, extensive bool, upperBoundPtr *int64) (err error) { + var ub int64 + rawChoice := present - 1 + if upperBoundPtr == nil { + err = fmt.Errorf("The upper bound of CHIOCE is missing") + } else if ub = *upperBoundPtr; ub < 0 { + err = fmt.Errorf("The upper bound of CHIOCE is negative") + } else if extensive && rawChoice > int(ub) { + err = fmt.Errorf("Unsupport value of CHOICE type is in Extensed") + } + if err != nil { + return + } + perTrace(2, fmt.Sprintf("Encoding Present index of CHOICE %d - 1", present)) + err = pd.appendConstraintValue(ub+1, uint64(rawChoice)) + return +} + +func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) (err error) { + + pdOpenType := &perRawBitData{[]byte(""), 0} + perTrace(2, fmt.Sprintf("Encoding OpenType %s to temp RawData", v.Type().String())) + if err = pdOpenType.makeField(v, params); err != nil { + return + } + openTypeBytes := pdOpenType.bytes + rawLength := uint64(len(pdOpenType.bytes)) + perTrace(2, fmt.Sprintf("Encoding OpenType %s RawData : 0x%0x(%d bytes)", v.Type().String(), pdOpenType.bytes, rawLength)) + + var byteOffset, partOfRawLength uint64 + for { + if rawLength > 65536 { + partOfRawLength = 65536 + } else if rawLength >= 16384 { + partOfRawLength = rawLength & 0xc000 + } else { + partOfRawLength = rawLength + } + if err = pd.appendLength(-1, partOfRawLength); err != nil { + return + } + perTrace(2, fmt.Sprintf("Encoding Part of OpenType RawData size %d", partOfRawLength)) + if partOfRawLength == 0 { + return + } + pd.appendAlignBits() + pd.bytes = append(pd.bytes, openTypeBytes[byteOffset:byteOffset+partOfRawLength]...) + perTrace(1, perRawBitLog(partOfRawLength*8, len(pd.bytes), pd.bitsOffset, openTypeBytes)) + perTrace(2, fmt.Sprintf("Encoded OpenType RawData (length = %d): 0x%0x", partOfRawLength, openTypeBytes[byteOffset:byteOffset+partOfRawLength])) + rawLength -= partOfRawLength + if rawLength > 0 { + byteOffset += partOfRawLength + } else { + pd.appendAlignBits() + break + } + } + + perTrace(2, fmt.Sprintf("Encoded OpenType %s", v.Type().String())) + return +} +func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err error) { + if !v.IsValid() { + return fmt.Errorf("aper: cannot marshal nil value") + } + // If the field is an interface{} then recurse into it. + if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { + return pd.makeField(v.Elem(), params) + } + if v.Kind() == reflect.Ptr { + return pd.makeField(v.Elem(), params) + } + fieldType := v.Type() + + // We deal with the structures defined in this package first. + switch fieldType { + case BitStringType: + err = pd.appendBitString(v.Field(0).Bytes(), v.Field(1).Uint(), params.sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) + return + case ObjectIdentifierType: + err = fmt.Errorf("Unsupport ObjectIdenfier type") + return + case OctetStringType: + err = pd.appendOctetString(v.Bytes(), params.sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) + return + case EnumeratedType: + err = pd.appendEnumerated(v.Uint(), params.valueExtensible, params.valueLowerBound, params.valueUpperBound) + return + } + switch val := v; val.Kind() { + case reflect.Bool: + err = pd.appendBool(v.Bool()) + return + case reflect.Int, reflect.Int32, reflect.Int64: + err = pd.appendInteger(v.Int(), params.valueExtensible, params.valueLowerBound, params.valueUpperBound) + return + + case reflect.Struct: + + structType := fieldType + var structParams []fieldParameters + var optionalCount uint + var optionalPresents uint64 + var sequenceType bool + // struct extensive TODO: support extensed type + if params.valueExtensible { + perTrace(2, fmt.Sprintf("Encoding Value Extensive Bit : %t", false)) + if err = pd.putBitsValue(0, 1); err != nil { + return + } + } + sequenceType = (structType.NumField() <= 0 || structType.Field(0).Name != "Present") + // pass tag for optional + for i := 0; i < structType.NumField(); i++ { + if structType.Field(i).PkgPath != "" { + err = fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) + return + } + tempParams := parseFieldParameters(structType.Field(i).Tag.Get("aper")) + if sequenceType { + + // for optional flag + if tempParams.optional { + optionalCount++ + optionalPresents <<= 1 + if !v.Field(i).IsNil() { + optionalPresents++ + } + } else if v.Field(i).Type().Kind() == reflect.Ptr && v.Field(i).IsNil() { + err = fmt.Errorf("nil element in SEQUENCE type") + } + } + + structParams = append(structParams, tempParams) + } + if optionalCount > 0 { + perTrace(2, fmt.Sprintf("putting optional(%d), optionalPresents is %0b", optionalCount, optionalPresents)) + if err = pd.putBitsValue(optionalPresents, optionalCount); err != nil { + return + } + } + + // CHOICE or OpenType + if !sequenceType { + present := int(v.Field(0).Int()) + if present == 0 { + err = fmt.Errorf("CHOICE or OpenType present is 0(present's field number)") + } else if present >= structType.NumField() { + err = fmt.Errorf("Present is bigger than number of struct field") + } else if params.openType { + if params.referenceFieldValue == nil { + err = fmt.Errorf("OpenType reference value is empty") + return + } + refValue := *params.referenceFieldValue + + if structParams[present].referenceFieldValue == nil || *structParams[present].referenceFieldValue != refValue { + err = fmt.Errorf("reference value and present reference value is not match") + return + } + perTrace(2, fmt.Sprintf("Encoding Present index of OpenType is %d ", present)) + err = pd.appendOpenType(val.Field(present), structParams[present]) + } else { + err = pd.appendChoiceIndex(present, params.valueExtensible, params.valueUpperBound) + + if err != nil { + return + } + err = pd.makeField(val.Field(present), structParams[present]) + } + return + + } + + for i := 0; i < structType.NumField(); i++ { + // optional + if structParams[i].optional && optionalCount > 0 { + optionalCount-- + if optionalPresents&(1< Date: Sun, 24 May 2020 20:52:50 +0000 Subject: [PATCH 2/5] v2020-05-25-01 --- logger/logger.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/logger/logger.go b/logger/logger.go index 63be0ea..a6aa8ae 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -6,6 +6,9 @@ import ( "os" "runtime" "strings" + + "free5gc/lib/logger_conf" + "free5gc/lib/logger_util" ) var log *logrus.Logger @@ -35,6 +38,16 @@ func init() { }, } + free5gcLogHook, err := logger_util.NewFileHook(logger_conf.Free5gcLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) + if err == nil { + log.Hooks.Add(free5gcLogHook) + } + + selfLogHook, err := logger_util.NewFileHook(logger_conf.LibLogDir+"aper.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) + if err == nil { + log.Hooks.Add(selfLogHook) + } + AperLog = log.WithFields(logrus.Fields{"aper": "aper"}) } From bfb191960c4117a8ebb7a4258990af19e9f332a9 Mon Sep 17 00:00:00 2001 From: free5gc-org Date: Tue, 21 Jul 2020 04:51:49 +0000 Subject: [PATCH 3/5] v2020-07-21-01 --- aper_test.go | 1000 ----------------------------------------------- marshal_test.go | 254 ------------ 2 files changed, 1254 deletions(-) delete mode 100644 aper_test.go delete mode 100644 marshal_test.go diff --git a/aper_test.go b/aper_test.go deleted file mode 100644 index cf7bc55..0000000 --- a/aper_test.go +++ /dev/null @@ -1,1000 +0,0 @@ -package aper - -import ( - "fmt" - "free5gc/lib/aper/logger" - "reflect" - "strings" - "testing" -) - -var perTestTraceLevel = 2 - -func perTestTrace(level int, s string) { - if level <= perTestTraceLevel { - logger.AperLog.Traceln(s) - } -} - -type testData struct { - in []byte - Out interface{} -} - -// TEST BIT STRING - -// BitStringTest1 is for no constraint -type BitStringTest1 struct { - BitString BitString -} - -var bitStringTest1Data = []BitStringTest1{ - {BitString{[]byte{0xd4, 0xa5, 0x4a}, 23}}, - {BitString{[]byte{0xd4, 0xa5, 0x4b}, 24}}, - {BitString{[]byte{0x1f, 0xd4, 0xa5, 0x7f}, 32}}, -} - -// BitStringTest2 is for (lmin=lmax) < 17 -type BitStringTest2 struct { - BitString BitString `aper:"sizeLB:15,sizeUB:15"` -} - -var bitStringTest2Data = []BitStringTest2{ - {BitString{[]byte{0xaa, 0x56}, 15}}, - {BitString{[]byte{0xab, 0xd6}, 15}}, -} - -// BitStringTest3 is for 17 <= (lmin=lmax) <= 65536 -type BitStringTest3 struct { - BitString BitString `aper:"sizeLB:20,sizeUB:20"` -} - -var bitStringTest3Data = []BitStringTest3{ - {BitString{[]byte{0xff, 0x5e, 0xb0}, 20}}, -} - -// the following is for lmax != min - -// BitStringTest4 is for 2 <= (lmax-lmin+1) <= 255 -type BitStringTest4 struct { - BitString BitString `aper:"sizeLB:1,sizeUB:160"` -} - -var bitStringTest4Data = []BitStringTest4{ - {BitString{[]byte{0x56, 0x2a, 0xdf}, 24}}, - {BitString{[]byte{0xd1}, 8}}, -} - -// BitStringTest5 is for (lmax-lmin+1) == 256 -type BitStringTest5 struct { - BitString BitString `aper:"sizeLB:0,sizeUB:255"` -} - -var bitStringTest5Data = []BitStringTest5{ - {BitString{[]byte{0xf5, 0x5e, 0xb0}, 20}}, - {BitString{[]byte{0xf5, 0x5f, 0xff, 0x58}, 29}}, -} - -// BitStringTest6 is for 257 <= (lmax-lmin+1) <= 65536 -type BitStringTest6 struct { - BitString BitString `aper:"sizeLB:0,sizeUB:355"` -} - -var bitStringTest6Data = []BitStringTest6{ - {BitString{[]byte{0xff, 0x5e, 0xb0}, 20}}, - {BitString{[]byte{0xf5, 0x5f, 0xff, 0x58}, 29}}, - {BitString{[]byte{0xd4, 0xa5, 0x4b}, 24}}, - {BitString{[]byte{0xb2}, 7}}, -} - -// BitStringTest7 is for 65535 <= lmax -type BitStringTest7 struct { - BitString BitString `aper:"sizeLB:0,sizeUB:333333"` -} - -var bitStringTest7Data = []BitStringTest7{ - {BitString{[]byte{0xd4, 0xa5, 0x4a}, 23}}, - {BitString{[]byte{0xd4, 0xa5, 0x4b}, 24}}, - {BitString{[]byte{0x1f, 0xd4, 0xa5, 0x7f}, 32}}, - {BitString{[]byte(strings.Repeat("ab", 6000) + "cd"), 96016}}, -} - -// BitStringTest8 is for extensed data -type BitStringTest8 struct { - BitString BitString `aper:"sizeExt,sizeLB:1,sizeUB:1"` -} - -var bitStringTest8Data = []BitStringTest8{ - {BitString{[]byte{0x12, 0x3a, 0xaa}, 24}}, - {BitString{[]byte{0x80}, 1}}, -} - -var bigData = "\xC4" + strings.Repeat("ab", 4096) + "\xC1" + strings.Repeat("ab", 1024) + "\xb7\x10" + strings.Repeat("ab", 880) + "cd" - -var singleBitStringTestData = []testData{ - {[]byte{0x17, 0xD4, 0xA5, 0x4A}, bitStringTest1Data[0]}, - {[]byte{0x18, 0xD4, 0xA5, 0x4B}, bitStringTest1Data[1]}, - {[]byte{0x20, 0x1F, 0xD4, 0xA5, 0x7F}, bitStringTest1Data[2]}, - {[]byte{0xAA, 0x56}, bitStringTest2Data[0]}, - {[]byte{0xAB, 0xd6}, bitStringTest2Data[1]}, - {[]byte{0xFF, 0x5E, 0xB0}, bitStringTest3Data[0]}, - {[]byte{0x17, 0x56, 0x2a, 0xdf}, bitStringTest4Data[0]}, - {[]byte{0x07, 0xd1}, bitStringTest4Data[1]}, - {[]byte{0x14, 0xF5, 0x5E, 0xB0}, bitStringTest5Data[0]}, - {[]byte{0x1D, 0xF5, 0x5F, 0xFF, 0x58}, bitStringTest5Data[1]}, - {[]byte{0x00, 0x14, 0xFF, 0x5E, 0xB0}, bitStringTest6Data[0]}, - {[]byte{0x00, 0x1D, 0xF5, 0x5F, 0xFF, 0x58}, bitStringTest6Data[1]}, - {[]byte{0x00, 0x18, 0xD4, 0xA5, 0x4B}, bitStringTest6Data[2]}, - {[]byte{0x00, 0x07, 0xB2}, bitStringTest6Data[3]}, - {[]byte{0x17, 0xD4, 0xA5, 0x4A}, bitStringTest7Data[0]}, - {[]byte{0x18, 0xD4, 0xA5, 0x4B}, bitStringTest7Data[1]}, - {[]byte{0x20, 0x1F, 0xD4, 0xA5, 0x7F}, bitStringTest7Data[2]}, - {[]byte(bigData), bitStringTest7Data[3]}, - {[]byte{0x80, 0x18, 0x12, 0x3A, 0xAA}, bitStringTest8Data[0]}, - {[]byte{0x40}, bitStringTest8Data[1]}, -} - -func TestSingleBitString(t *testing.T) { - - for i, test := range singleBitStringTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - perTestTrace(2, fmt.Sprintf(" out.Bytes : %0x, out.BitsLength: %d", out.Elem().Field(0).Field(0).Bytes(), out.Elem().Field(0).Field(1).Uint())) - perTestTrace(2, fmt.Sprintf(" exp.Bytes : %0x, exp.BitsLength: %d", reflect.ValueOf(test.Out).Field(0).Field(0).Bytes(), reflect.ValueOf(test.Out).Field(0).Field(1).Uint())) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -type BitStringStructTest1 struct { - BitString1 BitString `aper:"sizeLB:3,sizeUB:3"` - BitString2 BitString `aper:"sizeLB:3,sizeUB:3"` -} - -var BitStringStructTest1Data = []BitStringStructTest1{ - {BitString{[]byte{0xa0}, 3}, BitString{[]byte{0xa0}, 3}}, -} - -type BitStringStructTest2 struct { - BitString1 BitString `aper:"sizeLB:3,sizeUB:3"` - BitString2 BitString `aper:"sizeLB:4,sizeUB:4"` -} - -var BitStringStructTest2Data = []BitStringStructTest2{ - {BitString{[]byte{0xa0}, 3}, BitString{[]byte{0xb0}, 4}}, -} - -type BitStringStructTest3 struct { - BitString1 BitString `aper:"sizeLB:3,sizeUB:3"` - BitString2 BitString `aper:"sizeLB:0,sizeUB:125"` - BitString3 BitString `aper:"sizeLB:0,sizeUB:255"` - BitString4 BitString `aper:"sizeLB:0,sizeUB:555"` -} - -var BitStringStructTest3Data = []BitStringStructTest3{ - {BitString{[]byte{0xa0}, 3}, BitString{[]byte{0xfe}, 8}, BitString{[]byte{0xec}, 6}, BitString{[]byte{0xd8}, 5}}, -} - -var structBitStringTestData = []testData{ - {[]byte{0xB4}, BitStringStructTest1Data[0]}, - {[]byte{0xB6}, BitStringStructTest2Data[0]}, - {[]byte{0xA2, 0x00, 0xFE, 0x06, 0xEC, 0x00, 0x05, 0xD8}, BitStringStructTest3Data[0]}, -} - -func TestStructBitString(t *testing.T) { - - for i, test := range structBitStringTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - - for j := 0; j < reflect.TypeOf(out.Elem().Interface()).NumField(); j++ { - perTestTrace(2, fmt.Sprintf(" out.Bytes : %0x, out.BitsLength: %d", out.Elem().Field(j).Field(0).Bytes(), out.Elem().Field(j).Field(1).Uint())) - perTestTrace(2, fmt.Sprintf(" exp.Bytes : %0x, exp.BitsLength: %d", reflect.ValueOf(test.Out).Field(j).Field(0).Bytes(), reflect.ValueOf(test.Out).Field(j).Field(1).Uint())) - } - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -// TEST OCTET STRING - -// oCTETStringTest1 is for no constraint -type oCTETStringTest1 struct { - OctetString OctetString -} - -var oCTETStringTest1Data = []oCTETStringTest1{ - {OctetString("free5GC")}, - {OctetString("\x23\x34\x52\x97")}, - {OctetString("Jennifer")}, -} - -// oCTETStringTest2 is for (lmin=lmax) < 3 -type oCTETStringTest2 struct { - OctetString OctetString `aper:"sizeLB:2,sizeUB:2"` -} - -var oCTETStringTest2Data = []oCTETStringTest2{ - {OctetString("\xaa\x56")}, - {OctetString("\x43\x12")}, -} - -// oCTETStringTest3 is for 3 <= (lmin=lmax) <= 65536 -type oCTETStringTest3 struct { - OctetString OctetString `aper:"sizeLB:20,sizeUB:20"` -} - -var oCTETStringTest3Data = []oCTETStringTest3{ - {OctetString("LLpRB9oV8zOkfraw1Nf5")}, -} - -// the following is for lmax != min - -// oCTETStringTest4 is for 2 <= (lmax-lmin+1) <= 255 -type oCTETStringTest4 struct { - OctetString OctetString `aper:"sizeLB:1,sizeUB:160"` -} - -var oCTETStringTest4Data = []oCTETStringTest4{ - {OctetString("LLpRB9oV8zOkfraw1Nf5")}, - {OctetString("1yYPj2WH4Uzex3sU40P1Kq7SgDB2sz0Ksg7fA76zcI5pxVDWtkUrfPti95h7xkzWpAcLaU7fMBBIJ981")}, -} - -// oCTETStringTest5 is for (lmax-lmin+1) == 256 -type oCTETStringTest5 struct { - OctetString OctetString `aper:"sizeLB:0,sizeUB:255"` -} - -var oCTETStringTest5Data = []oCTETStringTest5{ - {OctetString("LLpRB9oV8zOkfraw1Nf5")}, - {OctetString("cGUpp6MH*7@55mntftf$k@eVdd3k2-*dVbGt?BmdTvTvs#ee9cktn6uA5u2g@cvE955P4rUqReG$Ybd83YY?r5DqTYqrwDtHzeX+tFVK5RkBmns3GFhU9rPtX-eRfh62+Mmdeav2UFRy$wNghwSm?8RpeqBZTe8W-3Yfm#n=NR..r@z6BRXGAX.DMz34ad@-N8Xy-V9AkC-6kPU*Yh$MW7+m-$B6e32!WCCeFe?d-QyV+@z#vKy6meZN87bV2hd")}, -} - -// oCTETStringTest6 is for 257 <= (lmax-lmin+1) <= 65536 -type oCTETStringTest6 struct { - OctetString OctetString `aper:"sizeLB:0,sizeUB:355"` -} - -var oCTETStringTest6Data = []oCTETStringTest6{ - {OctetString("I!nGUXiqNpCP&a")}, - {OctetString("u^YlZwgYxf7swQqweqw")}, - {OctetString("iClFlb&YgrS4basdas")}, - {OctetString("wirelab")}, -} - -// oCTETStringTest7 is for extensed data -type oCTETStringTest7 struct { - OctetString OctetString `aper:"sizeExt,sizeLB:1,sizeUB:1"` -} - -var oCTETStringTest7Data = []oCTETStringTest7{ - {OctetString("a")}, - {OctetString("free5GC")}, -} - -// oCTETStringTest8 is for 65537 <= (lmax-lmin+1) -type oCTETStringTest8 struct { - OctetString OctetString `aper:"sizeLB:0,sizeUB:343434"` -} - -var bigOctetData = "\xC4" + strings.Repeat("ab", 32768) + "\xB8\x82" + strings.Repeat("ab", 7232) + "cd" - -var oCTETStringTest8Data = []oCTETStringTest8{ - {OctetString("I!nGUXiqNpCP&a")}, - {OctetString(strings.Repeat("ab", 40000) + "cd")}, -} - -var singleOctetStringTestData = []testData{ - {[]byte("\x07free5GC"), oCTETStringTest1Data[0]}, - {[]byte("\x04\x23\x34\x52\x97"), oCTETStringTest1Data[1]}, - {[]byte("\x08Jennifer"), oCTETStringTest1Data[2]}, - {[]byte("\xaa\x56"), oCTETStringTest2Data[0]}, - {[]byte("\x43\x12"), oCTETStringTest2Data[1]}, - {[]byte("LLpRB9oV8zOkfraw1Nf5"), oCTETStringTest3Data[0]}, - {[]byte("\x13LLpRB9oV8zOkfraw1Nf5"), oCTETStringTest4Data[0]}, - {[]byte("O1yYPj2WH4Uzex3sU40P1Kq7SgDB2sz0Ksg7fA76zcI5pxVDWtkUrfPti95h7xkzWpAcLaU7fMBBIJ981"), oCTETStringTest4Data[1]}, - {[]byte("\x14LLpRB9oV8zOkfraw1Nf5"), oCTETStringTest5Data[0]}, - {[]byte("\xFFcGUpp6MH*7@55mntftf$k@eVdd3k2-*dVbGt?BmdTvTvs#ee9cktn6uA5u2g@cvE955P4rUqReG$Ybd83YY?r5DqTYqrwDtHzeX+tFVK5RkBmns3GFhU9rPtX-eRfh62+Mmdeav2UFRy$wNghwSm?8RpeqBZTe8W-3Yfm#n=NR..r@z6BRXGAX.DMz34ad@-N8Xy-V9AkC-6kPU*Yh$MW7+m-$B6e32!WCCeFe?d-QyV+@z#vKy6meZN87bV2hd"), oCTETStringTest5Data[1]}, - {[]byte("\x00\x0EI!nGUXiqNpCP&a"), oCTETStringTest6Data[0]}, - {[]byte("\x00\x13u^YlZwgYxf7swQqweqw"), oCTETStringTest6Data[1]}, - {[]byte("\x00\x12iClFlb&YgrS4basdas"), oCTETStringTest6Data[2]}, - {[]byte("\x00\x07wirelab"), oCTETStringTest6Data[3]}, - {[]byte("\x30\x80"), oCTETStringTest7Data[0]}, - {[]byte("\x80\x07free5GC"), oCTETStringTest7Data[1]}, - {[]byte("\x0EI!nGUXiqNpCP&a"), oCTETStringTest8Data[0]}, - {[]byte(bigOctetData), oCTETStringTest8Data[1]}, -} - -func TestSingleOctetString(t *testing.T) { - - for i, test := range singleOctetStringTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - perTestTrace(2, fmt.Sprintf(" out : %0x, len : %d", out.Elem().Field(0).Bytes(), len(out.Elem().Field(0).Bytes()))) - perTestTrace(2, fmt.Sprintf(" exp : %0x, len : %d", reflect.ValueOf(test.Out).Field(0).Bytes(), len(reflect.ValueOf(test.Out).Field(0).Bytes()))) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -type oCTETStringStructTest1 struct { - OctetString1 OctetString `aper:"sizeExt,sizeLB:1,sizeUB:1"` - OctetString2 OctetString `aper:"sizeLB:0,sizeUB:20"` - OctetString3 OctetString `aper:"sizeLB:2,sizeUB:2"` -} - -var oCTETStringStructTest1Data = []oCTETStringStructTest1{ - {OctetString("a"), OctetString("bcd"), OctetString("ef")}, - {OctetString("a"), OctetString("abcdefgh"), OctetString("ij")}, - {OctetString("a"), OctetString(""), OctetString("bc")}, -} - -type oCTETStringStructTest2 struct { - OctetString1 OctetString `aper:"sizeExt,sizeLB:1,sizeUB:1"` - OctetString3 OctetString `aper:"sizeLB:2,sizeUB:2"` - OctetString2 OctetString `aper:"sizeLB:0,sizeUB:20"` -} - -var oCTETStringStructTest2Data = []oCTETStringStructTest2{ - {OctetString("a"), OctetString("bc"), OctetString("de")}, - {OctetString("a"), OctetString("34"), OctetString("5678")}, - {OctetString("a"), OctetString("12"), OctetString("")}, -} - -var structOctetStringTestData = []testData{ - {[]byte("\x30\x8Cbcdef"), oCTETStringStructTest1Data[0]}, - {[]byte("\x30\xA0abcdefghij"), oCTETStringStructTest1Data[1]}, - {[]byte("\x30\x81\x89\x8C"), oCTETStringStructTest1Data[2]}, - {[]byte("\x30\xB1\x31\x88de"), oCTETStringStructTest2Data[0]}, - {[]byte("\x30\x99\x9A\x105678"), oCTETStringStructTest2Data[1]}, - {[]byte("\x30\x98\x99\x00"), oCTETStringStructTest2Data[2]}, -} - -func TestStructOctetString(t *testing.T) { - for i, test := range structOctetStringTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - - for j := 0; j < reflect.TypeOf(out.Elem().Interface()).NumField(); j++ { - perTestTrace(2, fmt.Sprintf(" out : %0x, len : %d", out.Elem().Field(j).Bytes(), len(out.Elem().Field(j).Bytes()))) - perTestTrace(2, fmt.Sprintf(" exp : %0x, len : %d", reflect.ValueOf(test.Out).Field(j).Bytes(), len(reflect.ValueOf(test.Out).Field(j).Bytes()))) - } - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - } -} - -// TEST INTEGER - -// value is unconstraint -type intTest1 struct { - Value int64 -} - -var intTest1Data = []intTest1{ - {3}, - {333333}, - {-333333}, -} - -// value is definite -type intTest2 struct { - Value int64 `aper:"valueLB:3,valueUB:3"` -} - -var intTest2Data = []intTest2{ - {3}, -} - -// 2 <= bmax-bmin <= 255 -type intTest3 struct { - Value int64 `aper:"valueLB:1,valueUB:110"` -} - -var intTest3Data = []intTest3{ - {11}, - {13}, - {28}, - {110}, -} - -// bmax-bmin == 256 -type intTest4 struct { - Value int64 `aper:"valueLB:0,valueUB:255"` -} - -var intTest4Data = []intTest4{ - {140}, -} - -// 257 <= bmax-bmin <= 65536 -type intTest5 struct { - Value int64 `aper:"valueLB:0,valueUB:65535"` -} - -var intTest5Data = []intTest5{ - {140}, -} - -// 65537 <= bmax-bmin -type intTest6 struct { - Value int64 `aper:"valueLB:0,valueUB:4294967295"` -} - -var intTest6Data = []intTest6{ - {140}, - {4294967295}, - {65535}, - {65536}, -} - -// value extensed -type intTest7 struct { - Value int64 `aper:"valueExt,valueLB:0,valueUB:45"` -} - -var intTest7Data = []intTest7{ - {140}, - {2147483647}, - {65535}, - {65536}, - {33}, -} - -var integerTestData = []testData{ - {[]byte{0x01, 0x03}, intTest1Data[0]}, - {[]byte{0x03, 0x05, 0x16, 0x15}, intTest1Data[1]}, - {[]byte{0x03, 0xFA, 0xE9, 0xEB}, intTest1Data[2]}, - {[]byte{0x00}, intTest2Data[0]}, - {[]byte{0x14}, intTest3Data[0]}, - {[]byte{0x18}, intTest3Data[1]}, - {[]byte{0x36}, intTest3Data[2]}, - {[]byte{0xDA}, intTest3Data[3]}, - {[]byte{0x8C}, intTest4Data[0]}, - {[]byte{0x00, 0x8C}, intTest5Data[0]}, - {[]byte{0x00, 0x8C}, intTest6Data[0]}, - {[]byte{0xC0, 0xFF, 0xFF, 0xFF, 0xFF}, intTest6Data[1]}, - {[]byte{0x40, 0xFF, 0xFF}, intTest6Data[2]}, - {[]byte{0x80, 0x01, 0x00, 0x00}, intTest6Data[3]}, - {[]byte{0x80, 0x02, 0x00, 0x8C}, intTest7Data[0]}, - {[]byte{0x80, 0x04, 0x7F, 0xFF, 0xFF, 0xFF}, intTest7Data[1]}, - {[]byte{0x80, 0x03, 0x00, 0xFF, 0xFF}, intTest7Data[2]}, - {[]byte{0x80, 0x03, 0x01, 0x00, 0x00}, intTest7Data[3]}, - {[]byte{0x42}, intTest7Data[4]}, -} - -func TestSingleInteger(t *testing.T) { - for i, test := range integerTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - perTestTrace(2, fmt.Sprintf(" out : %0d", out.Elem().Field(0).Int())) - perTestTrace(2, fmt.Sprintf(" exp : %0d", reflect.ValueOf(test.Out).Field(0).Int())) - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -type intStructTest1 struct { - Int1 int64 `aper:"valueLB:1,valueUB:110"` - Int2 int64 `aper:"valueLB:0,valueUB:255"` - Int3 int64 `aper:"valueExt,valueLB:0,valueUB:45"` -} - -var intStructTest1Data = []intStructTest1{ - {45, 123, 6445}, -} - -var integerStructTestData = []testData{ - {[]byte{0x58, 0x7B, 0x80, 0x02, 0x19, 0x2D}, intStructTest1Data[0]}, -} - -func TestStructInteger(t *testing.T) { - for i, test := range integerStructTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - for j := 0; j < reflect.TypeOf(out.Elem().Interface()).NumField(); j++ { - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - perTestTrace(2, fmt.Sprintf(" out : %0d", out.Elem().Field(j).Int())) - perTestTrace(2, fmt.Sprintf(" exp : %0d", reflect.ValueOf(test.Out).Field(j).Int())) - } - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -// TEST ENUMERATED - -// value is unconstraint -type enumTest1 struct { - Value Enumerated `aper:"valueLB:0,valueUB:3"` -} - -var enumTest1Data = []enumTest1{ - {0}, - {1}, -} - -// value is definite -type enumTest2 struct { - Value Enumerated `aper:"valueExt,valueLB:0,valueUB:4"` -} - -var enumTest2Data = []enumTest2{ - {1}, - {2}, -} - -var enumTestData = []testData{ - {[]byte{0x00}, enumTest1Data[0]}, - {[]byte{0x40}, enumTest1Data[1]}, - {[]byte{0x10}, enumTest2Data[0]}, - {[]byte{0x20}, enumTest2Data[1]}, -} - -func TestSingleEnum(t *testing.T) { - for i, test := range enumTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - perTestTrace(2, fmt.Sprintf(" out : %0d", out.Elem().Field(0).Uint())) - perTestTrace(2, fmt.Sprintf(" exp : %0d", reflect.ValueOf(test.Out).Field(0).Uint())) - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -// TEST POINTER - -type ptrTest1 struct { - Ptr *intTest1 -} - -var ptrTest1Data = []ptrTest1{ - {&intTest1Data[0]}, - {&intTest1Data[1]}, - {&intTest1Data[2]}, -} - -type ptrTest2 struct { - Ptr *intTest2 -} - -var ptrTest2Data = []ptrTest2{ - {&intTest2Data[0]}, -} - -type ptrTest3 struct { - Ptr *intTest3 -} - -var ptrTest3Data = []ptrTest3{ - {&intTest3Data[0]}, -} - -type ptrTest4 struct { - Ptr *intTest4 -} - -var ptrTest4Data = []ptrTest4{ - {&intTest4Data[0]}, -} - -var ptrTestData = []testData{ - {[]byte{0x01, 0x03}, ptrTest1Data[0]}, - {[]byte{0x03, 0x05, 0x16, 0x15}, ptrTest1Data[1]}, - {[]byte{0x03, 0xFA, 0xE9, 0xEB}, ptrTest1Data[2]}, - {[]byte{0x00}, ptrTest2Data[0]}, - {[]byte{0x14}, ptrTest3Data[0]}, - {[]byte{0x8C}, ptrTest4Data[0]}, -} - -func TestSinglePtr(t *testing.T) { - for i, test := range ptrTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - perTestTrace(2, fmt.Sprintf(" out : %0d", out.Elem().Field(0).Elem().Field(0).Int())) - perTestTrace(2, fmt.Sprintf(" exp : %0d", reflect.ValueOf(test.Out).Field(0).Elem().Field(0).Int())) - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -// TEST SEQUENCE OF -type seqofTest1 struct { - List []intTest1 `aper:"sizeLB:0,sizeUB:3"` -} - -var seqofTest1Data = []seqofTest1{ - {intTest1Data}, -} - -type seqofTest2 struct { - List []intStructTest1 `aper:"sizeLB:0,sizeUB:30"` -} - -var seqofTest2Data = []seqofTest2{ - {intStructTest1Data}, -} - -type seqofTest3 struct { - List []BitStringStructTest3 `aper:"sizeLB:0,sizeUB:50"` -} - -var seqofTest3Data = []seqofTest3{ - {BitStringStructTest3Data}, -} - -type seqofTest4 struct { - List []intTest7 `aper:"sizeLB:0,sizeUB:16"` -} - -var seqofTest4Data = []seqofTest4{ - {intTest7Data}, -} - -type seqofTest5 struct { - List []intTest3 `aper:"sizeLB:0,sizeUB:255"` -} - -var seqofTest5Data = []seqofTest5{ - {intTest3Data}, -} - -type seqofTest6 struct { - List []intTest3 -} - -var seqofTest6Data = []seqofTest6{ - {intTest3Data}, -} - -type seqofTest7 struct { - List []intTest3 `aper:"sizeLB:4,sizeUB:4"` -} - -var seqofTest7Data = []seqofTest7{ - {intTest3Data}, -} - -var seqofTestData = []testData{ - {[]byte{0xC0, 0x01, 0x03, 0x03, 0x05, 0x16, 0x15, 0x03, 0xFA, 0xE9, 0xEB}, seqofTest1Data[0]}, - {[]byte{0x0A, 0xC0, 0x7B, 0x80, 0x02, 0x19, 0x2D}, seqofTest2Data[0]}, - {[]byte{0x06, 0x88, 0xFE, 0x06, 0xEC, 0x00, 0x05, 0xD8}, seqofTest3Data[0]}, - {[]byte("\x2C\x02\x00\x8C\x80\x04\x7F\xFF\xFF\xFF\x80\x03\x00\xFF\xFF\x80\x03\x01\x00\x00\x42"), seqofTest4Data[0]}, - {[]byte{0x04, 0x14, 0x30, 0xDE, 0xD0}, seqofTest5Data[0]}, - {[]byte{0x04, 0x14, 0x30, 0xDE, 0xD0}, seqofTest6Data[0]}, - {[]byte{0x14, 0x30, 0xDE, 0xD0}, seqofTest7Data[0]}, -} - -func TestSingleSequenceOf(t *testing.T) { - for i, test := range seqofTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - for j := 0; j < out.Elem().Field(0).Len(); j++ { - perTestTrace(2, fmt.Sprintf(" out : %v", out.Elem().Field(0).Index(j))) - perTestTrace(2, fmt.Sprintf(" exp : %v", reflect.ValueOf(test.Out).Field(0).Index(j))) - } - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -// TEST CHOICE -type choiceTest1 struct { - Choice choiceStruct `aper:"valueLB:0,valueUB:2"` -} -type choiceStruct struct { - Present int - List1 []intTest1 `aper:"sizeLB:0,sizeUB:3"` - List2 []intStructTest1 `aper:"sizeLB:0,sizeUB:30"` - List3 []BitStringStructTest3 `aper:"sizeLB:0,sizeUB:50"` -} - -var choiceTest1Data = []choiceTest1{ - {choiceStruct{1, intTest1Data, nil, nil}}, - {choiceStruct{2, nil, intStructTest1Data, nil}}, - {choiceStruct{3, nil, nil, BitStringStructTest3Data}}, -} - -type choiceTest2 struct { - Choice choiceStruct `aper:"valueExt,valueLB:0,valueUB:2"` -} - -var choiceTest2Data = []choiceTest2{ - {choiceStruct{3, nil, nil, BitStringStructTest3Data}}, -} - -var choiceTestData = []testData{ - {[]byte{0x30, 0x01, 0x03, 0x03, 0x05, 0x16, 0x15, 0x03, 0xFA, 0xE9, 0xEB}, choiceTest1Data[0]}, - {[]byte{0x42, 0xB0, 0x7B, 0x80, 0x02, 0x19, 0x2D}, choiceTest1Data[1]}, - {[]byte{0x81, 0xA2, 0x00, 0xFE, 0x06, 0xEC, 0x00, 0x05, 0xD8}, choiceTest1Data[2]}, - {[]byte{0x40, 0xD1, 0x00, 0xFE, 0x06, 0xEC, 0x00, 0x05, 0xD8}, choiceTest2Data[0]}, -} - -func TestChoice(t *testing.T) { - for i, test := range choiceTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - - perTestTrace(2, fmt.Sprintf(" out : %v", out.Elem().Field(0))) - perTestTrace(2, fmt.Sprintf(" exp : %v", reflect.ValueOf(test.Out).Field(0))) - - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -// TEST PrintableString -type printableStringStructTest1 struct { - PrintableString1 string `aper:"sizeExt,sizeLB:1,sizeUB:1"` - PrintableString2 string `aper:"sizeLB:0,sizeUB:20"` - PrintableString3 string `aper:"sizeLB:2,sizeUB:2"` -} - -var printableStringStructTest1Data = []printableStringStructTest1{ - {"a", "bcd", "ef"}, - {"a", "abcdefgh", "ij"}, - {"a", "", "bc"}, -} - -type printableStringStructTest2 struct { - PrintableString1 string `aper:"sizeExt,sizeLB:1,sizeUB:1"` - PrintableString2 string `aper:"sizeLB:2,sizeUB:2"` - PrintableString3 string `aper:"sizeLB:0,sizeUB:20"` -} - -var printableStringStructTest2Data = []printableStringStructTest2{ - {"a", "bc", "de"}, - {"a", "34", "5678"}, - {"a", "12", ""}, -} - -var printableStringStructTestData = []testData{ - {[]byte("\x30\x8Cbcdef"), printableStringStructTest1Data[0]}, - {[]byte("\x30\xA0abcdefghij"), printableStringStructTest1Data[1]}, - {[]byte("\x30\x81\x89\x8C"), printableStringStructTest1Data[2]}, - {[]byte("\x30\xB1\x31\x88de"), printableStringStructTest2Data[0]}, - {[]byte("\x30\x99\x9A\x105678"), printableStringStructTest2Data[1]}, - {[]byte("\x30\x98\x99\x00"), printableStringStructTest2Data[2]}, -} - -func TestStructPrintableString(t *testing.T) { - for i, test := range printableStringStructTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - - for j := 0; j < reflect.TypeOf(out.Elem().Interface()).NumField(); j++ { - perTestTrace(2, fmt.Sprintf(" out : %s, len : %d", out.Elem().Field(j).String(), len(out.Elem().Field(j).String()))) - perTestTrace(2, fmt.Sprintf(" exp : %s, len : %d", reflect.ValueOf(test.Out).Field(j).String(), len(reflect.ValueOf(test.Out).Field(j).String()))) - } - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - } -} - -// TEST Open Type -type openTypeTest1 struct { - ID int64 `aper:"valueLB:0,valueUB:255"` - Value openTypeStruct `aper:"openType,referenceFieldName:ID"` -} -type openTypeStruct struct { - Present int - List1 []intTest1 `aper:"sizeLB:0,sizeUB:3,referenceFieldValue:2"` - List2 []intStructTest1 `aper:"sizeLB:0,sizeUB:30,referenceFieldValue:3"` - List3 []BitStringStructTest3 `aper:"sizeLB:0,sizeUB:50,referenceFieldValue:5"` -} - -var openTypeTest1Data = []openTypeTest1{ - {2, openTypeStruct{1, intTest1Data, nil, nil}}, - {3, openTypeStruct{2, nil, intStructTest1Data, nil}}, - {5, openTypeStruct{3, nil, nil, BitStringStructTest3Data}}, -} - -var openTypeTestData = []testData{ - {[]byte{0x02, 0x0B, 0xC0, 0x01, 0x03, 0x03, 0x05, 0x16, 0x15, 0x03, 0xFA, 0xE9, 0xEB}, openTypeTest1Data[0]}, - {[]byte{0x03, 0x07, 0x0A, 0xC0, 0x7B, 0x80, 0x02, 0x19, 0x2D}, openTypeTest1Data[1]}, - {[]byte{0x05, 0x08, 0x06, 0x88, 0xFE, 0x06, 0xEC, 0x00, 0x05, 0xD8}, openTypeTest1Data[2]}, -} - -func TestOpenType(t *testing.T) { - for i, test := range openTypeTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - - perTestTrace(2, fmt.Sprintf(" out : %v", out.Elem())) - perTestTrace(2, fmt.Sprintf(" exp : %v", reflect.ValueOf(test.Out))) - - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -// BOOLEAN TEST -type boolTest1 struct { - Value bool -} - -var boolTest1Data = []boolTest1{ - {false}, - {true}, -} - -var boolTestData = []testData{ - {[]byte{0x00}, boolTest1Data[0]}, - {[]byte{0x80}, boolTest1Data[1]}, -} - -func TestSingleBoolean(t *testing.T) { - for i, test := range boolTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - perTestTrace(2, fmt.Sprintf(" out : %t", out.Elem().Field(0).Bool())) - perTestTrace(2, fmt.Sprintf(" exp : %t", reflect.ValueOf(test.Out).Field(0).Bool())) - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -type optionalTest1 struct { - OctetString1 *OctetString `aper:"sizeExt,sizeLB:1,sizeUB:16,optional"` - BitString2 BitString `aper:"sizeLB:2,sizeUB:5"` - Int3 int64 `aper:"valueLB:0,valueUB:20"` -} - -var optionalTest1Data = []optionalTest1{ - {&oCTETStringTest1Data[1].OctetString, BitString{[]byte{0x50}, 4}, 19}, -} -var optionalTestData = []testData{ - {[]byte("\x8C\x23\x34\x52\x97\x80\x59\x80"), optionalTest1Data[0]}, -} - -func TestOptional(t *testing.T) { - for i, test := range optionalTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out := reflect.New(reflect.TypeOf(test.Out)) - err := Unmarshal(test.in, out.Interface()) - perTestTrace(2, fmt.Sprintf(" in : %0x", test.in)) - - for j := 0; j < reflect.TypeOf(out.Elem().Interface()).NumField(); j++ { - exp := reflect.ValueOf(test.Out).Field(j) - v := out.Elem().Field(j) - if v.Kind() == reflect.Ptr { - v = v.Elem() - exp = exp.Elem() - } - - perTestTrace(2, fmt.Sprintf(" out : %v", v)) - perTestTrace(2, fmt.Sprintf(" exp : %v", exp)) - } - if err != nil { - logger.AperLog.Errorln(" [ERROR]: " + err.Error()) - } else if reflect.DeepEqual(test.Out, out.Elem().Interface()) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - } -} diff --git a/marshal_test.go b/marshal_test.go deleted file mode 100644 index fc42ba5..0000000 --- a/marshal_test.go +++ /dev/null @@ -1,254 +0,0 @@ -package aper - -import ( - "fmt" - "reflect" - "testing" -) - -func TestEncodeSingleBitString(t *testing.T) { - - for i, test := range singleBitStringTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in.Bytes : %0x, in.BitsLength: %d", reflect.ValueOf(test.Out).Field(0).Field(0).Bytes(), reflect.ValueOf(test.Out).Field(0).Field(1).Uint())) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeStructBitString(t *testing.T) { - - for i, test := range structBitStringTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - for j := 0; j < reflect.TypeOf(test.Out).NumField(); j++ { - perTestTrace(2, fmt.Sprintf(" in.Bytes : %0x, in.BitsLength: %d", reflect.ValueOf(test.Out).Field(j).Field(0).Bytes(), reflect.ValueOf(test.Out).Field(j).Field(1).Uint())) - } - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeSingleOctetString(t *testing.T) { - - for i, test := range singleOctetStringTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in : %0x, len: %d", reflect.ValueOf(test.Out).Field(0).Bytes(), len(reflect.ValueOf(test.Out).Field(0).Bytes()))) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeSingleInt(t *testing.T) { - - for i, test := range integerTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in : %d", reflect.ValueOf(test.Out).Field(0).Int())) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeStructInt(t *testing.T) { - - for i, test := range integerStructTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - for j := 0; j < reflect.TypeOf(test.Out).NumField(); j++ { - perTestTrace(2, fmt.Sprintf(" in : %d", reflect.ValueOf(test.Out).Field(j).Int())) - } - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeEnum(t *testing.T) { - - for i, test := range enumTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in : %d", reflect.ValueOf(test.Out).Field(0).Uint())) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodePtr(t *testing.T) { - - for i, test := range ptrTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in : %v", reflect.ValueOf(test.Out).Field(0).Elem())) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeSequenceOf(t *testing.T) { - - for i, test := range seqofTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - for j := 0; j < reflect.ValueOf(test.Out).Field(0).Len(); j++ { - perTestTrace(2, fmt.Sprintf(" in : %v", reflect.ValueOf(test.Out).Field(0).Index(j))) - } - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeStructPrintableString(t *testing.T) { - - for i, test := range printableStringStructTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - for j := 0; j < reflect.ValueOf(test.Out).NumField(); j++ { - perTestTrace(2, fmt.Sprintf(" in : %s", reflect.ValueOf(test.Out).Field(j).String())) - } - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeChoice(t *testing.T) { - - for i, test := range choiceTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in : %v", reflect.ValueOf(test.Out).Field(0))) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} - -func TestEncodeOpenType(t *testing.T) { - - for i, test := range openTypeTestData { - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in : %v", reflect.ValueOf(test.Out))) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} -func TestEncodeBoolean(t *testing.T) { - for i, test := range boolTestData { - - perTestTrace(1, fmt.Sprintf("[TEST %d]\n", i+1)) - out, err := Marshal(test.Out) - perTestTrace(2, fmt.Sprintf(" in : %t", reflect.ValueOf(test.Out).Field(0).Bool())) - perTestTrace(2, fmt.Sprintf(" out : 0x%0x", out)) - perTestTrace(2, fmt.Sprintf(" exp : 0x%0x", test.in)) - if err != nil { - perTestTrace(1, fmt.Sprintln(" [ERROR]: "+err.Error())) - } else if reflect.DeepEqual(test.in, out) { - perTestTrace(1, fmt.Sprintf("[PASS]\n")) - continue - } - perTestTrace(1, fmt.Sprintf("[FAIL]\n")) - t.Errorf("TEST %d is FAILED", i+1) - - } -} From 3752b8b3a1b8adbd51b2a33f9358ecc87a999fc1 Mon Sep 17 00:00:00 2001 From: free5gc-org Date: Mon, 28 Sep 2020 15:14:57 +0800 Subject: [PATCH 4/5] v2020-09-28-01 --- aper.go | 306 +++++++++++++++++++++------------------- asn_type.go | 10 +- common.go | 2 +- logger/logger.go | 42 +++--- marshal.go | 286 ++++++++++++++++++------------------- version/version.go | 2 + version/version_test.go | 11 ++ 7 files changed, 338 insertions(+), 321 deletions(-) create mode 100644 version/version_test.go diff --git a/aper.go b/aper.go index 3f2a18c..32885f5 100644 --- a/aper.go +++ b/aper.go @@ -173,7 +173,7 @@ func (pd *perBitData) parseConstraintValue(valueRange int64) (value uint64, err return } value, err = pd.getBitsValue(bytes * 8) - return + return value, err } func (pd *perBitData) parseLength(sizeRange int64, repeat *bool) (value uint64, err error) { @@ -207,10 +207,10 @@ func (pd *perBitData) parseLength(sizeRange int64, repeat *bool) (value uint64, } *repeat = true value = 16384 * firstByte - return + return value, err } -func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (bitString BitString, err error) { +func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (BitString, error) { var lb, ub, sizeRange int64 = 0, -1, -1 if !extensed { if lowerBoundPtr != nil { @@ -225,19 +225,19 @@ func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperB sizeRange = -1 } // initailization - bitString = BitString{[]byte{}, 0} + bitString := BitString{[]byte{}, 0} // lowerbound == upperbound if sizeRange == 1 { sizes := uint64(ub+7) >> 3 bitString.BitLength = uint64(ub) perTrace(2, fmt.Sprintf("Decoding BIT STRING size %d", ub)) if sizes > 2 { - if err = pd.parseAlignBits(); err != nil { - return + if err := pd.parseAlignBits(); err != nil { + return bitString, err } if (pd.byteOffset + sizes) > uint64(len(pd.bytes)) { - err = fmt.Errorf("PER data out of range") - return + err := fmt.Errorf("PER data out of range") + return bitString, err } bitString.Bytes = pd.bytes[pd.byteOffset : pd.byteOffset+sizes] pd.byteOffset += sizes @@ -247,31 +247,38 @@ func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperB } perTrace(1, perBitLog(uint64(ub), pd.byteOffset, pd.bitsOffset, bitString.Bytes)) } else { - bitString.Bytes, err = pd.getBitString(uint(ub)) + if byte, err := pd.getBitString(uint(ub)); err != nil { + logger.AperLog.Warnf("PD GetBitString error: %+v", err) + return bitString, err + } else { + bitString.Bytes = byte + } } perTrace(2, fmt.Sprintf("Decoded BIT STRING (length = %d): %0.8b", ub, bitString.Bytes)) - return + return bitString, nil } repeat := false for { var rawLength uint64 - if rawLength, err = pd.parseLength(sizeRange, &repeat); err != nil { - return + if length, err := pd.parseLength(sizeRange, &repeat); err != nil { + return bitString, err + } else { + rawLength = length } rawLength += uint64(lb) perTrace(2, fmt.Sprintf("Decoding BIT STRING size %d", rawLength)) if rawLength == 0 { - return + return bitString, nil } sizes := (rawLength + 7) >> 3 - if err = pd.parseAlignBits(); err != nil { - return + if err := pd.parseAlignBits(); err != nil { + return bitString, err } if (pd.byteOffset + sizes) > uint64(len(pd.bytes)) { - err = fmt.Errorf("PER data out of range") - return + err := fmt.Errorf("PER data out of range") + return bitString, err } bitString.Bytes = append(bitString.Bytes, pd.bytes[pd.byteOffset:pd.byteOffset+sizes]...) bitString.BitLength += rawLength @@ -290,9 +297,10 @@ func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperB break } } - return + return bitString, nil } -func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (octetString OctetString, err error) { +func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) ( + OctetString, error) { var lb, ub, sizeRange int64 = 0, -1, -1 if !extensed { if lowerBoundPtr != nil { @@ -307,45 +315,51 @@ func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, uppe sizeRange = -1 } // initailization - octetString = OctetString("") + octetString := OctetString("") // lowerbound == upperbound if sizeRange == 1 { perTrace(2, fmt.Sprintf("Decoding OCTET STRING size %d", ub)) if ub > 2 { unsignedUB := uint64(ub) - if err = pd.parseAlignBits(); err != nil { - return + if err := pd.parseAlignBits(); err != nil { + return octetString, err } if (int64(pd.byteOffset) + ub) > int64(len(pd.bytes)) { - err = fmt.Errorf("per data out of range") - return + err := fmt.Errorf("per data out of range") + return octetString, err } octetString = pd.bytes[pd.byteOffset : pd.byteOffset+unsignedUB] pd.byteOffset += uint64(ub) perTrace(1, perBitLog(8*unsignedUB, pd.byteOffset, pd.bitsOffset, octetString)) } else { - octetString, err = pd.getBitString(uint(ub * 8)) + if octet, err := pd.getBitString(uint(ub * 8)); err != nil { + return octetString, err + } else { + octetString = octet + } } perTrace(2, fmt.Sprintf("Decoded OCTET STRING (length = %d): 0x%0x", ub, octetString)) - return + return octetString, nil } repeat := false for { var rawLength uint64 - if rawLength, err = pd.parseLength(sizeRange, &repeat); err != nil { - return + if length, err := pd.parseLength(sizeRange, &repeat); err != nil { + return octetString, err + } else { + rawLength = length } rawLength += uint64(lb) perTrace(2, fmt.Sprintf("Decoding OCTET STRING size %d", rawLength)) if rawLength == 0 { - return - } else if err = pd.parseAlignBits(); err != nil { - return + return octetString, nil + } else if err := pd.parseAlignBits(); err != nil { + return octetString, err } if (rawLength + pd.byteOffset) > uint64(len(pd.bytes)) { - err = fmt.Errorf("per data out of range ") - return + err := fmt.Errorf("per data out of range ") + return octetString, err } octetString = append(octetString, pd.bytes[pd.byteOffset:pd.byteOffset+rawLength]...) pd.byteOffset += rawLength @@ -358,11 +372,11 @@ func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, uppe break } } - return + return octetString, nil } func (pd *perBitData) parseBool() (value bool, err error) { - perTrace(3, fmt.Sprintf("Decoding BOOLEAN Value")) + perTrace(3, "Decoding BOOLEAN Value") bit, err1 := pd.getBitsValue(1) if err1 != nil { err = err1 @@ -370,19 +384,19 @@ func (pd *perBitData) parseBool() (value bool, err error) { } if bit == 1 { value = true - perTrace(2, fmt.Sprintf("Decoded BOOLEAN Value : ture")) + perTrace(2, "Decoded BOOLEAN Value : ture") } else { value = false - perTrace(2, fmt.Sprintf("Decoded BOOLEAN Value : false")) + perTrace(2, "Decoded BOOLEAN Value : false") } return } -func (pd *perBitData) parseInteger(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (value int64, err error) { +func (pd *perBitData) parseInteger(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (int64, error) { var lb, ub, valueRange int64 = 0, -1, 0 if !extensed { if lowerBoundPtr == nil { - perTrace(3, fmt.Sprintf("Decoding INTEGER with Unconstraint Value")) + perTrace(3, "Decoding INTEGER with Unconstraint Value") valueRange = -1 } else { lb = *lowerBoundPtr @@ -396,32 +410,29 @@ func (pd *perBitData) parseInteger(extensed bool, lowerBoundPtr *int64, upperBou } } else { valueRange = -1 - perTrace(3, fmt.Sprintf("Decoding INTEGER with Extensive Value")) + perTrace(3, "Decoding INTEGER with Extensive Value") } var rawLength uint if valueRange == 1 { - value = ub - return + return ub, nil } else if valueRange <= 0 { // semi-constraint or unconstraint - if err = pd.parseAlignBits(); err != nil { - return + if err := pd.parseAlignBits(); err != nil { + return int64(0), err } if pd.byteOffset >= uint64(len(pd.bytes)) { - err = fmt.Errorf("per data out of range") - return + return int64(0), fmt.Errorf("per data out of range") } rawLength = uint(pd.bytes[pd.byteOffset]) pd.byteOffset++ perTrace(1, perBitLog(8, pd.byteOffset, pd.bitsOffset, uint64(rawLength))) } else if valueRange <= 65536 { - rawValue, err1 := pd.parseConstraintValue(valueRange) - if err1 != nil { - err = err1 + rawValue, err := pd.parseConstraintValue(valueRange) + if err != nil { + return int64(0), err } else { - value = int64(rawValue) + lb + return int64(rawValue) + lb, nil } - return } else { // valueRange > 65536 var byteLen uint @@ -440,37 +451,36 @@ func (pd *perBitData) parseInteger(extensed bool, lowerBoundPtr *int64, upperBou break } } - if tempLength, err1 := pd.getBitsValue(i); err1 != nil { - err = err1 - return + if tempLength, err := pd.getBitsValue(i); err != nil { + return int64(0), err } else { rawLength = uint(tempLength) } rawLength++ - if err = pd.parseAlignBits(); err != nil { - return + if err := pd.parseAlignBits(); err != nil { + return int64(0), err } } perTrace(2, fmt.Sprintf("Decoding INTEGER Length with %d bytes", rawLength)) - var rawValue uint64 - if rawValue, err = pd.getBitsValue(rawLength * 8); err != nil { - return + + if rawValue, err := pd.getBitsValue(rawLength * 8); err != nil { + return int64(0), err } else if valueRange < 0 { signedBitMask := uint64(1 << (rawLength*8 - 1)) valueMask := signedBitMask - 1 // negative if rawValue&signedBitMask > 0 { - value = int64((^rawValue)&valueMask+1) * -1 - return + return int64((^rawValue)&valueMask+1) * -1, nil } + return int64(rawValue) + lb, nil + } else { + return int64(rawValue) + lb, nil } - value = int64(rawValue) + lb - return - } // parse ENUMERATED type but do not implement extensive value and different value with index -func (pd *perBitData) parseEnumerated(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (value uint64, err error) { +func (pd *perBitData) parseEnumerated(extensed bool, lowerBoundPtr *int64, upperBoundPtr *int64) (value uint64, + err error) { if extensed { err = fmt.Errorf("Unsupport the extensive value of ENUMERATED ") return @@ -489,7 +499,10 @@ func (pd *perBitData) parseEnumerated(extensed bool, lowerBoundPtr *int64, upper return } -func (pd *perBitData) parseSequenceOf(sizeExtensed bool, params fieldParameters, sliceType reflect.Type) (sliceContent reflect.Value, err error) { + +func (pd *perBitData) parseSequenceOf(sizeExtensed bool, params fieldParameters, sliceType reflect.Type) ( + reflect.Value, error) { + var sliceContent reflect.Value var lb int64 = 0 var sizeRange int64 if params.sizeLowerBound != nil && *params.sizeLowerBound < 65536 { @@ -506,17 +519,21 @@ func (pd *perBitData) parseSequenceOf(sizeExtensed bool, params fieldParameters, var numElements uint64 if sizeRange > 1 { - numElements, err = pd.parseConstraintValue(sizeRange) + if numElementsTmp, err := pd.parseConstraintValue(sizeRange); err != nil { + logger.AperLog.Warnf("Parse Constraint Value failed: %+v", err) + } else { + numElements = numElementsTmp + } numElements += uint64(lb) } else if sizeRange == 1 { numElements += uint64(lb) } else { - if err = pd.parseAlignBits(); err != nil { - return + if err := pd.parseAlignBits(); err != nil { + return sliceContent, err } if pd.byteOffset >= uint64(len(pd.bytes)) { - err = fmt.Errorf("per data out of range") - return + err := fmt.Errorf("per data out of range") + return sliceContent, err } numElements = uint64(pd.bytes[pd.byteOffset]) pd.byteOffset++ @@ -529,12 +546,12 @@ func (pd *perBitData) parseSequenceOf(sizeExtensed bool, params fieldParameters, intNumElements := int(numElements) sliceContent = reflect.MakeSlice(sliceType, intNumElements, intNumElements) for i := 0; i < intNumElements; i++ { - err = parseField(sliceContent.Index(i), pd, params) + err := parseField(sliceContent.Index(i), pd, params) if err != nil { - return + return sliceContent, err } } - return + return sliceContent, nil } func (pd *perBitData) getChoiceIndex(extensed bool, upperBoundPtr *int64) (present int, err error) { @@ -576,56 +593,55 @@ func getReferenceFieldValue(v reflect.Value) (value int64, err error) { return } -func (pd *perBitData) parseOpenType(v reflect.Value, params fieldParameters) (err error) { +func (pd *perBitData) parseOpenType(v reflect.Value, params fieldParameters) error { pdOpenType := &perBitData{[]byte(""), 0, 0} repeat := false for { var rawLength uint64 - if rawLength, err = pd.parseLength(-1, &repeat); err != nil { - return + if rawLengthTmp, err := pd.parseLength(-1, &repeat); err != nil { + return err + } else { + rawLength = rawLengthTmp } if rawLength == 0 { break - } else if err = pd.parseAlignBits(); err != nil { - return + } else if err := pd.parseAlignBits(); err != nil { + return err } if (rawLength + pd.byteOffset) > uint64(len(pd.bytes)) { - err = fmt.Errorf("per data out of range ") - return + return fmt.Errorf("per data out of range ") } pdOpenType.bytes = append(pdOpenType.bytes, pd.bytes[pd.byteOffset:pd.byteOffset+rawLength]...) pd.byteOffset += rawLength if !repeat { - if err = pd.parseAlignBits(); err != nil { - return + if err := pd.parseAlignBits(); err != nil { + return err } break } } perTrace(2, fmt.Sprintf("Decoding OpenType %s with (len = %d byte)", v.Type().String(), len(pdOpenType.bytes))) - err = parseField(v, pdOpenType, params) + err := parseField(v, pdOpenType, params) perTrace(2, fmt.Sprintf("Decoded OpenType %s", v.Type().String())) - return + return err } // parseField is the main parsing function. Given a byte slice and an offset // into the array, it will try to parse a suitable ASN.1 value out and store it // in the given Value. TODO : ObjectIdenfier, handle extension Field -func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err error) { +func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { fieldType := v.Type() // If we have run out of data return error. if pd.byteOffset == uint64(len(pd.bytes)) { - err = fmt.Errorf("sequence truncated") - return + return fmt.Errorf("sequence truncated") } if v.Kind() == reflect.Ptr { ptr := reflect.New(fieldType.Elem()) v.Set(ptr) - err = parseField(v.Elem(), pd, params) - return + return parseField(v.Elem(), pd, params) } sizeExtensible := false valueExtensible := false @@ -655,42 +671,41 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err er return err1 } v.Set(reflect.ValueOf(bitString)) - return + return nil case ObjectIdentifierType: - err = fmt.Errorf("Unsupport ObjectIdenfier type") - return + return fmt.Errorf("Unsupport ObjectIdenfier type") case OctetStringType: - octetString, err1 := pd.parseOctetString(sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) - if err1 == nil { + if octetString, err := pd.parseOctetString(sizeExtensible, params.sizeLowerBound, params.sizeUpperBound); err != nil { + return err + } else { v.Set(reflect.ValueOf(octetString)) + return nil } - err = err1 - return case EnumeratedType: - parsedEnum, err1 := pd.parseEnumerated(valueExtensible, params.valueLowerBound, params.valueUpperBound) - if err1 == nil { + if parsedEnum, err := pd.parseEnumerated(valueExtensible, params.valueLowerBound, + params.valueUpperBound); err != nil { + return err + } else { v.SetUint(parsedEnum) + return nil } - err = err1 - return } switch val := v; val.Kind() { case reflect.Bool: - parsedBool, err1 := pd.parseBool() - if err1 == nil { + if parsedBool, err := pd.parseBool(); err != nil { + return err + } else { val.SetBool(parsedBool) + return nil } - err = err1 - return case reflect.Int, reflect.Int32, reflect.Int64: - parsedInt, err1 := pd.parseInteger(valueExtensible, params.valueLowerBound, params.valueUpperBound) - if err1 == nil { + if parsedInt, err := pd.parseInteger(valueExtensible, params.valueLowerBound, params.valueUpperBound); err != nil { + return err + } else { val.SetInt(parsedInt) - perTrace(2, fmt.Sprintf("Decoded INTEGER Value : %d", parsedInt)) + perTrace(2, fmt.Sprintf("Decoded INTEGER Value: %d", parsedInt)) + return nil } - err = err1 - return - case reflect.Struct: structType := fieldType @@ -701,8 +716,7 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err er // pass tag for optional for i := 0; i < structType.NumField(); i++ { if structType.Field(i).PkgPath != "" { - err = fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) - return + return fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) } tempParams := parseFieldParameters(structType.Field(i).Tag.Get("aper")) // for optional flag @@ -713,8 +727,10 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err er } if optionalCount > 0 { - if optionalPresents, err = pd.getBitsValue(optionalCount); err != nil { - return + if optionalPresentsTmp, err := pd.getBitsValue(optionalCount); err != nil { + return err + } else { + optionalPresents = optionalPresentsTmp } perTrace(2, fmt.Sprintf("optionalPresents is %0b", optionalPresents)) } @@ -724,8 +740,7 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err er var present int = 0 if params.openType { if params.referenceFieldValue == nil { - err = fmt.Errorf("OpenType reference value is empty") - return + return fmt.Errorf("OpenType reference value is empty") } refValue := *params.referenceFieldValue @@ -739,30 +754,29 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err er } } if present == 0 { - err = fmt.Errorf("OpenType reference value does not match any field") + return fmt.Errorf("OpenType reference value does not match any field") } else if present >= structType.NumField() { - err = fmt.Errorf("OpenType Present is bigger than number of struct field") + return fmt.Errorf("OpenType Present is bigger than number of struct field") } else { val.Field(0).SetInt(int64(present)) perTrace(2, fmt.Sprintf("Decoded Present index of OpenType is %d ", present)) - err = pd.parseOpenType(val.Field(present), structParams[present]) + return pd.parseOpenType(val.Field(present), structParams[present]) } } else { - present, err = pd.getChoiceIndex(valueExtensible, params.valueUpperBound) - if err != nil { + if presentTmp, err := pd.getChoiceIndex(valueExtensible, params.valueUpperBound); err != nil { logger.AperLog.Errorf("pd.getChoiceIndex Error") + } else { + present = presentTmp } val.Field(0).SetInt(int64(present)) if present == 0 { - err = fmt.Errorf("CHOICE present is 0(present's field number)") + return fmt.Errorf("CHOICE present is 0(present's field number)") } else if present >= structType.NumField() { - err = fmt.Errorf("CHOICE Present is bigger than number of struct field") + return fmt.Errorf("CHOICE Present is bigger than number of struct field") } else { - err = parseField(val.Field(present), pd, structParams[present]) + return parseField(val.Field(present), pd, structParams[present]) } } - return - } for i := 0; i < structType.NumField(); i++ { @@ -785,44 +799,42 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) (err er } } if index == i { - err = fmt.Errorf("Open type is not reference to the other field in the struct") - return + return fmt.Errorf("Open type is not reference to the other field in the struct") } structParams[i].referenceFieldValue = new(int64) - *structParams[i].referenceFieldValue, err = getReferenceFieldValue(val.Field(index)) - if err != nil { - return + if referenceFieldValue, err := getReferenceFieldValue(val.Field(index)); err != nil { + return err + } else { + *structParams[i].referenceFieldValue = referenceFieldValue } } - err = parseField(val.Field(i), pd, structParams[i]) - if err != nil { - return + if err := parseField(val.Field(i), pd, structParams[i]); err != nil { + return err } } - return + return nil case reflect.Slice: sliceType := fieldType - newSlice, err1 := pd.parseSequenceOf(sizeExtensible, params, sliceType) - if err1 == nil { + if newSlice, err := pd.parseSequenceOf(sizeExtensible, params, sliceType); err != nil { + return err + } else { val.Set(newSlice) + return nil } - err = err1 - return case reflect.String: - perTrace(2, fmt.Sprintf("Decoding PrintableString using Octet String decoding method")) + perTrace(2, "Decoding PrintableString using Octet String decoding method") - octetString, err1 := pd.parseOctetString(sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) - err = err1 - if err1 == nil { + if octetString, err := pd.parseOctetString(sizeExtensible, params.sizeLowerBound, params.sizeUpperBound); err != nil { + return err + } else { printableString := string(octetString) val.SetString(printableString) perTrace(2, fmt.Sprintf("Decoded PrintableString : \"%s\"", printableString)) + return nil } - return } - err = fmt.Errorf("unsupported: " + v.Type().String()) - return + return fmt.Errorf("unsupported: " + v.Type().String()) } // Unmarshal parses the APER-encoded ASN.1 data structure b diff --git a/asn_type.go b/asn_type.go index d806f93..d267c23 100644 --- a/asn_type.go +++ b/asn_type.go @@ -28,8 +28,12 @@ type ObjectIdentifier []byte type Enumerated uint64 var ( - BitStringType = reflect.TypeOf(BitString{}) - OctetStringType = reflect.TypeOf(OctetString{}) + // BitStringType is the type of BitString + BitStringType = reflect.TypeOf(BitString{}) + // OctetStringType is the type of OctetString + OctetStringType = reflect.TypeOf(OctetString{}) + // ObjectIdentifierType is the type of ObjectIdentify ObjectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) - EnumeratedType = reflect.TypeOf(Enumerated(0)) + // EnumeratedType is the type of Enumerated + EnumeratedType = reflect.TypeOf(Enumerated(0)) ) diff --git a/common.go b/common.go index cab67f9..74a9b52 100644 --- a/common.go +++ b/common.go @@ -74,5 +74,5 @@ func parseFieldParameters(str string) (params fieldParameters) { } } } - return + return params } diff --git a/logger/logger.go b/logger/logger.go index a6aa8ae..4441eac 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,41 +1,31 @@ package logger import ( - "fmt" - "github.com/sirupsen/logrus" "os" - "runtime" - "strings" + "time" + + formatter "github.com/antonfisher/nested-logrus-formatter" + "github.com/sirupsen/logrus" "free5gc/lib/logger_conf" "free5gc/lib/logger_util" ) var log *logrus.Logger + +// AperLog : Log entry of aper var AperLog *logrus.Entry func init() { log = logrus.New() - - log.Formatter = &logrus.TextFormatter{ - ForceColors: true, - DisableColors: false, - EnvironmentOverrideColors: false, - DisableTimestamp: false, - FullTimestamp: true, - TimestampFormat: "", - DisableSorting: false, - SortingFunc: nil, - DisableLevelTruncation: false, - QuoteEmptyFields: false, - FieldMap: nil, - CallerPrettyfier: func(f *runtime.Frame) (string, string) { - orgFilename, _ := os.Getwd() - repopath := orgFilename - repopath = strings.Replace(repopath, "/bin", "", 1) - filename := strings.Replace(f.File, repopath, "", -1) - return fmt.Sprintf("%s()", f.Function), fmt.Sprintf("%s:%d", filename, f.Line) - }, + log.SetReportCaller(false) + + log.Formatter = &formatter.Formatter{ + TimestampFormat: time.RFC3339, + TrimMessages: true, + NoFieldsSpace: true, + HideKeys: true, + FieldsOrder: []string{"component", "category"}, } free5gcLogHook, err := logger_util.NewFileHook(logger_conf.Free5gcLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) @@ -48,14 +38,16 @@ func init() { log.Hooks.Add(selfLogHook) } - AperLog = log.WithFields(logrus.Fields{"aper": "aper"}) + AperLog = log.WithFields(logrus.Fields{"component": "LIB", "category": "Aper"}) } +// SetLogLevel : set the log level (panic|fatal|error|warn|info|debug|trace) func SetLogLevel(level logrus.Level) { AperLog.Infoln("set log level :", level) log.SetLevel(level) } +// SetReportCaller : Set whether shows the filePath and functionName on loggers func SetReportCaller(bool bool) { AperLog.Infoln("set report call :", bool) log.SetReportCaller(bool) diff --git a/marshal.go b/marshal.go index a1caed0..1312323 100644 --- a/marshal.go +++ b/marshal.go @@ -139,7 +139,8 @@ func (pd *perRawBitData) appendLength(sizeRange int64, value uint64) (err error) return } -func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extensive bool, lowerBoundPtr *int64, upperBoundPtr *int64) (err error) { +func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extensive bool, + lowerBoundPtr *int64, upperBoundPtr *int64) (err error) { var lb, ub, sizeRange int64 = 0, -1, -1 if lowerBoundPtr != nil { lb = *lowerBoundPtr @@ -152,15 +153,15 @@ func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extens return } if extensive { - perTrace(2, fmt.Sprintf("Putting size Extension Value")) + perTrace(2, "Putting size Extension Value") if sizeRange == -1 { - if err := pd.putBitsValue(1, 1); err != nil { - log.Printf("putBitsValue(1, 1) error: %v", err) + if errTmp := pd.putBitsValue(1, 1); errTmp != nil { + log.Printf("putBitsValue(1, 1) error: %v", errTmp) } lb = 0 } else { - if err := pd.putBitsValue(0, 1); err != nil { - log.Printf("putBitsValue(0, 1) error: %v", err) + if errTmp := pd.putBitsValue(0, 1); errTmp != nil { + log.Printf("putBitsValue(0, 1) error: %v", errTmp) } } } @@ -216,7 +217,8 @@ func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extens pd.appendAlignBits() pd.bytes = append(pd.bytes, bytes[byteOffset:byteOffset+sizes]...) perTrace(1, perRawBitLog(partOfRawLength, len(pd.bytes), pd.bitsOffset, bytes)) - perTrace(2, fmt.Sprintf("Encoded BIT STRING (length = %d): 0x%0x", partOfRawLength, bytes[byteOffset:byteOffset+sizes])) + perTrace(2, fmt.Sprintf("Encoded BIT STRING (length = %d): 0x%0x", partOfRawLength, + bytes[byteOffset:byteOffset+sizes])) rawLength -= (partOfRawLength - uint64(lb)) if rawLength > 0 { byteOffset += sizes @@ -226,11 +228,12 @@ func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extens break } } - return + return err } -func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBoundPtr *int64, upperBoundPtr *int64) (err error) { +func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBoundPtr *int64, + upperBoundPtr *int64) error { byteLen := uint64(len(bytes)) var lb, ub, sizeRange int64 = 0, -1, -1 if lowerBoundPtr != nil { @@ -240,19 +243,19 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo if byteLen <= uint64(ub) { sizeRange = ub - lb + 1 } else if !extensive { - err = fmt.Errorf("OctetString Length is over upperbound") - return + err := fmt.Errorf("OctetString Length is over upperbound") + return err } if extensive { - perTrace(2, fmt.Sprintf("Putting size Extension Value")) + perTrace(2, "Putting size Extension Value") if sizeRange == -1 { - if err := pd.putBitsValue(1, 1); err != nil { - log.Printf("putBitsValue(1, 1) err: %v", err) + if errTmp := pd.putBitsValue(1, 1); errTmp != nil { + log.Printf("putBitsValue(1, 1) err: %v", errTmp) } lb = 0 } else { - if err := pd.putBitsValue(0, 1); err != nil { - log.Printf("putBitsValue(0, 1) err: %v", err) + if errTmp := pd.putBitsValue(0, 1); errTmp != nil { + log.Printf("putBitsValue(0, 1) err: %v", errTmp) } } } @@ -266,7 +269,8 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo if sizeRange == 1 { if byteLen != uint64(ub) { - err = fmt.Errorf("OctetString Length(%d) is not match fix-sized : %d", byteLen, ub) + err := fmt.Errorf("OctetString Length(%d) is not match fix-sized : %d", byteLen, ub) + return err } perTrace(2, fmt.Sprintf("Encoding OCTET STRING size %d", ub)) if byteLen > 2 { @@ -274,10 +278,11 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo pd.bytes = append(pd.bytes, bytes...) perTrace(1, perRawBitLog(byteLen*8, len(pd.bytes), 0, bytes)) } else { - err = pd.putBitString(bytes, uint(byteLen*8)) + err := pd.putBitString(bytes, uint(byteLen*8)) + return err } perTrace(2, fmt.Sprintf("Encoded OCTET STRING (length = %d): 0x%0x", byteLen, bytes)) - return + return nil } rawLength := byteLen - uint64(lb) @@ -290,18 +295,19 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo } else { partOfRawLength = rawLength } - if err = pd.appendLength(sizeRange, partOfRawLength); err != nil { - return + if err := pd.appendLength(sizeRange, partOfRawLength); err != nil { + return err } partOfRawLength += uint64(lb) perTrace(2, fmt.Sprintf("Encoding OCTET STRING size %d", partOfRawLength)) if partOfRawLength == 0 { - return + return nil } pd.appendAlignBits() pd.bytes = append(pd.bytes, bytes[byteOffset:byteOffset+partOfRawLength]...) perTrace(1, perRawBitLog(partOfRawLength*8, len(pd.bytes), pd.bitsOffset, bytes)) - perTrace(2, fmt.Sprintf("Encoded OCTET STRING (length = %d): 0x%0x", partOfRawLength, bytes[byteOffset:byteOffset+partOfRawLength])) + perTrace(2, fmt.Sprintf("Encoded OCTET STRING (length = %d): 0x%0x", partOfRawLength, + bytes[byteOffset:byteOffset+partOfRawLength])) rawLength -= (partOfRawLength - uint64(lb)) if rawLength > 0 { byteOffset += partOfRawLength @@ -310,7 +316,7 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo break } } - return + return nil } @@ -318,42 +324,40 @@ func (pd *perRawBitData) appendBool(value bool) (err error) { perTrace(3, fmt.Sprintf("Encoding BOOLEAN Value %t", value)) if value { err = pd.putBitsValue(1, 1) - perTrace(2, fmt.Sprintf("Encoded BOOLEAN Value : 0x1")) + perTrace(2, "Encoded BOOLEAN Value : 0x1") } else { err = pd.putBitsValue(0, 1) - perTrace(2, fmt.Sprintf("Encoded BOOLEAN Value : 0x0")) + perTrace(2, "Encoded BOOLEAN Value : 0x0") } return } -func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPtr *int64, upperBoundPtr *int64) (err error) { +func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPtr *int64, upperBoundPtr *int64) error { var lb, valueRange int64 = 0, 0 if lowerBoundPtr != nil { lb = *lowerBoundPtr if value < lb { - err = fmt.Errorf("INTEGER value is smaller than lowerbound") - return + return fmt.Errorf("INTEGER value is smaller than lowerbound") } if upperBoundPtr != nil { ub := *upperBoundPtr if value <= ub { valueRange = ub - lb + 1 } else if !extensive { - err = fmt.Errorf("INTEGER value is larger than upperbound") - return + return fmt.Errorf("INTEGER value is larger than upperbound") } if extensive { - perTrace(2, fmt.Sprintf("Putting value Extension bit")) + perTrace(2, "Putting value Extension bit") if valueRange == 0 { - perTrace(3, fmt.Sprintf("Encoding INTEGER with Unconstraint Value")) + perTrace(3, "Encoding INTEGER with Unconstraint Value") valueRange = -1 - if err := pd.putBitsValue(1, 1); err != nil { - fmt.Printf("pd.putBitsValue(1, 1) error: %v", err) + if errTmp := pd.putBitsValue(1, 1); errTmp != nil { + fmt.Printf("pd.putBitsValue(1, 1) error: %v", errTmp) } } else { perTrace(3, fmt.Sprintf("Encoding INTEGER with Value Range(%d..%d)", lb, ub)) - if err := pd.putBitsValue(0, 1); err != nil { - fmt.Printf("pd.putBitsValue(0, 1) error: %v", err) + if errTmp := pd.putBitsValue(0, 1); errTmp != nil { + fmt.Printf("pd.putBitsValue(0, 1) error: %v", errTmp) } } } @@ -362,16 +366,16 @@ func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPt perTrace(3, fmt.Sprintf("Encoding INTEGER with Semi-Constraint Range(%d..)", lb)) } } else { - perTrace(3, fmt.Sprintf("Encoding INTEGER with Unconstraint Value")) + perTrace(3, "Encoding INTEGER with Unconstraint Value") valueRange = -1 } unsignedValue := uint64(value) var rawLength uint if valueRange == 1 { - perTrace(2, fmt.Sprintf("Value of INTEGER is fixed")) + perTrace(2, "Value of INTEGER is fixed") - return + return nil } if value < 0 { y := value >> 63 @@ -380,8 +384,7 @@ func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPt if valueRange <= 0 { unsignedValue >>= 7 } else if valueRange <= 65536 { - err = pd.appendConstraintValue(valueRange, uint64(value-lb)) - return + return pd.appendConstraintValue(valueRange, uint64(value-lb)) } else { unsignedValue >>= 8 } @@ -418,8 +421,8 @@ func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPt } } perTrace(2, fmt.Sprintf("Encoding INTEGER Length %d-1 in %d bits", rawLength, i)) - if err = pd.putBitsValue(uint64(rawLength-1), i); err != nil { - return + if err := pd.putBitsValue(uint64(rawLength-1), i); err != nil { + return err } } perTrace(2, fmt.Sprintf("Encoding INTEGER %d with %d bytes", value, rawLength)) @@ -429,49 +432,45 @@ func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPt if valueRange < 0 { mask := int64(1< ub { if extensive { - err = fmt.Errorf("Unsupport the extensive value of ENUMERATED ") + return fmt.Errorf("Unsupport the extensive value of ENUMERATED") } else { - err = fmt.Errorf("ENUMERATED value is larger than upperbound") + return fmt.Errorf("ENUMERATED value is larger than upperbound") } - return } else if signedValue < lb { - err = fmt.Errorf("ENUMERATED value is smaller than lowerbound") - return + return fmt.Errorf("ENUMERATED value is smaller than lowerbound") } if extensive { - if err = pd.putBitsValue(0, 1); err != nil { - return + if err := pd.putBitsValue(0, 1); err != nil { + return err } } valueRange := ub - lb + 1 perTrace(2, fmt.Sprintf("Encoding ENUMERATED Value : %d with Value Range(%d..%d)", value, lb, ub)) if valueRange > 1 { - err = pd.appendConstraintValue(valueRange, value) + return pd.appendConstraintValue(valueRange, value) } - return + return nil } -func (pd *perRawBitData) parseSequenceOf(v reflect.Value, params fieldParameters) (err error) { +func (pd *perRawBitData) parseSequenceOf(v reflect.Value, params fieldParameters) error { var lb, ub, sizeRange int64 = 0, -1, -1 numElements := int64(v.Len()) if params.sizeLowerBound != nil && *params.sizeLowerBound < 65536 { @@ -481,84 +480,82 @@ func (pd *perRawBitData) parseSequenceOf(v reflect.Value, params fieldParameters ub = *params.sizeUpperBound if params.sizeExtensible { if numElements > ub { - err = pd.putBitsValue(1, 1) + if err := pd.putBitsValue(1, 1); err != nil { + return err + } } else { - err = pd.putBitsValue(0, 1) + if err := pd.putBitsValue(0, 1); err != nil { + return err + } sizeRange = ub - lb + 1 } } else if numElements > ub { - err = fmt.Errorf("SEQUENCE OF Size is larger than upperbound") + return fmt.Errorf("SEQUENCE OF Size is larger than upperbound") } else { sizeRange = ub - lb + 1 } - if err != nil { - return - } - } else { sizeRange = -1 } if numElements < lb { - err = fmt.Errorf("SEQUENCE OF Size is lower than lowerbound") + return fmt.Errorf("SEQUENCE OF Size is lower than lowerbound") } else if sizeRange == 1 { perTrace(3, fmt.Sprintf("Encoding Length of \"SEQUENCE OF\" with fix-size %d", ub)) if numElements != ub { - err = fmt.Errorf("Encoding Length %d != fix-size %d", numElements, ub) + return fmt.Errorf("Encoding Length %d != fix-size %d", numElements, ub) } } else if sizeRange > 0 { perTrace(3, fmt.Sprintf("Encoding Length(%d) of \"SEQUENCE OF\" with Size Range(%d..%d)", numElements, lb, ub)) - err = pd.appendConstraintValue(sizeRange, uint64(numElements-lb)) + if err := pd.appendConstraintValue(sizeRange, uint64(numElements-lb)); err != nil { + return err + } } else { perTrace(3, fmt.Sprintf("Encoding Length(%d) of \"SEQUENCE OF\" with Semi-Constraint Range(%d..)", numElements, lb)) pd.appendAlignBits() pd.bytes = append(pd.bytes, byte(numElements&0xff)) perTrace(1, perRawBitLog(8, len(pd.bytes), pd.bitsOffset, uint64(numElements))) } - if err != nil { - return - } perTrace(2, fmt.Sprintf("Encoding \"SEQUENCE OF\" struct %s with len(%d)", v.Type().Elem().Name(), numElements)) params.sizeExtensible = false params.sizeUpperBound = nil params.sizeLowerBound = nil for i := 0; i < v.Len(); i++ { - err = pd.makeField(v.Index(i), params) - if err != nil { - return + if err := pd.makeField(v.Index(i), params); err != nil { + return err } } - return + return nil } -func (pd *perRawBitData) appendChoiceIndex(present int, extensive bool, upperBoundPtr *int64) (err error) { +func (pd *perRawBitData) appendChoiceIndex(present int, extensive bool, upperBoundPtr *int64) error { var ub int64 rawChoice := present - 1 if upperBoundPtr == nil { - err = fmt.Errorf("The upper bound of CHIOCE is missing") + return fmt.Errorf("The upper bound of CHIOCE is missing") } else if ub = *upperBoundPtr; ub < 0 { - err = fmt.Errorf("The upper bound of CHIOCE is negative") + return fmt.Errorf("The upper bound of CHIOCE is negative") } else if extensive && rawChoice > int(ub) { - err = fmt.Errorf("Unsupport value of CHOICE type is in Extensed") - } - if err != nil { - return + return fmt.Errorf("Unsupport value of CHOICE type is in Extensed") } perTrace(2, fmt.Sprintf("Encoding Present index of CHOICE %d - 1", present)) - err = pd.appendConstraintValue(ub+1, uint64(rawChoice)) - return + if err := pd.appendConstraintValue(ub+1, uint64(rawChoice)); err != nil { + return err + } + return nil } -func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) (err error) { +func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) error { pdOpenType := &perRawBitData{[]byte(""), 0} perTrace(2, fmt.Sprintf("Encoding OpenType %s to temp RawData", v.Type().String())) - if err = pdOpenType.makeField(v, params); err != nil { - return + if err := pdOpenType.makeField(v, params); err != nil { + return err } openTypeBytes := pdOpenType.bytes rawLength := uint64(len(pdOpenType.bytes)) - perTrace(2, fmt.Sprintf("Encoding OpenType %s RawData : 0x%0x(%d bytes)", v.Type().String(), pdOpenType.bytes, rawLength)) + perTrace(2, fmt.Sprintf("Encoding OpenType %s RawData : 0x%0x(%d bytes)", v.Type().String(), pdOpenType.bytes, + rawLength)) var byteOffset, partOfRawLength uint64 for { @@ -569,17 +566,18 @@ func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) } else { partOfRawLength = rawLength } - if err = pd.appendLength(-1, partOfRawLength); err != nil { - return + if err := pd.appendLength(-1, partOfRawLength); err != nil { + return err } perTrace(2, fmt.Sprintf("Encoding Part of OpenType RawData size %d", partOfRawLength)) if partOfRawLength == 0 { - return + return nil } pd.appendAlignBits() pd.bytes = append(pd.bytes, openTypeBytes[byteOffset:byteOffset+partOfRawLength]...) perTrace(1, perRawBitLog(partOfRawLength*8, len(pd.bytes), pd.bitsOffset, openTypeBytes)) - perTrace(2, fmt.Sprintf("Encoded OpenType RawData (length = %d): 0x%0x", partOfRawLength, openTypeBytes[byteOffset:byteOffset+partOfRawLength])) + perTrace(2, fmt.Sprintf("Encoded OpenType RawData (length = %d): 0x%0x", partOfRawLength, + openTypeBytes[byteOffset:byteOffset+partOfRawLength])) rawLength -= partOfRawLength if rawLength > 0 { byteOffset += partOfRawLength @@ -590,9 +588,9 @@ func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) } perTrace(2, fmt.Sprintf("Encoded OpenType %s", v.Type().String())) - return + return nil } -func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err error) { +func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) error { if !v.IsValid() { return fmt.Errorf("aper: cannot marshal nil value") } @@ -608,25 +606,26 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err // We deal with the structures defined in this package first. switch fieldType { case BitStringType: - err = pd.appendBitString(v.Field(0).Bytes(), v.Field(1).Uint(), params.sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) - return + err := pd.appendBitString(v.Field(0).Bytes(), v.Field(1).Uint(), params.sizeExtensible, params.sizeLowerBound, + params.sizeUpperBound) + return err case ObjectIdentifierType: - err = fmt.Errorf("Unsupport ObjectIdenfier type") - return + err := fmt.Errorf("Unsupport ObjectIdenfier type") + return err case OctetStringType: - err = pd.appendOctetString(v.Bytes(), params.sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) - return + err := pd.appendOctetString(v.Bytes(), params.sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) + return err case EnumeratedType: - err = pd.appendEnumerated(v.Uint(), params.valueExtensible, params.valueLowerBound, params.valueUpperBound) - return + err := pd.appendEnumerated(v.Uint(), params.valueExtensible, params.valueLowerBound, params.valueUpperBound) + return err } switch val := v; val.Kind() { case reflect.Bool: - err = pd.appendBool(v.Bool()) - return + err := pd.appendBool(v.Bool()) + return err case reflect.Int, reflect.Int32, reflect.Int64: - err = pd.appendInteger(v.Int(), params.valueExtensible, params.valueLowerBound, params.valueUpperBound) - return + err := pd.appendInteger(v.Int(), params.valueExtensible, params.valueLowerBound, params.valueUpperBound) + return err case reflect.Struct: @@ -638,16 +637,15 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err // struct extensive TODO: support extensed type if params.valueExtensible { perTrace(2, fmt.Sprintf("Encoding Value Extensive Bit : %t", false)) - if err = pd.putBitsValue(0, 1); err != nil { - return + if err := pd.putBitsValue(0, 1); err != nil { + return err } } sequenceType = (structType.NumField() <= 0 || structType.Field(0).Name != "Present") // pass tag for optional for i := 0; i < structType.NumField(); i++ { if structType.Field(i).PkgPath != "" { - err = fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) - return + return fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) } tempParams := parseFieldParameters(structType.Field(i).Tag.Get("aper")) if sequenceType { @@ -660,7 +658,7 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err optionalPresents++ } } else if v.Field(i).Type().Kind() == reflect.Ptr && v.Field(i).IsNil() { - err = fmt.Errorf("nil element in SEQUENCE type") + return fmt.Errorf("nil element in SEQUENCE type") } } @@ -668,8 +666,8 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err } if optionalCount > 0 { perTrace(2, fmt.Sprintf("putting optional(%d), optionalPresents is %0b", optionalCount, optionalPresents)) - if err = pd.putBitsValue(optionalPresents, optionalCount); err != nil { - return + if err := pd.putBitsValue(optionalPresents, optionalCount); err != nil { + return err } } @@ -677,31 +675,31 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err if !sequenceType { present := int(v.Field(0).Int()) if present == 0 { - err = fmt.Errorf("CHOICE or OpenType present is 0(present's field number)") + return fmt.Errorf("CHOICE or OpenType present is 0(present's field number)") } else if present >= structType.NumField() { - err = fmt.Errorf("Present is bigger than number of struct field") + return fmt.Errorf("Present is bigger than number of struct field") } else if params.openType { if params.referenceFieldValue == nil { - err = fmt.Errorf("OpenType reference value is empty") - return + return fmt.Errorf("OpenType reference value is empty") } refValue := *params.referenceFieldValue if structParams[present].referenceFieldValue == nil || *structParams[present].referenceFieldValue != refValue { - err = fmt.Errorf("reference value and present reference value is not match") - return + return fmt.Errorf("reference value and present reference value is not match") } perTrace(2, fmt.Sprintf("Encoding Present index of OpenType is %d ", present)) - err = pd.appendOpenType(val.Field(present), structParams[present]) + if err := pd.appendOpenType(val.Field(present), structParams[present]); err != nil { + return err + } } else { - err = pd.appendChoiceIndex(present, params.valueExtensible, params.valueUpperBound) - - if err != nil { - return + if err := pd.appendChoiceIndex(present, params.valueExtensible, params.valueUpperBound); err != nil { + return err + } + if err := pd.makeField(val.Field(present), structParams[present]); err != nil { + return err } - err = pd.makeField(val.Field(present), structParams[present]) } - return + return nil } @@ -726,33 +724,31 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) (err } } if index == i { - err = fmt.Errorf("Open type is not reference to the other field in the struct") - return + return fmt.Errorf("Open type is not reference to the other field in the struct") } structParams[i].referenceFieldValue = new(int64) - *structParams[i].referenceFieldValue, err = getReferenceFieldValue(val.Field(index)) - if err != nil { - return + if value, err := getReferenceFieldValue(val.Field(index)); err != nil { + return err + } else { + *structParams[i].referenceFieldValue = value } } - err = pd.makeField(val.Field(i), structParams[i]) - if err != nil { - return + if err := pd.makeField(val.Field(i), structParams[i]); err != nil { + return err } } - return + return nil case reflect.Slice: - err = pd.parseSequenceOf(v, params) - return + err := pd.parseSequenceOf(v, params) + return err case reflect.String: printableString := v.String() perTrace(2, fmt.Sprintf("Encoding PrintableString : \"%s\" using Octet String decoding method", printableString)) - err = pd.appendOctetString([]byte(printableString), params.sizeExtensible, params.sizeLowerBound, params.sizeUpperBound) - return + err := pd.appendOctetString([]byte(printableString), params.sizeExtensible, params.sizeLowerBound, + params.sizeUpperBound) + return err } - err = fmt.Errorf("unsupported: " + v.Type().String()) - return - + return fmt.Errorf("unsupported: " + v.Type().String()) } // Marshal returns the ASN.1 encoding of val. diff --git a/version/version.go b/version/version.go index f89f034..934feed 100644 --- a/version/version.go +++ b/version/version.go @@ -1,7 +1,9 @@ package version +// VERSION : lastest version var VERSION = "2020-03-31-01" +// GetVersion : Get the latest version func GetVersion() (version string) { return VERSION } diff --git a/version/version_test.go b/version/version_test.go new file mode 100644 index 0000000..433b286 --- /dev/null +++ b/version/version_test.go @@ -0,0 +1,11 @@ +package version_test + +import ( + "free5gc/lib/aper/version" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestVersion(t *testing.T) { + assert.Equal(t, "2020-03-31-01", version.GetVersion()) +} From 0b5fb52795bb69a4fe8de14c5e71c2ccf6bea907 Mon Sep 17 00:00:00 2001 From: calee_cs Date: Tue, 24 Nov 2020 20:32:58 +0800 Subject: [PATCH 5/5] Add Apache-2.0 license file --- LICENSE.txt | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..4124f39 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019 Communication Service/Software Laboratory, National Chiao Tung University + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file