001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.shared.asn1.ber; 021 022 023 import java.nio.ByteBuffer; 024 025 import org.apache.directory.shared.asn1.ber.grammar.IStates; 026 import org.apache.directory.shared.asn1.ber.tlv.ITLVBerDecoderMBean; 027 import org.apache.directory.shared.asn1.ber.tlv.TLV; 028 import org.apache.directory.shared.asn1.ber.tlv.TLVStateEnum; 029 import org.apache.directory.shared.asn1.ber.tlv.Value; 030 import org.apache.directory.shared.asn1.codec.DecoderException; 031 import org.apache.directory.shared.asn1.util.Asn1StringUtils; 032 import org.apache.directory.shared.i18n.I18n; 033 import org.slf4j.Logger; 034 import org.slf4j.LoggerFactory; 035 036 037 /** 038 * A BER TLV Tag component decoder. This decoder instanciate a Tag. The tag 039 * won't be implementations should not copy the handle to the Tag object 040 * delivered but should copy the data if they need it over the long term. 041 * 042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 043 * @version $Rev: 912399 $, $Date: 2010-02-21 21:52:31 +0100 (Sun, 21 Feb 2010) $ 044 */ 045 public class Asn1Decoder implements ITLVBerDecoderMBean 046 { 047 // ~ Static fields/initializers 048 // ----------------------------------------------------------------- 049 050 /** The logger */ 051 private static final Logger LOG = LoggerFactory.getLogger( Asn1Decoder.class ); 052 053 /** A speedup for logger */ 054 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 055 056 /** This flag is used to indicate that there are more bytes in the stream */ 057 private static final boolean MORE = true; 058 059 /** This flag is used to indicate that there are no more bytes in the stream */ 060 private static final boolean END = false; 061 062 // ~ Instance fields 063 // ---------------------------------------------------------------------------- 064 065 /** Flag that is used to allow/disallow the indefinite form of Length */ 066 private boolean indefiniteLengthAllowed; 067 068 /** The maximum number of bytes that could be used to encode the Length */ 069 private int maxLengthLength; 070 071 /** The maximum number of bytes that could be used to encode the Tag */ 072 private int maxTagLength; 073 074 075 // ~ Constructors 076 // ------------------------------------------------------------------------------- 077 078 /** 079 * A public constructor of an Asn1 Decoder. 080 */ 081 public Asn1Decoder() 082 { 083 indefiniteLengthAllowed = false; 084 maxLengthLength = 1; 085 maxTagLength = 1; 086 } 087 088 089 // ~ Methods 090 // ------------------------------------------------------------------------------------ 091 092 /** 093 * Treat the start of a TLV. It reads the tag and get its value. 094 * 095 * @param stream The ByteBuffer containing the PDU to decode 096 * @param container The container that stores the current state, 097 * the result and other informations. 098 * @return <code>true</code> if there are more bytes to read, <code>false 099 * </code> otherwise 100 */ 101 private boolean treatTagStartState( ByteBuffer stream, IAsn1Container container ) 102 { 103 104 if ( stream.hasRemaining() ) 105 { 106 107 byte octet = stream.get(); 108 109 TLV tlv = new TLV( container.getNewTlvId() ); 110 tlv.setTag( octet ); 111 112 // Store the current TLV in the container. 113 container.setCurrentTLV( tlv ); 114 115 // Create a link between the current TLV with its parent 116 tlv.setParent( container.getParentTLV() ); 117 118 // Switch to the next state, which is the Length decoding 119 container.setState( TLVStateEnum.LENGTH_STATE_START ); 120 121 if ( IS_DEBUG ) 122 { 123 byte tag = container.getCurrentTLV().getTag(); 124 LOG.debug( "Tag {} has been decoded", Asn1StringUtils.dumpByte( tag ) ); 125 } 126 127 return MORE; 128 } 129 else 130 { 131 132 // The stream has been exhausted 133 return END; 134 } 135 } 136 137 /** 138 * Dump the current TLV tree 139 * 140 * @param container The container 141 */ 142 private void dumpTLVTree( IAsn1Container container ) 143 { 144 StringBuffer sb = new StringBuffer(); 145 TLV current = container.getCurrentTLV(); 146 147 sb.append( "TLV" ).append( Asn1StringUtils.dumpByte( current.getTag() ) ).append( "(" ) 148 .append( current.getExpectedLength() ).append( ")" ); 149 150 current = current.getParent(); 151 152 while ( current != null ) 153 { 154 sb.append( "-TLV" ).append( Asn1StringUtils.dumpByte( current.getTag() ) ).append( "(" ) 155 .append( current.getExpectedLength() ).append( ")" ); 156 current = current.getParent(); 157 } 158 159 if ( IS_DEBUG ) 160 { 161 LOG.debug( "TLV Tree : {}", sb.toString() ); 162 } 163 } 164 165 166 /** 167 * Check if the TLV tree is fully decoded 168 * 169 * @param container The container 170 * @return <code>true</code> if the TLV has been decoded 171 */ 172 private boolean isTLVDecoded( IAsn1Container container ) 173 { 174 TLV current = container.getCurrentTLV(); 175 176 TLV parent = current.getParent(); 177 178 while ( parent != null ) 179 { 180 if ( parent.getExpectedLength() != 0 ) 181 { 182 return false; 183 } 184 185 parent = parent.getParent(); 186 } 187 188 Value value = current.getValue(); 189 190 if ( ( value != null ) && ( value.getData() != null ) ) 191 { 192 return ( current.getExpectedLength() == value.getData().length ); 193 } 194 else 195 { 196 return current.getExpectedLength() == 0; 197 } 198 } 199 200 /** 201 * Treat the Length start. The tag has been decoded, so we have to deal with 202 * the LENGTH, which can be multi-bytes. 203 * 204 * @param stream The ByteBuffer containing the PDU to decode 205 * @param container The container that stores the current state, 206 * the result and other informations. 207 * @return <code>true</code> if there are more bytes to read, <code>false 208 * </code> otherwise 209 * @throws DecoderException Thrown if anything went wrong 210 */ 211 private boolean treatLengthStartState( ByteBuffer stream, IAsn1Container container ) throws DecoderException 212 { 213 214 if ( stream.hasRemaining() ) 215 { 216 byte octet = stream.get(); 217 TLV tlv = container.getCurrentTLV(); 218 219 if ( ( octet & TLV.LENGTH_LONG_FORM ) == 0 ) 220 { 221 222 // We don't have a long form. The Length of the Value part is 223 // given by this byte. 224 tlv.setLength( octet ); 225 tlv.setLengthNbBytes( 1 ); 226 227 container.setState( TLVStateEnum.LENGTH_STATE_END ); 228 } 229 else if ( ( octet & TLV.LENGTH_EXTENSION_RESERVED ) != TLV.LENGTH_EXTENSION_RESERVED ) 230 { 231 232 int expectedLength = octet & TLV.LENGTH_SHORT_MASK; 233 234 if ( expectedLength > 4 ) 235 { 236 LOG.error( I18n.err( I18n.ERR_00005 ) ); 237 throw new DecoderException( I18n.err( I18n.ERR_00005 ) ); 238 } 239 240 tlv.setLength( 0 ); 241 tlv.setLengthNbBytes( 1 + expectedLength ); 242 tlv.setLengthBytesRead( 1 ); 243 container.setState( TLVStateEnum.LENGTH_STATE_PENDING ); 244 } 245 else 246 { 247 LOG.error( I18n.err( I18n.ERR_00006 ) ); 248 throw new DecoderException( I18n.err( I18n.ERR_00006 ) ); 249 } 250 251 return MORE; 252 } 253 else 254 { 255 return END; 256 } 257 } 258 259 260 /** 261 * This function is called when a Length is in the process of being decoded, 262 * but the lack of bytes in the buffer stopped the process. 263 * 264 * @param stream The ByteBuffer containing the PDU to decode 265 * @param container The container that stores the current state, 266 * the result and other informations. 267 * @return <code>true</code> if there are more bytes to read, <code>false 268 * </code> otherwise 269 */ 270 private boolean treatLengthPendingState( ByteBuffer stream, IAsn1Container container ) 271 { 272 273 if ( stream.hasRemaining() ) 274 { 275 276 TLV tlv = container.getCurrentTLV(); 277 int length = tlv.getLength(); 278 279 while ( tlv.getLengthBytesRead() < tlv.getLengthNbBytes() ) 280 { 281 282 byte octet = stream.get(); 283 284 if ( IS_DEBUG ) 285 { 286 LOG.debug( " current byte : {}", Asn1StringUtils.dumpByte( octet ) ); 287 } 288 289 tlv.incLengthBytesRead(); 290 length = ( length << 8 ) | ( octet & 0x00FF ); 291 292 if ( !stream.hasRemaining() ) 293 { 294 tlv.setLength( length ); 295 296 if ( tlv.getLengthBytesRead() < tlv.getLengthNbBytes() ) 297 { 298 container.setState( TLVStateEnum.LENGTH_STATE_PENDING ); 299 return END; 300 } 301 else 302 { 303 container.setState( TLVStateEnum.LENGTH_STATE_END ); 304 return MORE; 305 } 306 } 307 } 308 309 tlv.setLength( length ); 310 container.setState( TLVStateEnum.LENGTH_STATE_END ); 311 312 return MORE; 313 } 314 else 315 { 316 317 return END; 318 } 319 } 320 321 322 /** 323 * A debug function used to dump the expected length stack. 324 * 325 * @param tlv The current TLV. 326 * @return A string which represent the expected length stack. 327 */ 328 private String getParentLength( TLV tlv ) 329 { 330 StringBuffer buffer = new StringBuffer(); 331 332 buffer.append( "TLV expected length stack : " ); 333 334 while ( true ) 335 { 336 if ( tlv == null ) 337 { 338 buffer.append( " - null" ); 339 break; 340 } 341 else 342 { 343 buffer.append( " - " ).append( tlv.getExpectedLength() ); 344 } 345 346 tlv = tlv.getParent(); 347 } 348 349 return buffer.toString(); 350 } 351 352 353 /** 354 * The Length is fully decoded. We have to call an action to check the size. 355 * 356 * @param container The container that stores the current state, 357 * the result and other informations. 358 * @throws DecoderException Thrown if anything went wrong 359 */ 360 private void treatLengthEndState( IAsn1Container container ) throws DecoderException 361 { 362 TLV tlv = container.getCurrentTLV(); 363 364 if ( tlv == null ) 365 { 366 LOG.error( I18n.err( I18n.ERR_00007 ) ); 367 throw new DecoderException( I18n.err( I18n.ERR_00007 ) ); 368 } 369 370 int length = tlv.getLength(); 371 372 // We will check the length here. What we must control is 373 // that the enclosing constructed TLV expected length is not 374 // exceeded by the current TLV. 375 TLV parentTLV = container.getParentTLV(); 376 377 if ( IS_DEBUG ) 378 { 379 LOG.debug( "Parent length : {}", getParentLength( parentTLV ) ); 380 } 381 382 if ( parentTLV == null ) 383 { 384 // This is the first TLV, so we can't check anything. We will 385 // just store this TLV as the root of the PDU 386 tlv.setExpectedLength( length ); 387 container.setParentTLV( tlv ); 388 389 if ( IS_DEBUG ) 390 { 391 LOG.debug( "Root TLV[{}]", Integer.valueOf( length ) ); 392 } 393 } 394 else 395 { 396 // We have a parent, so we will check that its expected length is 397 // not exceeded. 398 int expectedLength = parentTLV.getExpectedLength(); 399 int currentLength = tlv.getSize(); 400 401 if ( expectedLength < currentLength ) 402 { 403 // The expected length is lower than the Value length of the 404 // current TLV. This is an error... 405 LOG.error( "tlv[{}, {}]", Integer.valueOf( expectedLength ), Integer.valueOf( currentLength ) ); 406 throw new DecoderException( I18n.err( I18n.ERR_00008, Integer.valueOf( currentLength ), Integer.valueOf( expectedLength ) ) ); 407 } 408 409 // deal with the particular case where expected length equal 410 // the current length, which means that the parentTLV has been 411 // completed. 412 if ( expectedLength == currentLength ) 413 { 414 parentTLV.setExpectedLength( 0 ); 415 416 // We also have to check that the current TLV is a constructed 417 // one. 418 // In this case, we have to switch from this parent TLV 419 // to the parent's parent TLV. 420 if ( tlv.isConstructed() ) 421 { 422 // here, we also have another special case : a 423 // zero length TLV. We must then unstack all 424 // the parents which length is null. 425 if ( length == 0 ) 426 { 427 // We will set the parent to the first parentTLV which 428 // expectedLength 429 // is not null, and it will become the new parent TLV 430 while ( parentTLV != null ) 431 { 432 if ( parentTLV.getExpectedLength() != 0 ) 433 { 434 // ok, we have an incomplete parent. we will 435 // stop the recursion right here 436 break; 437 } 438 else 439 { 440 parentTLV = parentTLV.getParent(); 441 } 442 } 443 444 container.setParentTLV( parentTLV ); 445 } 446 else 447 { 448 // The new Parent TLV is this Constructed TLV 449 container.setParentTLV( tlv ); 450 } 451 452 tlv.setParent( parentTLV ); 453 tlv.setExpectedLength( length ); 454 } 455 else 456 { 457 tlv.setExpectedLength( length ); 458 459 // It's over, the parent TLV has been completed. 460 // Go back to the parent's parent TLV until we find 461 // a tlv which is not complete. 462 while ( parentTLV != null ) 463 { 464 if ( parentTLV.getExpectedLength() != 0 ) 465 { 466 // ok, we have an incomplete parent. we will 467 // stop the recursion right here 468 break; 469 } 470 else 471 { 472 parentTLV = parentTLV.getParent(); 473 } 474 } 475 476 container.setParentTLV( parentTLV ); 477 } 478 } 479 else 480 { 481 // Renew the expected Length. 482 parentTLV.setExpectedLength( expectedLength - currentLength ); 483 tlv.setExpectedLength( length ); 484 485 if ( tlv.isConstructed() ) 486 { 487 // We have a constructed tag, so we must switch the 488 // parentTLV 489 tlv.setParent( parentTLV ); 490 container.setParentTLV( tlv ); 491 } 492 } 493 494 } 495 496 if ( IS_DEBUG ) 497 { 498 LOG.debug( "Length {} has been decoded", Integer.valueOf( length ) ); 499 } 500 501 if ( length == 0 ) 502 { 503 // The length is 0, so we can't expect a value. 504 container.setState( TLVStateEnum.TLV_STATE_DONE ); 505 } 506 else 507 { 508 // Go ahead and decode the value part 509 container.setState( TLVStateEnum.VALUE_STATE_START ); 510 } 511 } 512 513 514 /** 515 * Treat the Value part. We will distinguish two cases : - if the Tag is a 516 * Primitive one, we will get the value. - if the Tag is a Constructed one, 517 * nothing will be done. 518 * 519 * @param stream The ByteBuffer containing the PDU to decode 520 * @param container The container that stores the current state, 521 * the result and other informations. 522 * @return <code>true</code> if there are more bytes to read, <code>false 523 * </code> otherwise 524 */ 525 private boolean treatValueStartState( ByteBuffer stream, IAsn1Container container ) 526 { 527 528 TLV currentTlv = container.getCurrentTLV(); 529 530 if ( TLV.isConstructed( currentTlv.getTag() ) ) 531 { 532 container.setState( TLVStateEnum.TLV_STATE_DONE ); 533 534 return MORE; 535 } 536 else 537 { 538 539 int length = currentTlv.getLength(); 540 int nbBytes = stream.remaining(); 541 542 if ( nbBytes < length ) 543 { 544 currentTlv.getValue().init( length ); 545 currentTlv.getValue().setData( stream ); 546 container.setState( TLVStateEnum.VALUE_STATE_PENDING ); 547 548 return END; 549 } 550 else 551 { 552 currentTlv.getValue().init( length ); 553 stream.get( currentTlv.getValue().getData(), 0, length ); 554 container.setState( TLVStateEnum.TLV_STATE_DONE ); 555 556 return MORE; 557 } 558 } 559 } 560 561 562 /** 563 * Treat a pending Value when we get more bytes in the buffer. 564 * 565 * @param stream The ByteBuffer containing the PDU to decode 566 * @param container The container that stores the current state, 567 * the result and other informations. 568 * @return <code>MORE</code> if some bytes remain in the buffer when the 569 * value has been decoded, <code>END</code> if whe still need to get some 570 * more bytes. 571 */ 572 private boolean treatValuePendingState( ByteBuffer stream, IAsn1Container container ) 573 { 574 575 TLV currentTlv = container.getCurrentTLV(); 576 577 int length = currentTlv.getLength(); 578 int currentLength = currentTlv.getValue().getCurrentLength(); 579 int nbBytes = stream.remaining(); 580 581 if ( ( currentLength + nbBytes ) < length ) 582 { 583 currentTlv.getValue().addData( stream ); 584 container.setState( TLVStateEnum.VALUE_STATE_PENDING ); 585 586 return END; 587 } 588 else 589 { 590 591 int remaining = length - currentLength; 592 byte[] data = new byte[remaining]; 593 stream.get( data, 0, remaining ); 594 currentTlv.getValue().addData( data ); 595 container.setState( TLVStateEnum.TLV_STATE_DONE ); 596 597 return MORE; 598 } 599 } 600 601 602 /** 603 * When the TLV has been fully decoded, we have to execute the associated 604 * action and switch to the next TLV, which will start with a Tag. 605 * 606 * @param stream The ByteBuffer containing the PDU to decode 607 * @param container The container that stores the current state, 608 * the result and other informations. 609 * @return <code>true</code> if there are more bytes to read, <code>false 610 * </code> otherwise 611 * @throws DecoderException Thrown if anything went wrong 612 */ 613 private boolean treatTLVDoneState( ByteBuffer stream, IAsn1Container container ) throws DecoderException 614 { 615 if ( IS_DEBUG ) 616 { 617 dumpTLVTree( container ); 618 } 619 620 // First, we have to execute the associated action 621 container.getGrammar().executeAction( container ); 622 623 // Check if the PDU has been fully decoded. 624 if ( isTLVDecoded( container ) ) 625 { 626 if ( container.getState() == IStates.GRAMMAR_END ) 627 { 628 // Change the state to DECODED 629 container.setState( TLVStateEnum.PDU_DECODED ); 630 } 631 else 632 { 633 if ( container.isGrammarEndAllowed() ) 634 { 635 // Change the state to DECODED 636 container.setState( TLVStateEnum.PDU_DECODED ); 637 } 638 else 639 { 640 LOG.error( I18n.err( I18n.ERR_00009 ) ); 641 throw new DecoderException( I18n.err( I18n.ERR_00010 ) ); 642 } 643 } 644 645 } 646 else 647 { 648 // Then we switch to the Start tag state and free the current TLV 649 container.setState( TLVStateEnum.TAG_STATE_START ); 650 } 651 652 return stream.hasRemaining(); 653 } 654 655 656 /** 657 * An helper function that return a string representing the current state 658 * for debuging purpose. 659 * 660 * @param state The state 661 * @return A string representation of the state 662 */ 663 private String stateToString( int state ) 664 { 665 666 switch ( state ) 667 { 668 669 case TLVStateEnum.TAG_STATE_START: 670 return "TAG_STATE_START"; 671 672 case TLVStateEnum.TAG_STATE_END: 673 return "TAG_STATE_END"; 674 675 case TLVStateEnum.TAG_STATE_OVERFLOW: 676 return "TAG_STATE_OVERFLOW"; 677 678 case TLVStateEnum.LENGTH_STATE_START: 679 return "LENGTH_STATE_START"; 680 681 case TLVStateEnum.LENGTH_STATE_PENDING: 682 return "LENGTH_STATE_PENDING"; 683 684 case TLVStateEnum.LENGTH_STATE_END: 685 return "LENGTH_STATE_END"; 686 687 case TLVStateEnum.VALUE_STATE_START: 688 return "VALUE_STATE_START"; 689 690 case TLVStateEnum.VALUE_STATE_PENDING: 691 return "VALUE_STATE_PENDING"; 692 693 case TLVStateEnum.TLV_STATE_DONE: 694 return "TLV_STATE_DONE"; 695 696 default: 697 return "UNKNOWN_STATE"; 698 } 699 } 700 701 702 /** 703 * The decoder main function. This is where we read bytes from the stream 704 * and go through the automaton. It's an inifnite loop which stop when no 705 * more bytes are to be read. It can occurs if the ByteBuffer is exhausted 706 * or if the PDU has been fully decoded. 707 * 708 * @param stream The ByteBuffer containing the PDU to decode 709 * @param container The container that store the state, the result 710 * and other elements. 711 * @throws DecoderException Thrown if anything went wrong! 712 */ 713 public void decode( ByteBuffer stream, IAsn1Container container ) throws DecoderException 714 { 715 716 /* 717 * We have to deal with the current state. This is an infinite loop, 718 * which will stop for any of these reasons : 719 * - STATE_END has been reached (hopefully, the most frequent case) 720 * - buffer is empty (it could happen) 721 * - STATE_OVERFLOW : bad situation ! The PDU may be a 722 * malevolous hand crafted ones, that try to "kill" our decoder. Whe 723 * must log it with all information to track back this case, and punish 724 * the guilty ! 725 */ 726 727 boolean hasRemaining = stream.hasRemaining(); 728 729 // Increment the PDU size counter. 730 container.incrementDecodeBytes( stream.remaining() ); 731 732 if ( container.getDecodeBytes() > container.getMaxPDUSize() ) 733 { 734 String message = "The PDU current size (" + container.getDecodeBytes() + 735 ") exceeds the maximum allowed PDU size (" + container.getMaxPDUSize() +")"; 736 LOG.error( message ); 737 throw new DecoderException( message ); 738 } 739 740 if ( IS_DEBUG ) 741 { 742 LOG.debug( ">>>==========================================" ); 743 LOG.debug( "--> Decoding a PDU" ); 744 LOG.debug( ">>>------------------------------------------" ); 745 } 746 747 while ( hasRemaining ) 748 { 749 750 if ( IS_DEBUG ) 751 { 752 LOG.debug( "--- State = {} ---", stateToString( container.getState() ) ); 753 754 if ( stream.hasRemaining() ) 755 { 756 byte octet = stream.get( stream.position() ); 757 758 LOG.debug( " current byte : {}", Asn1StringUtils.dumpByte( octet ) ); 759 } 760 else 761 { 762 LOG.debug( " no more byte to decode in the stream" ); 763 } 764 } 765 766 switch ( container.getState() ) 767 { 768 769 case TLVStateEnum.TAG_STATE_START: 770 // Reset the GrammarEnd flag first 771 container.grammarEndAllowed( false ); 772 hasRemaining = treatTagStartState( stream, container ); 773 774 break; 775 776 case TLVStateEnum.LENGTH_STATE_START: 777 hasRemaining = treatLengthStartState( stream, container ); 778 779 break; 780 781 case TLVStateEnum.LENGTH_STATE_PENDING: 782 hasRemaining = treatLengthPendingState( stream, container ); 783 784 break; 785 786 case TLVStateEnum.LENGTH_STATE_END: 787 treatLengthEndState( container ); 788 789 break; 790 791 case TLVStateEnum.VALUE_STATE_START: 792 hasRemaining = treatValueStartState( stream, container ); 793 794 break; 795 796 case TLVStateEnum.VALUE_STATE_PENDING: 797 hasRemaining = treatValuePendingState( stream, container ); 798 799 break; 800 801 case TLVStateEnum.VALUE_STATE_END: 802 hasRemaining = stream.hasRemaining(); 803 804 // Nothing to do. We will never reach this state 805 break; 806 807 case TLVStateEnum.TLV_STATE_DONE: 808 hasRemaining = treatTLVDoneState( stream, container ); 809 810 break; 811 812 case TLVStateEnum.PDU_DECODED: 813 // We have to deal with the case where there are 814 // more bytes in the buffer, but the PDU has been decoded. 815 LOG.warn( "The PDU has been fully decoded but there are still bytes in the buffer." ); 816 817 hasRemaining = false; 818 819 break; 820 821 default : 822 break; 823 } 824 } 825 826 if ( IS_DEBUG ) 827 { 828 LOG.debug( "<<<------------------------------------------" ); 829 830 if ( container.getState() == TLVStateEnum.PDU_DECODED ) 831 { 832 if ( container.getCurrentTLV() != null ) 833 { 834 LOG.debug( "<-- Stop decoding : {}", container.getCurrentTLV().toString() ); 835 } 836 else 837 { 838 LOG.debug( "<-- Stop decoding : null current TLV" ); 839 } 840 } 841 else 842 { 843 if ( container.getCurrentTLV() != null ) 844 { 845 LOG.debug( "<-- End decoding : {}", container.getCurrentTLV().toString() ); 846 } 847 else 848 { 849 LOG.debug( "<-- End decoding : null current TLV" ); 850 } 851 } 852 853 LOG.debug( "<<<==========================================" ); 854 } 855 856 return; 857 } 858 859 860 /** 861 * Get the length's Length. 862 * 863 * @return Returns the length's Length. 864 */ 865 public int getMaxLengthLength() 866 { 867 return maxLengthLength; 868 } 869 870 871 /** 872 * Get the maximum Tag's length 873 * 874 * @return Returns the maximum tag Length. 875 */ 876 public int getMaxTagLength() 877 { 878 return maxTagLength; 879 } 880 881 882 /** 883 * Disallow indefinite length. 884 */ 885 public void disallowIndefiniteLength() 886 { 887 this.indefiniteLengthAllowed = false; 888 } 889 890 891 /** 892 * Allow indefinite length. 893 */ 894 public void allowIndefiniteLength() 895 { 896 this.indefiniteLengthAllowed = true; 897 } 898 899 900 /** 901 * Tells if indefinite length form could be used for Length 902 * 903 * @return Returns <code>true</code> if the current decoder support 904 * indefinite length 905 */ 906 public boolean isIndefiniteLengthAllowed() 907 { 908 909 return indefiniteLengthAllowed; 910 } 911 912 913 /** 914 * Set the maximul length for a Length 915 * 916 * @param maxLengthLength The lengthLength to set. 917 * @throws DecoderException Thrown if the indefinite length is 918 * allowed or if the length's Length is above 126 bytes 919 */ 920 public void setMaxLengthLength( int maxLengthLength ) throws DecoderException 921 { 922 923 if ( ( this.indefiniteLengthAllowed ) && ( maxLengthLength > 126 ) ) 924 { 925 throw new DecoderException( I18n.err( I18n.ERR_00011 ) ); 926 } 927 928 this.maxLengthLength = maxLengthLength; 929 } 930 931 932 /** 933 * Set the maximum Tag length 934 * 935 * @param maxTagLength The tagLength to set. 936 */ 937 public void setMaxTagLength( int maxTagLength ) 938 { 939 this.maxTagLength = maxTagLength; 940 } 941 }