示例#1
0
 /// <summary>
 /// Prepare a new instance with default values but do not connect
 /// to another user.
 /// </summary>
 internal DccFileSession(DccUser dccUser, DccFileInfo dccFileInfo, int bufferSize, int listenPort, string sessionID)
 {
     this.dccUser = dccUser;
     this.dccFileInfo = dccFileInfo;
     buffer = new byte[bufferSize];
     this.listenPort = listenPort;
     this.sessionID = sessionID;
     lastActivity = DateTime.Now;
     waitingOnAccept = false;
 }
示例#2
0
 internal DccChatSession(DccUser dccUser)
 {
     this.dccUser = dccUser;
     listening = false;
     receiving = false;
 }
示例#3
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="dccUser">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(DccUser dccUser, string listenIPAddress, int listenPort, long timeout)
 {
     Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Request()");
     //Create session object
     DccChatSession session = new DccChatSession(dccUser);
     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;
 }
示例#4
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="dccUser">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(DccUser dccUser, string listenIPAddress, int listenPort)
 {
     return Request(dccUser, listenIPAddress, listenPort, DefaultTimeout);
 }
示例#5
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="dccUser">A collection of information about the remote user.</param>
 /// <returns>The DccChatSession instance for this session.</returns>
 public static DccChatSession Accept(DccUser dccUser)
 {
     Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Accept()");
     DccChatSession session = new DccChatSession(dccUser);
     //Start session Thread
     session.thread = new Thread(new ThreadStart(session.Connect));
     session.thread.Name = session.ToString();
     session.thread.Start();
     return session;
 }
示例#6
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
                 DccUser dccUser = null;
                 try
                 {
                     dccUser = new DccUser(
                         connection,
                         Rfc2812Util.ParseUserLine( 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( dccUser );
                 }
                 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 )
             {
                 DccUser dccUser = null;
                 try
                 {
                     dccUser = new DccUser(
                         connection,
                         Rfc2812Util.ParseUserLine( 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(
                         dccUser,
                         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 DccUser(
                         connection,
                         Rfc2812Util.ParseUserLine( 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;
     }
 }
示例#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="dccUser">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(
     DccUser dccUser,
     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(dccUser, 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 ex)
     {
         if (session != null)
         {
             DccFileSessionManager.DefaultInstance.RemoveSession(session);
         }
         throw ex;
     }
 }
示例#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="dccUser">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(DccUser dccUser, 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" + dccUser.remoteEndPoint.Port))
     {
         throw new ArgumentException("Already listening on port " + dccUser.remoteEndPoint.Port);
     }
     DccFileSession session = null;
     try
     {
         session = new DccFileSession(dccUser, dccFileInfo, (64 * 1024),
             dccUser.remoteEndPoint.Port, "C" + dccUser.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 ex)
     {
         if (session != null)
         {
             DccFileSessionManager.DefaultInstance.RemoveSession(session);
         }
         throw ex;
     }
 }