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    }