/// <summary> Create an error SIF_Ack for this message.</summary> /// <param name="category">The value of the SIF_Error/SIF_Category element /// </param> /// <param name="code">The value of the SIF_Error/SIF_Code element /// </param> /// <param name="desc">The value of the SIF_Error/SIF_Desc element /// </param> /// <param name="extDesc">The value of the SIF_Error/SIF_ExtendedDesc element /// </param> /// <returns> A new SIF_Ack instance with a SIF_Error element and SIF_Ack /// header values derived from this message's header values /// </returns> public virtual SIF_Ack AckError(SifErrorCategoryCode category, int code, string desc, string extDesc) { SIF_Ack ack = new SIF_Ack(); ack.SIF_OriginalMsgId = this.MsgId; ack.SIF_OriginalSourceId = this.SourceId; SIF_Error error = new SIF_Error ( (int)category, code, desc ?? ""); if (extDesc != null) { error.SIF_ExtendedDesc = extDesc; } ack.SIF_Error = error; // Ack using the same version of SIF as this message ack.SifVersion = SifVersion; return(ack); }
/// <summary> Create a SIF_Ack for this message.</summary> /// <param name="code">The SIF_Status/SIF_Code value /// </param> /// <returns> A new SIF_Ack instance where the SIF_Status/SIF_Code value is /// set to the specified value and SIF_Ack header values are derived /// from this message's header values /// </returns> public virtual SIF_Ack ackStatus(int code) { SIF_Ack ack = new SIF_Ack(); SIF_Status status = new SIF_Status(code); ack.SIF_Status = status; ack.SIF_OriginalMsgId = MsgId; ack.SIF_OriginalSourceId = SourceId; SifVersion msgVersion = this.SifVersion; if (code == 8 /* Receiver is sleeping */) { if (msgVersion.Major == 1) { // SIF 1.x used SIF_Data for text SIF_Data d = new SIF_Data(); d.TextValue = "Receiver is sleeping"; status.SIF_Data = d; } else { status.SIF_Desc = "Receiver is sleeping"; } } ack.message = this; // Ack using the same version of SIF as this message ack.SifVersion = msgVersion; return(ack); }
/// <summary> Constructs an exception to wrap one or more SIF_Errors received from an /// inbound SIF_Ack message. This form of constructor is only called by /// the Adk. /// </summary> public SifException(SIF_Ack ack, IZone zone) : base(null, zone) { fAck = ack; fError = ack != null ? ack.SIF_Error : null; }
private void AckPush(SIF_Ack ack, AdkHttpResponse response) { try { // Set SIF_Ack / SIF_Header fields SIF_Header hdr = ack.Header; hdr.SIF_Timestamp = DateTime.Now; hdr.SIF_MsgId = SifFormatter.GuidToSifRefID(Guid.NewGuid()); hdr.SIF_SourceId = this.Zone.Agent.Id; ack.LogSend(this.Zone.Log); response.ContentType = SifIOFormatter.CONTENTTYPE; // TODO: This code may need to change. The ADKHttpResponse should not automatically set the content length // and other implementations will not do so. SifWriter w = new SifWriter(response.GetResponseStream()); w.Write(ack); w.Flush(); } catch (Exception thr) { Console.Out.WriteLine ("HttpProtocolHandler failed to send SIF_Ack for pushed message (zone=" + this.Zone.ZoneId + "): " + thr); throw new AdkHttpException (AdkHttpStatusCode.ServerError_500_Internal_Server_Error, thr.Message, thr); } }
/// <summary> Constructs an exception to wrap one or more SIF_Errors received from an /// inbound SIF_Ack message. This form of constructor is only called by /// the Adk. /// </summary> public SifException(string msg, SIF_Ack ack, IZone zone) : base(msg, zone) { fAck = ack; fError = ack != null ? ack.SIF_Error : null; }
/// <summary> /// Constructs a SifException for delivery to the ZIS /// </summary> /// <param name="category">A <c>SifErrorCategoryCode.</c> error category</param> /// <param name="code">A <c>SifErrorCodes</c> error code</param> /// <param name="desc">The error description</param> /// <param name="extDesc">An option extended error description</param> /// <param name="zone">The zone on which the error occurred</param> /// <param name="innerException">The internal error that was thrown by the agent</param> /// <remarks> /// The Adk will include /// the error information provided by the exception when it sends a SIF_Ack /// in response to the message being processed. This form of constructor is /// typically called by the Adk, but may also be called by agent code if an /// exception occurs in a <c>IPublisher</c>, <c>ISubscriber</c>, or <c>IQueryResults</c> /// message handler implementation. /// </remarks> public SifException(SifErrorCategoryCode category, int code, string desc, string extDesc, IZone zone, Exception innerException) : base(desc, zone, innerException) { fAck = null; fError = new SIF_Error((int)category, code, desc == null ? "" : desc); if (extDesc != null) { fError.SIF_ExtendedDesc = extDesc; } }
public void ParseSIF_LogEntry2() { // This test attempts to parse SIF_LogEntry, Console.WriteLine("Parsing from file..."); SifParser p = SifParser.NewInstance(); SIF_Ack logMsg = null; using (Stream inStream = GetResourceStream("SIF_LogEntry2.xml")) { logMsg = (SIF_Ack)p.Parse(inStream, null, SifParserFlags.ExpectInnerEnvelope, SifVersion.SIF20r1); inStream.Close(); } Assert.IsNotNull(logMsg); //AdkObjectParseHelper.runParsingTest( logMsg ); }
/** * If the SIF_OriginalMsgID or SIF_OriginalSourceId are not set, * process according to Infrastructure resolution #157 * @param errorAck */ public static void SetRequiredAckValues(SIF_Ack errorAck) { // Return a SIF_Ack with a blank SIF_OriginalSourceId and // SIF_OriginalMsgId per SIFInfra resolution #157 // Also See 4.1.2.1 SIF_Message processing if (errorAck.GetField(InfraDTD.SIF_ACK_SIF_ORIGINALMSGID) == null) { // Set SIF_OriginalMsgId to xsi:nill errorAck.SetField(InfraDTD.SIF_ACK_SIF_ORIGINALMSGID, new SifString(null)); } if (errorAck.GetField(InfraDTD.SIF_ACK_SIF_ORIGINALSOURCEID) == null) { // Set SIF_OriginalSource to an empty string errorAck.SIF_OriginalSourceId = ""; } }
private static IMessageInputStream makeAck() { SIF_Ack retval = new SIF_Ack(); retval.SIF_Status = new SIF_Status( 0 ); MemoryStream ms = new MemoryStream(); try { SifWriter sifWriter = new SifWriter( ms ); sifWriter.Write( retval ); sifWriter.Flush(); //sifWriter.Close(); MessageStreamImpl imp = new MessageStreamImpl( ms ); return (IMessageInputStream) imp; } catch ( Exception ) { return null; } }
/// <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> /// Attempts to parse attributes out of the source message enough to make a valid /// SIF_Ack with a SIF_Error. This is useful in conditions where the source message cannot /// be parsed by the ADK /// </summary> /// <param name="sourceMessage"> The original message as a string</param> /// <param name="error">The error to place in the SIF_Ack/SIF_Error</param> /// <param name="zone">The zone associated with this message</param> /// <returns></returns> /// <exception cref="AdkMessagingException"></exception> public static SIF_Ack ackError(String sourceMessage, SifException error, ZoneImpl zone) { SifMessageInfo parsed = null; try { StringReader reader = new StringReader(sourceMessage); parsed = SifMessageInfo.Parse(reader, false, zone); reader.Close(); } catch (Exception e) { zone.Log.Error(e, e); } SIF_Ack errorAck = new SIF_Ack(zone.HighestEffectiveZISVersion); if (parsed != null) { // Set SIFVersion, OriginalSourceId, and OriginalMsgId; if (parsed.SifVersion != null) { errorAck.SifVersion = parsed.SifVersion; } errorAck.SIF_OriginalMsgId = parsed.GetAttribute("SIF_MsgId"); errorAck.SIF_OriginalSourceId = parsed.GetAttribute("SIF_SourceId"); } SetRequiredAckValues(errorAck); SIF_Error newErr = new SIF_Error(); newErr.SIF_Category = (int)error.ErrorCategory; newErr.SIF_Code = error.ErrorCode; newErr.SIF_Desc = error.ErrorDesc; newErr.SIF_ExtendedDesc = error.ErrorExtDesc; errorAck.SIF_Error = newErr; return(errorAck); }
public void EmbeddedSIFMessage() { SifElement element = null; using (Stream aStream = GetResourceStream("GetNextMessageResponse.xml")) { TextReader aReader = new StreamReader(aStream); SifParser parser = SifParser.NewInstance(); element = parser.Parse(aReader, null, SifParserFlags.ExpectInnerEnvelope, SifVersion.SIF11); aReader.Close(); aStream.Close(); } Assert.IsNotNull(element, "SIFElement was not parsed"); SIF_Ack ack = (SIF_Ack)element; SifElement messageElement = ack.SIF_Status.SIF_Data.GetChild("SIF_Message"); SIF_Event aEvent = (SIF_Event)messageElement.GetChild("SIF_Event"); SIF_EventObject eventObject = aEvent.SIF_ObjectData.SIF_EventObject; Assert.AreEqual("SchoolCourseInfo", eventObject.ObjectName, "Wrong object name"); Assert.AreEqual("Change", eventObject.Action, "Wrong Action"); Assert.IsTrue(eventObject.GetChildList()[0] is SchoolCourseInfo, "Wrong object type"); }
//public string Send(string msg) //{ // lock (this) // { // fMessages.AddLast(msg); // } // return makeAck(); //} public IMessageInputStream Send( IMessageOutputStream msg ) { lock ( this ) { try { MemoryStream stream = new MemoryStream(); msg.CopyTo( stream ); stream.Seek( 0, SeekOrigin.Begin ); SifParser parser = SifParser.NewInstance(); SifMessagePayload smp = (SifMessagePayload) parser.Parse( stream, fZone ); fMessages.Add( smp ); parser = null; SIF_Ack ack = smp.ackStatus( 0 ); SIF_Header hdr = ack.Header; hdr.SIF_Timestamp = DateTime.Now; hdr.SIF_MsgId = Adk.MakeGuid(); hdr.SIF_SourceId = fZone.Agent.Id; StringWriter str = new StringWriter(); SifWriter writer = new SifWriter( str ); writer.Write( ack ); writer.Flush(); writer.Close(); writer = null; return new MessageStreamImpl( str.ToString() ); } catch( Exception ex ) { // Possible error parsing. Write the message to console out Console.Out.WriteLine(msg.Decode()); throw new AdkMessagingException(ex.Message, fZone, ex); } } }
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); }