diff --git a/Client/Examples.xml b/Client/Examples.xml index 48b0203e..4498f543 100644 --- a/Client/Examples.xml +++ b/Client/Examples.xml @@ -1,171 +1,169 @@ - - - - - - This example shows how to use the GetFeatures method to print out a - list of features supported by the XMPP client of a chat contact. - - string hostname = "jabber.se", - username = "myUsername", - password = "myPassword"; - Jid juliet = "juliet@capulet.com/balcony"; - - using (var cl = new XmppClient(hostname, username, password)) { - cl.Connect(); - - Console.WriteLine("Juliet's XMPP client supports: "); - foreach (var feat in cl.GetFeatures(juliet)) - Console.WriteLine(" - " + feat); - } - - - - - - This example demonstrates how to use the SendMessage method in order - to send a chat-message to a contact. - - string hostname = "jabber.se", - username = "myUsername", - password = "myPassword"; - Jid juliet = "juliet@capulet.com/balcony"; - - using (var cl = new XmppClient(hostname, username, password)) { - cl.Connect(); - - while(true) { - Console.Write("Type a message or type 'quit' to exit: "); - string s = Console.ReadLine(); - if(s == "quit") - return; - // Send the message to Juliet. - cl.SendMessage(juliet, s); - } - } - - - - - - This example demonstrates how to use the SendMessage method in order - to send a multi-language chat-message to a contact. - - string hostname = "jabber.se", - username = "myUsername", - password = "myPassword"; - Jid juliet = "juliet@capulet.com/balcony"; - - using (var cl = new XmppClient(hostname, username, password)) { - cl.Connect(); - - cl.SendMessage(juliet, new Dictionary<string, string>() { - { "en", "Hi, how are you?" }, - { "dk", "Hej, hvordan har du det?" }, - { "de", "Hallo, wie geht es dir?" }, - { "jp", "お元気ですか?" } - }); - } - - - - - - This example demonstrates how to use the GetRoster method in order - to retrieve a list of all of the user's contacts. - - string hostname = "jabber.se", - username = "myUsername", - password = "myPassword"; - - using (var cl = new XmppClient(hostname, username, password)) { - cl.Connect(); - - Console.WriteLine("Contacts on " + cl.Jid.Node + "'s contact-list:"); - foreach (var item in cl.GetRoster()) - Console.WriteLine(" - " + item.Jid); - } - - - - - - This example demonstrates how to use the SetTune method in order - to publish tune information to other contacts. - - string hostname = "jabber.se", - username = "myUsername", - password = "myPassword"; - - using (var cl = new XmppClient(hostname, username, password)) { - cl.Connect(); - - // Let your contacts know what you are currently listening to. - cl.SetTune(new TuneInformation("Every Breath You Take", "The Police")); - - Console.WriteLine("Type 'quit' to exit."); - while(Console.ReadLine() != "quit"); - } - - - - - - This example demonstrates how to use the SetActivity method in order - to publish the user's current activity. - - string hostname = "jabber.se", - username = "myUsername", - password = "myPassword"; - - using (var cl = new XmppClient(hostname, username, password)) { - cl.Connect(); - - // Let your contacts know what you are currently doing. - cl.SetActivity(GeneralActivity.Eating, SpecificActivity.HavingBreakfast); - - Console.WriteLine("Type 'quit' to exit."); - while(Console.ReadLine() != "quit"); - } - - - - - - This example demonstrates how to set up the SubscriptionRequest delegate in - order to process incoming subscription requests. - - static void Main(string[] args) { - string hostname = "jabber.se", - username = "myUsername", - password = "myPassword"; - - using (var cl = new XmppClient(hostname, username, password)) { - cl.SubscriptionRequest = OnSubscriptionRequest; - cl.Connect(); - - // Put the thread to sleep and wait for subscription requests. - Thread.Sleep(Timeout.Infinite); - } - } - - /// <summary> - /// A callback method that is invoked whenever a subscription request from - /// another XMPP user is received. - /// </summary> - /// <param name="from">The JID of the XMPP user who wishes to subscribe to our - /// presence.</param> - /// <returns>true to approve the request; Otherwise false.</returns> - static bool OnSubscriptionRequest(Jid from) { - Console.WriteLine(from + " wants to subscribe to your presence."); - Console.Write("Type Y to approve the request, or any other key to refuse it: "); - - // Return true to approve the request, or false to refuse it. - return Console.ReadLine().ToLowerInvariant() == "y"; - } - - - - - - \ No newline at end of file + + + + + This example shows how to use the GetFeatures method to print out a + list of features supported by the XMPP client of a chat contact. + + string hostname = "jabber.se", + username = "myUsername", + password = "myPassword"; + Jid juliet = "juliet@capulet.com/balcony"; + + using (var cl = new XmppClient(hostname, username, password)) { + cl.Connect(); + + Console.WriteLine("Juliet's XMPP client supports: "); + foreach (var feat in cl.GetFeatures(juliet)) + Console.WriteLine(" - " + feat); + } + + + + + + This example demonstrates how to use the SendMessage method in order + to send a chat-message to a contact. + + string hostname = "jabber.se", + username = "myUsername", + password = "myPassword"; + Jid juliet = "juliet@capulet.com/balcony"; + + using (var cl = new XmppClient(hostname, username, password)) { + cl.Connect(); + + while(true) { + Console.Write("Type a message or type 'quit' to exit: "); + string s = Console.ReadLine(); + if(s == "quit") + return; + // Send the message to Juliet. + cl.SendMessage(juliet, s); + } + } + + + + + + This example demonstrates how to use the SendMessage method in order + to send a multi-language chat-message to a contact. + + string hostname = "jabber.se", + username = "myUsername", + password = "myPassword"; + Jid juliet = "juliet@capulet.com/balcony"; + + using (var cl = new XmppClient(hostname, username, password)) { + cl.Connect(); + + cl.SendMessage(juliet, new Dictionary<string, string>() { + { "en", "Hi, how are you?" }, + { "dk", "Hej, hvordan har du det?" }, + { "de", "Hallo, wie geht es dir?" }, + { "jp", "お元気ですか?" } + }); + } + + + + + + This example demonstrates how to use the GetRoster method in order + to retrieve a list of all of the user's contacts. + + string hostname = "jabber.se", + username = "myUsername", + password = "myPassword"; + + using (var cl = new XmppClient(hostname, username, password)) { + cl.Connect(); + + Console.WriteLine("Contacts on " + cl.Jid.Node + "'s contact-list:"); + foreach (var item in cl.GetRoster()) + Console.WriteLine(" - " + item.Jid); + } + + + + + + This example demonstrates how to use the SetTune method in order + to publish tune information to other contacts. + + string hostname = "jabber.se", + username = "myUsername", + password = "myPassword"; + + using (var cl = new XmppClient(hostname, username, password)) { + cl.Connect(); + + // Let your contacts know what you are currently listening to. + cl.SetTune(new TuneInformation("Every Breath You Take", "The Police")); + + Console.WriteLine("Type 'quit' to exit."); + while(Console.ReadLine() != "quit"); + } + + + + + + This example demonstrates how to use the SetActivity method in order + to publish the user's current activity. + + string hostname = "jabber.se", + username = "myUsername", + password = "myPassword"; + + using (var cl = new XmppClient(hostname, username, password)) { + cl.Connect(); + + // Let your contacts know what you are currently doing. + cl.SetActivity(GeneralActivity.Eating, SpecificActivity.HavingBreakfast); + + Console.WriteLine("Type 'quit' to exit."); + while(Console.ReadLine() != "quit"); + } + + + + + + This example demonstrates how to set up the SubscriptionRequest delegate in + order to process incoming subscription requests. + + static void Main(string[] args) { + string hostname = "jabber.se", + username = "myUsername", + password = "myPassword"; + + using (var cl = new XmppClient(hostname, username, password)) { + cl.SubscriptionRequest = OnSubscriptionRequest; + cl.Connect(); + + // Put the thread to sleep and wait for subscription requests. + Thread.Sleep(Timeout.Infinite); + } + } + + /// <summary> + /// A callback method that is invoked whenever a subscription request from + /// another XMPP user is received. + /// </summary> + /// <param name="from">The JID of the XMPP user who wishes to subscribe to our + /// presence.</param> + /// <returns>true to approve the request; Otherwise false.</returns> + static bool OnSubscriptionRequest(Jid from) { + Console.WriteLine(from + " wants to subscribe to your presence."); + Console.Write("Type Y to approve the request, or any other key to refuse it: "); + + // Return true to approve the request, or false to refuse it. + return Console.ReadLine().ToLowerInvariant() == "y"; + } + + + + + \ No newline at end of file diff --git a/Client/FileTransferSettings.cs b/Client/FileTransferSettings.cs index 71a0c76c..79578b6a 100644 --- a/Client/FileTransferSettings.cs +++ b/Client/FileTransferSettings.cs @@ -1,9 +1,9 @@ -using Sharp.Xmpp.Extensions; +using XMPPEngineer.Extensions; using System; using System.Collections.Generic; using System.Net; -namespace Sharp.Xmpp.Client +namespace XMPPEngineer.Client { /// /// Contains settings for configuring various file-transfer options. diff --git a/Client/XmppClient.cs b/Client/XmppClient.cs index b2f5ec23..56a8630e 100644 --- a/Client/XmppClient.cs +++ b/Client/XmppClient.cs @@ -1,12 +1,12 @@ -using Sharp.Xmpp.Extensions; -using Sharp.Xmpp.Im; +using XMPPEngineer.Extensions; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Net.Security; -namespace Sharp.Xmpp.Client +namespace XMPPEngineer.Client { /// /// Implements an XMPP client providing basic instant messaging (IM) and @@ -162,6 +162,53 @@ public class XmppClient : IDisposable /// private MessageCarbons messageCarbons; + /// + /// What extensions to load? Defaults to all. + /// + private AvailableExtensions loadExtensions = AvailableExtensions.All; + + /// + /// The extensions available on the client. Use with the loadExtensions property. + /// + [Flags] + public enum AvailableExtensions : Int64 + { + // 64 maximum values + None = 0, + SoftwareVersion = 1, + ServiceDiscovery = 2, + EntityCapabilities = 4, + Ping = 8, + Attention = 16, + EntityTime = 32, + BlockingCommand = 64, + Pep = 128, + UserTune = 256, + UserAvatar = 512, + UserMood = 1024, + DataForms = 2048, + FeatureNegotiation = 4096, + StreamInitiation = 8192, + SIFileTransfer = 16384, + InBandBytestreams = 32768, + UserActivity = 65536, + Socks5Bytestreams = 131072, + FileTransfer = 262144, + ServerIpCheck = 524288, + MessageCarbons = 1048576, + InBandRegistration = 2097152, + ChatStateNotifications = 4194304, + BitsOfBinary = 8388608, + VCardAvatars = 16777216, + CustomIqExtension = 33554432, + MultiUserChat = 67108864, + Default = SoftwareVersion | ServiceDiscovery | EntityCapabilities, + All = SoftwareVersion | ServiceDiscovery | EntityCapabilities | Ping | Attention | EntityTime | BlockingCommand | Pep | UserTune | UserAvatar | + UserMood | DataForms | FeatureNegotiation | StreamInitiation | SIFileTransfer | InBandBytestreams | UserActivity | Socks5Bytestreams + | FileTransfer | ServerIpCheck | MessageCarbons | InBandRegistration | ChatStateNotifications | BitsOfBinary | VCardAvatars | CustomIqExtension + | MultiUserChat + //134217728, 268435456, 536870912, 1073741824 ... up to 32. + } /// /// The hostname of the XMPP server to connect to. /// @@ -260,6 +307,15 @@ public RemoteCertificateValidationCallback Validate } } + /// + /// If false the connection will not try to retrieve the rooster automatically + /// + public bool RetrieveRoster + { + get { return im.RetrieveRoster; } + set { im.RetrieveRoster = value; } + } + /// /// Determines whether the session with the server is TLS/SSL encrypted. /// @@ -458,6 +514,36 @@ public event EventHandler Tune } } + /// + /// The event that is raised when stream management is enabled. + /// + public event EventHandler StreamManagementEnabled + { + add + { + im.StreamManagementEnabled += value; + } + remove + { + im.StreamManagementEnabled -= value; + } + } + + /// + /// The event that is raised when a stream is resumed. + /// + public event EventHandler StreamResumed + { + add + { + im.StreamResumed += value; + } + remove + { + im.StreamResumed -= value; + } + } + /// /// The event that is raised when a chat message is received. /// @@ -697,12 +783,41 @@ public event EventHandler Error /// Use this constructor if you wish to connect to an XMPP server using /// an existing set of user credentials. public XmppClient(string hostname, string username, string password, - int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) - { - im = new XmppIm(hostname, username, password, port, tls, validate); - // Initialize the various extension modules. - LoadExtensions(); - } + AvailableExtensions extensions = AvailableExtensions.All, + int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) : + this(hostname, username, password, null, extensions, port, tls, validate) { } + + /// + /// Initializes a new instance of the XmppClient class. + /// + /// The hostname of the XMPP server to connect to. + /// The username with which to authenticate. In XMPP jargon + /// this is known as the 'node' part of the JID. + /// The password with which to authenticate. + /// The IP address or domain of the XMPP server, if different from the hostname. eg. xmpp.server.com + /// The port number of the XMPP service of the server. + /// If true the session will be TLS/SSL-encrypted if the server + /// supports TLS/SSL-encryption. + /// A delegate used for verifying the remote Secure Sockets + /// Layer (SSL) certificate which is used for authentication. Can be null if not + /// needed. + /// The hostname parameter or the + /// username parameter or the password parameter is null. + /// The hostname parameter or the username + /// parameter is the empty string. + /// The value of the port parameter + /// is not a valid port number. + /// Use this constructor if you wish to connect to an XMPP server using + /// an existing set of user credentials. + public XmppClient(string hostname, string username, string password, string server, + AvailableExtensions extensions = AvailableExtensions.All, + int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) + { + im = new XmppIm(hostname, username, password, server, port, tls, validate); + loadExtensions = extensions; + // Initialize the various extension modules. + LoadExtensions(); + } /// /// Initializes a new instance of the XmppClient class. @@ -722,12 +837,37 @@ public XmppClient(string hostname, string username, string password, /// is not a valid port number. /// Use this constructor if you wish to register an XMPP account using /// the in-band account registration process supported by some servers. - public XmppClient(string hostname, int port = 5222, bool tls = true, - RemoteCertificateValidationCallback validate = null) - { - im = new XmppIm(hostname, port, tls, validate); - LoadExtensions(); - } + public XmppClient(string hostname, AvailableExtensions extensions = AvailableExtensions.All, int port = 5222, bool tls = true, + RemoteCertificateValidationCallback validate = null) : + this(hostname, null, extensions, port, tls, validate) { } + + /// + /// Initializes a new instance of the XmppClient class. + /// + /// The hostname of the XMPP server to connect to. + /// The IP address or domain of the XMPP server, if different from the hostname eg. xmpp.server.com + /// The port number of the XMPP service of the server. + /// If true the session will be TLS/SSL-encrypted if the server + /// supports TLS/SSL-encryption. + /// A delegate used for verifying the remote Secure Sockets + /// Layer (SSL) certificate which is used for authentication. Can be null if not + /// needed. + /// The hostname parameter is + /// null. + /// The hostname parameter is the empty + /// string. + /// The value of the port parameter + /// is not a valid port number. + /// Use this constructor if you wish to register an XMPP account using + /// the in-band account registration process supported by some servers. + public XmppClient(string hostname, string server, AvailableExtensions extensions = AvailableExtensions.All, + int port = 5222, bool tls = true, + RemoteCertificateValidationCallback validate = null) + { + im = new XmppIm(hostname, server, port, tls, validate); + loadExtensions = extensions; + LoadExtensions(); + } /// /// Establishes a connection to the XMPP server. @@ -774,40 +914,55 @@ public void Connect(string resource = null) /// of an XMPP extension failed. public void Authenticate(string username, string password) { - im.Autenticate(username, password); + im.Authenticate(username, password); } - /// - /// Sends a chat message with the specified content to the specified JID. - /// - /// The JID of the intended recipient. - /// The content of the message. - /// The subject of the message. - /// The conversation thread the message belongs to. - /// The type of the message. Can be one of the values from - /// the MessagType enumeration. - /// The language of the XML character data of - /// the stanza. - /// The to parameter or the body parameter - /// is null. - /// The body parameter is the empty - /// string. - /// There was a failure while writing to or reading - /// from the network. - /// The XmppClient instance is not - /// connected to a remote host, or the XmppClient instance has not authenticated with - /// the XMPP server. - /// The XmppClient object has been - /// disposed. - /// - public void SendMessage(Jid to, string body, string subject = null, - string thread = null, MessageType type = MessageType.Normal, + /// + /// Enables stream management. You should listen for the StreamManagementEnabled event + /// to know when it is ready. + /// Whether we should enabled resumption on the stream. + /// The max timeout client request - the server can override this. + /// + public void EnableStreamManagement(bool withresumption = true, int maxTimeout = 60) + { + AssertValid(); + + // enable sm + im.EnableStreamManagement(withresumption, maxTimeout); + } + + /// + /// Sends a chat message with the specified content to the specified JID. + /// + /// The JID of the intended recipient. + /// The content of the message. + /// The subject of the message. + /// Any additional address to send to XEP-0033. + /// The conversation thread the message belongs to. + /// The type of the message. Can be one of the values from + /// the MessagType enumeration. + /// The language of the XML character data of + /// the stanza. + /// The to parameter or the body parameter + /// is null. + /// The body parameter is the empty + /// string. + /// There was a failure while writing to or reading + /// from the network. + /// The XmppClient instance is not + /// connected to a remote host, or the XmppClient instance has not authenticated with + /// the XMPP server. + /// The XmppClient object has been + /// disposed. + /// + public void SendMessage(Jid to, string body, string subject = null, + List additionalAddresses = null, string thread = null, MessageType type = MessageType.Normal, CultureInfo language = null) { AssertValid(); to.ThrowIfNull("to"); body.ThrowIfNullOrEmpty("body"); - im.SendMessage(to, body, subject, thread, type, language); + im.SendMessage(to, body, subject, additionalAddresses, thread, type, language); } /// @@ -847,7 +1002,7 @@ public void SendMessage(Jid to, IDictionary bodies, AssertValid(); to.ThrowIfNull("to"); bodies.ThrowIfNull("bodies"); - im.SendMessage(to, bodies, subjects, thread, type, language); + im.SendMessage(to, bodies, subjects, thread, null, type, language); } /// @@ -1997,41 +2152,44 @@ private void AssertValid() throw new InvalidOperationException("Not authenticated with XMPP server."); } + /// /// Initializes the various XMPP extension modules. /// private void LoadExtensions() { - version = im.LoadExtension(); - sdisco = im.LoadExtension(); - ecapa = im.LoadExtension(); - ping = im.LoadExtension(); - attention = im.LoadExtension(); - time = im.LoadExtension(); - block = im.LoadExtension(); - pep = im.LoadExtension(); - userTune = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.SoftwareVersion) == AvailableExtensions.SoftwareVersion) version = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.ServiceDiscovery) == AvailableExtensions.ServiceDiscovery) sdisco = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.EntityCapabilities) == AvailableExtensions.EntityCapabilities) ecapa = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.Ping) == AvailableExtensions.Ping) ping = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.Attention) == AvailableExtensions.Attention) attention = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.EntityTime) == AvailableExtensions.EntityTime) time = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.BlockingCommand) == AvailableExtensions.BlockingCommand) block = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.Pep) == AvailableExtensions.Pep) pep = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.UserTune) == AvailableExtensions.UserTune) userTune = im.LoadExtension(); #if WINDOWSPLATFORM - userAvatar = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.UserAvatar) == AvailableExtensions.UserAvatar) userAvatar = im.LoadExtension(); #endif - userMood = im.LoadExtension(); - dataForms = im.LoadExtension(); - featureNegotiation = im.LoadExtension(); - streamInitiation = im.LoadExtension(); - siFileTransfer = im.LoadExtension(); - inBandBytestreams = im.LoadExtension(); - userActivity = im.LoadExtension(); - socks5Bytestreams = im.LoadExtension(); - FileTransferSettings = new FileTransferSettings(socks5Bytestreams, - siFileTransfer); - serverIpCheck = im.LoadExtension(); - messageCarbons = im.LoadExtension(); - inBandRegistration = im.LoadExtension(); - chatStateNotifications = im.LoadExtension(); - bitsOfBinary = im.LoadExtension(); - vcardAvatars = im.LoadExtension(); - cusiqextension = im.LoadExtension(); - groupChat = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.UserMood) == AvailableExtensions.UserMood) userMood = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.DataForms) == AvailableExtensions.DataForms) dataForms = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.FeatureNegotiation) == AvailableExtensions.FeatureNegotiation) featureNegotiation = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.StreamInitiation) == AvailableExtensions.StreamInitiation) streamInitiation = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.SIFileTransfer) == AvailableExtensions.SIFileTransfer) siFileTransfer = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.InBandBytestreams) == AvailableExtensions.InBandBytestreams) inBandBytestreams = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.UserActivity) == AvailableExtensions.UserActivity) userActivity = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.Socks5Bytestreams) == AvailableExtensions.Socks5Bytestreams) socks5Bytestreams = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.FileTransfer) == AvailableExtensions.FileTransfer) + FileTransferSettings = new FileTransferSettings(socks5Bytestreams, + siFileTransfer); + + if ((loadExtensions & AvailableExtensions.ServerIpCheck) == AvailableExtensions.ServerIpCheck) serverIpCheck = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.MessageCarbons) == AvailableExtensions.MessageCarbons) messageCarbons = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.InBandRegistration) == AvailableExtensions.InBandRegistration) inBandRegistration = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.ChatStateNotifications) == AvailableExtensions.ChatStateNotifications) chatStateNotifications = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.BitsOfBinary) == AvailableExtensions.BitsOfBinary) bitsOfBinary = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.VCardAvatars) == AvailableExtensions.VCardAvatars) vcardAvatars = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.CustomIqExtension) == AvailableExtensions.CustomIqExtension) cusiqextension = im.LoadExtension(); + if ((loadExtensions & AvailableExtensions.MultiUserChat) == AvailableExtensions.MultiUserChat) groupChat = im.LoadExtension(); } } } \ No newline at end of file diff --git a/Core/ErrorEventArgs.cs b/Core/ErrorEventArgs.cs index 9b750f1f..65c1bf1a 100644 --- a/Core/ErrorEventArgs.cs +++ b/Core/ErrorEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Provides data for the Error event. diff --git a/Core/Iq.cs b/Core/Iq.cs index ca7e8ff6..31095949 100644 --- a/Core/Iq.cs +++ b/Core/Iq.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Xml; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Represents an IQ XML stanza. diff --git a/Core/IqEventArgs.cs b/Core/IqEventArgs.cs index 7805c318..f740909e 100644 --- a/Core/IqEventArgs.cs +++ b/Core/IqEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Provides data for the Iq event. diff --git a/Core/IqType.cs b/Core/IqType.cs index 5def7dc0..f1e8c149 100644 --- a/Core/IqType.cs +++ b/Core/IqType.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Defines the possible types for IQ stanzas. diff --git a/Core/Message.cs b/Core/Message.cs index 526e2620..edc904f6 100644 --- a/Core/Message.cs +++ b/Core/Message.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Xml; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Represents a Message XML stanza. diff --git a/Core/MessageEventArgs.cs b/Core/MessageEventArgs.cs index 704dc9d7..a7c1228d 100644 --- a/Core/MessageEventArgs.cs +++ b/Core/MessageEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Provides data for the Message event. diff --git a/Core/Presence.cs b/Core/Presence.cs index d65e0217..8ecf83b8 100644 --- a/Core/Presence.cs +++ b/Core/Presence.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Xml; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Represents a Presence XML stanza. diff --git a/Core/PresenceEventArgs.cs b/Core/PresenceEventArgs.cs index 44e146a9..84254a5c 100644 --- a/Core/PresenceEventArgs.cs +++ b/Core/PresenceEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Provides data for the Presence event. diff --git a/Core/Sasl/Mechanisms/SaslDigestMd5.cs b/Core/Sasl/Mechanisms/SaslDigestMd5.cs index 4d92e881..45542198 100644 --- a/Core/Sasl/Mechanisms/SaslDigestMd5.cs +++ b/Core/Sasl/Mechanisms/SaslDigestMd5.cs @@ -3,7 +3,7 @@ using System.Security.Cryptography; using System.Text; -namespace Sharp.Xmpp.Core.Sasl.Mechanisms +namespace XMPPEngineer.Core.Sasl.Mechanisms { /// /// Implements the Sasl Digest-Md5 authentication method as described in @@ -299,7 +299,7 @@ private static string Dquote(string s) /// Add an additional backslash, if any backslashes are found in the username /// For XEP106 jid nodes, Openfire seems that it needs to escape the backslash /// within the user name. See discussion at https://community.igniterealtime.org/message/254096#254096 - /// It is not clear if this is an Openfire bug or a Sharp.Xmpp issue, so please treat this + /// It is not clear if this is an Openfire bug or a XMPPEngineer issue, so please treat this /// as experimental /// /// String to escape in order to resolve https://community.igniterealtime.org/message/254096#254096 issue diff --git a/Core/Sasl/Mechanisms/SaslPlain.cs b/Core/Sasl/Mechanisms/SaslPlain.cs index c078c500..56cba3b1 100644 --- a/Core/Sasl/Mechanisms/SaslPlain.cs +++ b/Core/Sasl/Mechanisms/SaslPlain.cs @@ -1,7 +1,7 @@ using System; using System.Text; -namespace Sharp.Xmpp.Core.Sasl.Mechanisms +namespace XMPPEngineer.Core.Sasl.Mechanisms { /// /// Implements the Sasl Plain authentication method as described in diff --git a/Core/Sasl/Mechanisms/SaslScramSha1.cs b/Core/Sasl/Mechanisms/SaslScramSha1.cs index 5b8f2249..37320a70 100644 --- a/Core/Sasl/Mechanisms/SaslScramSha1.cs +++ b/Core/Sasl/Mechanisms/SaslScramSha1.cs @@ -4,7 +4,7 @@ using System.Security.Cryptography; using System.Text; -namespace Sharp.Xmpp.Core.Sasl.Mechanisms +namespace XMPPEngineer.Core.Sasl.Mechanisms { /// /// Implements the Sasl SCRAM-SHA-1 authentication method as described in diff --git a/Core/Sasl/SaslException.cs b/Core/Sasl/SaslException.cs index c22e62d4..cf2933a6 100644 --- a/Core/Sasl/SaslException.cs +++ b/Core/Sasl/SaslException.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace Sharp.Xmpp.Core.Sasl +namespace XMPPEngineer.Core.Sasl { /// /// The exception is thrown when a Sasl-related error or unexpected condition occurs. diff --git a/Core/Sasl/SaslFactory.cs b/Core/Sasl/SaslFactory.cs index 84e3dda2..a8d875a7 100644 --- a/Core/Sasl/SaslFactory.cs +++ b/Core/Sasl/SaslFactory.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Core.Sasl +namespace XMPPEngineer.Core.Sasl { /// /// A factory class for producing instances of Sasl mechanisms. diff --git a/Core/Sasl/SaslMechanism.cs b/Core/Sasl/SaslMechanism.cs index 3ce0b634..fde0a9cb 100644 --- a/Core/Sasl/SaslMechanism.cs +++ b/Core/Sasl/SaslMechanism.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Core.Sasl +namespace XMPPEngineer.Core.Sasl { /// /// The abstract base class from which all classes implementing a Sasl diff --git a/Core/Stanza.cs b/Core/Stanza.cs index 99f7bd0f..80b56000 100644 --- a/Core/Stanza.cs +++ b/Core/Stanza.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Xml; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Represents the base class for XML stanzas as are used by XMPP from which diff --git a/Core/StreamParser.cs b/Core/StreamParser.cs index 41b29681..18932a2e 100644 --- a/Core/StreamParser.cs +++ b/Core/StreamParser.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Xml; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Implements a parser for parsing XMPP XML-streams as defined per XMPP:Core diff --git a/Core/XmppCore.cs b/Core/XmppCore.cs index 6ebd67ad..d18e1392 100644 --- a/Core/XmppCore.cs +++ b/Core/XmppCore.cs @@ -1,5 +1,4 @@ -using ARSoft.Tools.Net.Dns; -using Sharp.Xmpp.Core.Sasl; +using XMPPEngineer.Core.Sasl; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -14,7 +13,7 @@ using System.Threading.Tasks; using System.Xml; -namespace Sharp.Xmpp.Core +namespace XMPPEngineer.Core { /// /// Implements the core features of the XMPP protocol. @@ -22,21 +21,6 @@ namespace Sharp.Xmpp.Core /// For implementation details, refer to RFC 3920. public class XmppCore : IDisposable { - /// - /// The DNS SRV name records - /// - private List dnsRecordList; - - /// - /// The current SRV DNS record to use - /// - private SrvRecord dnsCurrent; - - /// - /// Bool variable indicating whether DNS records are initialised - /// - private bool dnsIsInit = false; - /// /// The TCP connection to the XMPP server. /// @@ -72,6 +56,11 @@ public class XmppCore : IDisposable /// private string hostname; + /// + /// The server IP or domain name of the XMPP server to connect to. + /// + private string server; + /// /// The username with which to authenticate. /// @@ -157,6 +146,22 @@ public string Hostname } } + /// + /// The server IP address or domain name of the XMPP server, if different from the Hostname. + /// + public string Server + { + get + { + return server; + } + + set + { + server = value; + } + } + /// /// The port number of the XMPP service of the server. /// @@ -339,24 +344,48 @@ public bool Authenticated /// The value of the port parameter /// is not a valid port number. public XmppCore(string hostname, string username, string password, - int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) - { - moveNextSrvDNS(hostname); - if (dnsCurrent != null) - { - Hostname = dnsCurrent.Target.ToString(); - Port = dnsCurrent.Port; - } - else - { - Hostname = hostname; - Port = port; - } - Username = username; - Password = password; - Tls = tls; - Validate = validate; - } + int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null): + this(hostname, username, password, null, port, tls, validate) { } + + /// + /// Initializes a new instance of the XmppCore class. + /// + /// The hostname of the XMPP server to connect to. + /// The username with which to authenticate. In XMPP jargon + /// this is known as the 'node' part of the JID. + /// The password with which to authenticate. + /// The IP address or domain of the XMPP server, if different from the hostname eg. xmpp.server.com + /// The port number of the XMPP service of the server. + /// If true the session will be TLS/SSL-encrypted if the server + /// supports TLS/SSL-encryption. + /// A delegate used for verifying the remote Secure Sockets + /// Layer (SSL) certificate which is used for authentication. Can be null if not + /// needed. + /// The hostname parameter or the + /// username parameter or the password parameter is null. + /// The hostname parameter or the username + /// parameter is the empty string. + /// The value of the port parameter + /// is not a valid port number. + public XmppCore(string hostname, string username, string password, string server, + int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) + { + if (String.IsNullOrWhiteSpace(server)) { + Hostname = hostname; + Server = hostname; + Port = port; + } + else { + Server = server; + Hostname = hostname; + Port = port; + } + + Username = username; + Password = password; + Tls = tls; + Validate = validate; + } /// /// Initializes a new instance of the XmppCore class. @@ -375,77 +404,45 @@ public XmppCore(string hostname, string username, string password, /// The value of the port parameter /// is not a valid port number. public XmppCore(string hostname, int port = 5222, bool tls = true, - RemoteCertificateValidationCallback validate = null) - { - moveNextSrvDNS(hostname); - if (dnsCurrent != null) - { - Hostname = dnsCurrent.Target.ToString(); - Port = dnsCurrent.Port; - } - else - { - Hostname = hostname; - Port = port; - } - Tls = tls; - Validate = validate; - } - - /// - /// Initialises and resolves the DNS Domain, and set to dnsCurrent the next - /// SRV record to use - /// - /// XMPP Domain - /// XMPP server hostname for the Domain - private SrvRecord moveNextSrvDNS(string domain) - { - domain.ThrowIfNullOrEmpty("domain"); - //If already a lookup has being made return - if (dnsIsInit) - { - //If it is already init we remove the current - if (dnsRecordList != null && dnsCurrent != null) dnsRecordList.Remove(dnsCurrent); - dnsCurrent = dnsRecordList.FirstOrDefault(); - return dnsCurrent; - }; - dnsIsInit = true; - - var domainName = ARSoft.Tools.Net.DomainName.Parse(("_xmpp-client._tcp." + domain)); - DnsMessage dnsMessage = DnsClient.Default.Resolve(domainName, RecordType.Srv); - if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain))) - { - //If DNS SRV records lookup fails then continue with the host name -#if DEBUG - System.Diagnostics.Debug.WriteLine("DNS Lookup Failed"); -#endif - return null; - } - else - { - var tempList = new List(); - - foreach (DnsRecordBase dnsRecord in dnsMessage.AnswerRecords) - { - SrvRecord srvRecord = dnsRecord as SrvRecord; - if (srvRecord != null) - { - tempList.Add(srvRecord); - Console.WriteLine(srvRecord.ToString()); - Console.WriteLine(" |--- Name " + srvRecord.Name); - Console.WriteLine(" |--- Port: " + srvRecord.Port); - Console.WriteLine(" |--- Priority" + srvRecord.Priority); - Console.WriteLine(" |--- Type " + srvRecord.RecordType); - Console.WriteLine(" |--- Target: " + srvRecord.Target); - Console.WriteLine(); - } - } - dnsRecordList = tempList.OrderBy(o => o.Priority).ThenBy(order => order.Weight).ToList(); - - dnsCurrent = dnsRecordList.FirstOrDefault(); - return dnsCurrent; - } - } + RemoteCertificateValidationCallback validate = null): + this(hostname, null, port, tls, validate) { } + + /// + /// Initializes a new instance of the XmppCore class. + /// + /// The hostname of the XMPP server to connect to. + /// The IP address or domain of the XMPP server, if different from the hostname eg. xmpp.server.com + /// The port number of the XMPP service of the server. + /// If true the session will be TLS/SSL-encrypted if the server + /// supports TLS/SSL-encryption. + /// A delegate used for verifying the remote Secure Sockets + /// Layer (SSL) certificate which is used for authentication. Can be null if not + /// needed. + /// The hostname parameter is + /// null. + /// The hostname parameter is the empty + /// string. + /// The value of the port parameter + /// is not a valid port number. + public XmppCore(string hostname, string server, int port = 5222, bool tls = true, + RemoteCertificateValidationCallback validate = null) + { + if (String.IsNullOrWhiteSpace(server)) + { + + Hostname = hostname; + Server = hostname; + Port = port; + } + else { + Server = server; + Hostname = hostname; + Port = port; + } + + Tls = tls; + Validate = validate; + } /// /// Establishes a connection to the XMPP server. @@ -465,17 +462,17 @@ private SrvRecord moveNextSrvDNS(string domain) /// disposed. /// If a username has been supplied, this method automatically performs /// authentication. - public void Connect(string resource = null) + public void Connect(string resource = null, bool bind = true) { if (disposed) throw new ObjectDisposedException(GetType().FullName); this.resource = resource; try { - client = new TcpClient(Hostname, Port); + client = new TcpClient(Server, Port); stream = client.GetStream(); // Sets up the connection which includes TLS and possibly SASL negotiation. - SetupConnection(this.resource); + SetupConnection(this.resource, bind); // We are connected. Connected = true; // Set up the listener and dispatcher tasks. @@ -904,6 +901,7 @@ private void AssertValid() /// /// The resource identifier to bind with. If this is null, /// it is assigned by the server. + /// Do we bind - this is false in Stream Resumption but usually true. /// The resource binding process failed. /// Invalid or unexpected XML data has been /// received from the XMPP server. @@ -911,7 +909,7 @@ private void AssertValid() /// trying to establish a secure connection, or the provided credentials were /// rejected by the server, or the server requires TLS/SSL and TLS has been /// turned off. - private void SetupConnection(string resource = null) + private void SetupConnection(string resource = null, bool bind = true) { // Request the initial stream. XmlElement feats = InitiateStream(Hostname); @@ -944,7 +942,7 @@ private void SetupConnection(string resource = null) feats = Authenticate(list, Username, Password, Hostname); // FIXME: How is the client's JID constructed if the server does not support // resource binding? - if (feats["bind"] != null) + if (bind && feats["bind"] != null) Jid = BindResource(resource); } catch (SaslException e) @@ -1177,11 +1175,22 @@ private void Send(string xml) /// The stanza parameter is null. /// There was a failure while writing to /// the network. - private void Send(Stanza stanza) + private void Send(Stanza stanza, bool addToCache = true) { - stanza.ThrowIfNull("stanza"); + stanza.ThrowIfNull("stanza"); Send(stanza.ToString()); - } + + // we only want to cache specific stanzas if they are not being resent + if (addToCache && + (stanza is XMPPEngineer.Core.Presence || stanza is XMPPEngineer.Core.Iq || stanza is XMPPEngineer.Core.Message)) + { + // cache until receipt is confirmed + stanzaQueueCache.Add(stanza); + + // add one to the sequence + currentOutboundStanzaSequence++; + } + } /// /// Serializes and sends the specified XML element to the server and @@ -1223,11 +1232,13 @@ private void ReadXmlStream() { while (true) { - XmlElement elem = parser.NextElement("iq", "message", "presence"); + XmlElement elem = parser.NextElement("iq", "message", "presence", "enabled", "resumed", "a", "r", "failed"); // Parse element and dispatch. switch (elem.Name) { case "iq": + currentInboundStanzaSequence++; + Iq iq = new Iq(elem); if (iq.IsRequest) stanzaQueue.Add(iq); @@ -1236,11 +1247,40 @@ private void ReadXmlStream() break; case "message": + currentInboundStanzaSequence++; + stanzaQueue.Add(new Message(elem)); break; case "presence": + currentInboundStanzaSequence++; + stanzaQueue.Add(new Presence(elem)); + break; + + // xep 1098 ### + case "failed": + HandleStreamManagementFailedResponse(elem); + break; + + case "enabled": + HandleStreamManagementEnabledResponse(elem); + break; + + case "resumed": + HandleResumedStreamResponse(elem); + break; + + case "a": + currentInboundStanzaSequence++; + HandleAcknowledgementResponse(elem); + break; + + case "r": + lastConfirmationAttemptServerTime = DateTime.Now; + + // we tell the server about the number of items we have received in this stream + Send(""); break; } } @@ -1266,6 +1306,501 @@ private void ReadXmlStream() } } + #region xep-0198 ### + + /// + /// The event that is raised when stream management is enabled. + /// + public event EventHandler StreamManagementEnabled; + + /// + /// The event that is raised when a stream is resumed. + /// + public event EventHandler StreamResumed; + + /// + /// Is stream management enabled. + /// + private bool streamManagementEnabled = false; + + /// + /// Is stream management resumption enabled. + /// + private bool resumptionEnabled = false; + + /// + /// The resumption id that can be used if the stream drops. + /// + private string resumptionId = null; + + /// + /// The cycle that checks for items to process and timeouts. + /// + private int streamCycleCheckTimeInSeconds = 10; + + /// + /// The maximum time between a connection being dropped and being allowed to reconnect the stream. + /// The server can choose to override what is set here. + /// + private int maxResumptionPeriodInSeconds = 30; + + /// + /// The maximum number of times we can try to resume a broken connection + /// + private const int MAX_RESUMPTION_ATTEMPTS = 3; + + /// + /// The maximum number of times we can try to create a broken stream + /// + private const int MAX_STREAM_ATTEMPTS = 3; + + /// + /// The current resumption attempt downward counter + /// + private int currentResumptionAttempt = 0; + + /// + /// The current stream attempt downward counter + /// + private int currentStreamAttempt = 0; + + /// + /// The last time any kind of confirmation was asked of the server. + /// Acknowledgements, Resumption and so on. + /// + private DateTime lastConfirmationAttemptServerTime = DateTime.MinValue; + + /// + /// The last sequence number we have that was confirmed by the server + /// + private int lastConfirmedServerSequence = 0; + + /// + /// When the server confirmed the above sequence number. + /// + private DateTime lastConfirmedServerTime = DateTime.MinValue; + + /// + /// The maximum time without any kind of confirmation from the server. + /// + private int maxTimeBetweenConfirmationsInSeconds = 60; + + /// + /// The namespace for stream management. + /// + const string STREAM_MANAGEMENT_NS = "urn:xmpp:sm:3"; + + /// + /// A global so we know if we are in the process of trying to resume the stream + /// + private bool isAttemptingStreamResumption = false; + + /// + /// A record of when the last attempt to resume the stream started - must reset it on success. + /// + private DateTime? lastAttemptAtStreamResumptionTime = null; + + /// + /// The max time we will wait before we regard resumption is failed and lost. + /// + private int maxStreamResumptionTimeoutInSecond = 30; + + /// + /// A global so we know if we are in the process of trying to create a new stream + /// + private bool isAttemptingNewStream = false; + + /// + /// A record of when the last attempt to create a new stream - must reset it on success. + /// + private DateTime? lastAttemptAtNewStreamTime = null; + + /// + /// The max time we will wait before we regard creating a new stream has failed. + /// + private int maxNewStreamTimeoutInSecond = 30; + + /// + /// The maximum number of times we can try to resume a broken connection + /// + private const int MAX_STANZAS_BEFORE_ACK_REQUEST = 3; + + /// + /// The maximum time without any kind of acknowledgement request to the server. + /// + private int maxTimeBetweenAcknowledgementInSeconds = 20; + + + /// + /// The sequence of stanzas that has been sent for this connection. + /// + private int currentOutboundStanzaSequence = 0; + + /// + /// The number of messages that have been receieved by this client. + /// + private int currentInboundStanzaSequence = 0; + + /// + /// A cache of items that have been sent but not confirmed. + /// + private BlockingCollection stanzaQueueCache = new BlockingCollection(); + + /// + /// Stores the sequence identifier from the previous stream if there was a failure. + /// Allows us to at least attempt a recovery. + /// + int? resumedStreamServerSequence = null; + + /// + /// Enables stream management. You should listen for the StreamManagementEnabled event + /// to know when it is ready. + /// Whether we should enabled resumption on the stream. + /// The max timeout client request - the server can override this. + /// + public void EnableStreamManagement(bool withresumption = true, int maxTimeout = 60) + { + // Send + XmlElement sm = Xml.Element("enable", STREAM_MANAGEMENT_NS); + sm.SetAttribute("resume", withresumption.ToString().ToLower()); + sm.SetAttribute("max", maxTimeout.ToString()); + + // send to the server - a message will be sent back later + Send(sm); + } + + /// + /// This will check if the stream management has been re-enabled after a previous stream failure. + /// If so, it will try to send anything that may hvae been missed. + /// + private void CheckIfResumedFromFailure() + { + // IF WE ARE COMING FROM A STREAM THAT WAS BROUGHT BACK FROM A PREVIOUS FAILURE + if (resumedStreamServerSequence.HasValue) + { + // update as the last sequence + lastConfirmedServerSequence = resumedStreamServerSequence.Value; + + // from the last confirmed value up to the one it has now, remove from the cache + for (int i = lastConfirmedServerSequence; i < resumedStreamServerSequence; i++) + { + stanzaQueueCache.Take(); + } + + // now resend anything left over + for (int i = 0; i < stanzaQueueCache.Count; i++) + { + Stanza stanza = stanzaQueueCache.ElementAt(i); + Send(stanza, false); + } + + // reset + resumedStreamServerSequence = null; + } + else + { + // if we have anything in the cache (from a previously fauiled session) then send it + for (int i = 0; i < stanzaQueueCache.Count; i++) + { + Stanza stanza = stanzaQueueCache.ElementAt(i); + Send(stanza, false); + } + } + } + + /// + /// The callback when stream management is enabled. + /// + /// Enabled. + private void HandleStreamManagementEnabledResponse(XmlElement enabled) + { + CheckIfResumedFromFailure(); + + // normal behaviour below ... + + // reset other variables - usually these are set when there was a previous stream + isAttemptingNewStream = false; + lastAttemptAtNewStreamTime = null; + isAttemptingStreamResumption = false; + lastAttemptAtStreamResumptionTime = null; + lastConfirmedServerTime = DateTime.Now; + currentResumptionAttempt = 0; //reset for next time + currentStreamAttempt = 0; + currentOutboundStanzaSequence = 0; //resets when it is a new stream + currentInboundStanzaSequence = 0; + + // we have stream management enabled so lets get started + streamManagementEnabled = true; + resumptionEnabled = Boolean.Parse(enabled.GetAttribute("resume")); + resumptionId = enabled.GetAttribute("id"); + int.TryParse(enabled.GetAttribute("max"), out maxResumptionPeriodInSeconds); + + // manage the stream uptime + CheckStreamCycle(); + + // throw an event to say we're ready with resumption + StreamManagementEnabled.Raise(this, null); + } + + /// + /// This will periodically check whether the server connection is up and + /// if not it will kick of a process to try and resume it, or create a new stream. + /// + private void CheckStreamCycle() + { + System.Timers.Timer timer = new System.Timers.Timer(); + timer.Interval = streamCycleCheckTimeInSeconds * 1000; + timer.Enabled = true; + + // inside here we manage the stream uptime - AT THE MOMENT we assume one attempt at stream resumption and then one attempt at connecting + timer.Elapsed += (sender, e) => { + + // if we are in the process of trying to create a new stream and that has been going on too long throw an error (for now) + + if (isAttemptingNewStream + && currentStreamAttempt > MAX_STREAM_ATTEMPTS + && lastAttemptAtNewStreamTime.HasValue + && DateTime.Now > lastAttemptAtNewStreamTime.Value.AddSeconds(maxNewStreamTimeoutInSecond)) + { + var connex = new XmppDisconnectionException("Unable to create a new connection in the time period."); + Error.Raise(this, new ErrorEventArgs(connex)); + } + else if (isAttemptingNewStream && currentStreamAttempt > MAX_STREAM_ATTEMPTS) // we are in the process of creating so let it run + return; + + // if we are in the process of trying to resume and that has been going on too long, consider it failed and restart the stream + if (isAttemptingStreamResumption + && currentResumptionAttempt > MAX_RESUMPTION_ATTEMPTS + && lastAttemptAtStreamResumptionTime.HasValue + && DateTime.Now > lastAttemptAtStreamResumptionTime.Value.AddSeconds(maxStreamResumptionTimeoutInSecond)) + { + // full stream restart - we cannot use resumption in this case as it is a brand new stream + isAttemptingNewStream = true; + lastAttemptAtNewStreamTime = DateTime.Now; + + try + { + // we will try getting the connection back again + currentStreamAttempt++; + + // try to create a new connection + Connect(this.resource); + + // finally, we enable stream management if it is on - IF WE DO THIS HERE + // ARE THERE ANY RACE CONDITIONS BY RESETING THE VARIBLES ABOVE BEFORE THE RESPONSE ? + if (streamManagementEnabled) + { + // we will reset the variables below when we get a stream management response + EnableStreamManagement(resumptionEnabled, maxResumptionPeriodInSeconds); + + // send items we have in the cache - we don't know what failed + for (int i = 0; i < stanzaQueueCache.Count; i++) + { + Stanza stanza = stanzaQueueCache.ElementAt(i); + Send(stanza, false); + } + + } else { + + // if successful then reset + isAttemptingNewStream = false; + lastAttemptAtNewStreamTime = null; + isAttemptingStreamResumption = false; + lastAttemptAtStreamResumptionTime = null; + lastConfirmedServerTime = DateTime.Now; + currentResumptionAttempt = 0; //reset for next time + currentStreamAttempt = 0; + currentOutboundStanzaSequence = 0; //resets when it is a new stream + currentInboundStanzaSequence = 0; + } + + return; + } + catch { + + // a network error of some kind - timer will ensure a rerty is done shortly. + return; + } + } + + // If we are not trying to resume the connection && have had no response from the server at all in a given period despite an attempt we will try to resume the stream + if (!isAttemptingStreamResumption + && DateTime.Now > lastConfirmedServerTime.AddSeconds(maxTimeBetweenConfirmationsInSeconds)) + { + // we will try getting the connection back again + currentResumptionAttempt++; + + // try to resume the connection + ResumeStream(); + + // we don't want to send through a request until the stream says it is ready + return; + } + + // if you ARE attempting a resumption but it has been going on too long then we need to try again + if (isAttemptingStreamResumption + && lastAttemptAtStreamResumptionTime.HasValue + && DateTime.Now > lastAttemptAtStreamResumptionTime.Value.AddSeconds(maxStreamResumptionTimeoutInSecond)) + { + // we will try getting the connection back again + currentResumptionAttempt++; + + // try to resume the connection + ResumeStream(); + + // we don't want to send through a request until the stream says it is ready + return; + } + + // Normal path here - have we got to the threshhold of items added or the timeout for checks for acks? + if ((currentOutboundStanzaSequence > 0 + && currentOutboundStanzaSequence % MAX_STANZAS_BEFORE_ACK_REQUEST == 0) + || DateTime.Now > lastConfirmedServerTime.AddSeconds(maxTimeBetweenAcknowledgementInSeconds)) + { + // request for acknowlegement + Send(""); + } + }; + + timer.Start(); + } + + /// + /// This will try to resume a stream, often caused by a dropped connection. + /// + private void ResumeStream() + { + // don't run multiple of these + if (isAttemptingStreamResumption) return; + + // set these management vars + isAttemptingStreamResumption = true; + lastAttemptAtStreamResumptionTime = DateTime.Now; + + // recreate the connection without binding + Connect(this.resource, false); + + // Send + XmlElement rs = Xml.Element("resume", STREAM_MANAGEMENT_NS); + rs.SetAttribute("h", lastConfirmedServerSequence.ToString()); + rs.SetAttribute("previd", resumptionId); + + // send to the server - a message will be sent back later + Send(rs); + } + + /// + /// Thrown when we receive an exception in stream management. + /// + /// Failure element. + private void HandleStreamManagementFailedResponse(XmlElement failed) + { + /* + + + + */ + + // I think it is supposed to create a new session when this happens - even if it is not the same + // as the previous one, but this doesn't *seem* to be working. In this case, let's create a brand new + // session. + + if (failed.FirstChild.LocalName == "item-not-found") + { + // store this so we can resend after the stream is back up + if (failed.HasAttribute("h")) + { + // store the sequence so we can resend once we've connected + resumedStreamServerSequence = int.Parse(failed.GetAttribute("h")); + } + + // create a new connection + Connect(this.resource); + lastConfirmedServerTime = DateTime.Now; + + // ### reset as we are now no longer trying to resume the stream + isAttemptingStreamResumption = false; + lastAttemptAtStreamResumptionTime = null; + currentResumptionAttempt = 0; //reset for next time + // ### + + ///// we will reset the variables below when we get a stream management response + EnableStreamManagement(resumptionEnabled, maxResumptionPeriodInSeconds); + } + else + { + // we have some other issue + var err = new XmppErrorException(new XmppError(failed)); + Error.Raise(this, new ErrorEventArgs(err)); + } + + // throw an event to say we're ready with resumption + StreamResumed.Raise(this, null); + } + + /// + /// The callback when stream is resumed. + /// + /// Resumed xml element. + private void HandleResumedStreamResponse(XmlElement resumed) + { + // reset as we are now no longer trying to resume the stream + isAttemptingStreamResumption = false; + lastAttemptAtStreamResumptionTime = null; + currentResumptionAttempt = 0; //reset for next time + + // what is the last item the server is aware of and record at what point that is + int sequence = int.Parse(resumed.GetAttribute("h")); + + // from the last confirmed value up to the one it has now, remove from the cache + for (int i = lastConfirmedServerSequence; i < sequence; i++) + { + stanzaQueueCache.Take(); + } + + // now resend anything left over + for (int i = 0; i < stanzaQueueCache.Count; i++) + { + Stanza stanza = stanzaQueueCache.ElementAt(i); + Send(stanza, false); + } + + // update as the last sequence + lastConfirmedServerSequence = sequence; + lastConfirmedServerTime = DateTime.Now; + + // throw an event to say we're ready with resumption + StreamResumed.Raise(this, null); + } + + /// + /// When an acknowledgement event is recieved. + /// + /// Ack element. + private void HandleAcknowledgementResponse(XmlElement ack) + { + // what sequence does the server have> + int sequence = int.Parse(ack.GetAttribute("h")); + + // from the last confirmed value up to the one it has now, remove from the cache + for (int i = lastConfirmedServerSequence; i < sequence; i++) + { + stanzaQueueCache.Take(); + } + + // ### + isAttemptingStreamResumption = false; + lastAttemptAtStreamResumptionTime = null; + currentResumptionAttempt = 0; //reset for next time + + // update as the last sequence + lastConfirmedServerSequence = sequence; + lastConfirmedServerTime = DateTime.Now; + } + + #endregion + /// /// Continously removes stanzas from the FIFO of incoming stanzas and raises /// the respective events. diff --git a/ErrorCondition.cs b/ErrorCondition.cs index 787ed17a..8104da65 100644 --- a/ErrorCondition.cs +++ b/ErrorCondition.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// Defines possible values for the condition of XMPP errors. diff --git a/ErrorType.cs b/ErrorType.cs index 152437fa..b940981a 100644 --- a/ErrorType.cs +++ b/ErrorType.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// Defines possible values for the type of XMPP errors. diff --git a/Extensions/CustomExtension/CustomIqExtension.cs b/Extensions/CustomExtension/CustomIqExtension.cs index ec4d2153..c94c47ee 100644 --- a/Extensions/CustomExtension/CustomIqExtension.cs +++ b/Extensions/CustomExtension/CustomIqExtension.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements Mechanism for providing Custom IQ Extensions @@ -25,7 +25,7 @@ public override IEnumerable Namespaces { get { - return new string[] { "urn:sharp.xmpp:customiq" }; + return new string[] { "urn:xmppengineer.xmpp:customiq" }; } } @@ -67,7 +67,7 @@ public bool Input(Iq stanza) // return false; //get,set, result are supported var customIqStanza = stanza.Data["customiq"]; - if (customIqStanza == null || customIqStanza.NamespaceURI != "urn:sharp.xmpp:customiq") + if (customIqStanza == null || customIqStanza.NamespaceURI != "urn:xmppengineer.xmpp:customiq") return false; //Result indicates that the request has been received. //It has not to do with the semantics of the message @@ -77,7 +77,7 @@ public bool Input(Iq stanza) CopyNodes(targetDocument, targetDocument, query.FirstChild); - var xmlresponse = Xml.Element("customiq", "urn:sharp.xmpp:customiq"); + var xmlresponse = Xml.Element("customiq", "urn:xmppengineer.xmpp:customiq"); try { //call the callback for receiving a relevant stanza @@ -142,7 +142,7 @@ public void RequestCustomIqAsync(Jid jid, string request, Action callback) throw new NotSupportedException("The XMPP entity does not support the " + "'CustomIqExtension' extension."); } - var xml = Xml.Element("customiq", "urn:sharp.xmpp:customiq").Text(request); + var xml = Xml.Element("customiq", "urn:xmppengineer.xmpp:customiq").Text(request); //The Request is Async im.IqRequestAsync(IqType.Get, jid, im.Jid, xml, null, (id, iq) => @@ -195,7 +195,7 @@ public void RequestCustomIq(Jid jid, string request) throw new NotSupportedException("The XMPP entity does not support the " + "'CustomIqExtension' extension."); } - var xml = Xml.Element("customiq", "urn:sharp.xmpp:customiq").Text(request); + var xml = Xml.Element("customiq", "urn:xmppengineer.xmpp:customiq").Text(request); //The Request is Async im.IqRequest(IqType.Get, jid, im.Jid, xml); diff --git a/Extensions/CustomExtension/CustomIqRequestDelegate.cs b/Extensions/CustomExtension/CustomIqRequestDelegate.cs index f9f19247..4993ac5a 100644 --- a/Extensions/CustomExtension/CustomIqRequestDelegate.cs +++ b/Extensions/CustomExtension/CustomIqRequestDelegate.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Invoked when a CustomIqRequest is made. diff --git a/Extensions/Extension.cs b/Extensions/Extension.cs index e5187c77..50026d4e 100644 --- a/Extensions/Extension.cs +++ b/Extensions/Extension.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// An enumeration of supported XMPP extensions. diff --git a/Extensions/IInputFilter.cs b/Extensions/IInputFilter.cs index 52b8f31c..fd12fb0d 100644 --- a/Extensions/IInputFilter.cs +++ b/Extensions/IInputFilter.cs @@ -1,6 +1,6 @@ -using Sharp.Xmpp.Core; +using XMPPEngineer.Core; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an extension that filters incoming stanzas. diff --git a/Extensions/IOutputFilter.cs b/Extensions/IOutputFilter.cs index 34894b3c..6d3a64bf 100644 --- a/Extensions/IOutputFilter.cs +++ b/Extensions/IOutputFilter.cs @@ -1,6 +1,6 @@ -using Sharp.Xmpp.Core; +using XMPPEngineer.Core; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an extension that filters outgoing stanzas. diff --git a/Extensions/XEP-0004/DataForms.cs b/Extensions/XEP-0004/DataForms.cs index 731a4a93..2877b03f 100644 --- a/Extensions/XEP-0004/DataForms.cs +++ b/Extensions/XEP-0004/DataForms.cs @@ -1,7 +1,7 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Data Forms' extension as defined in XEP-0004. diff --git a/Extensions/XEP-0004/Dataforms/BooleanField.cs b/Extensions/XEP-0004/Dataforms/BooleanField.cs index e97af276..60515ab0 100644 --- a/Extensions/XEP-0004/Dataforms/BooleanField.cs +++ b/Extensions/XEP-0004/Dataforms/BooleanField.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field that provides an either-or choice between two options. diff --git a/Extensions/XEP-0004/Dataforms/CancelForm.cs b/Extensions/XEP-0004/Dataforms/CancelForm.cs index e5729176..24fd701e 100644 --- a/Extensions/XEP-0004/Dataforms/CancelForm.cs +++ b/Extensions/XEP-0004/Dataforms/CancelForm.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a data-form that signals cancellation of submission of data. diff --git a/Extensions/XEP-0004/Dataforms/DataField.cs b/Extensions/XEP-0004/Dataforms/DataField.cs index f12a47aa..78b7a5b8 100644 --- a/Extensions/XEP-0004/Dataforms/DataField.cs +++ b/Extensions/XEP-0004/Dataforms/DataField.cs @@ -3,7 +3,7 @@ using System.Text; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// The base class from which all implementations of data-fields must derive. diff --git a/Extensions/XEP-0004/Dataforms/DataFieldType.cs b/Extensions/XEP-0004/Dataforms/DataFieldType.cs index 468cb2a8..5563dcc2 100644 --- a/Extensions/XEP-0004/Dataforms/DataFieldType.cs +++ b/Extensions/XEP-0004/Dataforms/DataFieldType.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Defines possible values for the different types of data-fields. diff --git a/Extensions/XEP-0004/Dataforms/DataForm.cs b/Extensions/XEP-0004/Dataforms/DataForm.cs index d970f938..051b219a 100644 --- a/Extensions/XEP-0004/Dataforms/DataForm.cs +++ b/Extensions/XEP-0004/Dataforms/DataForm.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// The abstract base class from which all implementations of concrete diff --git a/Extensions/XEP-0004/Dataforms/DataFormFactory.cs b/Extensions/XEP-0004/Dataforms/DataFormFactory.cs index 01d0a878..987a5b9a 100644 --- a/Extensions/XEP-0004/Dataforms/DataFormFactory.cs +++ b/Extensions/XEP-0004/Dataforms/DataFormFactory.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// A factory for creating data-form instances. diff --git a/Extensions/XEP-0004/Dataforms/DataFormType.cs b/Extensions/XEP-0004/Dataforms/DataFormType.cs index 8f1277ac..e137c922 100644 --- a/Extensions/XEP-0004/Dataforms/DataFormType.cs +++ b/Extensions/XEP-0004/Dataforms/DataFormType.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Defines possible values for the different types of data-forms. diff --git a/Extensions/XEP-0004/Dataforms/FieldList.cs b/Extensions/XEP-0004/Dataforms/FieldList.cs index cf098696..a112e4f7 100644 --- a/Extensions/XEP-0004/Dataforms/FieldList.cs +++ b/Extensions/XEP-0004/Dataforms/FieldList.cs @@ -4,7 +4,7 @@ using System.Text; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a list of data-fields contained in a data-form. diff --git a/Extensions/XEP-0004/Dataforms/FixedField.cs b/Extensions/XEP-0004/Dataforms/FixedField.cs index c192d325..b2a7f164 100644 --- a/Extensions/XEP-0004/Dataforms/FixedField.cs +++ b/Extensions/XEP-0004/Dataforms/FixedField.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field that is intended for data description rather diff --git a/Extensions/XEP-0004/Dataforms/HiddenField.cs b/Extensions/XEP-0004/Dataforms/HiddenField.cs index 2f5633ab..3789805a 100644 --- a/Extensions/XEP-0004/Dataforms/HiddenField.cs +++ b/Extensions/XEP-0004/Dataforms/HiddenField.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field that is intended to be invisible to the form-submitting diff --git a/Extensions/XEP-0004/Dataforms/JidField.cs b/Extensions/XEP-0004/Dataforms/JidField.cs index 639f43c3..8dcbc7ff 100644 --- a/Extensions/XEP-0004/Dataforms/JidField.cs +++ b/Extensions/XEP-0004/Dataforms/JidField.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field for gathering or providing a single Jabber ID. diff --git a/Extensions/XEP-0004/Dataforms/JidMultiField.cs b/Extensions/XEP-0004/Dataforms/JidMultiField.cs index 74fab1ff..73ba7be2 100644 --- a/Extensions/XEP-0004/Dataforms/JidMultiField.cs +++ b/Extensions/XEP-0004/Dataforms/JidMultiField.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field for gathering or providing multiple Jabber IDs. diff --git a/Extensions/XEP-0004/Dataforms/ListField.cs b/Extensions/XEP-0004/Dataforms/ListField.cs index 0f9297fb..864065ca 100644 --- a/Extensions/XEP-0004/Dataforms/ListField.cs +++ b/Extensions/XEP-0004/Dataforms/ListField.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field for gathering or providing one option from among many. diff --git a/Extensions/XEP-0004/Dataforms/ListMultiField.cs b/Extensions/XEP-0004/Dataforms/ListMultiField.cs index 0a39da7e..3fcb2aae 100644 --- a/Extensions/XEP-0004/Dataforms/ListMultiField.cs +++ b/Extensions/XEP-0004/Dataforms/ListMultiField.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field for gathering or providing one or more options diff --git a/Extensions/XEP-0004/Dataforms/Option.cs b/Extensions/XEP-0004/Dataforms/Option.cs index effd1a6f..be104360 100644 --- a/Extensions/XEP-0004/Dataforms/Option.cs +++ b/Extensions/XEP-0004/Dataforms/Option.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents an option of a list data-field. diff --git a/Extensions/XEP-0004/Dataforms/PasswordField.cs b/Extensions/XEP-0004/Dataforms/PasswordField.cs index c61dd453..e4c99d72 100644 --- a/Extensions/XEP-0004/Dataforms/PasswordField.cs +++ b/Extensions/XEP-0004/Dataforms/PasswordField.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field for gathering or providing a single line or word of diff --git a/Extensions/XEP-0004/Dataforms/RequestForm.cs b/Extensions/XEP-0004/Dataforms/RequestForm.cs index f7173534..2d32ba2e 100644 --- a/Extensions/XEP-0004/Dataforms/RequestForm.cs +++ b/Extensions/XEP-0004/Dataforms/RequestForm.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a requesting data-form. diff --git a/Extensions/XEP-0004/Dataforms/ResultForm.cs b/Extensions/XEP-0004/Dataforms/ResultForm.cs index f9f0b34b..a562350a 100644 --- a/Extensions/XEP-0004/Dataforms/ResultForm.cs +++ b/Extensions/XEP-0004/Dataforms/ResultForm.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a result form containing returned data or a generic data set. diff --git a/Extensions/XEP-0004/Dataforms/SubmitForm.cs b/Extensions/XEP-0004/Dataforms/SubmitForm.cs index 05ba174d..2aeef4f0 100644 --- a/Extensions/XEP-0004/Dataforms/SubmitForm.cs +++ b/Extensions/XEP-0004/Dataforms/SubmitForm.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a data-form for data submission. diff --git a/Extensions/XEP-0004/Dataforms/TextField.cs b/Extensions/XEP-0004/Dataforms/TextField.cs index 2c381d3f..57d1e953 100644 --- a/Extensions/XEP-0004/Dataforms/TextField.cs +++ b/Extensions/XEP-0004/Dataforms/TextField.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field for gathering or providing a single line or word of diff --git a/Extensions/XEP-0004/Dataforms/TextMultiField.cs b/Extensions/XEP-0004/Dataforms/TextMultiField.cs index fcd6687e..1b927537 100644 --- a/Extensions/XEP-0004/Dataforms/TextMultiField.cs +++ b/Extensions/XEP-0004/Dataforms/TextMultiField.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents a field for gathering or providing multiple lines of text. diff --git a/Extensions/XEP-0004/Dataforms/XmlCollection.cs b/Extensions/XEP-0004/Dataforms/XmlCollection.cs index 6169f8e2..b7149a55 100644 --- a/Extensions/XEP-0004/Dataforms/XmlCollection.cs +++ b/Extensions/XEP-0004/Dataforms/XmlCollection.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions.Dataforms +namespace XMPPEngineer.Extensions.Dataforms { /// /// Represents an XML-backed generic collection. diff --git a/Extensions/XEP-0020/FeatureNegotiation.cs b/Extensions/XEP-0020/FeatureNegotiation.cs index 50f49d9e..0dff32f8 100644 --- a/Extensions/XEP-0020/FeatureNegotiation.cs +++ b/Extensions/XEP-0020/FeatureNegotiation.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Extensions.Dataforms; -using Sharp.Xmpp.Im; +using XMPPEngineer.Extensions.Dataforms; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Feature Negotiation' extension as defined in XEP-0020. diff --git a/Extensions/XEP-0030/Identity.cs b/Extensions/XEP-0030/Identity.cs index b8a3f353..e79579e6 100644 --- a/Extensions/XEP-0030/Identity.cs +++ b/Extensions/XEP-0030/Identity.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an identity of an XMPP entity as defined in XEP-0030. diff --git a/Extensions/XEP-0030/Item.cs b/Extensions/XEP-0030/Item.cs index d8b2b0a0..492b59fd 100644 --- a/Extensions/XEP-0030/Item.cs +++ b/Extensions/XEP-0030/Item.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an item of an XMPP entity as defined in XEP-0030. diff --git a/Extensions/XEP-0030/ServiceDiscovery.cs b/Extensions/XEP-0030/ServiceDiscovery.cs index be4d56eb..5255bbf3 100644 --- a/Extensions/XEP-0030/ServiceDiscovery.cs +++ b/Extensions/XEP-0030/ServiceDiscovery.cs @@ -1,12 +1,12 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Service Discovery' extension as defined in XEP-0030. diff --git a/Extensions/XEP-0045/Affiliation.cs b/Extensions/XEP-0045/Affiliation.cs index 56ccbdaa..33b2c323 100644 --- a/Extensions/XEP-0045/Affiliation.cs +++ b/Extensions/XEP-0045/Affiliation.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes the Affiliation of a participant in a group chat. diff --git a/Extensions/XEP-0045/GroupErrorEventArgs.cs b/Extensions/XEP-0045/GroupErrorEventArgs.cs index 9adb4e79..ef1109ca 100644 --- a/Extensions/XEP-0045/GroupErrorEventArgs.cs +++ b/Extensions/XEP-0045/GroupErrorEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents a group presence error event in a group chat. Ref XEP-0045 diff --git a/Extensions/XEP-0045/GroupInviteDeclinedEventArgs.cs b/Extensions/XEP-0045/GroupInviteDeclinedEventArgs.cs index 5a0e28f2..ce26b113 100644 --- a/Extensions/XEP-0045/GroupInviteDeclinedEventArgs.cs +++ b/Extensions/XEP-0045/GroupInviteDeclinedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents a group invite event in a group chat. Ref XEP-0045 diff --git a/Extensions/XEP-0045/GroupInviteEventArgs.cs b/Extensions/XEP-0045/GroupInviteEventArgs.cs index 4ec38b71..3b0d7863 100644 --- a/Extensions/XEP-0045/GroupInviteEventArgs.cs +++ b/Extensions/XEP-0045/GroupInviteEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents a group invite event in a group chat. Ref XEP-0045 diff --git a/Extensions/XEP-0045/GroupPresenceEventArgs.cs b/Extensions/XEP-0045/GroupPresenceEventArgs.cs index 73cb9def..1ebe81c3 100644 --- a/Extensions/XEP-0045/GroupPresenceEventArgs.cs +++ b/Extensions/XEP-0045/GroupPresenceEventArgs.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents a presence change event in a group chat. Ref XEP-0045 @@ -13,6 +13,8 @@ public class GroupPresenceEventArgs : EventArgs /// public Occupant Person { get; set; } + public Jid Group { get; } + /// /// /// @@ -22,10 +24,12 @@ public class GroupPresenceEventArgs : EventArgs /// /// /// + /// /// - public GroupPresenceEventArgs(Occupant person, IEnumerable statuses) : base() + public GroupPresenceEventArgs(Occupant person, Jid group, IEnumerable statuses) : base() { Person = person; + Group = group; Statuses = statuses; } } diff --git a/Extensions/XEP-0045/History.cs b/Extensions/XEP-0045/History.cs index b2a931bd..b0646ebb 100644 --- a/Extensions/XEP-0045/History.cs +++ b/Extensions/XEP-0045/History.cs @@ -1,8 +1,8 @@ using System; using System.Xml; -using Sharp.Xmpp.Core; +using XMPPEngineer.Core; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the message history request object as described in XEP-0045. diff --git a/Extensions/XEP-0045/Invite.cs b/Extensions/XEP-0045/Invite.cs index 2441fe74..d994b97f 100644 --- a/Extensions/XEP-0045/Invite.cs +++ b/Extensions/XEP-0045/Invite.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Xml; -using Sharp.Xmpp.Core; +using XMPPEngineer.Core; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements MUC Mediated Invitation as described in XEP-0045. diff --git a/Extensions/XEP-0045/InviteDeclined.cs b/Extensions/XEP-0045/InviteDeclined.cs index 1e131dfd..c04f5744 100644 --- a/Extensions/XEP-0045/InviteDeclined.cs +++ b/Extensions/XEP-0045/InviteDeclined.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Xml; -using Sharp.Xmpp.Core; +using XMPPEngineer.Core; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements MUC Mediated Invitation as described in XEP-0045. diff --git a/Extensions/XEP-0045/MucError.cs b/Extensions/XEP-0045/MucError.cs index 6ed87c97..b93a83e7 100644 --- a/Extensions/XEP-0045/MucError.cs +++ b/Extensions/XEP-0045/MucError.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements a MUC error response which may be contained in either an IQ or a Presence. diff --git a/Extensions/XEP-0045/MucNs.cs b/Extensions/XEP-0045/MucNs.cs index ac23cc86..96db64bb 100644 --- a/Extensions/XEP-0045/MucNs.cs +++ b/Extensions/XEP-0045/MucNs.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Identifiers used to describe objects in objects in the MUC Namespace. diff --git a/Extensions/XEP-0045/MucStatusType.cs b/Extensions/XEP-0045/MucStatusType.cs index 347b10be..115919c2 100644 --- a/Extensions/XEP-0045/MucStatusType.cs +++ b/Extensions/XEP-0045/MucStatusType.cs @@ -1,5 +1,5 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Defines an extensible format for status conditions in MUC. diff --git a/Extensions/XEP-0045/MultiUserChat.cs b/Extensions/XEP-0045/MultiUserChat.cs index 81ba6f57..72fb843c 100644 --- a/Extensions/XEP-0045/MultiUserChat.cs +++ b/Extensions/XEP-0045/MultiUserChat.cs @@ -4,11 +4,11 @@ using System.Text; using System.Threading.Tasks; using System.Xml; -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Extensions.Dataforms; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Extensions.Dataforms; +using XMPPEngineer.Im; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { internal class MultiUserChat : XmppExtension, IInputFilter, IInputFilter { @@ -169,10 +169,11 @@ public bool Input (Im.Presence stanza) } } + bool hasNoAvailability = string.IsNullOrWhiteSpace(stanza.Data["show"]?.InnerText); if (person != null) { - PrescenceChanged.Raise (this, new GroupPresenceEventArgs (person, statusCodeList)); - return true; + PrescenceChanged.Raise (this, new GroupPresenceEventArgs (person, new Jid(stanza.From.Domain, stanza.From.Node), statusCodeList)); + return hasNoAvailability; } } @@ -397,7 +398,7 @@ public void DeclineInvite(Invite invite, string reason) public void EditRoomSubject(Jid room, string subject) { subject.ThrowIfNull("subject"); - Im.Message message = new Im.Message(room, null, subject, null, MessageType.Groupchat); + Im.Message message = new Im.Message(room, null, subject, null, null, MessageType.Groupchat); SendMessage(message); } diff --git a/Extensions/XEP-0045/Occupant.cs b/Extensions/XEP-0045/Occupant.cs index 5d68d7ed..a63c4152 100644 --- a/Extensions/XEP-0045/Occupant.cs +++ b/Extensions/XEP-0045/Occupant.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an participant in a group chat. diff --git a/Extensions/XEP-0045/Role.cs b/Extensions/XEP-0045/Role.cs index 1d3e4c6d..80f8e5b4 100644 --- a/Extensions/XEP-0045/Role.cs +++ b/Extensions/XEP-0045/Role.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes the role of a participant in a group chat. diff --git a/Extensions/XEP-0045/RoomAnonymity.cs b/Extensions/XEP-0045/RoomAnonymity.cs index be6028a8..28317f6d 100644 --- a/Extensions/XEP-0045/RoomAnonymity.cs +++ b/Extensions/XEP-0045/RoomAnonymity.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes whether a conference room occupant's full JID is visible diff --git a/Extensions/XEP-0045/RoomInfoBasic.cs b/Extensions/XEP-0045/RoomInfoBasic.cs index 9835be8b..b015968e 100644 --- a/Extensions/XEP-0045/RoomInfoBasic.cs +++ b/Extensions/XEP-0045/RoomInfoBasic.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// The most basic form of a chat room diff --git a/Extensions/XEP-0045/RoomInfoExtended.cs b/Extensions/XEP-0045/RoomInfoExtended.cs index 7e621722..30fd77e4 100644 --- a/Extensions/XEP-0045/RoomInfoExtended.cs +++ b/Extensions/XEP-0045/RoomInfoExtended.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using Sharp.Xmpp.Extensions.Dataforms; +using XMPPEngineer.Extensions.Dataforms; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Room information provided upon inspection. diff --git a/Extensions/XEP-0045/RoomModeration.cs b/Extensions/XEP-0045/RoomModeration.cs index cd2c4228..70116975 100644 --- a/Extensions/XEP-0045/RoomModeration.cs +++ b/Extensions/XEP-0045/RoomModeration.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes whether a conference room is moderated. diff --git a/Extensions/XEP-0045/RoomPersistence.cs b/Extensions/XEP-0045/RoomPersistence.cs index 6fa28274..7a206c47 100644 --- a/Extensions/XEP-0045/RoomPersistence.cs +++ b/Extensions/XEP-0045/RoomPersistence.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes how long a conference room will exist for. diff --git a/Extensions/XEP-0045/RoomPrivacy.cs b/Extensions/XEP-0045/RoomPrivacy.cs index 374e64f7..ec9c01d6 100644 --- a/Extensions/XEP-0045/RoomPrivacy.cs +++ b/Extensions/XEP-0045/RoomPrivacy.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes whether a conference room requires a membership to enter. diff --git a/Extensions/XEP-0045/RoomProtection.cs b/Extensions/XEP-0045/RoomProtection.cs index d84ce315..0b68d449 100644 --- a/Extensions/XEP-0045/RoomProtection.cs +++ b/Extensions/XEP-0045/RoomProtection.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes whether a conference room is password protected. diff --git a/Extensions/XEP-0045/RoomVisibility.cs b/Extensions/XEP-0045/RoomVisibility.cs index 29169389..a9019f4c 100644 --- a/Extensions/XEP-0045/RoomVisibility.cs +++ b/Extensions/XEP-0045/RoomVisibility.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Describes the visibility of a conference room. diff --git a/Extensions/XEP-0047/InBandBytestreams.cs b/Extensions/XEP-0047/InBandBytestreams.cs index 2b79ff48..b4c8ca79 100644 --- a/Extensions/XEP-0047/InBandBytestreams.cs +++ b/Extensions/XEP-0047/InBandBytestreams.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.IO; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'In-Band Bytestreams' extension as defined in XEP-0047. diff --git a/Extensions/XEP-0065/IPAddressExtensions.cs b/Extensions/XEP-0065/IPAddressExtensions.cs index 343f2346..01768ad3 100644 --- a/Extensions/XEP-0065/IPAddressExtensions.cs +++ b/Extensions/XEP-0065/IPAddressExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Net; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Contains extension methods for the IPAddress class. diff --git a/Extensions/XEP-0065/Socks5/ATyp.cs b/Extensions/XEP-0065/Socks5/ATyp.cs index 2282cca3..c530d63f 100644 --- a/Extensions/XEP-0065/Socks5/ATyp.cs +++ b/Extensions/XEP-0065/Socks5/ATyp.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Defines possible values for the address type field. diff --git a/Extensions/XEP-0065/Socks5/AuthMethod.cs b/Extensions/XEP-0065/Socks5/AuthMethod.cs index 853017ad..ea95e7c0 100644 --- a/Extensions/XEP-0065/Socks5/AuthMethod.cs +++ b/Extensions/XEP-0065/Socks5/AuthMethod.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Defines possible values for the different authentication methods diff --git a/Extensions/XEP-0065/Socks5/AuthRequest.cs b/Extensions/XEP-0065/Socks5/AuthRequest.cs index 3218608a..f7ba7df1 100644 --- a/Extensions/XEP-0065/Socks5/AuthRequest.cs +++ b/Extensions/XEP-0065/Socks5/AuthRequest.cs @@ -1,7 +1,7 @@ using System; using System.Text; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Represents a SOCKS5 Username/Password auth-request message. diff --git a/Extensions/XEP-0065/Socks5/AuthResponse.cs b/Extensions/XEP-0065/Socks5/AuthResponse.cs index fc96f5cb..64250b72 100644 --- a/Extensions/XEP-0065/Socks5/AuthResponse.cs +++ b/Extensions/XEP-0065/Socks5/AuthResponse.cs @@ -2,7 +2,7 @@ using System.IO; using System.Runtime.Serialization; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Represents a SOCKS5 Username/Password auth-response message. diff --git a/Extensions/XEP-0065/Socks5/BinaryReader.cs b/Extensions/XEP-0065/Socks5/BinaryReader.cs index 507d4b70..d64bd12b 100644 --- a/Extensions/XEP-0065/Socks5/BinaryReader.cs +++ b/Extensions/XEP-0065/Socks5/BinaryReader.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Adds extension methods to the BinaryReader class to simplify the diff --git a/Extensions/XEP-0065/Socks5/ByteBuilder.cs b/Extensions/XEP-0065/Socks5/ByteBuilder.cs index e6d0c796..d694e220 100644 --- a/Extensions/XEP-0065/Socks5/ByteBuilder.cs +++ b/Extensions/XEP-0065/Socks5/ByteBuilder.cs @@ -1,7 +1,7 @@ using System; using System.Text; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// A utility class modeled after the BCL StringBuilder to simplify diff --git a/Extensions/XEP-0065/Socks5/ClientGreeting.cs b/Extensions/XEP-0065/Socks5/ClientGreeting.cs index 984bd259..7864f0cd 100644 --- a/Extensions/XEP-0065/Socks5/ClientGreeting.cs +++ b/Extensions/XEP-0065/Socks5/ClientGreeting.cs @@ -3,7 +3,7 @@ using System.IO; using System.Runtime.Serialization; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Represents a SOCKS5 client-greeting message. diff --git a/Extensions/XEP-0065/Socks5/ReplyStatus.cs b/Extensions/XEP-0065/Socks5/ReplyStatus.cs index 03115851..590b98ad 100644 --- a/Extensions/XEP-0065/Socks5/ReplyStatus.cs +++ b/Extensions/XEP-0065/Socks5/ReplyStatus.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Defines possible values for the reply field of a SOCKS5 reply. diff --git a/Extensions/XEP-0065/Socks5/ServerGreeting.cs b/Extensions/XEP-0065/Socks5/ServerGreeting.cs index cc99e6b2..3a4179d2 100644 --- a/Extensions/XEP-0065/Socks5/ServerGreeting.cs +++ b/Extensions/XEP-0065/Socks5/ServerGreeting.cs @@ -2,7 +2,7 @@ using System.IO; using System.Runtime.Serialization; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Represents a SOCKS5 server-greeting message. diff --git a/Extensions/XEP-0065/Socks5/Socks5Client.cs b/Extensions/XEP-0065/Socks5/Socks5Client.cs index 6296dcba..4ce0980b 100644 --- a/Extensions/XEP-0065/Socks5/Socks5Client.cs +++ b/Extensions/XEP-0065/Socks5/Socks5Client.cs @@ -5,7 +5,7 @@ using System.Net.Sockets; using System.Text; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Provides client connections for SOCKS5 network services. diff --git a/Extensions/XEP-0065/Socks5/Socks5Exception.cs b/Extensions/XEP-0065/Socks5/Socks5Exception.cs index a36f1c06..fd6602ce 100644 --- a/Extensions/XEP-0065/Socks5/Socks5Exception.cs +++ b/Extensions/XEP-0065/Socks5/Socks5Exception.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// The exception that is thrown when a SOCKS5 error has been encountered. diff --git a/Extensions/XEP-0065/Socks5/Socks5Server.cs b/Extensions/XEP-0065/Socks5/Socks5Server.cs index a1d21f82..d0ce7584 100644 --- a/Extensions/XEP-0065/Socks5/Socks5Server.cs +++ b/Extensions/XEP-0065/Socks5/Socks5Server.cs @@ -5,7 +5,7 @@ using System.Net.Sockets; using System.Text; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Listens for connections from SOCKS5 network clients. diff --git a/Extensions/XEP-0065/Socks5/SocksCommand.cs b/Extensions/XEP-0065/Socks5/SocksCommand.cs index 5d5c078f..8ea1e380 100644 --- a/Extensions/XEP-0065/Socks5/SocksCommand.cs +++ b/Extensions/XEP-0065/Socks5/SocksCommand.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Defines possible values for the command field of a SOCKS5 request. diff --git a/Extensions/XEP-0065/Socks5/SocksReply.cs b/Extensions/XEP-0065/Socks5/SocksReply.cs index affa850e..29b3b0db 100644 --- a/Extensions/XEP-0065/Socks5/SocksReply.cs +++ b/Extensions/XEP-0065/Socks5/SocksReply.cs @@ -5,7 +5,7 @@ using System.Runtime.Serialization; using System.Text; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Represents a SOCKS5 reply message. diff --git a/Extensions/XEP-0065/Socks5/SocksRequest.cs b/Extensions/XEP-0065/Socks5/SocksRequest.cs index 1fcf9b5f..9e14ce6f 100644 --- a/Extensions/XEP-0065/Socks5/SocksRequest.cs +++ b/Extensions/XEP-0065/Socks5/SocksRequest.cs @@ -5,7 +5,7 @@ using System.Runtime.Serialization; using System.Text; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Represents a SOCKS5 request message. diff --git a/Extensions/XEP-0065/Socks5/TcpListenerExtensions.cs b/Extensions/XEP-0065/Socks5/TcpListenerExtensions.cs index 65b1e898..aadf05a8 100644 --- a/Extensions/XEP-0065/Socks5/TcpListenerExtensions.cs +++ b/Extensions/XEP-0065/Socks5/TcpListenerExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Net.Sockets; -namespace Sharp.Xmpp.Extensions.Socks5 +namespace XMPPEngineer.Extensions.Socks5 { /// /// Provides extension methods for the TcpListener class. diff --git a/Extensions/XEP-0065/Socks5Bytestreams.cs b/Extensions/XEP-0065/Socks5Bytestreams.cs index 6df39596..6333b2e6 100644 --- a/Extensions/XEP-0065/Socks5Bytestreams.cs +++ b/Extensions/XEP-0065/Socks5Bytestreams.cs @@ -1,7 +1,7 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Extensions.Socks5; -using Sharp.Xmpp.Extensions.Stun; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Extensions.Socks5; +using XMPPEngineer.Extensions.Stun; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.IO; @@ -14,7 +14,7 @@ using System.Threading.Tasks; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'SOCKS5 Bytestreams' extension as defined in XEP-0065. diff --git a/Extensions/XEP-0065/Streamhost.cs b/Extensions/XEP-0065/Streamhost.cs index 1c83e610..14a9f969 100644 --- a/Extensions/XEP-0065/Streamhost.cs +++ b/Extensions/XEP-0065/Streamhost.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents a streamhost entry as is used during S5B negotiation. diff --git a/Extensions/XEP-0065/Stun/BindingRequest.cs b/Extensions/XEP-0065/Stun/BindingRequest.cs index 04cee379..fc55da87 100644 --- a/Extensions/XEP-0065/Stun/BindingRequest.cs +++ b/Extensions/XEP-0065/Stun/BindingRequest.cs @@ -1,8 +1,8 @@ -using Sharp.Xmpp.Extensions.Socks5; +using XMPPEngineer.Extensions.Socks5; using System; using System.Security.Cryptography; -namespace Sharp.Xmpp.Extensions.Stun +namespace XMPPEngineer.Extensions.Stun { /// /// Represents a STUN 'Binding Request' message. diff --git a/Extensions/XEP-0065/Stun/BindingResponse.cs b/Extensions/XEP-0065/Stun/BindingResponse.cs index a584d89b..6f28f2c3 100644 --- a/Extensions/XEP-0065/Stun/BindingResponse.cs +++ b/Extensions/XEP-0065/Stun/BindingResponse.cs @@ -1,11 +1,11 @@ -using Sharp.Xmpp.Extensions.Socks5; +using XMPPEngineer.Extensions.Socks5; using System; using System.IO; using System.Linq; using System.Net; using System.Runtime.Serialization; -namespace Sharp.Xmpp.Extensions.Stun +namespace XMPPEngineer.Extensions.Stun { /// /// Represents a STUN 'Binding Response' message. diff --git a/Extensions/XEP-0065/Stun/StunClient.cs b/Extensions/XEP-0065/Stun/StunClient.cs index b2299c36..408ea796 100644 --- a/Extensions/XEP-0065/Stun/StunClient.cs +++ b/Extensions/XEP-0065/Stun/StunClient.cs @@ -4,7 +4,7 @@ using System.Net.Sockets; using System.Runtime.Serialization; -namespace Sharp.Xmpp.Extensions.Stun +namespace XMPPEngineer.Extensions.Stun { /// /// Implements a rudimentary STUN client for allowing an end host to discover diff --git a/Extensions/XEP-0065/UPnP/DeviceFinderCallback.cs b/Extensions/XEP-0065/UPnP/DeviceFinderCallback.cs index 9df83d30..dbdbcb7c 100644 --- a/Extensions/XEP-0065/UPnP/DeviceFinderCallback.cs +++ b/Extensions/XEP-0065/UPnP/DeviceFinderCallback.cs @@ -2,7 +2,7 @@ using UPNPLib; #endif -namespace Sharp.Xmpp.Extensions.Upnp +namespace XMPPEngineer.Extensions.Upnp { #if WINDOWSPLATFORM /// diff --git a/Extensions/XEP-0065/UPnP/UPnP.cs b/Extensions/XEP-0065/UPnP/UPnP.cs index 44a08548..bb234d10 100644 --- a/Extensions/XEP-0065/UPnP/UPnP.cs +++ b/Extensions/XEP-0065/UPnP/UPnP.cs @@ -2,7 +2,7 @@ using UPNPLib; #endif -namespace Sharp.Xmpp.Extensions.Upnp +namespace XMPPEngineer.Extensions.Upnp { #if WINDOWSPLATFORM diff --git a/Extensions/XEP-0077/InBandRegistration.cs b/Extensions/XEP-0077/InBandRegistration.cs index cb0519a9..3cc6a309 100644 --- a/Extensions/XEP-0077/InBandRegistration.cs +++ b/Extensions/XEP-0077/InBandRegistration.cs @@ -1,12 +1,12 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Extensions.Dataforms; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Extensions.Dataforms; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Linq; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'In-Band Registration' extension as defined in XEP-0077. diff --git a/Extensions/XEP-0077/RegistrationCallback.cs b/Extensions/XEP-0077/RegistrationCallback.cs index 833cef48..677debd5 100644 --- a/Extensions/XEP-0077/RegistrationCallback.cs +++ b/Extensions/XEP-0077/RegistrationCallback.cs @@ -1,6 +1,6 @@ -using Sharp.Xmpp.Extensions.Dataforms; +using XMPPEngineer.Extensions.Dataforms; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// A callback method which is invoked during the registration process to diff --git a/Extensions/XEP-0084/AvatarChangedEventArgs.cs b/Extensions/XEP-0084/AvatarChangedEventArgs.cs index d26489cb..e0210a1a 100644 --- a/Extensions/XEP-0084/AvatarChangedEventArgs.cs +++ b/Extensions/XEP-0084/AvatarChangedEventArgs.cs @@ -4,7 +4,7 @@ using System.Drawing; #endif -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the AvatarChanged event. diff --git a/Extensions/XEP-0084/UserAvatar.cs b/Extensions/XEP-0084/UserAvatar.cs index 14bcef93..c12ed610 100644 --- a/Extensions/XEP-0084/UserAvatar.cs +++ b/Extensions/XEP-0084/UserAvatar.cs @@ -3,7 +3,7 @@ using System.Drawing.Imaging; #endif -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { #if WINDOWSPLATFORM diff --git a/Extensions/XEP-0085/ChatState.cs b/Extensions/XEP-0085/ChatState.cs index e23a5e34..db277d0d 100644 --- a/Extensions/XEP-0085/ChatState.cs +++ b/Extensions/XEP-0085/ChatState.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Defines possible values for the chat state of an XMPP user. diff --git a/Extensions/XEP-0085/ChatStateChangedEventArgs.cs b/Extensions/XEP-0085/ChatStateChangedEventArgs.cs index 778a483f..6ed9b96b 100644 --- a/Extensions/XEP-0085/ChatStateChangedEventArgs.cs +++ b/Extensions/XEP-0085/ChatStateChangedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the ChatStateChanged event. diff --git a/Extensions/XEP-0085/ChatStateNotifications.cs b/Extensions/XEP-0085/ChatStateNotifications.cs index c74adb42..49f9faa3 100644 --- a/Extensions/XEP-0085/ChatStateNotifications.cs +++ b/Extensions/XEP-0085/ChatStateNotifications.cs @@ -1,8 +1,8 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Chat States Notifications' extension as defined in XEP-0085. diff --git a/Extensions/XEP-0092/SoftwareVersion.cs b/Extensions/XEP-0092/SoftwareVersion.cs index 27dc603d..d8951c5c 100644 --- a/Extensions/XEP-0092/SoftwareVersion.cs +++ b/Extensions/XEP-0092/SoftwareVersion.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Reflection; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Software Version' extension as defined in XEP-0092. @@ -134,7 +134,7 @@ public SoftwareVersion(XmppIm im) Attribute attr = Assembly.GetExecutingAssembly(). GetCustomAttribute(typeof(AssemblyProductAttribute)); string name = attr != null ? ((AssemblyProductAttribute)attr).Product : - "Sharp.Xmpp"; + "XMPPEngineer"; string version = Assembly.GetExecutingAssembly().GetName(). Version.ToString(); Version = new VersionInformation(name, version, diff --git a/Extensions/XEP-0092/VersionInformation.cs b/Extensions/XEP-0092/VersionInformation.cs index d04d3aa2..c6f4766c 100644 --- a/Extensions/XEP-0092/VersionInformation.cs +++ b/Extensions/XEP-0092/VersionInformation.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides information about the software application associated with an diff --git a/Extensions/XEP-0095/InitiationResult.cs b/Extensions/XEP-0095/InitiationResult.cs index 9478d272..3aef9d02 100644 --- a/Extensions/XEP-0095/InitiationResult.cs +++ b/Extensions/XEP-0095/InitiationResult.cs @@ -1,7 +1,7 @@ using System; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents the result of a stream initiation. diff --git a/Extensions/XEP-0095/StreamInitiation.cs b/Extensions/XEP-0095/StreamInitiation.cs index 2bfe9d60..911fffa7 100644 --- a/Extensions/XEP-0095/StreamInitiation.cs +++ b/Extensions/XEP-0095/StreamInitiation.cs @@ -1,12 +1,12 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Extensions.Dataforms; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Extensions.Dataforms; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Linq; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Stream Initiation' extension as defined in XEP-0095. diff --git a/Extensions/XEP-0096/BytesTransferredEventArgs.cs b/Extensions/XEP-0096/BytesTransferredEventArgs.cs index 41b35ff8..1d04dfb2 100644 --- a/Extensions/XEP-0096/BytesTransferredEventArgs.cs +++ b/Extensions/XEP-0096/BytesTransferredEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the 'BytesTransferred' event which is raised by diff --git a/Extensions/XEP-0096/FileMetaData.cs b/Extensions/XEP-0096/FileMetaData.cs index 5ce742c8..18a12871 100644 --- a/Extensions/XEP-0096/FileMetaData.cs +++ b/Extensions/XEP-0096/FileMetaData.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents meta-data of a file. diff --git a/Extensions/XEP-0096/FileTransfer.cs b/Extensions/XEP-0096/FileTransfer.cs index 70fb87c4..99d24de9 100644 --- a/Extensions/XEP-0096/FileTransfer.cs +++ b/Extensions/XEP-0096/FileTransfer.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an on-going file-transfer operation. diff --git a/Extensions/XEP-0096/FileTransferAbortedEventArgs.cs b/Extensions/XEP-0096/FileTransferAbortedEventArgs.cs index 1828c7b9..c91794f7 100644 --- a/Extensions/XEP-0096/FileTransferAbortedEventArgs.cs +++ b/Extensions/XEP-0096/FileTransferAbortedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the 'FileTransferAborted' event. diff --git a/Extensions/XEP-0096/FileTransferProgressEventArgs.cs b/Extensions/XEP-0096/FileTransferProgressEventArgs.cs index 3248d133..7da8562a 100644 --- a/Extensions/XEP-0096/FileTransferProgressEventArgs.cs +++ b/Extensions/XEP-0096/FileTransferProgressEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the 'FileTransferProgress' event. diff --git a/Extensions/XEP-0096/FileTransferRequest.cs b/Extensions/XEP-0096/FileTransferRequest.cs index e07f02b0..5b6b3d56 100644 --- a/Extensions/XEP-0096/FileTransferRequest.cs +++ b/Extensions/XEP-0096/FileTransferRequest.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents a request for a file-transfer. diff --git a/Extensions/XEP-0096/IDataStream.cs b/Extensions/XEP-0096/IDataStream.cs index 901149c9..75a8fc9e 100644 --- a/Extensions/XEP-0096/IDataStream.cs +++ b/Extensions/XEP-0096/IDataStream.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an XMPP extension that implements a data-stream for transferring diff --git a/Extensions/XEP-0096/SIFileTransfer.cs b/Extensions/XEP-0096/SIFileTransfer.cs index d1fb9805..f11b1a6a 100644 --- a/Extensions/XEP-0096/SIFileTransfer.cs +++ b/Extensions/XEP-0096/SIFileTransfer.cs @@ -1,6 +1,6 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Extensions.Dataforms; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Extensions.Dataforms; +using XMPPEngineer.Im; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -8,7 +8,7 @@ using System.Linq; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'SI File Transfer' extension as defined in XEP-0096. diff --git a/Extensions/XEP-0096/SISession.cs b/Extensions/XEP-0096/SISession.cs index 311ccdc8..3d22e223 100644 --- a/Extensions/XEP-0096/SISession.cs +++ b/Extensions/XEP-0096/SISession.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents an SI session as is negotiated during stream initiation. diff --git a/Extensions/XEP-0096/TransferAbortedEventArgs.cs b/Extensions/XEP-0096/TransferAbortedEventArgs.cs index e47c22a1..6e486ab8 100644 --- a/Extensions/XEP-0096/TransferAbortedEventArgs.cs +++ b/Extensions/XEP-0096/TransferAbortedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the 'TransferAborted' event which is raised by diff --git a/Extensions/XEP-0107/Mood.cs b/Extensions/XEP-0107/Mood.cs index 6de0f4ca..5f8edf7f 100644 --- a/Extensions/XEP-0107/Mood.cs +++ b/Extensions/XEP-0107/Mood.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Defines possible values for the mood of an XMPP user. diff --git a/Extensions/XEP-0107/MoodChangedEventArgs.cs b/Extensions/XEP-0107/MoodChangedEventArgs.cs index 47bbc6f4..4ece0664 100644 --- a/Extensions/XEP-0107/MoodChangedEventArgs.cs +++ b/Extensions/XEP-0107/MoodChangedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the MoodChanged event. diff --git a/Extensions/XEP-0107/UserMood.cs b/Extensions/XEP-0107/UserMood.cs index 494c6200..183bd869 100644 --- a/Extensions/XEP-0107/UserMood.cs +++ b/Extensions/XEP-0107/UserMood.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Text; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'User Mood' extension as defined in XEP-0107. diff --git a/Extensions/XEP-0108/ActivityChangedEventArgs.cs b/Extensions/XEP-0108/ActivityChangedEventArgs.cs index b25b8dca..9fe02c7b 100644 --- a/Extensions/XEP-0108/ActivityChangedEventArgs.cs +++ b/Extensions/XEP-0108/ActivityChangedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the ActivityChanged event. diff --git a/Extensions/XEP-0108/GeneralActivity.cs b/Extensions/XEP-0108/GeneralActivity.cs index b18d29bb..dfe7975c 100644 --- a/Extensions/XEP-0108/GeneralActivity.cs +++ b/Extensions/XEP-0108/GeneralActivity.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Defines possible values for the general activity of an XMPP user. diff --git a/Extensions/XEP-0108/SpecificActivity.cs b/Extensions/XEP-0108/SpecificActivity.cs index 2c55b87f..67462c70 100644 --- a/Extensions/XEP-0108/SpecificActivity.cs +++ b/Extensions/XEP-0108/SpecificActivity.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Defines possible values for more specific activities of an XMPP user. diff --git a/Extensions/XEP-0108/UserActivity.cs b/Extensions/XEP-0108/UserActivity.cs index 1727dde4..0f4d51a5 100644 --- a/Extensions/XEP-0108/UserActivity.cs +++ b/Extensions/XEP-0108/UserActivity.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Text; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'User Activity' extension as defined in XEP-0108. diff --git a/Extensions/XEP-0115/EntityCapabilities.cs b/Extensions/XEP-0115/EntityCapabilities.cs index c883ceb7..319e3401 100644 --- a/Extensions/XEP-0115/EntityCapabilities.cs +++ b/Extensions/XEP-0115/EntityCapabilities.cs @@ -1,11 +1,11 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Entity Capabilities' extension as defined in XEP-0092. @@ -38,7 +38,7 @@ private string nodeUri get { // FIXME: Move this to a resource file or to assembly metadata? - return "Sharp.Xmpp"; + return "XMPPEngineer"; } } diff --git a/Extensions/XEP-0118/TuneEventArgs.cs b/Extensions/XEP-0118/TuneEventArgs.cs index 539aac7d..9def76ab 100644 --- a/Extensions/XEP-0118/TuneEventArgs.cs +++ b/Extensions/XEP-0118/TuneEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides data for the Tune event. diff --git a/Extensions/XEP-0118/TuneInformation.cs b/Extensions/XEP-0118/TuneInformation.cs index 1f4ae16d..7a08dbef 100644 --- a/Extensions/XEP-0118/TuneInformation.cs +++ b/Extensions/XEP-0118/TuneInformation.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Provides information about the music to which a user is listening. diff --git a/Extensions/XEP-0118/UserTune.cs b/Extensions/XEP-0118/UserTune.cs index 840d79b8..2cffd631 100644 --- a/Extensions/XEP-0118/UserTune.cs +++ b/Extensions/XEP-0118/UserTune.cs @@ -1,9 +1,9 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'User Tune' extension as defined in XEP-0118. diff --git a/Extensions/XEP-0153/vCardAvatars.cs b/Extensions/XEP-0153/vCardAvatars.cs index d0c95261..4e16ac32 100644 --- a/Extensions/XEP-0153/vCardAvatars.cs +++ b/Extensions/XEP-0153/vCardAvatars.cs @@ -1,5 +1,5 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.IO; @@ -8,7 +8,7 @@ using System.Xml; using System.Xml.Linq; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'vCard based Avatars' extension as defined in XEP-0153. @@ -103,7 +103,7 @@ public void SetAvatar(Stream stream) if (iq.Type == IqType.Result) { // Result must contain a 'feature' element. - im.SendPresence(new Sharp.Xmpp.Im.Presence(null, null, PresenceType.Available, null, null, Xml.Element("x", "vcard-temp:x:update").Child(Xml.Element("photo").Text(hash)))); + im.SendPresence(new XMPPEngineer.Im.Presence(null, null, PresenceType.Available, null, null, Xml.Element("x", "vcard-temp:x:update").Child(Xml.Element("photo").Text(hash)))); } }); } diff --git a/Extensions/XEP-0163/Pep.cs b/Extensions/XEP-0163/Pep.cs index 9639da32..e3404472 100644 --- a/Extensions/XEP-0163/Pep.cs +++ b/Extensions/XEP-0163/Pep.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Personal Eventing Protocol' extension as defined in XEP-0163. diff --git a/Extensions/XEP-0191/BlockingCommand.cs b/Extensions/XEP-0191/BlockingCommand.cs index 0ec8d3b1..586effb6 100644 --- a/Extensions/XEP-0191/BlockingCommand.cs +++ b/Extensions/XEP-0191/BlockingCommand.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Blocking Command' extension as defined in XEP-0191. diff --git a/Extensions/XEP-0199/Ping.cs b/Extensions/XEP-0199/Ping.cs index 3911d5dc..108a7f61 100644 --- a/Extensions/XEP-0199/Ping.cs +++ b/Extensions/XEP-0199/Ping.cs @@ -1,9 +1,9 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Ping' extension as defined in XEP-0199. diff --git a/Extensions/XEP-0202/EntityTime.cs b/Extensions/XEP-0202/EntityTime.cs index 9a2050cd..404c1190 100644 --- a/Extensions/XEP-0202/EntityTime.cs +++ b/Extensions/XEP-0202/EntityTime.cs @@ -1,9 +1,9 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Entity Time' extension as defined in XEP-0202. diff --git a/Extensions/XEP-0224/Attention.cs b/Extensions/XEP-0224/Attention.cs index e333040f..a04c0308 100644 --- a/Extensions/XEP-0224/Attention.cs +++ b/Extensions/XEP-0224/Attention.cs @@ -1,8 +1,8 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Attention' extension as defined in XEP-0224. diff --git a/Extensions/XEP-0231/BitsOfBinary.cs b/Extensions/XEP-0231/BitsOfBinary.cs index b3c51ec8..d22f57ee 100644 --- a/Extensions/XEP-0231/BitsOfBinary.cs +++ b/Extensions/XEP-0231/BitsOfBinary.cs @@ -1,9 +1,9 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Bits of Binary' extension as defined in XEP-0231. diff --git a/Extensions/XEP-0231/BobData.cs b/Extensions/XEP-0231/BobData.cs index 0e93a06a..ab8150bb 100644 --- a/Extensions/XEP-0231/BobData.cs +++ b/Extensions/XEP-0231/BobData.cs @@ -3,7 +3,7 @@ using System.Text; using System.Xml; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Represents a piece of binary data in the context of the 'Bits of Binary' diff --git a/Extensions/XEP-0279/ServerIpCheck.cs b/Extensions/XEP-0279/ServerIpCheck.cs index c542791d..0f1b976b 100644 --- a/Extensions/XEP-0279/ServerIpCheck.cs +++ b/Extensions/XEP-0279/ServerIpCheck.cs @@ -1,10 +1,10 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; using System.Net; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// Implements the 'Server IP Check' extension as defined in XEP-0279. diff --git a/Extensions/XEP-0280/MessageCarbons.cs b/Extensions/XEP-0280/MessageCarbons.cs index 3f5f958a..b7dad301 100644 --- a/Extensions/XEP-0280/MessageCarbons.cs +++ b/Extensions/XEP-0280/MessageCarbons.cs @@ -1,9 +1,9 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Im; +using XMPPEngineer.Core; +using XMPPEngineer.Im; using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { internal class MessageCarbons : XmppExtension { diff --git a/Extensions/XmppExtension.cs b/Extensions/XmppExtension.cs index b35faae6..b5d010de 100644 --- a/Extensions/XmppExtension.cs +++ b/Extensions/XmppExtension.cs @@ -1,7 +1,7 @@ -using Sharp.Xmpp.Im; +using XMPPEngineer.Im; using System.Collections.Generic; -namespace Sharp.Xmpp.Extensions +namespace XMPPEngineer.Extensions { /// /// The base class from which all implementations of XMPP extensions must diff --git a/Extensions/vCardAvatars.cs b/Extensions/vCardAvatars.cs index 3fcc4700..c0ec3f48 100644 --- a/Extensions/vCardAvatars.cs +++ b/Extensions/vCardAvatars.cs @@ -1,5 +1,7 @@ -using S22.Xmpp.Core; -using S22.Xmpp.Im; +using XMPPEngineer; +using XMPPEngineer.Core; +using XMPPEngineer.Im; +using XMPPEngineer.Extensions; using System; using System.Collections.Generic; using System.IO; @@ -99,7 +101,7 @@ public void SetAvatar(Stream stream) if (iq.Type == IqType.Result) { // Result must contain a 'feature' element. - im.SendPresence(new S22.Xmpp.Im.Presence(null, null, PresenceType.Available, null, null, Xml.Element("x", "vcard-temp:x:update").Child(Xml.Element("photo").Text(hash)))); + im.SendPresence(new XMPPEngineer.Im.Presence(null, null, PresenceType.Available, null, null, Xml.Element("x", "vcard-temp:x:update").Child(Xml.Element("photo").Text(hash)))); } }); diff --git a/Im/Availability.cs b/Im/Availability.cs index 2b981301..7510c797 100644 --- a/Im/Availability.cs +++ b/Im/Availability.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Defines the possible values for a user's availability status. diff --git a/Im/ErrorEventArgs.cs b/Im/ErrorEventArgs.cs index dfe5b76a..8350e792 100644 --- a/Im/ErrorEventArgs.cs +++ b/Im/ErrorEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the Error event. diff --git a/Im/GroupPrivacyRule.cs b/Im/GroupPrivacyRule.cs index e525e759..49d7da33 100644 --- a/Im/GroupPrivacyRule.cs +++ b/Im/GroupPrivacyRule.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a privacy rule pertaining to a group. diff --git a/Im/JidPrivacyRule.cs b/Im/JidPrivacyRule.cs index d0ffcfcc..9c631364 100644 --- a/Im/JidPrivacyRule.cs +++ b/Im/JidPrivacyRule.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a privacy rule pertaining to a JID. diff --git a/Im/Message.cs b/Im/Message.cs index b4ea7232..59ca8ac1 100644 --- a/Im/Message.cs +++ b/Im/Message.cs @@ -2,15 +2,18 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Text; using System.Xml; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a Message stanza as defined in XMPP:IM. /// public class Message : Core.Message { + private List addresses; + /// /// The type of the message stanza. /// @@ -152,6 +155,71 @@ public string Body } } + /// + /// The addresses of the message. + /// + public List Addresses + { + get + { + XmlElement bare = GetBare("addresses"); + if (bare != null) + { + if (addresses == null) + { + addresses = new List(); + + foreach (XmlElement child in bare.ChildNodes) + { + string v = child.GetAttributeNode("jid").Value; + if (!String.IsNullOrWhiteSpace(v)) + addresses.Add(new Jid(v)); + } + } + } + + return addresses; + } + + set + { + XmlElement bare = GetBare("addresses"); + if (bare != null) + { + if (value == null) + element.RemoveChild(bare); + else + { + StringBuilder sb = new StringBuilder(); + foreach (Jid jid in value) + { + sb.Append(jid.ToString()); + } + bare.InnerXml = sb.ToString(); + //bare.InnerText = value; + } + + } + else + { + if (value != null) + { + System.Text.StringBuilder sb = new StringBuilder(); + foreach (Jid jid in value) + { + sb.Append(String.Format("
", jid.ToString())); + } + + XmlElement addressXml = Xml.Element("addresses"); + addressXml.InnerXml = sb.ToString(); + addressXml.SetAttribute("xmlns", "http://jabber.org/protocol/address"); + + element.Child(addressXml); + } + } + } + } + /// /// A dictionary of alternate forms of the message subjects. The keys of the /// dictionary denote ISO 2 language codes. @@ -172,58 +240,73 @@ public IDictionary AlternateBodies private set; } - /// - /// Initializes a new instance of the Message class. - /// - /// The JID of the intended recipient. - /// The content of the message. - /// The subject of the message. - /// The conversation thread this message belongs to. - /// The type of the message. Can be one of the values from - /// the MessagType enumeration. - /// The language of the XML character data of - /// the stanza. - /// The to parameter is null. - /// The body parameter is the empty string. - public Message(Jid to, string body = null, string subject = null, string thread = null, - MessageType type = MessageType.Normal, CultureInfo language = null) + /// + /// A dictionary of alternate forms of the message addresses. The keys of the + /// dictionary denote ISO 2 language codes. + /// + public IDictionary AlternateAddresses + { + get; + private set; + } + + /// + /// Initializes a new instance of the Message class. + /// + /// The JID of the intended recipient. + /// The content of the message. + /// The subject of the message. + /// The XEP-0033 of the message. + /// The conversation thread this message belongs to. + /// The type of the message. Can be one of the values from + /// the MessagType enumeration. + /// The language of the XML character data of + /// the stanza. + /// The to parameter is null. + /// The body parameter is the empty string. + public Message(Jid to, string body = null, string subject = null, List additionalAddresses = null, + string thread = null, MessageType type = MessageType.Normal, CultureInfo language = null) : base(to, null, null, null, language) { to.ThrowIfNull("to"); AlternateSubjects = new XmlDictionary(element, "subject", "xml:lang"); AlternateBodies = new XmlDictionary(element, "body", "xml:lang"); + AlternateAddresses = new XmlDictionary(element, "addresses", "xml:lang"); Type = type; Body = body; Subject = subject; Thread = thread; + Addresses = additionalAddresses; } - /// - /// Initializes a new instance of the Message class. - /// - /// The JID of the intended recipient. - /// A dictionary of message bodies. The dictionary - /// keys denote the languages of the message bodies and must be valid - /// ISO 2 letter language codes. - /// A dictionary of message subjects. The dictionary - /// keys denote the languages of the message subjects and must be valid - /// ISO 2 letter language codes. - /// The conversation thread this message belongs to. - /// The type of the message. Can be one of the values from - /// the MessagType enumeration. - /// The language of the XML character data of - /// the stanza. - /// The to parametr or the bodies - /// parameter is null. - public Message(Jid to, IDictionary bodies, - IDictionary subjects = null, string thread = null, - MessageType type = MessageType.Normal, CultureInfo language = null) + /// + /// Initializes a new instance of the Message class. + /// + /// The JID of the intended recipient. + /// A dictionary of message bodies. The dictionary + /// keys denote the languages of the message bodies and must be valid + /// ISO 2 letter language codes. + /// A dictionary of message subjects. The dictionary + /// keys denote the languages of the message subjects and must be valid + /// ISO 2 letter language codes. + /// The XEP-0033 of the message. + /// The conversation thread this message belongs to. + /// The type of the message. Can be one of the values from + /// the MessagType enumeration. + /// The language of the XML character data of + /// the stanza. + /// The to parametr or the bodies + /// parameter is null. + public Message(Jid to, IDictionary bodies, + IDictionary subjects = null, List additionalAddresses = null, + string thread = null, MessageType type = MessageType.Normal, CultureInfo language = null) : base(to, null, null, null, language) { to.ThrowIfNull("to"); bodies.ThrowIfNull("bodies"); AlternateSubjects = new XmlDictionary(element, "subject", "xml:lang"); AlternateBodies = new XmlDictionary(element, "body", "xml:lang"); + AlternateAddresses = new XmlDictionary(element, "addresses", "xml:lang"); Type = type; foreach (var pair in bodies) AlternateBodies.Add(pair.Key, pair.Value); @@ -233,8 +316,65 @@ public Message(Jid to, IDictionary bodies, AlternateSubjects.Add(pair.Key, pair.Value); } Thread = thread; + Addresses = additionalAddresses; } + /// + /// Initializes a new instance of the Message class. + /// + /// The JID of the intended recipient. + /// The content of the message. + /// The tag name the others items below will be wrapped in - they will have the appropriate namespace assigned. + /// A dictionary of additional message elements after body. The dictionary + /// keys denote the namespace of the message bodies. The element name should be the same for all items but you can have multiple - + /// each new element will have the namespace associated with it. + /// A dictionary of message subjects. The dictionary + /// keys denote the languages of the message subjects and must be valid + /// ISO 2 letter language codes. + /// The conversation thread this message belongs to. + /// The type of the message. Can be one of the values from + /// the MessagType enumeration. + /// The language of the XML character data of + /// the stanza. + /// The to parametr or the bodies + /// parameter is null. + public Message(Jid to, String body, string othertagname, IDictionary others, + IDictionary subjects = null, List additionalAddresses = null, + string thread = null, MessageType type = MessageType.Normal, CultureInfo language = null) + : base(to, null, null, null, language) + { + to.ThrowIfNull("to"); + others.ThrowIfNull("bodies"); + AlternateSubjects = new XmlDictionary(element, "subject", "xml:lang"); + Body = body; + AlternateBodies = new XmlDictionary(element, othertagname, "xmlns"); + AlternateAddresses = new XmlDictionary(element, "addresses", "xml:lang"); + Type = type; + foreach (var pair in others) + AlternateBodies.Add(pair.Key, pair.Value); + if (subjects != null) + { + foreach (var pair in subjects) + AlternateSubjects.Add(pair.Key, pair.Value); + } + Thread = thread; + Addresses = additionalAddresses; + } + + /// + /// Initializes a new instance of the Message class from the specified + /// instance. + /// + /// The message element + /// The Data parameter is null. + public Message(XmlElement data) + { + + Data.ThrowIfNull("data"); + type = ParseType(data.GetAttribute("type")); + element = data; + } + /// /// Initializes a new instance of the Message class from the specified /// instance. @@ -251,6 +391,7 @@ internal Message(Core.Message message) element = message.Data; AlternateSubjects = new XmlDictionary(element, "subject", "xml:lang"); AlternateBodies = new XmlDictionary(element, "body", "xml:lang"); + AlternateAddresses = new XmlDictionary(element, "addresses", "xml:lang"); } /// diff --git a/Im/MessageEventArgs.cs b/Im/MessageEventArgs.cs index c8891a1a..50972884 100644 --- a/Im/MessageEventArgs.cs +++ b/Im/MessageEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the Message event. @@ -37,5 +37,15 @@ public MessageEventArgs(Jid jid, Message message) Jid = jid; Message = message; } + + /// + /// Initializes a new instance of the MessageEventArgs class for bodyless messages. + /// + /// The message parameter is null. + public MessageEventArgs(Message message) + { + message.ThrowIfNull("message"); + Message = message; + } } } \ No newline at end of file diff --git a/Im/MessageType.cs b/Im/MessageType.cs index ee280c50..ea496938 100644 --- a/Im/MessageType.cs +++ b/Im/MessageType.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Defines the possible types for Message stanzas. diff --git a/Im/Presence.cs b/Im/Presence.cs index 7b45a991..bb7e224d 100644 --- a/Im/Presence.cs +++ b/Im/Presence.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Xml; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a Presence XML stanza as defined in XMPP:IM. diff --git a/Im/PresenceType.cs b/Im/PresenceType.cs index c49cd0e7..831728d2 100644 --- a/Im/PresenceType.cs +++ b/Im/PresenceType.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Defines the possible types for Presence stanzas. diff --git a/Im/PrivacyGranularity.cs b/Im/PrivacyGranularity.cs index a5a9f7ec..005879f7 100644 --- a/Im/PrivacyGranularity.cs +++ b/Im/PrivacyGranularity.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Defines the possible values for specifying more granular control over diff --git a/Im/PrivacyList.cs b/Im/PrivacyList.cs index 8eb8d494..5e258eac 100644 --- a/Im/PrivacyList.cs +++ b/Im/PrivacyList.cs @@ -2,7 +2,7 @@ using System.Collections; using System.Collections.Generic; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents an XMPP privacy list. diff --git a/Im/PrivacyRule.cs b/Im/PrivacyRule.cs index 98d2e13d..caebeac1 100644 --- a/Im/PrivacyRule.cs +++ b/Im/PrivacyRule.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a generic privacy rule. diff --git a/Im/Roster.cs b/Im/Roster.cs index 32c27bb6..98c5c2bf 100644 --- a/Im/Roster.cs +++ b/Im/Roster.cs @@ -1,7 +1,7 @@ using System.Collections; using System.Collections.Generic; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents the user's roster. diff --git a/Im/RosterItem.cs b/Im/RosterItem.cs index 927a54d9..df7a8052 100644 --- a/Im/RosterItem.cs +++ b/Im/RosterItem.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a roster item. diff --git a/Im/RosterUpdatedEventArgs.cs b/Im/RosterUpdatedEventArgs.cs index ac94f63a..fe10beb5 100644 --- a/Im/RosterUpdatedEventArgs.cs +++ b/Im/RosterUpdatedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the RosterUpdated Event. diff --git a/Im/Status.cs b/Im/Status.cs index 034500fe..532a45cd 100644 --- a/Im/Status.cs +++ b/Im/Status.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Linq; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides status information for a contact. diff --git a/Im/StatusEventArgs.cs b/Im/StatusEventArgs.cs index e5c30344..b0a4d35e 100644 --- a/Im/StatusEventArgs.cs +++ b/Im/StatusEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the Status event. diff --git a/Im/SubscriptionApprovedEventArgs.cs b/Im/SubscriptionApprovedEventArgs.cs index 867fe8e7..ded31be6 100644 --- a/Im/SubscriptionApprovedEventArgs.cs +++ b/Im/SubscriptionApprovedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the SubscriptionApproved Event. diff --git a/Im/SubscriptionPrivacyRule.cs b/Im/SubscriptionPrivacyRule.cs index cde0bd00..ce94a307 100644 --- a/Im/SubscriptionPrivacyRule.cs +++ b/Im/SubscriptionPrivacyRule.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a privacy rule pertaining to a subscription state. diff --git a/Im/SubscriptionRefusedEventArgs.cs b/Im/SubscriptionRefusedEventArgs.cs index 468ff0db..ef23425e 100644 --- a/Im/SubscriptionRefusedEventArgs.cs +++ b/Im/SubscriptionRefusedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the SubscriptionRefused Event. diff --git a/Im/SubscriptionRequest.cs b/Im/SubscriptionRequest.cs index d4085dc9..baabb147 100644 --- a/Im/SubscriptionRequest.cs +++ b/Im/SubscriptionRequest.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Represents a request for subscription. diff --git a/Im/SubscriptionRequestEventArgs.cs b/Im/SubscriptionRequestEventArgs.cs index 849800bf..348a5bc7 100644 --- a/Im/SubscriptionRequestEventArgs.cs +++ b/Im/SubscriptionRequestEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the SubscriptionRequest Event. diff --git a/Im/SubscriptionState.cs b/Im/SubscriptionState.cs index bf51c798..7a1536a5 100644 --- a/Im/SubscriptionState.cs +++ b/Im/SubscriptionState.cs @@ -1,4 +1,4 @@ -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Defines the possible values for the subscription state of a roster item. diff --git a/Im/UnsubscribedEventArgs.cs b/Im/UnsubscribedEventArgs.cs index 166bfc20..6da5c5b9 100644 --- a/Im/UnsubscribedEventArgs.cs +++ b/Im/UnsubscribedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Provides data for the Unsubscribed Event. diff --git a/Im/XmlDictionary.cs b/Im/XmlDictionary.cs index 5f810cb4..8fcc7ee3 100644 --- a/Im/XmlDictionary.cs +++ b/Im/XmlDictionary.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Xml; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// An XML-backed dictionary. diff --git a/Im/XmppIm.cs b/Im/XmppIm.cs index 388226b1..ace871e0 100644 --- a/Im/XmppIm.cs +++ b/Im/XmppIm.cs @@ -1,5 +1,5 @@ -using Sharp.Xmpp.Core; -using Sharp.Xmpp.Extensions; +using XMPPEngineer.Core; +using XMPPEngineer.Extensions; using System; using System.Collections.Generic; using System.Globalization; @@ -10,7 +10,7 @@ using System.Security.Authentication; using System.Xml; -namespace Sharp.Xmpp.Im +namespace XMPPEngineer.Im { /// /// Implements the basic instant messaging (IM) and presence functionality. @@ -28,6 +28,8 @@ public class XmppIm : IDisposable /// private bool disposed; + bool retrieveRoster = true; + /// /// The set of loaded extensions. /// @@ -143,6 +145,22 @@ public RemoteCertificateValidationCallback Validate } } + /// + /// If false the connection will not automatically retrieve the rooster + /// + public bool RetrieveRoster + { + get + { + return retrieveRoster; + } + + set + { + retrieveRoster = value; + } + } + /// /// Determines whether the session with the server is TLS/SSL encrypted. /// @@ -250,6 +268,16 @@ public CustomIqRequestDelegate CustomIqDelegate /// public event EventHandler Message; + /// + /// The event that is raised when stream management is enabled. + /// + public event EventHandler StreamManagementEnabled; + + /// + /// The event that is raised when a stream is resumed. + /// + public event EventHandler StreamResumed; + /// /// The event that is raised when a subscription request made by the JID /// associated with this instance has been approved. @@ -299,11 +327,36 @@ public CustomIqRequestDelegate CustomIqDelegate /// The value of the port parameter /// is not a valid port number. public XmppIm(string hostname, string username, string password, - int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) - { - core = new XmppCore(hostname, username, password, port, tls, validate); - SetupEventHandlers(); - } + int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) : + this (hostname, username, password, null, port, tls, validate) + { } + + /// + /// Initializes a new instance of the XmppIm. + /// + /// The hostname of the XMPP server to connect to. + /// The username with which to authenticate. In XMPP jargon + /// this is known as the 'node' part of the JID. + /// The password with which to authenticate. + /// The IP address or domain of the XMPP server, if different from the hostname eg. xmpp.server.com + /// The port number of the XMPP service of the server. + /// If true the session will be TLS/SSL-encrypted if the server + /// supports TLS/SSL-encryption. + /// A delegate used for verifying the remote Secure Sockets + /// Layer (SSL) certificate which is used for authentication. Can be null if not + /// needed. + /// The hostname parameter or the + /// username parameter or the password parameter is null. + /// The hostname parameter or the username + /// parameter is the empty string. + /// The value of the port parameter + /// is not a valid port number. + public XmppIm(string hostname, string username, string password, string server, + int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null) + { + core = new XmppCore(hostname, username, password, server, port, tls, validate); + SetupEventHandlers(); + } /// /// Initializes a new instance of the XmppIm. @@ -322,12 +375,37 @@ public XmppIm(string hostname, string username, string password, /// The value of the port parameter /// is not a valid port number. public XmppIm(string hostname, int port = 5222, bool tls = true, - RemoteCertificateValidationCallback validate = null) + RemoteCertificateValidationCallback validate = null) : + this (hostname, null, port , tls, validate) { core = new XmppCore(hostname, port, tls, validate); SetupEventHandlers(); } + /// + /// Initializes a new instance of the XmppIm. + /// + /// The hostname of the XMPP server to connect to. + /// The IP address or domain of the XMPP server, if different from the hostname eg. xmpp.server.com + /// The port number of the XMPP service of the server. + /// If true the session will be TLS/SSL-encrypted if the server + /// supports TLS/SSL-encryption. + /// A delegate used for verifying the remote Secure Sockets + /// Layer (SSL) certificate which is used for authentication. Can be null if not + /// needed. + /// The hostname parameter is + /// null. + /// The hostname parameter is the empty + /// string. + /// The value of the port parameter + /// is not a valid port number. + public XmppIm(string hostname, string server, int port = 5222, bool tls = true, + RemoteCertificateValidationCallback validate = null) + { + core = new XmppCore(hostname, server, port, tls, validate); + SetupEventHandlers(); + } + /// /// Establishes a connection to the XMPP server. /// @@ -370,11 +448,25 @@ public Roster Connect(string resource = null) return null; // Establish a session (Refer to RFC 3921, Section 3. Session Establishment). EstablishSession(); - // Retrieve user's roster as recommended (Refer to RFC 3921, Section 7.3). - Roster roster = GetRoster(); - // Send initial presence. - SendPresence(new Presence()); - return roster; + + //If roster is disabled don't send it + if (!retrieveRoster){ + + // Send initial presence so we can get messages routed + SendPresence(new Presence()); + + return null; + + } else { + + // Retrieve user's roster as recommended (Refer to RFC 3921, Section 7.3). + Roster roster = GetRoster(); + // Send initial presence so we can get messages routed + SendPresence(new Presence()); + + return roster; + } + } catch (SocketException e) { @@ -402,17 +494,23 @@ public Roster Connect(string resource = null) /// An XMPP error occurred while negotiating the /// XML stream with the server, or resource binding failed, or the initialization /// of an XMPP extension failed. - public void Autenticate(string username, string password) + public void Authenticate(string username, string password) { username.ThrowIfNull("username"); password.ThrowIfNull("password"); core.Authenticate(username, password); // Establish a session (Refer to RFC 3921, Section 3. Session Establishment). EstablishSession(); - // Retrieve user's roster as recommended (Refer to RFC 3921, Section 7.3). - Roster roster = GetRoster(); - // Send initial presence. - SendPresence(new Presence()); + + + //If roster is disabled don't send it nor the presence + if (retrieveRoster) + { + // Retrieve user's roster as recommended (Refer to RFC 3921, Section 7.3). + Roster roster = GetRoster(); + // Send initial presence. + SendPresence(new Presence()); + } } /// @@ -438,16 +536,31 @@ public void Autenticate(string username, string password) /// The XmppIm object has been /// disposed. public void SendMessage(Jid to, string body, string subject = null, - string thread = null, MessageType type = MessageType.Normal, + List additionalAddresses = null, string thread = null, MessageType type = MessageType.Normal, CultureInfo language = null) { AssertValid(); to.ThrowIfNull("to"); body.ThrowIfNullOrEmpty("body"); - Message m = new Message(to, body, subject, thread, type, language); + Message m = new Message(to, body, subject, additionalAddresses, thread, type, language); SendMessage(m); } + /// + /// Enables stream management. You should listen for the StreamManagementEnabled event + /// to know when it is ready. + /// Whether we should enabled resumption on the stream. + /// The max timeout client request - the server can override this. + /// + public void EnableStreamManagement(bool withresumption = true, int maxTimeout = 60) + { + // raise any events we get + core.StreamManagementEnabled += StreamManagementEnabled.Raise; + + // enable sm + core.EnableStreamManagement(withresumption, maxTimeout); + } + /// /// Sends a chat message with the specified content to the specified JID. /// @@ -474,12 +587,13 @@ public void SendMessage(Jid to, string body, string subject = null, /// disposed. public void SendMessage(Jid to, IDictionary bodies, IDictionary subjects = null, string thread = null, + List additionalAddresses = null, MessageType type = MessageType.Normal, CultureInfo language = null) { AssertValid(); to.ThrowIfNull("to"); bodies.ThrowIfNull("bodies"); - Message m = new Message(to, bodies, subjects, thread, type, language); + Message m = new Message(to, bodies, subjects, additionalAddresses, thread, type, language); SendMessage(m); } @@ -794,7 +908,7 @@ public void AddToRoster(RosterItem item) foreach (string group in item.Groups) xml.Child(Xml.Element("group").Text(group)); var query = Xml.Element("query", "jabber:iq:roster").Child(xml); - Iq iq = IqRequest(IqType.Set, null, Jid, query); + Iq iq = IqRequest(IqType.Set, item.Jid, Jid, query); if (iq.Type == IqType.Error) throw Util.ExceptionFromError(iq, "The item could not be added to the roster."); } @@ -1532,8 +1646,10 @@ private void EstablishSession() /// Sets up the event handlers for the events exposed by the XmppCore instance. /// private void SetupEventHandlers() - { - core.Iq += (sender, e) => { OnIq(e.Stanza); }; + { + core.Iq += (sender, e) => { + OnIq(e.Stanza); + }; core.Presence += (sender, e) => { // FIXME: Raise Error event if constructor raises exception? diff --git a/Jid.cs b/Jid.cs index 9be3a91b..4d2b18d0 100644 --- a/Jid.cs +++ b/Jid.cs @@ -2,7 +2,7 @@ using System.Text; using System.Text.RegularExpressions; -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// Represents the address of an XMPP entity, also known as Jabber Identifier (JID). diff --git a/License.md b/License.md index 8b2904ca..915fc003 100644 --- a/License.md +++ b/License.md @@ -1,6 +1,6 @@ -### The MIT License +### The MIT License -Sharp.Xmpp Copyright (c) 2015 Panos Georgiou Stath. +XMPPEngineer Copyright (c) 2015 Panos Georgiou Stath. S22.Xmpp Copyright (c) 2013-2014 Torben Könke Permission is hereby granted, free of charge, to any person obtaining diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs deleted file mode 100644 index 06b5e7e4..00000000 --- a/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Sharp.Xmpp")] -[assembly: AssemblyDescription("Sharp.Xmpp is a multiplatform, Windows and Android, .NET XMPP client assembly. Sharp.Xmpp supports IM functionality and a variety of XMPP extensions, is simple and is extensively tested against Android Xamarin. It is a fork of the currently frozen excellent S22.Xmpp project.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("PGStath")] -[assembly: AssemblyProduct("Sharp.Xmpp")] -[assembly: AssemblyCopyright("Sharp.Xmpp Panagiotis Georgiou Stathopoulos 2015, S22.Xmpp Torben Könke 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("45ecb660-1c32-4203-a39b-a1e522007ad4")] - -// VersionInformation information for an assembly consists of the following four values: -// -// Major VersionInformation -// Minor VersionInformation -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.2.2")] -[assembly: AssemblyFileVersion("1.0.2.2")] \ No newline at end of file diff --git a/Readme.md b/Readme.md index d3469f75..1e4bbc78 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,4 @@ -### Introduction +### Introduction This repository contains an easy-to-use and well-documented .NET assembly for communicating with an XMPP server. It supports basic Instant Messaging and Presence funtionality as well as a variety @@ -16,6 +16,7 @@ optional procotol extensions. More specifically, the following features are supp + User Avatars + SOCKS5 and In-Band File-Transfer + In-Band Registration ++ XEP 0198 Stream Management (alpha) + User Mood + User Tune + User Activity @@ -24,55 +25,78 @@ optional procotol extensions. More specifically, the following features are supp + Well documented with lots of example code + Free to use in commercial and personal projects (MIT License) - -### Where to get it - -You can always get the latest binary package on [Nuget](http://www.nuget.org/packages/S22.Xmpp) or -download the binaries as a .zip archive from [GitHub](http://smiley22.github.com/Downloads/S22.Xmpp.zip). -The [documentation](http://smiley22.github.com/S22.Xmpp/Documentation/) is also available for offline viewing -as HTML or CHM and can be downloaded from -[here](http://smiley22.github.com/Downloads/S22.Xmpp.Html.Documentation.zip) and -[here](http://smiley22.github.com/Downloads/S22.Xmpp.Chm.Documentaton.zip), respectively. - - ### Usage & Examples -To use the library add the S22.Xmpp.dll assembly to your project references in Visual Studio. Here's +To use the library add the XMPPEngineer.dll assembly to your project references in Visual Studio. Here's a simple example that initializes a new instance of the XmppClient class and connects to an XMPP server: using System; - using S22.Xmpp; - using S22.Xmpp.Client; - - namespace Test { - class Program { - static void Main(string[] args) { - /* connect on port 5222 using TLS/SSL if available */ - using (var client = new XmppClient("jabber.se", "username", "password")) - { - Console.WriteLine("Connected as " + client.Jid); - } - } - } + using XMPPEngineer; + using XMPPEngineer.Client; + using XMPPEngineer.Im; + + namespace XMPPEngineerTest + { + class MainClass + { + public static void Main(string[] args) + { + // basic + using (XmppClient client = new XmppClient("domain", "user", "password")) + { + client.Connect(); + + Message message = new Message(new Jid("user@domain"), "Hello, World."); + client.SendMessage(message); + } + + // with stream management + using (XmppClient clientsm = new XmppClient("domain", "user", "password")) + { + clientsm.Connect(); + + clientsm.StreamManagementEnabled += (sdr, evt) => + { + Message messagesm = new Message(new Jid("user@domain"), "Hello, World."); + clientsm.SendMessage(messagesm); + + // xep-0033 - multicast can send to a jid that can then route to multiple users + System.Collections.Generic.List jids = new System.Collections.Generic.List(); + jids.Add(new Jid("admin@domain")); + jids.Add(new Jid("test@domain")); + jids.Add(new Jid("other@domain")); + + Message multimessagesm = new Message(new Jid("multicast.domain"), "Test - " + DateTime.Now.ToLongTimeString(), null, jids); + clientsm.SendMessage(multimessagesm); + }; + + // enable stream management and recovery mode + clientsm.EnableStreamManagement(); + } + } + } } + +### Documention (to be updated) Please see the [documentation](http://smiley22.github.com/S22.Xmpp/Documentation/) for a getting started guide, examples and details on using the classes and methods exposed by the S22.Xmpp assembly. +I will update this shortly. -### Credits +### Credits +The XMPPEngineer library is copyright © 2017 Steven Livingstone. The Sharp.Xmpp library is copyright © 2015 Panagiotis Georgiou Stathopoulos. The initial S22.Xmpp library is copyright © 2013-2014 Torben Könke. ### License -This library is released under the [MIT license](https://github.com/pgstath/Sharp.Xmpp/blob/master/License.md). +This library is released under the [MIT license](https://github.com/pgstath/XMPPEngineer/blob/master/License.md). ### Bug reports -Please send your bug reports to [pgstath@gmail.com](mailto:pgstath@gmail.com) or create a new -issue on the GitHub project homepage. +Please create a new issue on the GitHub project homepage. diff --git a/ReleaseNotes.md b/ReleaseNotes.md index d1ee687b..6fd59e84 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -7,7 +7,7 @@ * Disconnection detection improvements #1.0.0.1 -First Sharp.Xmpp Release +First XMPPEngineer Release ##Bugs resolved * In SaslDigestMd5, replaced `digestUri = "xmpp/" + fields["realm"];` from initial `imap` which caused connection setup failure @@ -17,7 +17,7 @@ First Sharp.Xmpp Release ##Features Added * An easy way to add extensions and provide a custom XML messaging over IQ messages. 'XmppClient.RequestCustomIq' for GETing custom requests, and delegate CustomIqDelegate in order to call in the event of -custom IQ message arrived. Xml Element is customiq and namespace is urn:sharp.xmpp:customiq. +custom IQ message arrived. Xml Element is customiq and namespace is urn:xmppengineer.xmpp:customiq. * DNS XMPP SRV records lookup is added * XmppClient.InitiateFileTransfer now returns also the Sid of the file transfer for future reference and management of the transfer process. * Improved detection of XmppClient and Xmpp Im connection and disconnection events. With this regard: diff --git a/Sharp.Xmpp.csproj b/Sharp.Xmpp.csproj deleted file mode 100644 index 30a27614..00000000 --- a/Sharp.Xmpp.csproj +++ /dev/null @@ -1,271 +0,0 @@ - - - - - Debug - AnyCPU - {9EA99E39-8C5C-4F69-9F3F-8E3074C518FA} - Library - Properties - Sharp.Xmpp - Sharp.Xmpp - v4.5 - 512 - - - true - full - false - bin\Debug\ - TRACE;DEBUG - prompt - 4 - bin\Debug\Sharp.Xmpp.xml - AnyCPU - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - true - bin\x86\Debug\ - TRACE;DEBUG - bin\Debug\Sharp.Xmpp.xml - full - x86 - prompt - MinimumRecommendedRules.ruleset - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - prompt - MinimumRecommendedRules.ruleset - - - - ..\..\..\..\..\Desktop\SharpXmppWpf\SharpXmppWpf\packages\ARSoft.Tools.Net.2.2.5\lib\net45\ARSoft.Tools.Net.dll - True - - - ..\..\..\..\..\Desktop\SharpXmppWpf\SharpXmppWpf\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - \ No newline at end of file diff --git a/Sharp.Xmpp.sln b/Sharp.Xmpp.sln deleted file mode 100644 index cf67786b..00000000 --- a/Sharp.Xmpp.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sharp.Xmpp", "Sharp.Xmpp.csproj", "{9EA99E39-8C5C-4F69-9F3F-8E3074C518FA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9EA99E39-8C5C-4F69-9F3F-8E3074C518FA}.Debug|Any CPU.ActiveCfg = Release|Any CPU - {9EA99E39-8C5C-4F69-9F3F-8E3074C518FA}.Debug|Any CPU.Build.0 = Release|Any CPU - {9EA99E39-8C5C-4F69-9F3F-8E3074C518FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9EA99E39-8C5C-4F69-9F3F-8E3074C518FA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = S22.Xmpp.csproj - EndGlobalSection -EndGlobal diff --git a/Util.cs b/Util.cs index 4a3a7bdf..bbf8b429 100644 --- a/Util.cs +++ b/Util.cs @@ -1,8 +1,8 @@ -using Sharp.Xmpp.Core; +using XMPPEngineer.Core; using System; using System.Xml; -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// Contains utility and extension methods. diff --git a/XMPPEngineer.csproj b/XMPPEngineer.csproj new file mode 100644 index 00000000..9f9cb45a --- /dev/null +++ b/XMPPEngineer.csproj @@ -0,0 +1,5 @@ + + + netstandard2.0 + + \ No newline at end of file diff --git a/XMPPEngineer.sln b/XMPPEngineer.sln new file mode 100644 index 00000000..c92547e7 --- /dev/null +++ b/XMPPEngineer.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMPPEngineer", "XMPPEngineer.csproj", "{C462F45F-CC89-4E71-971D-79E4495B6C2B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMPPEngineerTest", "XMPPEngineerTest\XMPPEngineerTest.csproj", "{5FB57B73-A453-4489-8DBA-ED489832D81E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C462F45F-CC89-4E71-971D-79E4495B6C2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C462F45F-CC89-4E71-971D-79E4495B6C2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C462F45F-CC89-4E71-971D-79E4495B6C2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C462F45F-CC89-4E71-971D-79E4495B6C2B}.Release|Any CPU.Build.0 = Release|Any CPU + {5FB57B73-A453-4489-8DBA-ED489832D81E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FB57B73-A453-4489-8DBA-ED489832D81E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FB57B73-A453-4489-8DBA-ED489832D81E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FB57B73-A453-4489-8DBA-ED489832D81E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/XMPPEngineerTest/Program (copy).cs b/XMPPEngineerTest/Program (copy).cs new file mode 100644 index 00000000..82013842 --- /dev/null +++ b/XMPPEngineerTest/Program (copy).cs @@ -0,0 +1,111 @@ +//using System; + +//namespace XMPPEngineerTest +//{ +// class MainClass +// { +// public static void Main(string[] args) +// { +// /* +// XMPPEngineer.Core.XmppCore client = new XMPPEngineer.Core.XmppCore( +// "alchemy.local", +// "test", +// "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE0OTI2Mzc1NzMsImV4cCI6MTUyNDE3MzU3MywiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsInVzZXJuYW1lIjoidGVzdCIsIm5ldHdvcmsiOiJhbGNoZW15LmxvY2FsIn0.0IYkS8KH22kai_j6hRcjy5x7Lvwb6TG5XyRY8n9fym0", +// "dev-lite-citym-access.westeurope.cloudapp.azure.com" +// );*/ + +// XMPPEngineer.Client.XmppClient client = new XMPPEngineer.Client.XmppClient( +// "alchemy.local", +// "steven", +// "test", +// "dev-lite-citym-access.westeurope.cloudapp.azure.com" +// ); + +// client.Connect("mobile"); + +// client.Error += (sender, e) => { +// Console.WriteLine(e.ToString()); +// }; +// client.Message += (sender, e) => { +// Console.WriteLine(e.ToString()); +// }; +// //client.Iq += (sender, e) => { +// // Console.WriteLine(e.ToString()); +// //}; +// //client.Presence += (sender, e) => +// //{ +// // Console.WriteLine(e.ToString()); +// //}; +// ///client.A += (sender, e) => +// ///{ +// ///Console.WriteLine(e.ToString()); +// ///}; + +// //RunBasic(client); +// //RunStreamManagement(client); +// RunStreamManagement2(client); + +// Console.ReadKey(); +// } + +// private static void RunBasic(XMPPEngineer.Core.XmppCore client) +// { +// XMPPEngineer.Im.Message message = new XMPPEngineer.Im.Message(new XMPPEngineer.Jid("admin@alchemy.local"), "ok - " + DateTime.Now.ToLongTimeString()); +// client.SendMessage(message); +// } + +// private static void RunStreamManagement(XMPPEngineer.Core.XmppCore client) +// { +// client.StreamManagementEnabled += (sdr, evt) => +// { +// //XMPPEngineer.Im.Message message = new XMPPEngineer.Im.Message(new XMPPEngineer.Jid("admin@alchemy.local"), "ok - " + DateTime.Now.ToLongTimeString()); +// //client.SendMessage(message); + +// // send a message in a loop + +// System.Timers.Timer timer = new System.Timers.Timer(10000); +// timer.Elapsed += (sender, e) => { +// XMPPEngineer.Im.Message messagex = new XMPPEngineer.Im.Message(new XMPPEngineer.Jid("admin@alchemy.local"), "ok - " + DateTime.Now.ToLongTimeString()); +// client.SendMessage(messagex); +// }; +// timer.Enabled = true; +// timer.Start(); + +// // // Resumes a stream that was disconnected for some reason - this will only work within the time window allows by the server to stream resumption - which defaults to 20 seconds +// // // We only need to do this if we detect we have lost a connection to the server - probably from no acks. +// // ///client.StreamManagementResumed += (sender, e) => { +// // // continue in here +// // ///}; +// // //client.ResumeStream(); + +// // ///XMPPEngineer.Im.Message message = new XMPPEngineer.Im.Message(new XMPPEngineer.Jid("admin@alchemy.local"), "ok - " + DateTime.Now.ToLongTimeString()); +// // ///client.SendMessage(message); +// }; + +// // enable stream management and recovery mode +// ///client.NumberOfItemsBeforeServerAck = 3; +// ///client.NumberOfSecondsBeforeServerAck = 15;//30; +// client.EnableStreamManagement(true); +// } + +// private static void RunStreamManagement2(XMPPEngineer.Client.XmppClient client) +// { +// client.StreamManagementEnabled += (sdr, evt) => +// { +// // send a message in a loop + +// System.Timers.Timer timer = new System.Timers.Timer(10000); +// timer.Elapsed += (sender, e) => +// { +// XMPPEngineer.Im.Message messagex = new XMPPEngineer.Im.Message(new XMPPEngineer.Jid("admin@alchemy.local"), "ok - " + DateTime.Now.ToLongTimeString()); +// client.SendMessage(messagex); +// }; +// timer.Enabled = true; +// timer.Start(); +// }; + +// // enable stream management and recovery mode +// client.EnableStreamManagement(true); +// } +// } +//} diff --git a/XMPPEngineerTest/Program.cs b/XMPPEngineerTest/Program.cs new file mode 100644 index 00000000..43580d89 --- /dev/null +++ b/XMPPEngineerTest/Program.cs @@ -0,0 +1,74 @@ +using System; +using XMPPEngineer; +using XMPPEngineer.Client; +using XMPPEngineer.Im; + +namespace XMPPEngineerTest +{ + class MainClass + { + public static void Main(string[] args) + { + // basic + /* + using (XmppClient client = new XmppClient("domain", "user", "password")) + { + client.Connect(); + + Message message = new Message(new Jid("user@domain"), "Hello, World."); + client.SendMessage(message); + }*/ + + // with stream management + using (XmppClient clientsm = new XmppClient( + "alchemy.local", + "admin", + "PASSWORD", + "alchemy.local", + XmppClient.AvailableExtensions.Default | XmppClient.AvailableExtensions.Ping)) + //XmppClient.AvailableExtensions.DataForms + //XmppClient.AvailableExtensions.MessageCarbons + /*using (XMPPEngineer.Core.XmppCore clientsm = new XMPPEngineer.Core.XmppCore( + "alchemy.local", + "steven", + "test", + "dev-lite-citym-access.westeurope.cloudapp.azure.com"))*/ + { + clientsm.Error += (sender, e) => + { + Console.WriteLine(e.ToString()); + }; + clientsm.Message += (sender, e) => + { + Console.WriteLine(e.Message); + }; + + clientsm.RetrieveRoster = false; + clientsm.Connect("mobile"); + + clientsm.StreamManagementEnabled += (sdr, evt) => + { + // normal send + Message messagesm = new Message(new Jid("admin@alchemy.local"), "ok - " + DateTime.Now.ToLongTimeString()); + clientsm.SendMessage(messagesm); + + // xep-0033 - multicast can send to a jid that can then route to multiple users + /* + System.Collections.Generic.List jids = new System.Collections.Generic.List(); + jids.Add(new Jid("admin@alchemy.local")); + jids.Add(new Jid("test@alchemy.local")); + jids.Add(new Jid("steven@alchemy.local")); + + Message multimessagesm = new Message(new Jid("multicast.alchemy.local"), "ok5 - " + DateTime.Now.ToLongTimeString(), null, jids); + clientsm.SendMessage(multimessagesm); + */ + }; + + // enable stream management and recovery mode - // xep-0198 + clientsm.EnableStreamManagement(true); + + Console.ReadKey(); + } + } + } +} diff --git a/XMPPEngineerTest/XMPPEngineerTest.csproj b/XMPPEngineerTest/XMPPEngineerTest.csproj new file mode 100644 index 00000000..76b3991e --- /dev/null +++ b/XMPPEngineerTest/XMPPEngineerTest.csproj @@ -0,0 +1,11 @@ + + + + Exe + netcoreapp2.0 + + + + + + diff --git a/Xml.cs b/Xml.cs index 8b8223c1..258e3d30 100644 --- a/Xml.cs +++ b/Xml.cs @@ -4,7 +4,7 @@ using System.Text.RegularExpressions; using System.Xml; -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// Provides a factory method for creating XmlElement instances and adds @@ -81,6 +81,9 @@ public static XmlElement Text(this XmlElement e, string text) public static string ToXmlString(this XmlElement e, bool xmlDeclaration = false, bool leaveOpen = false) { + // avoid duplicate namespaces on elements by storing each in the list + System.Collections.Generic.IList ns = new System.Collections.Generic.List(); + // Can't use e.OuterXml because it "messes up" namespaces for elements with // a prefix, i.e. stream:stream (What it does is probably correct, but just // not what we need for XMPP). @@ -89,8 +92,20 @@ public static string ToXmlString(this XmlElement e, bool xmlDeclaration = false, b.Append(" xmlns='" + e.NamespaceURI + "'"); foreach (XmlAttribute a in e.Attributes) { + // 21 April 2017 - Removed skipping the namespaces so we can add custom namespaces. + //if (a.Name == "xmlns") + // continue; if (a.Name == "xmlns") - continue; + { + // If the namespace above was added to it, we don't want to add a duplicate. Causes of building Xml through strings. + if (!String.IsNullOrEmpty(e.NamespaceURI)) continue; + + if (ns.Contains(a.Value)) + continue; + else + ns.Add(a.Value); + } + if (a.Value != null) b.Append(" " + a.Name + "='" + SecurityElement.Escape(a.Value.ToString()) + "'"); diff --git a/XmppDisconnectionException.cs b/XmppDisconnectionException.cs index 049a5c51..1e8a690b 100644 --- a/XmppDisconnectionException.cs +++ b/XmppDisconnectionException.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// The exception that is thrown when a generic XMPP error condition has been encountered. diff --git a/XmppError.cs b/XmppError.cs index 0e92c237..521247f6 100644 --- a/XmppError.cs +++ b/XmppError.cs @@ -3,7 +3,7 @@ using System.Text; using System.Xml; -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// Represents an XMPP error. diff --git a/XmppErrorException.cs b/XmppErrorException.cs index 97bbcba5..0a58bbba 100644 --- a/XmppErrorException.cs +++ b/XmppErrorException.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// The exception that is thrown when a recoverable XMPP error condition diff --git a/XmppExceptions.cs b/XmppExceptions.cs index e46257f8..8055a823 100644 --- a/XmppExceptions.cs +++ b/XmppExceptions.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace Sharp.Xmpp +namespace XMPPEngineer { /// /// The exception that is thrown when a generic XMPP error condition has been encountered. diff --git a/packages.config b/packages.config deleted file mode 100644 index b446d709..00000000 --- a/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file