Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.location.cts.asn1.base;
     18 
     19 import com.google.common.collect.ImmutableList;
     20 
     21 import java.nio.ByteBuffer;
     22 import java.util.Collection;
     23 import java.util.NoSuchElementException;
     24 
     25 /**
     26  * Implements ASN.1 functionality.
     27  *
     28  */
     29 public abstract class Asn1Sequence extends Asn1Object {
     30   private static final Collection<Asn1Tag> possibleFirstTags =
     31       ImmutableList.of(Asn1Tag.SEQUENCE);
     32 
     33   protected abstract boolean isExtensible();
     34 
     35   protected abstract boolean containsExtensionValues();
     36 
     37   protected abstract Iterable<? extends SequenceComponent> getComponents();
     38 
     39   protected abstract Iterable<? extends SequenceComponent> getExtensionComponents();
     40 
     41   public static Collection<Asn1Tag> getPossibleFirstTags() {
     42     return possibleFirstTags;
     43   }
     44 
     45   @Override Asn1Tag getDefaultTag() {
     46     return Asn1Tag.SEQUENCE;
     47   }
     48 
     49   @Override boolean isConstructed() {
     50     return true;
     51   }
     52 
     53   @Override
     54   public int getBerValueLength() {
     55     int length = 0;
     56     for (SequenceComponent component : getComponents()) {
     57       if (component.isExplicitlySet()) {
     58         Asn1Tag tag = component.getTag();
     59         Asn1Object value = component.getComponentValue();
     60         if (tag == null) {
     61           length += value.getBerLength();
     62         } else {
     63           int valueLen = component.isImplicitTagging()
     64               ? value.getBerValueLength() : value.getBerLength();
     65           length += tag.getTaggedLength(valueLen);
     66         }
     67       }
     68     }
     69     return length;
     70   }
     71 
     72   @Override
     73   public void encodeBerValue(ByteBuffer buf) {
     74     for (SequenceComponent component : getComponents()) {
     75       if (component.isExplicitlySet()) {
     76         Asn1Object obj = component.getComponentValue();
     77         Asn1Tag componentTag = component.getTag();
     78         if (componentTag == null) {
     79           obj.encodeBer(buf);
     80         } else {
     81           if (component.isImplicitTagging()) {
     82             componentTag.writeTagAndLength(buf, obj.isConstructed(), obj.getBerValueLength());
     83             obj.encodeBerValue(buf);
     84           } else {
     85             componentTag.writeTagAndLength(buf, true, obj.getBerLength());
     86             obj.encodeBer(buf);
     87           }
     88         }
     89       } else if (!component.isOptional() && !component.hasDefaultValue()) {
     90         throw new IllegalStateException("Mandatory component "
     91             + component.getClass().getName()
     92             + " not set.");
     93       }
     94     }
     95   }
     96 
     97   @Override
     98   public void decodeBerValue(ByteBuffer buf) {
     99     Iterable<? extends SequenceComponent> components = getComponents();
    100 
    101     while (buf.hasRemaining()) {
    102       int bufStartPos = buf.position();
    103       int bufEndPos = buf.limit();
    104       Asn1Tag tag = Asn1Tag.readTag(buf);
    105       SequenceComponent component = getComponent(components, tag);
    106       if (component.isExplicitlySet()) {
    107         throw new IllegalArgumentException("Encountered duplicate field");
    108       }
    109       component.setToNewInstance();
    110       int valueLength = Asn1Tag.readLength(buf);
    111       buf.limit(buf.position() + valueLength);
    112       if (component.getTag() != null) {
    113         if (component.isImplicitTagging()) {
    114           component.getComponentValue().decodeBerValue(buf);
    115         } else {
    116           component.getComponentValue().decodeBer(buf);
    117         }
    118       } else {
    119         buf.position(bufStartPos); // rewind to before tag
    120         component.getComponentValue().decodeBer(buf);
    121       }
    122       buf.limit(bufEndPos); // set the limit back to the real end position
    123     }
    124 
    125     checkMandatoryFieldsPresent(components);
    126   }
    127 
    128   /**
    129    * Throws {@link IllegalArgumentException} if all mandatory fields not set on this sequence.
    130    */
    131   private void checkMandatoryFieldsPresent(Iterable<? extends SequenceComponent> components) {
    132     for (SequenceComponent component : components) {
    133       if (!component.isOptional() && !component.isExplicitlySet()) {
    134         throw new IllegalArgumentException("Mandatory field not present");
    135       }
    136     }
    137   }
    138 
    139   /**
    140    * Returns the child component that can start with the specified tag.
    141    * @throws NoSuchElementException if no child component can start with the tag
    142    */
    143   private SequenceComponent getComponent(Iterable<? extends SequenceComponent> components,
    144       Asn1Tag tag) {
    145     for (SequenceComponent component : components) {
    146       if (component.getPossibleFirstTags().contains(tag)) {
    147         return component;
    148       }
    149     }
    150     throw new NoSuchElementException("SEQUENCE=" + this + ", tag=" + tag);
    151   }
    152 
    153   private Iterable<BitStream> encodePerImpl(boolean aligned) {
    154     ImmutableList.Builder<BitStream> listBuilder = ImmutableList.builder();
    155     BitStream prefix = new BitStream();
    156 
    157     if (isExtensible()) {
    158       prefix.appendBit(containsExtensionValues());
    159     }
    160 
    161     Iterable<? extends SequenceComponent> components = getComponents();
    162     int bitFieldSize = calculateBitFieldSize(components);
    163     if (bitFieldSize >= PerAlignedUtils.SIXTYFOUR_K) {
    164       throw new UnsupportedOperationException("unimplemented");
    165     }
    166     for (SequenceComponent component : components) {
    167       if (component.isOptional() || component.hasDefaultValue()) {
    168         prefix.appendBit(component.isExplicitlySet());
    169       } else if (!component.isExplicitlySet()) {
    170         throw new IllegalStateException("Mandatory component "
    171                                         + component.getClass().getName()
    172                                         + " not set.");
    173       }
    174     }
    175     listBuilder.add(prefix);
    176 
    177     for (SequenceComponent component : components) {
    178       if (component.isExplicitlySet()) {
    179         Asn1Object value = component.getComponentValue();
    180         Iterable<BitStream> encodedValue = null;
    181         if (aligned) {
    182           encodedValue = value.encodePerAligned();
    183         } else {
    184           encodedValue = value.encodePerUnaligned();
    185         }
    186         listBuilder.addAll(encodedValue);
    187       }
    188     }
    189 
    190     if (isExtensible() && containsExtensionValues()) {
    191       Iterable<? extends SequenceComponent> extensionComponents =
    192           getExtensionComponents();
    193       BitStream extensions = new BitStream();
    194       int extensionBitFieldSize = 0;
    195       /*
    196        * Adding a bit marker per extension addition as ITU spec, however some
    197        * H323 implementations seem to only add markers up to the last set
    198        * extension.
    199        */
    200       for (SequenceComponent component : extensionComponents) {
    201         if (!component.isOptional() && !component.isExplicitlySet()) {
    202           throw new IllegalStateException("Mandatory extension component "
    203                                           + component.getClass().getName()
    204                                           + " not set.");
    205         }
    206         extensions.appendBit(component.isExplicitlySet());
    207         extensionBitFieldSize++;
    208       }
    209       if (extensionBitFieldSize <= 64) {
    210         //encode length to x.691-0207 10.9.3.4 (i.e. length -1)
    211         BitStream lengthDeterminant = new BitStream();
    212         lengthDeterminant.appendBit(false);
    213         lengthDeterminant.appendLowBits(6, (byte) (extensionBitFieldSize - 1));
    214         listBuilder.add(lengthDeterminant);
    215       } else {
    216         BitStream marker = new BitStream();
    217         marker.appendBit(true);
    218         listBuilder.add(marker);
    219         BitStream lengthDeterminant = null;
    220         if (aligned) {
    221           lengthDeterminant =
    222               PerAlignedUtils.encodeSemiConstrainedLength(extensionBitFieldSize);
    223           lengthDeterminant.setBeginByteAligned();
    224         } else {
    225           lengthDeterminant =
    226               PerUnalignedUtils.encodeSemiConstrainedLength(extensionBitFieldSize);
    227         }
    228         listBuilder.add(lengthDeterminant);
    229       }
    230       listBuilder.add(extensions);
    231       for (SequenceComponent component : extensionComponents) {
    232         if (component.isExplicitlySet()) {
    233           Iterable<BitStream> extensionValues = null;
    234           if (aligned) {
    235             extensionValues = PerAlignedUtils.
    236                 encodeOpenTypeField(component.getComponentValue());
    237           } else {
    238             extensionValues = PerUnalignedUtils.encodeOpenTypeField(component.getComponentValue());
    239           }
    240           listBuilder.addAll(extensionValues);
    241         }
    242       }
    243     }
    244     return listBuilder.build();
    245   }
    246 
    247   @Override public Iterable<BitStream> encodePerUnaligned() {
    248     return encodePerImpl(false);
    249   }
    250 
    251   @Override
    252   public Iterable<BitStream> encodePerAligned() {
    253     return encodePerImpl(true);
    254   }
    255 
    256   private int calculateBitFieldSize(
    257       Iterable<? extends SequenceComponent> components) {
    258     int bitFieldSize = 0;
    259     for (SequenceComponent component : components) {
    260       if (component.isOptional() || component.hasDefaultValue()) {
    261         bitFieldSize++;
    262       }
    263     }
    264     return bitFieldSize;
    265   }
    266 
    267   private void decodePerImpl(BitStreamReader reader, boolean aligned) {
    268     boolean hasExtensionValuesToDecode = false;
    269     if (isExtensible()) {
    270       hasExtensionValuesToDecode = reader.readBit();
    271     }
    272 
    273     Iterable<? extends SequenceComponent> components = getComponents();
    274     int bitFieldSize = calculateBitFieldSize(components);
    275     if (bitFieldSize >= PerAlignedUtils.SIXTYFOUR_K) {
    276       throw new UnsupportedOperationException("unimplemented");
    277     }
    278     for (SequenceComponent component : components) {
    279       if (component.isOptional() || component.hasDefaultValue()) {
    280         if (reader.readBit()) {
    281           component.setToNewInstance();
    282         }
    283       } else {
    284         component.setToNewInstance();
    285       }
    286     }
    287 
    288     for (SequenceComponent component : components) {
    289       if (component.isExplicitlySet()) {
    290         if (aligned) {
    291           component.getComponentValue().decodePerAligned(reader);
    292         } else {
    293           component.getComponentValue().decodePerUnaligned(reader);
    294         }
    295       }
    296     }
    297 
    298     if (hasExtensionValuesToDecode) {
    299       Iterable<? extends SequenceComponent> extensionComponents =
    300           getExtensionComponents();
    301       int extensionBitFieldSize;
    302       if (reader.readBit()) {
    303         if (aligned) {
    304           reader.spoolToByteBoundary();
    305           extensionBitFieldSize =
    306               PerAlignedUtils.decodeSemiConstrainedLength(reader);
    307         } else {
    308           extensionBitFieldSize =
    309               PerUnalignedUtils.decodeSemiConstrainedLength(reader);
    310         }
    311       } else {
    312         extensionBitFieldSize = 1 + reader.readLowBits(6);
    313       }
    314       for (SequenceComponent component : extensionComponents) {
    315         if (extensionBitFieldSize > 0) {
    316           --extensionBitFieldSize;
    317           if (reader.readBit()) {
    318             component.setToNewInstance();
    319           }
    320         }
    321       }
    322       int unknownExtensionCount = 0;
    323       for (; extensionBitFieldSize > 0; --extensionBitFieldSize) {
    324         if (reader.readBit()) {
    325           ++unknownExtensionCount;
    326         }
    327       }
    328       for (SequenceComponent component : extensionComponents) {
    329         if (component.isExplicitlySet()) {
    330           if (aligned) {
    331             byte[] encodedComponent =
    332                 PerAlignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
    333             component.getComponentValue().decodePerAligned(new BitStreamReader(encodedComponent));
    334           } else {
    335             byte[] encodedComponent =
    336                 PerUnalignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
    337             component.getComponentValue().decodePerUnaligned(new BitStreamReader(encodedComponent));
    338           }
    339         }
    340       }
    341       for (; unknownExtensionCount > 0; --unknownExtensionCount) {
    342         if (aligned) {
    343           byte[] unknownEncodedExtension =
    344               PerAlignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
    345         } else {
    346           byte[] unknownEncodedExtension =
    347               PerUnalignedUtils.decodeSemiConstrainedLengthOfBytes(reader);
    348         }
    349       }
    350     }
    351   }
    352 
    353   @Override public void decodePerUnaligned(BitStreamReader reader) {
    354     decodePerImpl(reader, false);
    355   }
    356 
    357   @Override public void decodePerAligned(BitStreamReader reader) {
    358     decodePerImpl(reader, true);
    359   }
    360 }
    361 
    362