Exemplo n.º 1
0
        /// <summary>
        /// Create an error SIF_Ack for this message.
        /// </summary>
        /// <param name="sifEx">The SIFException that is the cause of the error</param>
        /// <returns></returns>
        public SIF_Ack AckError(SifException sifEx)
        {
            SIF_Ack ack = new SIF_Ack();

            ack.message = this;

            ack.SIF_OriginalMsgId    = this.MsgId;
            ack.SIF_OriginalSourceId = this.SourceId;

            SIF_Error error = new SIF_Error(
                sifEx.ErrorCategory,
                sifEx.ErrorCode,
                sifEx.ErrorDesc,
                sifEx.ErrorExtDesc);

            ack.SIF_Error = error;

            //  Ack using the same version of SIF as this message
            ack.SifVersion = this.SifVersion;

            return(ack);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Create an error SIF_Ack for this message.
        /// </summary>
        /// <param name="sifEx">The SIFException that is the cause of the error</param>
        /// <returns></returns>
        public SIF_Ack AckError(SifException sifEx)
        {
            SIF_Ack ack = new SIF_Ack();
            ack.message = this;

            ack.SIF_OriginalMsgId = this.MsgId;
            ack.SIF_OriginalSourceId = this.SourceId;

            SIF_Error error = new SIF_Error(
                sifEx.ErrorCategory,
                sifEx.ErrorCode,
                sifEx.ErrorDesc,
                sifEx.ErrorExtDesc);

            ack.SIF_Error = error;

            //  Ack using the same version of SIF as this message
            ack.SifVersion = this.SifVersion;

            return ack;
        }
        public void ProcessRequest( AdkHttpRequestContext context )
        {
            if ( (Adk.Debug & AdkDebugFlags.Messaging) != 0 ) {
                Zone.Log.Debug
                    ( "Received push message from " + context.Request.RemoteAddress + " (" +
                      context.Request.Url.Scheme + ")" );
            }

            SIF_Ack ack = null;
            SifMessagePayload parsed = null;

            //Check request length and type
            if (!SifIOFormatter.IsValidContentLength(context.Request.ContentLength)) {
                throw new AdkHttpException
                    ( AdkHttpStatusCode.ClientError_400_Bad_Request,
                      "Content length Must be greater than zero" );
            }

            if (!SifIOFormatter.IsValidContentMediaType(context.Request.ContentType)) {
                throw new AdkHttpException(AdkHttpStatusCode.ClientError_415_Unsupported_Media_Type,
                    "Content header does not support the specified media type: " + context.Request.ContentType);
            }

            //  Read raw content
            Stream requestStream = context.Request.GetRequestStream();
            StringBuilder requestXml = null;

            // If we need to convert the request stream to a string for either logging or messaging, do so
            if ( (Adk.Debug & AdkDebugFlags.Message_Content) != 0 ) {
                requestXml = ConvertRequestToString( requestStream );
                Zone.Log.Debug
                    ( "Received " + context.Request.ContentLength + " bytes:\r\n" +
                      requestXml.ToString() );
            }

            TextReader requestReader = new StreamReader( requestStream, SifIOFormatter.ENCODING );

            Exception parseEx = null;
            bool reparse = false;
            bool cancelled = false;
            int reparsed = 0;

            do {
                try {
                    parseEx = null;

                    //  Parse content
                    parsed = (SifMessagePayload) CreateParser().Parse( requestReader, Zone );
                    reparse = false;
                    parsed.LogRecv( Zone.Log );
                }
                catch ( AdkParsingException adke ) {
                    parseEx = adke;
                }
                catch ( Exception ex ) {
                    parseEx = ex;
                }

                //
                //	Notify listeners...
                //
                //	If we're asked to reparse the message, do so but do not notify
                //	listeners the second time around.
                //
                if ( reparsed == 0 ) {
                   ICollection<IMessagingListener> msgList = MessageDispatcher.GetMessagingListeners(Zone);
                    if ( msgList.Count > 0 ) {
                        // Convert the stream to a string builder
                        if ( requestXml == null ) {
                            requestXml = ConvertRequestToString( requestStream );
                        }

                        //	Determine message type before parsing
                        foreach ( IMessagingListener listener in msgList ) {
                            try {
                                SifMessageType pload =
                                    Adk.Dtd.GetElementType( parsed.ElementDef.Name );
                                MessagingReturnCode code =
                                    listener.OnMessageReceived( pload, requestXml );
                                switch ( code ) {
                                    case MessagingReturnCode.Discard:
                                        cancelled = true;
                                        break;

                                    case MessagingReturnCode.Reparse:
                                        requestReader = new StringReader( requestXml.ToString() );
                                        reparse = true;
                                        break;
                                }
                            }
                            catch ( AdkException adke ) {
                                parseEx = adke;
                            }
                        }
                    }
                }

                if ( cancelled ) {
                    return;
                }

                reparsed++;
            }
            while ( reparse );

            if ( parseEx != null ) {
                //  TODO: Handle the case where SIF_OriginalSourceId and SIF_OriginalMsgId
                //  are not available because parsing failed. See SIFInfra
                //  Resolution #157.
                if( parseEx is SifException && parsed != null )
                {
                    //  Specific SIF error already provided to us by SIFParser
                    ack = parsed.AckError( (SifException)parseEx );
                }
                else{
                    String errorMessage = null;
                    if( parseEx is AdkException )
                    {
                        errorMessage = parseEx.Message;
                    } else {
                        // Unchecked Throwable
                        errorMessage = "Could not parse message";
                    }

                    if( parsed == null )
                    {
                        SifException sifError = null;
                        if( parseEx is SifException ){
                            sifError = (SifException) parseEx;

                        }else {
                            sifError = new SifException(
                                SifErrorCategoryCode.Xml,
                                SifErrorCodes.XML_GENERIC_ERROR_1,
                                "Could not parse message",
                                parseEx.ToString(),
                                this.Zone,
                                parseEx );
                        }
                        if( requestXml == null )
                        {
                            requestXml = ConvertRequestToString( requestStream );
                        }
                        ack = SIFPrimitives.ackError(
                                requestXml.ToString( ),
                                sifError,
                                this.Zone );
                    }
                    else
                    {
                        ack = parsed.AckError(
                            SifErrorCategoryCode.Generic,
                            SifErrorCodes.GENERIC_GENERIC_ERROR_1,
                            errorMessage,
                            parseEx.ToString() );
                    }

                }

                if ( (Adk.Debug & AdkDebugFlags.Messaging) != 0 ) {
                    Zone.Log.Warn
                        ( "Failed to parse push message from zone \"" + Zone + "\": " + parseEx );
                }

                if ( ack != null ) {
                    //  Ack messages in the same version of SIF as the original message
                    if ( parsed != null ) {
                        ack.SifVersion = parsed.SifVersion;
                    }
                    AckPush( ack, context.Response );
                }
                else {
                    //  If we couldn't build a SIF_Ack, returning an HTTP 500 is
                    //  probably the best we can do to let the server know that
                    //  we didn't get the message. Note this should cause the ZIS
                    //  to resend the message, which could result in a deadlock
                    //  condition. The administrator would need to manually remove
                    //  the offending message from the agent's queue.

                    if ( (Adk.Debug & AdkDebugFlags.Messaging) != 0 ) {
                        Zone.Log.Debug
                            ( "Could not generate SIF_Ack for failed push message (returning HTTP/1.1 500)" );
                    }
                    throw new AdkHttpException
                        ( AdkHttpStatusCode.ServerError_500_Internal_Server_Error,
                          "Could not generate SIF_Ack for failed push message (returning HTTP/1.1 500)" );
                }

                return;
            }

            //  Check SourceId to see if it matches this agent's SourceId
            String destId = parsed.DestinationId;
            if ( destId != null && !destId.Equals( Zone.Agent.Id ) ) {
                Zone.Log.Warn
                    ( "Received push message for DestinationId \"" + destId +
                      "\", but agent is registered as \"" + Zone.Agent.Id + "\"" );

                ack = parsed.AckError
                    (
                    SifErrorCategoryCode.Transport,
                    SifErrorCodes.WIRE_GENERIC_ERROR_1,
                    "Message not intended for this agent (SourceId of agent does not match DestinationId of message)",
                    "Message intended for \"" + destId + "\" but this agent is registered as \"" +
                    Zone.Agent.Id + "\"" );

                AckPush( ack, context.Response );

                return;
            }

            //  Convert content to SIF message object and dispatch it
            ack = ProcessPush( parsed );

            //  Send SIF_Ack reply
            AckPush( ack, context.Response );
        }