+
+ ServicePoint GetServicePoint ()
+ {
+ if (servicePoint == null)
+ servicePoint = ServicePointManager.FindServicePoint (requestUri, proxy);
+
+ return servicePoint;
+ }
+
+ // Probably move some code of command connection here
+ void ResolveHost ()
+ {
+ CheckIfAborted ();
+ hostEntry = GetServicePoint ().HostEntry;
+
+ if (hostEntry == null) {
+ ftpResponse.UpdateStatus (new FtpStatus(FtpStatusCode.ActionAbortedLocalProcessingError, "Cannot resolve server name"));
+ throw new WebException ("The remote server name could not be resolved: " + requestUri,
+ null, WebExceptionStatus.NameResolutionFailure, ftpResponse);
+ }
+ }
+
+ void ProcessRequest () {
+
+ if (State == RequestState.Scheduled) {
+ ftpResponse = new FtpWebResponse (requestUri, method, keepAlive);
+
+ try {
+ ProcessMethod ();
+ //State = RequestState.Finished;
+ //finalResponse = ftpResponse;
+ asyncResult.SetCompleted (false, ftpResponse);
+ }
+ catch (Exception e) {
+ State = RequestState.Error;
+ SetCompleteWithError (e);
+ }
+ }
+ else {
+ if (InProgress ()) {
+ FtpStatus status = GetResponseStatus ();
+
+ ftpResponse.UpdateStatus (status);
+
+ if (ftpResponse.IsFinal ()) {
+ State = RequestState.Finished;
+ }
+ }
+
+ asyncResult.SetCompleted (false, ftpResponse);
+ }
+ }
+
+ void ProcessMethod ()
+ {
+ State = RequestState.Connecting;
+
+ ResolveHost ();
+
+ OpenControlConnection ();
+
+ switch (method) {
+ // Open data connection and receive data
+ case WebRequestMethods.Ftp.DownloadFile:
+ case WebRequestMethods.Ftp.ListDirectory:
+ case WebRequestMethods.Ftp.ListDirectoryDetails:
+ DownloadData ();
+ break;
+ // Open data connection and send data
+ case WebRequestMethods.Ftp.AppendFile:
+ case WebRequestMethods.Ftp.UploadFile:
+ case WebRequestMethods.Ftp.UploadFileWithUniqueName:
+ UploadData ();
+ break;
+ // Get info from control connection
+ case WebRequestMethods.Ftp.GetFileSize:
+ case WebRequestMethods.Ftp.GetDateTimestamp:
+ case WebRequestMethods.Ftp.PrintWorkingDirectory:
+ case WebRequestMethods.Ftp.MakeDirectory:
+ case WebRequestMethods.Ftp.Rename:
+ ProcessSimpleMethod ();
+ break;
+ default: // What to do here?
+ throw new Exception (String.Format ("Support for command {0} not implemented yet", method));
+ }
+
+ CheckIfAborted ();
+ }
+
+ private void CloseControlConnection () {
+ SendCommand (QuitCommand);
+ controlStream.Close ();
+ }
+
+ private void CloseDataConnection () {
+ if(dataSocket != null)
+ dataSocket.Close ();
+ }
+
+ private void CloseConnection () {
+ CloseControlConnection ();
+ CloseDataConnection ();
+ }
+
+ void ProcessSimpleMethod ()
+ {
+ State = RequestState.TransferInProgress;
+
+ FtpStatus status;
+
+ if (method == WebRequestMethods.Ftp.PrintWorkingDirectory)
+ method = ChangeDir;
+
+ if (method == WebRequestMethods.Ftp.Rename)
+ method = RenameFromCommand;
+
+ status = SendCommand (method, requestUri.LocalPath);
+
+ ftpResponse.Stream = new EmptyStream ();
+
+ string desc = status.StatusDescription;
+
+ switch (method) {
+ case WebRequestMethods.Ftp.GetFileSize: {
+ if (status.StatusCode != FtpStatusCode.FileStatus)
+ throw CreateExceptionFromResponse (status);
+
+ int i, len;
+ long size;
+ for (i = 4, len = 0; i < desc.Length && Char.IsDigit (desc [i]); i++, len++)
+ ;
+
+ if (len == 0)
+ throw new WebException ("Bad format for server response in " + method);
+
+ if (!Int64.TryParse (desc.Substring (4, len), out size))
+ throw new WebException ("Bad format for server response in " + method);
+
+ ftpResponse.contentLength = size;
+ }
+ break;
+ case WebRequestMethods.Ftp.GetDateTimestamp:
+ if (status.StatusCode != FtpStatusCode.FileStatus)
+ throw CreateExceptionFromResponse (status);
+ ftpResponse.LastModified = DateTime.ParseExact (desc.Substring (4), "yyyyMMddHHmmss", null);
+ break;
+ case WebRequestMethods.Ftp.MakeDirectory:
+ if (status.StatusCode != FtpStatusCode.PathnameCreated)
+ throw CreateExceptionFromResponse (status);
+ break;
+ case ChangeDir:
+ method = WebRequestMethods.Ftp.PrintWorkingDirectory;
+
+ if (status.StatusCode != FtpStatusCode.FileActionOK)
+ throw CreateExceptionFromResponse (status);
+
+ status = SendCommand (method);
+
+ if (status.StatusCode != FtpStatusCode.PathnameCreated)
+ throw CreateExceptionFromResponse (status);
+ break;
+ case RenameFromCommand:
+ method = WebRequestMethods.Ftp.Rename;
+ if (status.StatusCode != FtpStatusCode.FileCommandPending)
+ throw CreateExceptionFromResponse (status);
+ // Pass an empty string if RenameTo wasn't specified
+ status = SendCommand (RenameToCommand, renameTo != null ? renameTo : String.Empty);
+ if (status.StatusCode != FtpStatusCode.FileActionOK)
+ throw CreateExceptionFromResponse (status);
+ break;
+ }
+
+ ftpResponse.UpdateStatus (status);
+ State = RequestState.Finished;
+ }
+
+ void UploadData ()
+ {
+ State = RequestState.OpeningData;
+
+ OpenDataConnection ();
+
+ State = RequestState.TransferInProgress;
+ requestStream = new FtpDataStream (this, dataSocket, false);
+ asyncResult.Stream = requestStream;
+ }
+
+ void DownloadData ()
+ {
+ State = RequestState.OpeningData;
+
+ // Handle content offset
+ if (offset > 0) {
+ FtpStatus status = SendCommand (RestCommand, offset.ToString ());
+
+ if (status.StatusCode != FtpStatusCode.FileCommandPending)
+ throw CreateExceptionFromResponse (status);
+ }
+
+ OpenDataConnection ();
+
+ State = RequestState.TransferInProgress;
+ ftpResponse.Stream = new FtpDataStream (this, dataSocket, true);
+ }