/// <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); }
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 ) ; } }
/// <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; }
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); }
/// <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> /// 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; } }
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; } }
/// <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 ); }
/// <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; }
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... }
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)); }
/// <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; }
internal DccChatSession( DccUserInfo dccUserInfo ) { this.dccUserInfo = dccUserInfo; listening = false; receiving = false; }