Example #1
0
 private Boolean TimedOut(DccFileSession session)
 {
     if ((DateTime.Now - session.LastActivity) >= timeout)
     {
         return(true);
     }
     return(false);
 }
Example #2
0
 internal void RemoveSession(DccFileSession session)
 {
     sessions.Remove(session.ID);
     if (sessions.Count == 0)
     {
         timerStopped = true;
         timerThread.Change(Timeout.Infinite, TimeoutCheckPeriod);
     }
     Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccSessionManager::RemoveSession() ID=" + session.ID);
 }
Example #3
0
 internal void AddSession(DccFileSession session)
 {
     sessions.Add(session.ID, session);
     if (timerStopped)
     {
         timerStopped = false;
         timerThread.Change(TimeoutCheckPeriod, TimeoutCheckPeriod);
     }
     Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccSessionManager::AddSession() ID=" + session.ID);
 }
Example #4
0
 internal void CheckSessions(object state)
 {
     Debug.WriteLineIf(DccUtil.DccTrace.TraceVerbose, "[" + Thread.CurrentThread.Name + "] DccSessionManager::CheckSessions()");
     sessionClone = (Hashtable)sessions.Clone();
     foreach (object session in sessionClone.Values)
     {
         DccFileSession fileSession = (DccFileSession)session;
         lock ( fileSession )
         {
             if (TimedOut(fileSession))
             {
                 fileSession.TimedOut();
             }
         }
     }
 }
Example #5
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;
            }
        }
Example #6
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;
            }
        }
 private Boolean TimedOut( DccFileSession session )
 {
     if( ( DateTime.Now - session.LastActivity ) >= timeout )
     {
         return true;
     }
     return false;
 }
 internal void RemoveSession( DccFileSession session )
 {
     sessions.Remove( session.ID );
     if( sessions.Count == 0 )
     {
         timerStopped = true;
         timerThread.Change( Timeout.Infinite, TimeoutCheckPeriod );
     }
     Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccSessionManager::RemoveSession() ID=" + session.ID );
 }
 internal void AddSession( DccFileSession session )
 {
     sessions.Add( session.ID, session );
     if( timerStopped )
     {
         timerStopped = false;
         timerThread.Change(TimeoutCheckPeriod, TimeoutCheckPeriod);
     }
     Debug.WriteLineIf( DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name +"] DccSessionManager::AddSession() ID=" + session.ID );
 }
Example #10
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;
     }
 }
Example #11
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;
     }
 }
Example #12
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;
            }
        }