/*
* (standard BSD license)
*
* Copyright (c) 2002, Chad Myers, et al.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. Redistributions in binary form
* must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with
* the distribution. Neither the name of SourceForge, nor Microsoft nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
namespace MSNP{
/// <summary>
/// Handles a connection to the Dispatch Server
/// </summary>
internal class DispatchConnectionHandler : ConnectionHandler
{
/**********************************************/
// Enumerations
/**********************************************/
/// <summary>
/// Determines which state the ProcessConnection method is currently in during this cycle
/// </summary>
private enum ConnectionState :int {STARTING, SETPROTOCOL, POLICYREQUEST, AUTHREQUEST}
/**********************************************/
// Fields
/**********************************************/
private string m_XFRHost; // The NS server to connect to after this dispatch session is complete
private int m_XFRPort = MSN_PORT; // The NS port to connect to
private int m_State = (int) ConnectionState.STARTING; // The current cycle state
/**********************************************/
// Constructors
/**********************************************/
/// <summary>
/// Configures this connection, but does not actually connect.
/// </summary>
/// <param name="host">The DNS name or IP address of the DS to connect to.</param>
/// <param name="port">The port of the DS server</param>
/// <param name="user">The username with which to authenticate</param>
/// <param name="pass">The user's password</param>
internal DispatchConnectionHandler(String host, int port, String user, String pass) :
base(host, port, user, pass){}
/**********************************************/
// Properties
/**********************************************/
/// <summary>
/// The NS server hostname or IP to conect to.
/// </summary>
/// <remarks>
/// Used after the DS connection is complete and an NS XFR has been received.
/// </remarks>
internal string XFRHost
{ get{ return m_XFRHost; } }
/// <summary>
/// The NS server port number to connect to.
/// </summary>
/// <remarks>
/// Used after the DS connection is complete and an NS XFR has been received.
/// </remarks>
internal int XFRPort
{ get{ return m_XFRPort; } }
/**********************************************/
// Events
/**********************************************/
/// <summary>
/// Thrown when an NS XFR message has been received from the DS.
/// </summary>
internal event EventHandler XFREvent;
/**********************************************/
// Protected Methods
/**********************************************/
/**********************************************/
// Private Methods
/**********************************************/
/// <summary>
/// Called to signal an XFREvent event.
/// </summary>
private void OnXFREvent()
{
if( XFREvent != null )
XFREvent(this, new EventArgs());
}
/// <summary>
/// Implementation of the abstract <see cref="ConnectionHandler.ProcessConnection"/> method.
/// </summary>
/// <remarks>
/// <para>This is the main processing method for this class. This method is called
/// every cycle in the connection thread.</para>
/// <para>This thread will process the initial protocol initialization dialogue and then
/// receive the XFR for the NS.</para>
/// </remarks>
protected override void ProcessConnection()
{
switch(m_State)
{
// Initial connection, send protocol and move on
case (int) ConnectionState.STARTING:
SetProtocol(DEFAULT_PROTOCOL);
m_State = (int) ConnectionState.SETPROTOCOL;
break;
// Protocol sent, awaiting reply. Check for reply and verify it is valid.
// Next, send the policy INF query to determine the auth policy.
case (int) ConnectionState.SETPROTOCOL:
Response response = LookForProtocolResponse(GetResponses());
if( response == null )
break;
if( response.Parameters.Length != 1 || response.Parameters[0] != DEFAULT_PROTOCOL )
throw new Exception("Unexpected version response");
response = null;
AddRequest( new Request(INF, null) );
m_State = (int) ConnectionState.POLICYREQUEST;
break;
// Check for policy response. In this version, it should always be MD5, otherwise
// and error. Next, send the USR auth request which should result in an XFR for a
// Notification Server.
case (int) ConnectionState.POLICYREQUEST:
response = LookForSpecificResponse(GetResponses(), INF);
if( response == null )
break;
if( response.Parameters.Length == 0 || response.Parameters[0] != "MD5" )
throw new Exception("Unexpected policy response from server");
response = null;
AddRequest( new Request(USR, "MD5 I " + User) );
m_State = (int) ConnectionState.AUTHREQUEST;
break;
// Check for XFR response, signal the event, then close down the connection.
case (int) ConnectionState.AUTHREQUEST:
response = LookForSpecificResponse(GetResponses(), XFR);
if( response == null )
break;
if( response.Parameters.Length < 2 || response.Parameters[0] != "NS" )
throw new Exception("Unexpected authentication response from server");
String[] hostAndPort = response.Parameters[1].Split(new char[]{':'});
m_XFRHost = hostAndPort[0];
m_XFRPort = Int32.Parse(hostAndPort[1]);
OnXFREvent();
response = null;
CloseConnection();
break;
}
}
}
}
|