/// <summary> /// Opens the specified type of active data stream /// </summary> /// <param name="type"></param> protected override void Open(FtpDataChannelType type) { string ipaddress = null; int port = 0; this.Socket.Bind(new IPEndPoint(((IPEndPoint)this.ControlConnection.LocalEndPoint).Address, 0)); this.Socket.Listen(1); ipaddress = ((IPEndPoint)this.Socket.LocalEndPoint).Address.ToString(); port = ((IPEndPoint)this.Socket.LocalEndPoint).Port; try { this.ControlConnection.LockControlConnection(); switch (type) { case FtpDataChannelType.ExtendedActive: this.ControlConnection.Execute("EPRT |1|{0}|{1}|", ipaddress, port); if (this.ControlConnection.ResponseType == FtpResponseType.PermanentNegativeCompletion) { this.ControlConnection.RemoveCapability(FtpCapability.EPSV); this.ControlConnection.RemoveCapability(FtpCapability.EPRT); this.ControlConnection.Execute("PORT {0},{1},{2}", ipaddress.Replace(".", ","), port / 256, port % 256); type = FtpDataChannelType.Active; } break; case FtpDataChannelType.Active: this.ControlConnection.Execute("PORT {0},{1},{2}", ipaddress.Replace(".", ","), port / 256, port % 256); break; default: throw new Exception("Active streams do not support " + type.ToString()); } if (!this.ControlConnection.ResponseStatus) { throw new FtpCommandException(this.ControlConnection); } } finally { this.ControlConnection.UnlockControlConnection(); } }
/// <summary> /// Opens the specified type of active data stream /// </summary> /// <param name="type"></param> protected override void Open(FtpDataChannelType type) { string ipaddress = null; int port = 0; this.Socket.Bind(new IPEndPoint(((IPEndPoint)this.ControlConnection.LocalEndPoint).Address, 0)); this.Socket.Listen(1); ipaddress = ((IPEndPoint)this.Socket.LocalEndPoint).Address.ToString(); port = ((IPEndPoint)this.Socket.LocalEndPoint).Port; try { this.ControlConnection.LockControlConnection(); switch(type) { case FtpDataChannelType.ExtendedActive: this.ControlConnection.Execute("EPRT |1|{0}|{1}|", ipaddress, port); if(this.ControlConnection.ResponseType == FtpResponseType.PermanentNegativeCompletion) { this.ControlConnection.RemoveCapability(FtpCapability.EPSV); this.ControlConnection.RemoveCapability(FtpCapability.EPRT); this.ControlConnection.Execute("PORT {0},{1},{2}", ipaddress.Replace(".", ","), port / 256, port % 256); type = FtpDataChannelType.Active; } break; case FtpDataChannelType.Active: this.ControlConnection.Execute("PORT {0},{1},{2}", ipaddress.Replace(".", ","), port / 256, port % 256); break; default: throw new Exception("Active streams do not support " + type.ToString()); } if(!this.ControlConnection.ResponseStatus) { throw new FtpCommandException(this.ControlConnection); } } finally { this.ControlConnection.UnlockControlConnection(); } }
/// <summary> /// Open the specified type of passive stream /// </summary> /// <param name="type"></param> protected override void Open(FtpDataChannelType type) { Match m = null; string host = null; int port = 0; try { this.ControlConnection.LockControlConnection(); switch (type) { case FtpDataChannelType.ExtendedPassive: this.ControlConnection.Execute("EPSV"); if (this.ControlConnection.ResponseType == FtpResponseType.PermanentNegativeCompletion) { // fall back to PASV if EPSV fails this.ControlConnection.RemoveCapability(FtpCapability.EPSV); this.ControlConnection.RemoveCapability(FtpCapability.EPRT); this.ControlConnection.Execute("PASV"); type = FtpDataChannelType.Passive; } break; case FtpDataChannelType.Passive: this.ControlConnection.Execute("PASV"); break; default: throw new Exception("Passive streams do not support " + type.ToString()); } if (!this.ControlConnection.ResponseStatus) { throw new FtpCommandException(this.ControlConnection); } if (type == FtpDataChannelType.Passive) { m = Regex.Match(this.ControlConnection.ResponseMessage, "([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+)"); if (!m.Success || m.Groups.Count != 7) { throw new FtpException(string.Format("Malformed PASV response: {0}", this.ControlConnection.ResponseMessage)); } host = string.Format("{0}.{1}.{2}.{3}", m.Groups[1].Value, m.Groups[2].Value, m.Groups[3].Value, m.Groups[4].Value); port = (int.Parse(m.Groups[5].Value) << 8) + int.Parse(m.Groups[6].Value); } else if (type == FtpDataChannelType.ExtendedPassive) { // according to RFC 2428, EPSV response must be exactly the // the same as EPRT response except the first two fields MUST BE blank // so that leaves us with (|||port_here|) m = Regex.Match(this.ControlConnection.ResponseMessage, @"\(\|\|\|(\d+)\|\)"); if (!m.Success) { throw new FtpException("Failed to get the EPSV port from: " + this.ControlConnection.ResponseMessage); } host = this.ControlConnection.Server; port = int.Parse(m.Groups[1].Value); } this.Socket.Connect(host, port); } finally { this.ControlConnection.UnlockControlConnection(); } }
/// <summary> /// Open the specified type of passive stream /// </summary> /// <param name="type"></param> protected override void Open(FtpDataChannelType type) { Match m = null; string host = null; int port = 0; try { this.ControlConnection.LockControlConnection(); switch(type) { case FtpDataChannelType.ExtendedPassive: this.ControlConnection.Execute("EPSV"); if(this.ControlConnection.ResponseType == FtpResponseType.PermanentNegativeCompletion) { // fall back to PASV if EPSV fails this.ControlConnection.RemoveCapability(FtpCapability.EPSV); this.ControlConnection.RemoveCapability(FtpCapability.EPRT); this.ControlConnection.Execute("PASV"); type = FtpDataChannelType.Passive; } break; case FtpDataChannelType.Passive: this.ControlConnection.Execute("PASV"); break; default: throw new Exception("Passive streams do not support " + type.ToString()); } if(!this.ControlConnection.ResponseStatus) { throw new FtpCommandException(this.ControlConnection); } if(type == FtpDataChannelType.Passive) { m = Regex.Match(this.ControlConnection.ResponseMessage, "([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+)"); if(!m.Success || m.Groups.Count != 7) { throw new FtpException(string.Format("Malformed PASV response: {0}", this.ControlConnection.ResponseMessage)); } host = string.Format("{0}.{1}.{2}.{3}", m.Groups[1].Value, m.Groups[2].Value, m.Groups[3].Value, m.Groups[4].Value); port = (int.Parse(m.Groups[5].Value) << 8) + int.Parse(m.Groups[6].Value); } else if(type == FtpDataChannelType.ExtendedPassive) { // according to RFC 2428, EPSV response must be exactly the // the same as EPRT response except the first two fields MUST BE blank // so that leaves us with (|||port_here|) m = Regex.Match(this.ControlConnection.ResponseMessage, @"\(\|\|\|(\d+)\|\)"); if(!m.Success) { throw new FtpException("Failed to get the EPSV port from: " + this.ControlConnection.ResponseMessage); } host = this.ControlConnection.Server; port = int.Parse(m.Groups[1].Value); } this.Socket.Connect(host, port); } finally { this.ControlConnection.UnlockControlConnection(); } }
/// <summary> /// Sets up sockets and executes necessary commands to initalize /// a data transfer. /// </summary> /// <param name="type"></param> protected abstract void Open(FtpDataChannelType type);