Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extensive changes #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions Client/XmppClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ namespace Sharp.Xmpp.Client
/// </remarks>
public class XmppClient : IDisposable
{
/// <summary>
/// If false the connection will not try to retrieve the rooster automatically
/// </summary>
public bool UseRooster
{
get { return im.UseRoster; }
set { im.UseRoster = value; }
}


/// <summary>
/// True if the instance has been disposed of.
/// </summary>
Expand Down Expand Up @@ -225,7 +235,7 @@ public string Password
/// <summary>
/// If true the session will be TLS/SSL-encrypted if the server supports it.
/// </summary>
public bool Tls
public Core.TLSMode Tls
{
get
{
Expand Down Expand Up @@ -451,6 +461,21 @@ public event EventHandler<MessageEventArgs> Message
}
}

/// <summary>
/// The event that is raised when a bodyless message is received.
/// </summary>
public event EventHandler<MessageEventArgs> BodylessMessage
{
add
{
im.BodylessMessage += value;
}
remove
{
im.BodylessMessage -= value;
}
}

/// <summary>
/// The event that is raised periodically for every file-transfer operation to
/// inform subscribers of the progress of the operation.
Expand Down Expand Up @@ -600,7 +625,7 @@ public event EventHandler<Im.ErrorEventArgs> Error
/// <remarks>Use this constructor if you wish to connect to an XMPP server using
/// an existing set of user credentials.</remarks>
public XmppClient(string hostname, string username, string password,
int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null)
int port = 5222, Core.TLSMode tls = Core.TLSMode.StartTLS, RemoteCertificateValidationCallback validate = null)
{
im = new XmppIm(hostname, username, password, port, tls, validate);
// Initialize the various extension modules.
Expand All @@ -625,7 +650,7 @@ public XmppClient(string hostname, string username, string password,
/// is not a valid port number.</exception>
/// <remarks>Use this constructor if you wish to register an XMPP account using
/// the in-band account registration process supported by some servers.</remarks>
public XmppClient(string hostname, int port = 5222, bool tls = true,
public XmppClient(string hostname, int port = 5222, Xmpp.Core.TLSMode tls = Core.TLSMode.StartTLS,
RemoteCertificateValidationCallback validate = null)
{
im = new XmppIm(hostname, port, tls, validate);
Expand Down
2 changes: 2 additions & 0 deletions Core/StreamParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace Sharp.Xmpp.Core
Expand Down Expand Up @@ -53,6 +54,7 @@ public CultureInfo Language
/// XML-stream in it's 'xml:lang' attribute could not be found.</exception>
public StreamParser(Stream stream, bool leaveOpen = false)
{

stream.ThrowIfNull("stream");
this.leaveOpen = leaveOpen;
this.stream = stream;
Expand Down
47 changes: 37 additions & 10 deletions Core/XmppCore.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ARSoft.Tools.Net.Dns;
using ARSoft.Tools.Net;
using ARSoft.Tools.Net.Dns;
using Sharp.Xmpp.Core.Sasl;
using System;
using System.Collections.Concurrent;
Expand Down Expand Up @@ -238,7 +239,7 @@ public bool DebugStanzas
/// <summary>
/// If true the session will be TLS/SSL-encrypted if the server supports it.
/// </summary>
public bool Tls
public TLSMode Tls
{
get;
set;
Expand Down Expand Up @@ -339,12 +340,12 @@ public bool Authenticated
/// <exception cref="ArgumentOutOfRangeException">The value of the port parameter
/// is not a valid port number.</exception>
public XmppCore(string hostname, string username, string password,
int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null)
int port = 5222, TLSMode tls = TLSMode.StartTLS, RemoteCertificateValidationCallback validate = null)
{
moveNextSrvDNS(hostname);
if (dnsCurrent != null)
{
Hostname = dnsCurrent.Target;
Hostname = dnsCurrent.Target.ToString();
Port = dnsCurrent.Port;
}
else
Expand Down Expand Up @@ -374,13 +375,13 @@ public XmppCore(string hostname, string username, string password,
/// string.</exception>
/// <exception cref="ArgumentOutOfRangeException">The value of the port parameter
/// is not a valid port number.</exception>
public XmppCore(string hostname, int port = 5222, bool tls = true,
public XmppCore(string hostname, int port = 5222, TLSMode tls = TLSMode.StartTLS,
RemoteCertificateValidationCallback validate = null)
{
moveNextSrvDNS(hostname);
if (dnsCurrent != null)
{
Hostname = dnsCurrent.Target;
Hostname = dnsCurrent.Target.ToString();
Port = dnsCurrent.Port;
}
else
Expand Down Expand Up @@ -411,7 +412,7 @@ private SrvRecord moveNextSrvDNS(string domain)
};
dnsIsInit = true;

DnsMessage dnsMessage = DnsClient.Default.Resolve("_xmpp-client._tcp." + domain, RecordType.Srv);
DnsMessage dnsMessage = DnsClient.Default.Resolve(DomainName.Parse("_xmpp-client._tcp." + domain), 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
Expand Down Expand Up @@ -472,7 +473,14 @@ public void Connect(string resource = null)
try
{
client = new TcpClient(Hostname, Port);
stream = client.GetStream();

if (Tls == TLSMode.TLSSocket)
{
var ssl = new SslStream(client.GetStream());
ssl.AuthenticateAsClient(Hostname);
stream = ssl;
}

// Sets up the connection which includes TLS and possibly SASL negotiation.
SetupConnection(this.resource);
// We are connected.
Expand Down Expand Up @@ -918,9 +926,9 @@ private void SetupConnection(string resource = null)
if (feats["starttls"] != null)
{
// TLS is mandatory and user opted out of it.
if (feats["starttls"]["required"] != null && Tls == false)
if (feats["starttls"]["required"] != null && Tls != TLSMode.StartTLS)
throw new AuthenticationException("The server requires TLS/SSL.");
if (Tls)
if (Tls == TLSMode.StartTLS)
feats = StartTls(Hostname, Validate);
}
// If no Username has been provided, don't perform authentication.
Expand Down Expand Up @@ -1342,4 +1350,23 @@ private void Disconnect()
Authenticated = false;
}
}

/// <summary>
/// Enumeration for selecting the TLS mode of the connection
/// </summary>
public enum TLSMode
{
/// <summary>
/// No TLS
/// </summary>
None,
/// <summary>
/// Use extension STARTTLS
/// </summary>
StartTLS,
/// <summary>
/// Use Ssl socket
/// </summary>
TLSSocket
}
}
14 changes: 14 additions & 0 deletions Im/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,20 @@ internal Message(Core.Message message)
AlternateBodies = new XmlDictionary(element, "body", "xml:lang");
}

/// <summary>
/// Initializes a new instance of the Message class from the specified
/// instance.
/// </summary>
/// <param name="data">The message element</param>
/// <exception cref="ArgumentNullException">The Data parameter is null.</exception>
public Message(XmlElement data)
{

Data.ThrowIfNull("data");
type = ParseType(data.GetAttribute("type"));
element = data;
}

/// <summary>
/// Parses the Message type from the specified string.
/// </summary>
Expand Down
10 changes: 10 additions & 0 deletions Im/MessageEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,15 @@ public MessageEventArgs(Jid jid, Message message)
Jid = jid;
Message = message;
}

/// <summary>
/// Initializes a new instance of the MessageEventArgs class for bodyless messages.
/// </summary>
/// <exception cref="ArgumentNullException">The message parameter is null.</exception>
public MessageEventArgs(Message message)
{
message.ThrowIfNull("message");
Message = message;
}
}
}
60 changes: 51 additions & 9 deletions Im/XmppIm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@ namespace Sharp.Xmpp.Im
/// <remarks>For implementation details, refer to RFC 3921.</remarks>
public class XmppIm : IDisposable
{

bool useRoster = true;

/// <summary>
/// If false the connection will not automatically retrieve the rooster
/// </summary>
public bool UseRoster
{
get
{
return useRoster;
}

set
{
useRoster = value;
}
}

/// <summary>
/// Provides access to the core facilities of XMPP.
/// </summary>
Expand Down Expand Up @@ -113,7 +132,7 @@ public string Password
/// <summary>
/// If true the session will be TLS/SSL-encrypted if the server supports it.
/// </summary>
public bool Tls
public TLSMode Tls
{
get
{
Expand Down Expand Up @@ -250,6 +269,11 @@ public CustomIqRequestDelegate CustomIqDelegate
/// </summary>
public event EventHandler<MessageEventArgs> Message;

/// <summary>
/// The event that is raised when a chat message is received.
/// </summary>
public event EventHandler<MessageEventArgs> BodylessMessage;

/// <summary>
/// The event that is raised when a subscription request made by the JID
/// associated with this instance has been approved.
Expand Down Expand Up @@ -299,7 +323,7 @@ public CustomIqRequestDelegate CustomIqDelegate
/// <exception cref="ArgumentOutOfRangeException">The value of the port parameter
/// is not a valid port number.</exception>
public XmppIm(string hostname, string username, string password,
int port = 5222, bool tls = true, RemoteCertificateValidationCallback validate = null)
int port = 5222, TLSMode tls = TLSMode.StartTLS, RemoteCertificateValidationCallback validate = null)
{
core = new XmppCore(hostname, username, password, port, tls, validate);
SetupEventHandlers();
Expand All @@ -321,7 +345,7 @@ public XmppIm(string hostname, string username, string password,
/// string.</exception>
/// <exception cref="ArgumentOutOfRangeException">The value of the port parameter
/// is not a valid port number.</exception>
public XmppIm(string hostname, int port = 5222, bool tls = true,
public XmppIm(string hostname, int port = 5222, TLSMode tls = TLSMode.StartTLS,
RemoteCertificateValidationCallback validate = null)
{
core = new XmppCore(hostname, port, tls, validate);
Expand Down Expand Up @@ -370,11 +394,19 @@ 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 nor the presence
if (useRoster)
{
// Retrieve user's roster as recommended (Refer to RFC 3921, Section 7.3).
Roster roster = GetRoster();
// Send initial presence.
SendPresence(new Presence());
return roster;
}

return null;
}
catch (SocketException e)
{
Expand Down Expand Up @@ -1324,7 +1356,7 @@ internal IEnumerable<XmppExtension> Extensions
return extensions;
}
}

/// <summary>
/// Sends the specified presence stanza to the server.
/// </summary>
Expand All @@ -1349,6 +1381,14 @@ internal void SendPresence(Presence presence)
core.SendPresence(presence);
}

/// <summary>
/// Sends a default presence stanza to the server
/// </summary>
public void SendPresence()
{
SendPresence(new Presence());
}

/// <summary>
/// Performs an IQ set/get request and blocks until the response IQ comes in.
/// </summary>
Expand Down Expand Up @@ -1662,6 +1702,8 @@ private void OnMessage(Message message)
// a body.
if (message.Data["body"] != null)
Message.Raise(this, new MessageEventArgs(message.From, message));
else
BodylessMessage.Raise(this, new MessageEventArgs(message));
}

/// <summary>
Expand Down
8 changes: 6 additions & 2 deletions Sharp.Xmpp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="ARSoft.Tools.Net, Version=1.8.1.0, Culture=neutral, PublicKeyToken=1940454cd762ec57, processorArchitecture=MSIL">
<HintPath>packages\ARSoft.Tools.Net.1.8.1\lib\ARSoft.Tools.Net.dll</HintPath>
<Reference Include="ARSoft.Tools.Net, Version=2.2.4.0, Culture=neutral, PublicKeyToken=1940454cd762ec57, processorArchitecture=MSIL">
<HintPath>..\packages\ARSoft.Tools.Net.2.2.4\lib\net45\ARSoft.Tools.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
2 changes: 1 addition & 1 deletion Xml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Sharp.Xmpp
/// Provides a factory method for creating XmlElement instances and adds
/// a couple of useful shortcut extensions to the XmlElement class.
/// </summary>
internal static class Xml
public static class Xml
{
/// <summary>
/// Creates a new XmlElement instance.
Expand Down
3 changes: 2 additions & 1 deletion packages.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ARSoft.Tools.Net" version="1.8.1" targetFramework="net45" />
<package id="ARSoft.Tools.Net" version="2.2.4" targetFramework="net45" />
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
</packages>