boolean consumeBuffer()

in yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPIncomingMessage.java [306:586]


    boolean consumeBuffer(org.apache.yoko.orb.OCI.Buffer buf) {
        //
        // Consume input buffer
        //
        boolean result = false;

        //
        // Handle initial fragmented message
        //
        if (fragment_ && type_ != org.omg.GIOP.MsgType_1_1.Fragment) {
            if (version_.minor < 1) {
                throw new org.omg.CORBA.COMM_FAILURE(org.apache.yoko.orb.OB.MinorCodes
                        .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorFragment),
                        org.apache.yoko.orb.OB.MinorCodes.MinorFragment,
                        org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
            } else if (version_.minor == 1) {
                //
                // In GIOP 1.1, fragments are only supported for request and
                // reply messages
                //
                if (type_ != org.omg.GIOP.MsgType_1_1.Request
                        && type_ != org.omg.GIOP.MsgType_1_1.Reply)
                    throw new org.omg.CORBA.COMM_FAILURE(org.apache.yoko.orb.OB.MinorCodes
                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorFragment),
                            org.apache.yoko.orb.OB.MinorCodes.MinorFragment,
                            org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);

                //
                // If lastFragment_ is not 0, then the previous fragmented
                // message may have been cancelled
                //
                if (lastFragment_ != null)
                    lastFragment_ = null;

                //
                // Try to obtain the request ID by unmarshalling the
                // Request or Reply header data. If the header is fragmented,
                // a MARSHAL exception could be raised if we don't have enough
                // data.
                //
                int reqId = 0;
                boolean haveReqId = false;
                try {
                    org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
                            buf, 12, swap());
                    skipServiceContextList(in);
                    reqId = in.read_ulong();
                    haveReqId = true;
                } catch (org.omg.CORBA.MARSHAL ex) {
                }

                lastFragment_ = new Fragment();
                lastFragment_.version = new org.omg.GIOP.Version(
                        version_.major, version_.minor);
                lastFragment_.byteOrder = byteOrder_;
                lastFragment_.reqId = reqId;
                lastFragment_.haveReqId = haveReqId;
                lastFragment_.type = type_;
                lastFragment_.buf = buf;
                lastFragment_.next = null;
            } else // GIOP 1.2
            {
                //
                // In GIOP 1.2, fragments are only supported for request,
                // reply, locate request and locate reply messages
                //
                if (type_ != org.omg.GIOP.MsgType_1_1.Request
                        && type_ != org.omg.GIOP.MsgType_1_1.Reply
                        && type_ != org.omg.GIOP.MsgType_1_1.LocateRequest
                        && type_ != org.omg.GIOP.MsgType_1_1.LocateReply) {
                    throw new org.omg.CORBA.COMM_FAILURE(org.apache.yoko.orb.OB.MinorCodes
                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorFragment),
                            org.apache.yoko.orb.OB.MinorCodes.MinorFragment,
                            org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
                }

                //
                // Try to obtain the request ID by unmarshalling the
                // header data. If the header is fragmented, a MARSHAL
                // exception could be raised if we don't have enough
                // data.
                //
                int reqId = 0;
                boolean haveReqId = false;
                try {
                    org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
                            buf, 12, swap());
                    reqId = in.read_ulong();
                    haveReqId = true;
                } catch (org.omg.CORBA.MARSHAL ex) {
                }

                //
                // What to do if initial message doesn't contain the
                // request ID?
                //
                Assert._OB_assert(haveReqId);

                //
                // Add new fragment to fragment list
                //
                Fragment f = new Fragment();
                f.version = new org.omg.GIOP.Version(version_.major,
                        version_.minor);
                f.byteOrder = byteOrder_;
                f.reqId = reqId;
                f.haveReqId = haveReqId;
                f.type = type_;
                f.buf = buf;
                f.next = fragmentHead_;
                fragmentHead_ = f;
            }
        } else if (type_ == org.omg.GIOP.MsgType_1_1.Fragment) {
            Fragment complete = null;

            if (version_.minor < 1) {
                //
                // Fragment not supported in GIOP 1.0
                //
                throw new org.omg.CORBA.COMM_FAILURE(org.apache.yoko.orb.OB.MinorCodes
                        .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorFragment),
                        org.apache.yoko.orb.OB.MinorCodes.MinorFragment,
                        org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
            } else if (version_.minor == 1) {
                //
                // If lastFragment_ == 0, then we received a Fragment message
                // without an initial message
                //
                if (lastFragment_ == null)
                    throw new org.omg.CORBA.COMM_FAILURE(org.apache.yoko.orb.OB.MinorCodes
                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorFragment),
                            org.apache.yoko.orb.OB.MinorCodes.MinorFragment,
                            org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);

                //
                // Append buffer to existing data. We need to skip the
                // header data (the input stream is already positioned
                // past the header).
                //
                lastFragment_.add(orbInstance_, buf);

                //
                // If we haven't read the request ID yet, then try to
                // get it now
                //
                if (!lastFragment_.haveReqId) {
                    org.apache.yoko.orb.CORBA.InputStream reqIn = new org.apache.yoko.orb.CORBA.InputStream(
                            lastFragment_.buf, 12, swap());
                    try {
                        skipServiceContextList(reqIn);
                        lastFragment_.reqId = reqIn.read_ulong();
                        lastFragment_.haveReqId = true;
                    } catch (org.omg.CORBA.MARSHAL ex) {
                    }
                }

                //
                // If fragment_ == false, then this is the last fragment
                //
                if (!fragment_) {
                    complete = lastFragment_;
                    lastFragment_ = null;
                }
            } else // GIOP 1.2
            {
                //
                // GIOP 1.2 defines the FragmentHeader message header,
                // to allow interleaving of Fragment messages for
                // different requests
                //
                org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
                        buf, 12, swap());
                int reqId = readFragmentHeader(in);

                //
                // Find fragment data for request
                //
                Fragment frag = null;
                Fragment p = fragmentHead_;
                Fragment prev = null;
                while (p != null) {
                    Fragment f = p;
                    if (f.haveReqId && f.reqId == reqId) {
                        frag = f;
                        break;
                    } else {
                        prev = p;
                        p = f.next;
                    }
                }

                //
                // If no fragment was found for the request, then either
                // the request was discarded, or the server is sending
                // invalid messages. Otherwise, we can append the buffer
                // to the existing data.
                //
                if (frag != null) {
                    //
                    // Append buffer to existing data. We need to skip the
                    // header data (the input stream is already positioned
                    // past the header).
                    //
                    frag.add(orbInstance_, in._OB_buffer());

                    //
                    // If fragment_ == false, then this is the last fragment
                    //
                    if (!fragment_) {
                        //
                        // Remove fragment from list
                        //
                        if (prev == null)
                            fragmentHead_ = frag.next;
                        else
                            prev.next = frag.next;
                        complete = frag;
                    }
                }
            }

            //
            // We have received the last fragment, so reset our internal
            // state to appear as if we had just received the entire message
            //
            if (complete != null) {
                version_ = complete.version;
                byteOrder_ = complete.byteOrder;
                type_ = complete.type;
                fragment_ = false;
                // NOTE:  size_ is the size of the message, which doesn't 
                // include the message header.  We need to adjust this for 
                // fragmented messages otherwise we risk not detecting the 
                // correct end of the buffer. 
                size_ = complete.buf.length() - 12;
                in_ = new org.apache.yoko.orb.CORBA.InputStream(complete.buf,
                        12, swap());
                complete = null;
                result = true;
            }
        } else if (type_ == org.omg.GIOP.MsgType_1_1.CancelRequest) {
            in_ = new org.apache.yoko.orb.CORBA.InputStream(buf, 12, swap());

            //
            // Check if cancelled message corresponds to a fragment
            //
            int reqId = readCancelRequestHeader();

            if (version_.minor == 1) // GIOP 1.1
            {
                if (lastFragment_ != null && lastFragment_.haveReqId
                        && lastFragment_.reqId == reqId) {
                    lastFragment_ = null;
                }
            } else // GIOP 1.2
            {
                Fragment p = fragmentHead_;
                while (p != null) {
                    Fragment f = p;
                    if (f.haveReqId && f.reqId == reqId) {
                        p = f.next;
                        f = null;
                        break;
                    } else
                        p = f.next;
                }
            }

            in_._OB_reset();
            result = true;
        } else {
            //
            // Message is not fragmented and is not a CancelRequest, so
            // we must have the complete message
            //
            in_ = new org.apache.yoko.orb.CORBA.InputStream(buf, 12, swap());
            result = true;
        }

        return result;
    }