Ejemplo n.º 1
0
        internal void Execute(int timeout,
                              string cmd,
                              FtpDataType dataType,
                              long restart,
                              DTPStream userStream)
        {
            bool ccLocked = false;

            //protected component against simultaneuous usage
            SetProgress(true);
            try
            {
                //----------------------------------------
                //Lock Control connection to prevent
                //run the command like abort, quit, stat
                //during configuring of data connection
                ccLocked = _cc.Lock(Timeout.Infinite);

                FtpResponse response = null;
                //----------------------------------------
                //send transfser type command
                if ((false == _client.IsDataTypeWasCached) ||
                    ((true == _client.IsDataTypeWasCached) && (_client.CachedDataType != dataType)))
                {
                    string typeCmd = GetTypeCommand(dataType);
                    response = _cc.SendCommandEx(timeout, typeCmd);
                    FtpClient.CheckCompletionResponse(response);

                    _client.IsDataTypeWasCached = true;
                    _client.CachedDataType      = dataType;
                }

                //----------------------------------------
                //Initialize data connection
                _currentDC = null;
                Cmd_GetDataConnection getDC = new Cmd_GetDataConnection(_client);
                lock (this)
                {
                    if (!_disposed)
                    {
                        _currentDC = getDC.Execute(timeout);
                    }
                }
                CheckDisposed();

                //----------------------------------------
                //send restart position, if needed
                if (0 < restart)
                {
                    string restCmd = "REST " + restart.ToString();
                    response = _cc.SendCommandEx(timeout, restCmd);
                    if (false == response.IsIntermediateReply)
                    {
                        throw GetRestartNotSuppException(response);
                    }
                    CheckDisposed();
                }

                //----------------------------------------
                //establish connection now, if it is outbound
                if (FtpDataConnectionType.Outbound == _currentDC.Type)
                {
                    _currentDC.Establish(timeout);
                    CheckDisposed();
                }

                //----------------------------------------
                //send transfer request to the server
                response = _cc.SendCommandEx(timeout, cmd);
                CheckDisposed();

                //----------------------------------------
                //first respone should be one
                //of the 1** - let's check it
                if (response.IsCompletionReply)                 //should not happen
                {
                    NSTrace.WriteLineError("Executing DTP: receive completion as first reply.");
                    //_currentDC.AbortAsyncEstablish();
                }
                else
                {
                    FtpClient.CheckPreliminaryResponse(response);

                    //----------------------------------------
                    //establish connection now, if it is inbound
                    if (FtpDataConnectionType.Inbound == _currentDC.Type)
                    {
                        _currentDC.Establish(timeout);
                        CheckDisposed();
                    }

                    FtpAbortedException abortEx = null;
                    try
                    {
                        //----------------------------------------
                        //subscribe to data events
                        _currentDC.DataTransfered += new FtpDataConnection.DataTransferedEventHandler(OnDataTransfered);
                        _currentDC.Completed      += new FtpDataConnection.CompletedEventHandler(OnCompleted);

                        //----------------------------------------
                        //prepare for abortion
                        _aborted           = false;
                        _client.CurrentDTP = this;

                        //----------------------------------------
                        //Unlock control connection, now the command
                        //like abort, stat, quit could be issued
                        ccLocked = false;
                        _cc.Unlock();

                        //----------------------------------------
                        //start DTP
                        _currentDC.RunDTPStream(timeout, userStream);
                    }
                    catch (FtpAbortedException ex)
                    {
                        abortEx = ex;
                    }
                    finally
                    {
                        _currentDC.DataTransfered -= new FtpDataConnection.DataTransferedEventHandler(OnDataTransfered);
                        _currentDC.Completed      -= new FtpDataConnection.CompletedEventHandler(OnCompleted);
                    }

                    //----------------------------------------
                    //Lock control connection again - reading
                    //responses
                    ccLocked = _cc.Lock(Timeout.Infinite);

                    //----------------------------------------
                    //Skip preliminary responses
                    //
                    for (int i = 0; i < 10; i++)
                    {
                        response = _cc.ReadResponse(timeout);
                        CheckDisposed();
                        if (response.IsPreliminaryReply)
                        {
                            continue;
                        }
                        break;
                    }

                    //----------------------------------------
                    //If still receiving priliminary responses
                    //then it looks suspecious?
                    //
                    if (response.IsPreliminaryReply)
                    {
                        throw GetTooManyRespException();
                    }

                    //----------------------------------------
                    // Dealing with Abort or Reset
                    //
                    if (!_aborted && (null == abortEx))
                    {
                        if (!_currentDC.ManuallyClosed)
                        {
                            FtpClient.CheckCompletionResponse(response);
                        }
                        else
                        {
                            //----------------------------------------
                            //we DID close the data connection,
                            //so, in general, the response should be
                            //errorneous - therefore skip checking of it
                        }
                    }
                    else
                    {
                        if (null != abortEx)                        //&& !response.IsCompletionReply)
                        {
                            abortEx.SetResponse(response);
                        }

                        //----------------------------------------
                        //If "ABOR" command was sent we need to
                        //one more response...
                        //
                        if (_aborted)
                        {
                            response = _cc.ReadResponse(timeout);
                        }
                    }

                    //------------------------------------------
                    //If "QUIT" was sent during data transfer
                    //then here we need read one more response
                    if (_quited)
                    {
                        response = _cc.ReadResponse(timeout);
                    }

                    if (null != abortEx)
                    {
                        throw abortEx;
                    }
                }
            }
            catch (Exception e)
            {
                CheckDisposed();
                NSTrace.WriteLineError(_errMsg + e.ToString());
                throw;
            }
            catch
            {
                CheckDisposed();
                NSTrace.WriteLineError(_errMsgNonCls + Environment.StackTrace.ToString());
                throw;
            }
            finally
            {
                SetProgress(false);
                _client.CurrentDTP = null;

                if (true == ccLocked)
                {
                    _cc.Unlock();
                }
            }
        }