/// <summary>
        /// Send a DCC Chat request to a remote user and wait for a connection
        /// using timeout period specified.
        /// </summary>
        /// <remarks>
        /// <para>If the user does not respond within the timeout period the DccChatSession
        /// will stop listening for a connection. The sesssion instance created then becomes
        /// invalid. This methods must be called again and a new instance created in order to
        /// initiate a try again.
        /// </para>
        /// <para>
        /// This method should be called from within a try/catch block
        /// in case there are socket errors.
        /// </para>
        /// </remarks>
        /// <param name="dccUserInfo">A collection of information about the remote user.</param>
        /// <param name="listenIPAddress">The IP address that will be sent to the remote user. It must
        /// be in dotted quad format (i.e. 192.168.0.2). If the client is behind a NAT system then
        /// this should be the address of that system and not the local host.</param>
        /// <param name="listenPort">The TCP/IP port to listen on</param>
        /// <param name="timeout">How long to wait for a response in milliseconds.
        /// A value of zero will disable the timeout.</param>
        public static DccChatSession Request(DccUserInfo dccUserInfo, string listenIPAddress, int listenPort, long timeout)
        {
            Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Request()");
            //Create session object
            DccChatSession session = new DccChatSession(dccUserInfo);

            session.listenPort = listenPort;
            //Start session Thread
            session.thread      = new Thread(new ThreadStart(session.Listen));
            session.thread.Name = session.ToString();
            session.thread.Start();
            //Send Chat request to remote user
            session.SendChatRequest(listenIPAddress, listenPort);
            //Start timeout thread if timeout > 0
            if (timeout > 0)
            {
                Timer timer = new Timer(
                    new TimerCallback(session.TimerExpired),
                    session,
                    timeout,
                    0);
                Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Request timeout thread started");
            }
            return(session);
        }
Example #2
0
        public void OnDccFileTransferRequest(DccUserInfo dccUserInfo, string fileName, int size, bool turbo )
        {
            try
            {
                //We need to pass the Receive()  method a DccFileInfo which tells Thresher
                //where to store the file. If this is an existing file that was only partially downloaded
                //then Thresher will automatically Resume the file from where it left off. Size  represents the total
                //size in bytes of the file and is provided by the sender.
                DccFileInfo dccFileInfo = new DccFileInfo( new FileInfo( directory +  "\\" + fileName ), size );

                //Using the DccFileInfo we created and the parameters from the event we can Receive the file.
                //A large receive buffer works the best so 32k should be good.
                DccFileSession session =  DccFileSession.Receive( dccUserInfo, dccFileInfo,  turbo );

                //Use the FileClient as the single source of delegates for the file sessions.
                session.OnFileTransferCompleted += new FileTransferCompletedEventHandler( OnFileTransferCompleted );
                session.OnFileTransferInterrupted += new FileTransferInterruptedEventHandler( OnFileTransferInterrupted );
                session.OnFileTransferStarted += new FileTransferStartedEventHandler( OnFileTransferStarted );
                session.OnFileTransferTimeout += new FileTransferTimeoutEventHandler( OnFileTransferTimeout );
            }
            catch( Exception e )
            {
                Console.WriteLine("Error trying to receive file: " + e ) ;
            }
        }
Example #3
0
 /// <summary>
 /// Prepare a new instance with default values but do not connect
 /// to another user.
 /// </summary>
 internal DccFileSession(DccUserInfo dccUserInfo, DccFileInfo dccFileInfo, int bufferSize, int listenPort, string sessionID)
 {
     this.dccUserInfo = dccUserInfo;
     this.dccFileInfo = dccFileInfo;
     buffer           = new byte[bufferSize];
     this.listenPort  = listenPort;
     this.sessionID   = sessionID;
     lastActivity     = DateTime.Now;
     waitingOnAccept  = false;
 }
Example #4
0
 public void OnDccChatRequest(DccUserInfo dccUserInfo )
 {
     //Test for protocol too
     Assertion.AssertEquals("OnDccChatRequest: Hostname", "irc.sventech.com", dccUserInfo.Connection.connectionArgs.Hostname );
     Assertion.AssertEquals("OnDccChatRequest: userInfo.Nick","Scurvy", dccUserInfo.Nick );
     Assertion.AssertEquals("OnDccChatRequest: userInfo.User","~Scurvy", dccUserInfo.User );
     Assertion.AssertEquals("OnDccChatRequest: userInfo.Host","pcp825822pcs.nrockv01.md.comcast.net", dccUserInfo.Hostname );
     Assertion.AssertEquals("OnDccChatRequest: end point", "192.168.0.11:46000", dccUserInfo.RemoteEndPoint.ToString() );
     Console.WriteLine("OnDccChatRequest");
 }
		/// <summary>
		/// Prepare a new instance with default values but do not connect
		/// to another user.
		/// </summary>
		internal DccFileSession( DccUserInfo dccUserInfo, DccFileInfo dccFileInfo, int bufferSize, int listenPort, string sessionID ) 
		{
			this.dccUserInfo = dccUserInfo;
			this.dccFileInfo = dccFileInfo;
			buffer = new byte[ bufferSize ];
			this.listenPort = listenPort;
			this.sessionID = sessionID;
			lastActivity = DateTime.Now;
			waitingOnAccept = false;
		}
        /// <summary>
        /// When another a remote user has sent a chat request, this
        /// method is called to accept the request and
        /// start a chat session with that user.
        /// </summary>
        /// <remarks>
        /// This method should be called from within a try/catch block
        /// because there are many things that could prevent this
        /// connection attempt from succeeding.
        /// </remarks>
        /// <param name="dccUserInfo">A collection of information about the remote user.</param>
        /// <returns>The DccChatSession instance for this session.</returns>
        public static DccChatSession Accept(DccUserInfo dccUserInfo)
        {
            Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Accept()");
            DccChatSession session = new DccChatSession(dccUserInfo);

            //Start session Thread
            session.thread      = new Thread(new ThreadStart(session.Connect));
            session.thread.Name = session.ToString();
            session.thread.Start();
            return(session);
        }
Example #7
0
        /// <summary>
        /// Attempt to send a file to a remote user. Start listening
        /// on the given port and address. If the remote user does not accept
        /// the offer within the timeout period the the session
        /// will be closed.
        /// </summary>
        /// <remarks>
        /// This method should be called from within a try/catch block
        /// in case there are socket errors. This methods will also automatically
        /// handle a Resume if the remote client requests it.
        /// </remarks>
        /// <param name="dccUserInfo">The information about the remote user.</param>
        /// <param name="listenIPAddress">The IP address of the local machine in dot
        /// quad format (e.g. 192.168.0.25). This is the address that will be sent to the
        /// remote user. The IP address of the NAT machine must be used if the
        /// client is behind a NAT/Firewall system. </param>
        /// <param name="listenPort">The port that the session will listen on.</param>
        /// <param name="dccFileInfo">The file to be sent. If the file name has spaces in it
        /// they will be replaced with underscores when the name is sent.</param>
        /// <param name="bufferSize">The size of the send buffer. Generally should
        /// be between 4k and 32k.</param>
        /// <param name="turbo">True to use send-ahead mode for transfers.</param>
        /// <returns>A unique session instance for this file and remote user.</returns>
        /// <exception cref="ArgumentException">If the listen port is already in use.</exception>
        public static DccFileSession Send(
            DccUserInfo dccUserInfo,
            string listenIPAddress,
            int listenPort,
            DccFileInfo dccFileInfo,
            int bufferSize,
            bool turbo)
        {
            Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccFileSession::Send()");
            DccFileSession session = null;

            //Test if we are already using this port
            if (DccFileSessionManager.DefaultInstance.ContainsSession("S" + listenPort))
            {
                throw new ArgumentException("Already listening on port " + listenPort);
            }
            try
            {
                session = new DccFileSession(dccUserInfo, dccFileInfo, bufferSize, listenPort, "S" + listenPort);
                //set turbo mode
                session.turboMode = turbo;
                //Set server IP address
                session.listenIPAddress = listenIPAddress;
                //Add session to active sessions hashtable
                DccFileSessionManager.DefaultInstance.AddSession(session);
                //Create stream to file
                dccFileInfo.OpenForRead();
                //Start session Thread
                session.thread      = new Thread(new ThreadStart(session.Listen));
                session.thread.Name = session.ToString();
                session.thread.Start();
                //Send DCC Send request to remote user
                session.DccSend(IPAddress.Parse(listenIPAddress));
                return(session);
            }
            catch (Exception e)
            {
                if (session != null)
                {
                    DccFileSessionManager.DefaultInstance.RemoveSession(session);
                }
                throw e;
            }
        }
Example #8
0
        /// <summary>
        /// Another user has offered to send a file. This method should be called
        /// to accept the offer and save the file to the give location. The parameters
        /// needed to call this method are provided by the <c>OnDccFileTransferRequest()</c>
        /// event.
        /// </summary>
        /// <remarks>
        /// This method should be called from within a try/catch block
        /// in case it is unable to connect or there are other socket
        /// errors.
        /// </remarks>
        /// <param name="dccUserInfo">Information on the remote user.</param>
        /// <param name="dccFileInfo">The local file that will hold the data being sent. If the file
        /// is the result of a previous incomplete download the the attempt will be made
        /// to resume where the previous left off.</param>
        /// <param name="turbo">Will the send ahead protocol be used.</param>
        /// <returns>A unique session instance for this file and remote user.</returns>
        /// <exception cref="ArgumentException">If the listen port is already in use.</exception>
        public static DccFileSession Receive(DccUserInfo dccUserInfo, DccFileInfo dccFileInfo, bool turbo)
        {
            Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccFileSession::Receive()");
            //Test if we are already using this port
            if (DccFileSessionManager.DefaultInstance.ContainsSession("C" + dccUserInfo.remoteEndPoint.Port))
            {
                throw new ArgumentException("Already listening on port " + dccUserInfo.remoteEndPoint.Port);
            }
            DccFileSession session = null;

            try
            {
                session = new DccFileSession(dccUserInfo, dccFileInfo, (64 * 1024),
                                             dccUserInfo.remoteEndPoint.Port, "C" + dccUserInfo.remoteEndPoint.Port);
                //Has the initiator specified the turbo protocol?
                session.turboMode = turbo;
                //Open file for writing
                dccFileInfo.OpenForWrite();
                DccFileSessionManager.DefaultInstance.AddSession(session);
                //Determine if we can resume a download
                if (session.dccFileInfo.ShouldResume())
                {
                    session.waitingOnAccept = true;
                    session.dccFileInfo.SetResumeToFileSize();
                    session.SendResume();
                }
                else
                {
                    session.thread      = new Thread(new ThreadStart(session.Download));
                    session.thread.Name = session.ToString();
                    session.thread.Start();
                }
                return(session);
            }
            catch (Exception e)
            {
                if (session != null)
                {
                    DccFileSessionManager.DefaultInstance.RemoveSession(session);
                }
                throw e;
            }
        }
        internal void Parse(Connection connection, string message)
        {
            Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccListener::Parse()");
            Match  match     = parser.Match(message);
            string requestor = match.Groups[1].ToString();

            string[] tokens = tokenizer.Split(match.Groups[2].ToString().Trim());
            switch (tokens[Action])
            {
            case CHAT:
                if (OnDccChatRequest != null)
                {
                    //Test for sufficient number of arguments
                    if (tokens.Length < 4)
                    {
                        connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect CHAT arguments: " + message);
                        return;
                    }
                    //Send event
                    DccUserInfo dccUserInfo = null;
                    try
                    {
                        dccUserInfo = new DccUserInfo(
                            connection,
                            Rfc2812Util.ParseUserInfoLine(requestor),
                            new IPEndPoint(DccUtil.LongToIPAddress(tokens[Address]), int.Parse(tokens[Port], CultureInfo.InvariantCulture)));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.BadDccEndpoint, "Invalid TCP/IP connection information sent.");
                        return;
                    }
                    try
                    {
                        OnDccChatRequest(dccUserInfo);
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString());
                    }
                }
                break;

            case SEND:
                //Test for sufficient number of arguments
                if (tokens.Length < 5)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect SEND arguments: " + message);
                    return;
                }
                if (OnDccSendRequest != null)
                {
                    DccUserInfo dccUserInfo = null;
                    try
                    {
                        dccUserInfo = new DccUserInfo(
                            connection,
                            Rfc2812Util.ParseUserInfoLine(requestor),
                            new IPEndPoint(DccUtil.LongToIPAddress(tokens[Address]), int.Parse(tokens[Port], CultureInfo.InvariantCulture)));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.BadDccEndpoint, ae.ToString());
                        return;
                    }
                    try
                    {
                        OnDccSendRequest(
                            dccUserInfo,
                            tokens[FileName],
                            int.Parse(tokens[FileSize], CultureInfo.InvariantCulture),
                            IsTurbo(5, tokens));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString());
                    }
                }
                break;

            case GET:
                //Test for sufficient number of arguments
                if (tokens.Length < 2)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect GET arguments: " + message);
                    return;
                }
                if (OnDccGetRequest != null)
                {
                    try
                    {
                        OnDccGetRequest(
                            new DccUserInfo(
                                connection,
                                Rfc2812Util.ParseUserInfoLine(requestor)),
                            tokens[FileName],
                            IsTurbo(2, tokens));
                    }
                    catch (ArgumentException ae)
                    {
                        connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString());
                    }
                }
                break;

            case ACCEPT:
                //Test for sufficient number of arguments
                if (tokens.Length < 4)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect DCC ACCEPT arguments: " + message);
                    return;
                }
                //DccListener will try to handle Receive at correct file position
                try
                {
                    DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession("C" + tokens[2]);
                    session.OnDccAcceptReceived(long.Parse(tokens[3], CultureInfo.InvariantCulture));
                }
                catch (ArgumentException e)
                {
                    connection.Listener.Error(ReplyCode.UnableToResume, e.ToString());
                }
                break;

            case RESUME:
                //Test for sufficient number of arguments
                if (tokens.Length < 4)
                {
                    connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect DCC RESUME arguments: " + message);
                    return;
                }
                //DccListener will automatically handle Resume/Accept interaction
                try
                {
                    DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession("S" + tokens[2]);
                    session.OnDccResumeRequest(long.Parse(tokens[3], CultureInfo.InvariantCulture));
                }
                catch (ArgumentException e)
                {
                    connection.Listener.Error(ReplyCode.UnableToResume, e.ToString());
                }
                break;

            default:
                connection.Listener.Error(ReplyCode.UnparseableMessage, message);
                Debug.WriteLineIf(DccUtil.DccTrace.TraceError, "[" + Thread.CurrentThread.Name + "] DccListener::Parse() Unknown DCC command");
                break;
            }
        }
Example #10
0
		internal void Parse( Connection connection, string message ) 
		{
			Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccListener::Parse()");
			Match match = parser.Match( message );
			string requestor = match.Groups[1].ToString();
			string[] tokens =tokenizer.Split( match.Groups[2].ToString().Trim() );
			switch( tokens[Action] )
			{
				case CHAT:
					if( OnDccChatRequest != null ) 
					{
						//Test for sufficient number of arguments
						if( tokens.Length < 4 ) 
						{
							connection.Listener.Error( ReplyCode.UnparseableMessage, "Incorrect CHAT arguments: " + message );
							return;
						}
						//Send event
						DccUserInfo dccUserInfo = null;
						try
						{
							dccUserInfo = new DccUserInfo(
								connection,
								Rfc2812Util.ParseUserInfoLine( requestor ),
								new IPEndPoint( DccUtil.LongToIPAddress( tokens[ Address ]), int.Parse( tokens[ Port], CultureInfo.InvariantCulture ) ) );
						}
						catch( ArgumentException ) 
						{
							connection.Listener.Error( ReplyCode.BadDccEndpoint, "Invalid TCP/IP connection information sent." );
							return;
						}
						try 
						{
							OnDccChatRequest( dccUserInfo );
						}
						catch( ArgumentException ae ) 
						{
							connection.Listener.Error( ReplyCode.UnknownEncryptionProtocol, ae.ToString() );
						}
					}
					break;
				case SEND:
					//Test for sufficient number of arguments
					if( tokens.Length < 5 ) 
					{
						connection.Listener.Error( ReplyCode.UnparseableMessage, "Incorrect SEND arguments: " + message );
						return;
					}
					if( OnDccSendRequest != null ) 
					{
						DccUserInfo dccUserInfo = null;
						try
						{
							dccUserInfo = new DccUserInfo(
								connection,
								Rfc2812Util.ParseUserInfoLine( requestor ),
								new IPEndPoint( DccUtil.LongToIPAddress( tokens[ Address ]), int.Parse( tokens[ Port], CultureInfo.InvariantCulture ) ) );
						}
						catch( ArgumentException ae ) 
						{
							connection.Listener.Error( ReplyCode.BadDccEndpoint, ae.ToString() );
							return;
						}
						try
						{
							OnDccSendRequest( 
								dccUserInfo,
								tokens[FileName],
								int.Parse( tokens[FileSize], CultureInfo.InvariantCulture ),
								IsTurbo( 5, tokens) );
						}
						catch( ArgumentException ae ) 
						{
							connection.Listener.Error( ReplyCode.UnknownEncryptionProtocol, ae.ToString() );
						}
					}
					break;
				case GET:
					//Test for sufficient number of arguments
					if( tokens.Length < 2 ) 
					{
						connection.Listener.Error( ReplyCode.UnparseableMessage, "Incorrect GET arguments: " + message );
						return;
					}
					if( OnDccGetRequest != null ) 
					{
						try 
						{
							OnDccGetRequest(
								new DccUserInfo( 
								connection,
								Rfc2812Util.ParseUserInfoLine( requestor ) ),
								tokens[ FileName], 
								IsTurbo( 2, tokens) );
						}
						catch( ArgumentException ae ) 
						{
							connection.Listener.Error( ReplyCode.UnknownEncryptionProtocol, ae.ToString() );
						}
					}
					break;
				case ACCEPT:
					//Test for sufficient number of arguments
					if( tokens.Length < 4 ) 
					{
						connection.Listener.Error( ReplyCode.UnparseableMessage, "Incorrect DCC ACCEPT arguments: " + message );
						return;
					}
					//DccListener will try to handle Receive at correct file position
					try 
					{
						DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession( "C" + tokens[2] );
						session.OnDccAcceptReceived( long.Parse( tokens[3] , CultureInfo.InvariantCulture) );
					}
					catch( ArgumentException e ) 
					{
						connection.Listener.Error( ReplyCode.UnableToResume, e.ToString() );
					}
					break;
				case RESUME:
					//Test for sufficient number of arguments
					if( tokens.Length < 4 ) 
					{
						connection.Listener.Error( ReplyCode.UnparseableMessage, "Incorrect DCC RESUME arguments: " + message );
						return;
					}
					//DccListener will automatically handle Resume/Accept interaction
					try 
					{
						DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession( "S" + tokens[2] );
						session.OnDccResumeRequest( long.Parse( tokens[3], CultureInfo.InvariantCulture ) );
					}
					catch( ArgumentException e ) 
					{
						connection.Listener.Error( ReplyCode.UnableToResume, e.ToString() );
					}
					break;
				default: 
					connection.Listener.Error( ReplyCode.UnparseableMessage, message );
					Debug.WriteLineIf( DccUtil.DccTrace.TraceError, "[" + Thread.CurrentThread.Name +"] DccListener::Parse() Unknown DCC command");
					break;
			}
		}
Example #11
0
 /// <summary>
 /// Send a DCC Chat request to a remote user and use the default
 /// timeout period of 30 seconds.
 /// </summary>
 /// <remarks>
 /// <para>If the user does not respond within the timeout period the DccChatSession
 /// will stop listening for a connection. The sesssion instance created then becomes
 /// invalid. This methods must be called again and a new instance created in order to
 /// initiate a try again.
 /// </para>
 /// <para>
 /// This method should be called from within a try/catch block
 /// in case there are socket errors.
 /// </para>
 /// </remarks>
 /// <param name="dccUserInfo">A collection of information about the remote user.</param>
 /// <param name="listenIPAddress">The IP address of the local machine in dot
 /// quad format (e.g. 192.168.0.25). This is the address that will be sent to the
 /// remote user. The IP address of the NAT machine must be used if the
 /// client is behind a a NAT/Firewall system. </param>
 /// <param name="listenPort">The TCP/IP port to listen on</param>
 public static DccChatSession Request( DccUserInfo dccUserInfo, string listenIPAddress, int listenPort )
 {
     return Request( dccUserInfo, listenIPAddress, listenPort, DefaultTimeout );
 }
Example #12
0
 /// <summary>
 /// When another a remote user has sent a chat request, this
 /// method is called to accept the request and
 /// start a chat session with that user.
 /// </summary>
 /// <remarks>
 /// This method should be called from within a try/catch block
 /// because there are many things that could prevent this
 /// connection attempt from succeeding.
 /// </remarks>
 /// <param name="dccUserInfo">A collection of information about the remote user.</param>
 /// <returns>The DccChatSession instance for this session.</returns>
 public static DccChatSession Accept( DccUserInfo dccUserInfo )
 {
     Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccChatSession::Accept()");
     DccChatSession session = new DccChatSession( dccUserInfo );
     //Start session Thread
     session.thread = new Thread(new ThreadStart( session.Connect ) );
     session.thread.Name = session.ToString();
     session.thread.Start();
     return session;
 }
Example #13
0
        private void InitiateChat( string nick )
        {
            //Initiating a chat is only slightly more complicated than accepting one.

            //First we must create a DccUserInfo instance which contains the information
            //on how to send the request, i.e. what connection to use and who should receive it.
            DccUserInfo userInfo = new DccUserInfo( connection, nick );

            //Now we need to send our IP address and the port we will be listening on. Those
            //behind a NAT firewall should read the API docs for more information on what to use
            //as an IP address. The port can be any value above 1024. Thresher does not manage these
            //so it is up to us not to pick a port already in use.
            //Request() can take other arguments including a crypto protocol. See the API
            //docs for more information.
            chatSession =  DccChatSession.Request( userInfo, "192.168.0.11", 50000, 30000 );

            //Add delegates
            RegisterDelegates();

            //At this point one of two things will happen: the remote user will accept
            //and OnChatSessionOpened() will be called or the user will not respond
            //and OnChatRequestTimeout() will be called instead.

            //The new session Thread is now running and waiting for a response...
        }
Example #14
0
        public void OnDccChatRequest( DccUserInfo dccUserInfo )
        {
            //This event will be raised if someone is attempting to initiate a Chat session.
            //DccUserInfo extends UserInfo and contains some additional networking information
            //as well as the Connection instance used to send the request.

            //There are lots of things which can go wrong with DCC so the creation of any
            //type of DCC session should always be in a try/catch block.
            try
            {
                Console.WriteLine("Chat request from " + dccUserInfo.Nick ) ;

                //Untill we call accept on the session it will not be opened so we could ignore
                //it if we wanted to. The Accept parameters  are the same ones kindly provided
                //by the ChatRequest event.
                chatSession =  DccChatSession.Accept( dccUserInfo );

                //Now add delegate to the session
                RegisterDelegates();

                //All DCC sessions are direct connections to other users and do not pass through
                //the IRC server. The IRC server is only a means of sending session requests. DCC
                //sessions also run in their own separate Threads, one for each session instance.
                //When a session is closed the Thread ends.

                //Since we don't want to be notified of any more chat request we will
                //remove ourselves form the list. It is always important to remove yourself from
                //events when they are no longer needed.
                DccListener.DefaultInstance.OnDccChatRequest -= new DccChatRequestEventHandler( OnDccChatRequest );

                //Now we wait for messages...

            }
            catch( Exception e )
            {
                Console.WriteLine("Exception handling Chat request: " + e);
            }
        }
		/// <summary>
		/// Another user has offered to send a file. This method should be called
		/// to accept the offer and save the file to the give location. The parameters
		/// needed to call this method are provided by the <c>OnDccFileTransferRequest()</c>
		/// event.
		/// </summary>
		/// <remarks>
		/// This method should be called from within a try/catch block 
		/// in case it is unable to connect or there are other socket
		/// errors.
		/// </remarks>
		/// <param name="dccUserInfo">Information on the remote user.</param>
		/// <param name="dccFileInfo">The local file that will hold the data being sent. If the file 
		/// is the result of a previous incomplete download the the attempt will be made
		/// to resume where the previous left off.</param>
		/// <param name="turbo">Will the send ahead protocol be used.</param>
		/// <returns>A unique session instance for this file and remote user.</returns>
		/// <exception cref="ArgumentException">If the listen port is already in use.</exception>
		public static DccFileSession Receive(DccUserInfo dccUserInfo, DccFileInfo dccFileInfo, bool turbo ) 
		{
			Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccFileSession::Receive()");
			//Test if we are already using this port
			if( DccFileSessionManager.DefaultInstance.ContainsSession( "C" + dccUserInfo.remoteEndPoint.Port ) ) 
			{
				throw new ArgumentException("Already listening on port " + dccUserInfo.remoteEndPoint.Port );
			}
			DccFileSession session = null;
			try 
			{
				session = new DccFileSession( dccUserInfo, dccFileInfo, (64 * 1024 ), 
					dccUserInfo.remoteEndPoint.Port, "C" + dccUserInfo.remoteEndPoint.Port );
				//Has the initiator specified the turbo protocol? 
				session.turboMode = turbo;
				//Open file for writing
				dccFileInfo.OpenForWrite();
				DccFileSessionManager.DefaultInstance.AddSession( session );
				//Determine if we can resume a download
				if( session.dccFileInfo.ShouldResume() ) 
				{
					session.waitingOnAccept = true;
					session.dccFileInfo.SetResumeToFileSize();
					session.SendResume();
				}
				else 
				{
					session.thread = new Thread( new ThreadStart( session.Download ) );
					session.thread.Name = session.ToString();
					session.thread.Start();	
				}
				return session;
			}
			catch( Exception e ) 
			{
				if( session != null ) 
				{
					DccFileSessionManager.DefaultInstance.RemoveSession( session );
				}
				throw e;
			}
		}
		/// <summary>
		/// Attempt to send a file to a remote user. Start listening
		/// on the given port and address. If the remote user does not accept
		/// the offer within the timeout period the the session
		/// will be closed.
		/// </summary>
		/// <remarks>
		/// This method should be called from within a try/catch block 
		/// in case there are socket errors. This methods will also automatically 
		/// handle a Resume if the remote client requests it.
		/// </remarks>
		/// <param name="dccUserInfo">The information about the remote user.</param>
		/// <param name="listenIPAddress">The IP address of the local machine in dot 
		/// quad format (e.g. 192.168.0.25). This is the address that will be sent to the 
		/// remote user. The IP address of the NAT machine must be used if the
		/// client is behind a NAT/Firewall system. </param>
		/// <param name="listenPort">The port that the session will listen on.</param>
		/// <param name="dccFileInfo">The file to be sent. If the file name has spaces in it
		/// they will be replaced with underscores when the name is sent.</param>
		/// <param name="bufferSize">The size of the send buffer. Generally should
		/// be between 4k and 32k.</param>
		/// <param name="turbo">True to use send-ahead mode for transfers.</param>
		/// <returns>A unique session instance for this file and remote user.</returns>
		/// <exception cref="ArgumentException">If the listen port is already in use.</exception>
		public static DccFileSession Send( 
			DccUserInfo dccUserInfo, 
			string listenIPAddress, 
			int listenPort, 
			DccFileInfo dccFileInfo, 
			int bufferSize,
			bool turbo)
		{
			Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccFileSession::Send()");
			DccFileSession session = null;
			//Test if we are already using this port
			if( DccFileSessionManager.DefaultInstance.ContainsSession( "S" + listenPort ) ) 
			{
				throw new ArgumentException("Already listening on port " + listenPort );
			}
			try
			{
				session = new DccFileSession( dccUserInfo, dccFileInfo , bufferSize, listenPort, "S" + listenPort );
				//set turbo mode
				session.turboMode = turbo;
				//Set server IP address
				session.listenIPAddress = listenIPAddress; 
				//Add session to active sessions hashtable
				DccFileSessionManager.DefaultInstance.AddSession( session );
				//Create stream to file
				dccFileInfo.OpenForRead();
				//Start session Thread
				session.thread = new Thread(new ThreadStart( session.Listen ) );
				session.thread.Name = session.ToString();
				session.thread.Start();	
				//Send DCC Send request to remote user
				session.DccSend( IPAddress.Parse( listenIPAddress) );
				return session;
			}
			catch( Exception e ) 
			{
				if( session != null ) 
				{
					DccFileSessionManager.DefaultInstance.RemoveSession( session );
				}
				throw e;
			}
		}
 /// <summary>
 /// Send a DCC Chat request to a remote user and use the default
 /// timeout period of 30 seconds.
 /// </summary>
 /// <remarks>
 /// <para>If the user does not respond within the timeout period the DccChatSession
 /// will stop listening for a connection. The sesssion instance created then becomes
 /// invalid. This methods must be called again and a new instance created in order to
 /// initiate a try again.
 /// </para>
 /// <para>
 /// This method should be called from within a try/catch block
 /// in case there are socket errors.
 /// </para>
 /// </remarks>
 /// <param name="dccUserInfo">A collection of information about the remote user.</param>
 /// <param name="listenIPAddress">The IP address of the local machine in dot
 /// quad format (e.g. 192.168.0.25). This is the address that will be sent to the
 /// remote user. The IP address of the NAT machine must be used if the
 /// client is behind a a NAT/Firewall system. </param>
 /// <param name="listenPort">The TCP/IP port to listen on</param>
 public static DccChatSession Request(DccUserInfo dccUserInfo, string listenIPAddress, int listenPort)
 {
     return(Request(dccUserInfo, listenIPAddress, listenPort, DefaultTimeout));
 }
Example #18
0
 /// <summary>
 /// Send a DCC Chat request to a remote user and wait for a connection
 /// using timeout period specified.
 /// </summary>
 /// <remarks>
 /// <para>If the user does not respond within the timeout period the DccChatSession
 /// will stop listening for a connection. The sesssion instance created then becomes
 /// invalid. This methods must be called again and a new instance created in order to
 /// initiate a try again.
 /// </para>
 /// <para>
 /// This method should be called from within a try/catch block
 /// in case there are socket errors.
 /// </para>
 /// </remarks>
 /// <param name="dccUserInfo">A collection of information about the remote user.</param>
 /// <param name="listenIPAddress">The IP address that will be sent to the remote user. It must
 /// be in dotted quad format (i.e. 192.168.0.2). If the client is behind a NAT system then
 /// this should be the address of that system and not the local host.</param>
 /// <param name="listenPort">The TCP/IP port to listen on</param>
 /// <param name="timeout">How long to wait for a response in milliseconds.
 /// A value of zero will disable the timeout.</param>
 public static DccChatSession Request( DccUserInfo dccUserInfo, string listenIPAddress, int listenPort, long timeout )
 {
     Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccChatSession::Request()");
     //Create session object
     DccChatSession session = new DccChatSession( dccUserInfo );
     session.listenPort = listenPort;
     //Start session Thread
     session.thread = new Thread(new ThreadStart( session.Listen ) );
     session.thread.Name = session.ToString();
     session.thread.Start();
     //Send Chat request to remote user
     session.SendChatRequest( listenIPAddress, listenPort );
     //Start timeout thread if timeout > 0
     if( timeout > 0 )
     {
         Timer timer = new Timer(
             new TimerCallback( session.TimerExpired ),
             session,
             timeout,
             0);
         Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccChatSession::Request timeout thread started");
     }
     return session;
 }
 internal DccChatSession(DccUserInfo dccUserInfo)
 {
     this.dccUserInfo = dccUserInfo;
     listening        = false;
     receiving        = false;
 }
Example #20
0
 internal DccChatSession( DccUserInfo dccUserInfo  )
 {
     this.dccUserInfo = dccUserInfo;
     listening = false;
     receiving = false;
 }