/// <summary> Adds a zone to this topic</summary> /// <param name="zone">The Zone to join with this topic /// </param> /// <exception cref="OpenADK.Library.AdkException"> AdkException is thrown if the zone is already joined to a /// topic or if there is a SIF error during agent registration. /// </exception> public void Join(IZone zone) { lock (this) { // Check that zone is not already joined with this topic if (fZones.Contains(zone)) { AdkUtils._throw (new SystemException ("Zone already joined with topic \"" + fObjType + "\""), ((ZoneImpl)zone).Log); } // Check that topic has a Provider, Subscriber, or QueryResults object if (fSub == null && fPub == null && fQueryResults == null) { AdkUtils._throw ( new SystemException ( "Agent has not registered a Subscriber, Publisher, or QueryResults object with this topic"), ((ZoneImpl)zone).Log); } fZones.Add(zone); if (zone.Connected) { ((ZoneImpl)zone).Provision(); } } }
public void Query(Query query, IMessagingListener listener, string destinationId, AdkQueryOptions queryOptions) { if (query == null) { AdkUtils._throw (new ArgumentException("Query object cannot be null"), Agent.GetLog()); } // Validate that the query object type and SIF Context are valid for this Topic if (query.ObjectType != fObjType) { AdkUtils._throw(new ArgumentException("Query object type: {" + query.ObjectTag + "} does not match Topic object type: " + fObjType + "}"), log); } if (!query.SifContext.Equals(fContext)) { AdkUtils._throw(new ArgumentException("Query SIF_Context: {" + query.SifContext + "} does not match Topic SIF_Context: " + fContext + "}"), log); } _checkZones(); AdkMessagingException err = null; // Send the SIF_Request to each zone foreach (ZoneImpl z in fZones) { try { z.Query(query, listener, destinationId, queryOptions); } catch (Exception th) { if (err == null) { err = new AdkMessagingException ("Error querying topic \"" + fObjType + "\"", z); } if (th is AdkException) { err.Add(th); } else { err.Add(new AdkMessagingException(th.ToString(), z)); } } } if (err != null) { AdkUtils._throw(err, Agent.GetLog()); } }
/// <summary> Configure the server for HTTP as needed based on the settings of /// this Transport object. If the server does not have a SocketListener on /// the port specified for this transport, one is created. /// configuration is performed dynamically as HttpTransport objects are /// created, so listeners are added to the server the first time they are /// needed. /// </summary> protected void ConfigureServer(IZone zone) { AdkSocketBinding newListener; if (String.Compare(Protocol, "http", true) == 0) { newListener = ConfigureHttp(zone); } else if (String.Compare(Protocol, "https", true) == 0) { newListener = ConfigureHttps(zone); } else { throw new Exception("HttpTransport object configured with properties for another protocol: " + fProps.Protocol); } if (newListener != null) { sServer.AddListener(newListener); try { newListener.Start(); } catch (Exception le) { AdkUtils._throw( new AdkTransportException("Error starting SocketListener: " + le.Message, zone, le), log); } } }
public void PublishEvent(Event data) { AdkMessagingException err = null; _checkZones(); foreach (ZoneImpl z in fZones) { try { z.fPrimitives.SifEvent(z, data, null, null); } catch (Exception th) { if (err == null) { err = new AdkMessagingException ("Error publishing event to topic \"" + fObjType + "\"", z); } if (th is AdkException) { err.Add(th); } else { err.Add(new AdkMessagingException(th.ToString(), z)); } } } if (err != null) { AdkUtils._throw(err, Agent.GetLog()); } }
/// <summary> /// Sends a specific packet to the zone /// </summary> /// <param name="file"></param> /// <param name="morePackets"></param> protected internal virtual void SendPacket(FileInfo file, bool morePackets) { long extraBytes = 0; ResponsePacketInfo responsePacket = DeserializeResponseFileName(file.Name); /* If we're processing SIF_ReportObject responses, read the ReportInfo * data from the "requestMsgId.rpt" file * * TT 894 - If a SIFException is thrown after the ReportInfo is set on * the ReportObjectStream, then we don't want to include that ReportInfo * in the packet with the error. In that case, rptInfoReader will be * null and will not be included in the list of payloads below. */ FileStream rptInfoStream = null; if (fSrc == ResponseDeliveryType.SIFReportObject && !responsePacket.errorPacket) { try { FileInfo f = new FileInfo (fWorkDir + Path.DirectorySeparatorChar.ToString() + responsePacket.destinationId + "." + responsePacket.requestMsgId + ".rpt"); rptInfoStream = f.OpenRead(); extraBytes = f.Length; } catch (FileNotFoundException fnfe) { fZone.Log.Debug ("Error sending SIF_ReportObject packet #" + responsePacket.packetNumber + (morePackets ? "" : " (last packet)") + ", file not found: " + fnfe.Message); } } if ((Adk.Debug & AdkDebugFlags.Messaging) != 0) { fZone.Log.Debug ("Sending " + (responsePacket.errorPacket ? "SIF_Error response" : "SIF_Response") + " packet #" + responsePacket.packetNumber + (morePackets ? "" : " (last packet)")); } // Prepare SIF_Response SIF_Response rsp = new SIF_Response(); rsp.SetSIF_MorePackets(morePackets ? YesNo.YES : YesNo.NO); rsp.SIF_RequestMsgId = responsePacket.requestMsgId; rsp.SIF_PacketNumber = responsePacket.packetNumber; // The SIF_Response is rendered in the same version of SIF as the original SIF_Request rsp.SifVersion = responsePacket.version; if (responsePacket.errorPacket) { // Write an empty "<SIF_Error> </SIF_Error>" for the MessageStreamer // to replace SIF_Error err = new SIF_Error(); err.TextValue = " "; rsp.SIF_Error = err; } if (!responsePacket.errorPacket || responsePacket.version.Major == 1) { // Write an empty "<SIF_ObjectData> </SIFObjectData>" for the // MessageStreamer to fill in. If this is an errorPacket, the empty // element is required per the SIF 1.x Specifications, but disallowed // in SIF 2.x. SIF_ObjectData placeholder = new SIF_ObjectData(); placeholder.TextValue = " "; rsp.SIF_ObjectData = placeholder; } // Assign values to message header - this is usually done by // MessageDispatcher.send() but because we're preparing a SIF_Response // output stream we need to do it manually SIF_Header hdr = rsp.Header; hdr.SIF_Timestamp = DateTime.Now; hdr.SIF_MsgId = SifFormatter.GuidToSifRefID(Guid.NewGuid()); hdr.SIF_SourceId = fZone.Agent.Id; hdr.SIF_Security = fZone.Dispatcher.secureChannel(); hdr.SIF_DestinationId = responsePacket.destinationId; // Write SIF_Response -- without its SIF_ObjectData payload -- to a buffer using (MemoryStream envelope = new MemoryStream()) { SifWriter writer = new SifWriter(envelope); writer.Write(rsp); writer.Flush(); envelope.Seek(0, SeekOrigin.Begin); FileStream fs = file.OpenRead(); try { // Send the SIF_Response as a stream Stream [] payloads; if (fSrc == ResponseDeliveryType.Generic) { payloads = new Stream [] { fs }; } else { if (rptInfoStream != null) { payloads = new Stream [] { rptInfoStream, fs }; } else { payloads = new Stream [] { fs }; } } using (MessageStreamer ms = new MessageStreamer ( envelope, payloads, responsePacket.errorPacket ? "<SIF_Error>" : "<SIF_ObjectData>", responsePacket.errorPacket)) { if ((Adk.Debug & AdkDebugFlags.Messaging) != 0) { fZone.Log.Debug("Send SIF_Response"); } if ((Adk.Debug & AdkDebugFlags.Messaging_Detailed) != 0) { fZone.Log.Debug(" MsgId: " + rsp.MsgId); } SIF_Ack ack; using (IMessageInputStream ackStream = fZone.ProtocolHandler.Send(ms)) { ack = (SIF_Ack) fParser.Parse (ackStream.GetInputStream(), fZone, SifParserFlags.None); } if (ack != null) { ack.LogRecv(fZone.Log); } } // If we get here, the message was sent successfully envelope.Close(); for (int i = 0; i < payloads.Length; i++) { payloads[i].Close(); } fs.Close(); if (DELETE_ON_SUCCESS && file.Exists) { file.Delete(); } } catch (AdkException adke) { AdkUtils._throw(adke, fZone.Log); } catch (Exception e) { AdkUtils._throw (new AdkException("Failed to send SIF_Response: " + e, fZone), fZone.Log); } finally { if (fs != null) { fs.Close(); } if (rptInfoStream != null) { rptInfoStream.Close(); } } } }