/// <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); }
/// <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 ); }