This project is read-only.

FTP - Azure website - An attempt was made to access a socket in a way forbidden by its access permissions

Feb 28, 2014 at 11:04 AM
Hello everyone,

I have a website that uses the FtpClient in passive mode on a azure website. I have not however been able to get passed the first great message. Using the generic FTP parts in .Net I have successfully got it listing, downloading and uploading files but still rather use FtpClient. I've tired all the passive modes and forcing it to use ip v4 but it still gets trapped in the same place.

I have this snippet from my logs:
FTP TRACE
014-02-27 16:53:50,411 [10] MyAndromeda.Framework.Logging.IMyAndromedaLogger - 220-FileZilla Server version 0.9.41 beta

2014-02-27 16:53:50,427 [10] MyAndromeda.Framework.Logging.IMyAndromedaLogger - 220-written by Tim Kosse (Tim.Kosse@gmx.de) 2014-02-27 16:53:50,442 [10] MyAndromeda.Framework.Logging.IMyAndromedaLogger - 220 Please visit http://sourceforge.net/projects/filezilla/
END of FTP Trace

2014-02-27 16:53:50,458 [10] MyAndromeda.Menus.Ftp.MenuFtpService - An attempt was made to access a socket in a way forbidden by its access permissions
2014-02-27 16:53:50,474 [10] MyAndromeda.Menus.Ftp.MenuFtpService - System
2014-02-27 16:53:50,489 [10] MyAndromeda.Menus.Ftp.MenuFtpService - at System.Net.Sockets.Socket.get_Available()
at System.Net.FtpClient.FtpSocketStream.get_SocketDataAvailable()
at System.Net.FtpClient.FtpClient.Execute(String command)
at System.Net.FtpClient.FtpClient.Authenticate()
at System.Net.FtpClient.FtpClient.Connect()
at ...
2014-02-27 16:53:51,208 [10] MyAndromeda.Framework.Logging.IMyAndromedaLogger - Disposing FtpClient object...

2014-02-27 16:53:51,208 [10] MyAndromeda.Framework.Logging.IMyAndromedaLogger - Disposing FtpSocketStream...
Anyone any ideas what FtpClient is doing differently to cause the above problem:
An attempt was made to access a socket in a way forbidden by its access permissions

Thanks
Matt
Mar 3, 2014 at 5:04 PM
Hi,

I'm encountering the very same issue on one of my Websites (independently on the "Compute mode" used). On the other hand, using a WebRole does not exhibit this permission issue.

@Matt : From your story and my own experience, it is not a problem on Azure Websites to both 1) Make FTP requests to an arbitrary FTP Server 2) Open a persistent TCP Connection to an arbitrary destination (port/address).
So the issue is closely related to the netfp use of Sockets.
I'll submit the issue to Microsoft support directly too. (Even though it is somewhat related to this specific library, such a limitation of Azure Websites should be at least documented).

Gabriel.
Mar 3, 2014 at 10:18 PM
Edited Mar 3, 2014 at 10:20 PM
It seems the problem is with checking the Socket.Available (internal to .net) property which takes place in FtpSocketStream.cs:
internal int SocketDataAvailable {
            get {
                if (m_socket != null)
                    return m_socket.Available;
                return 0;
            }
        }
That property is used in the FtpClient.Execute() method to detect if a connection timeout may have occurred (the server may send a 4xx error and close the connection):
if (m_stream != null && m_stream.SocketDataAvailable > 0) {
                    // Data shouldn't be on the socket, if it is it probably
                    // means we've been disconnected. Read and discard
                    // whatever is there and close the connection.

                    FtpTrace.WriteLine("There is stale data on the socket, maybe our connection timed out. Re-connecting.");
                    if (m_stream.IsConnected && !m_stream.IsEncrypted) {
                        byte[] buf = new byte[m_stream.SocketDataAvailable];
                        m_stream.RawSocketRead(buf);
                        FtpTrace.Write("The data was: ");
                        FtpTrace.WriteLine(Encoding.GetString(buf).TrimEnd('\r', '\n'));
                    }

                    m_stream.Close();
                }
Taking this check out isn't really an option. What I can do is make it configurable via a property (on by default). If you'll try removing that block of code from FtpClient.Execute and testing to see if it clears up the problem I'll add accommodations to System.Net.FtpClient for you guys.
Mar 4, 2014 at 3:52 AM
It occurs to me that it could also be where the KeepAlive socket option is set in the Connect() method of FtpClient:
m_stream.SetSocketOption(Sockets.SocketOptionLevel.Socket,
                    Sockets.SocketOptionName.KeepAlive, m_keepAlive);
Mar 4, 2014 at 10:08 AM
Will do:
Taking this check out isn't really an option. What I can do is make it configurable via a property (on by default). If you'll try removing that block of code from FtpClient.Execute and testing to see if it clears up the problem I'll add accommodations to System.Net.FtpClient for you guys.
and:
m_stream.SetSocketOption(Sockets.SocketOptionLevel.Socket, Sockets.SocketOptionName.KeepAlive, m_keepAlive);
I'll take a peak to see if that does remedy it and keep a eye on the keep alive part as well.

Thanks, Matt
Mar 4, 2014 at 4:14 PM
@Gabriel this will be useful to you as well I suspect ;-)

Ok I found some time to test it:

jptrosclair wrote:
if (m_stream != null && m_stream.SocketDataAvailable > 0) {
    // Data shouldn't be on the socket, if it is it probably
    // means we've been disconnected. Read and discard
    // whatever is there and close the connection.

    FtpTrace.WriteLine("There is stale data on the socket, maybe our connection timed out. Re-connecting.");
    if (m_stream.IsConnected && !m_stream.IsEncrypted) {
        byte[] buf = new byte[m_stream.SocketDataAvailable];
        m_stream.RawSocketRead(buf);
        FtpTrace.Write("The data was: ");
        FtpTrace.WriteLine(Encoding.GetString(buf).TrimEnd('\r', '\n'));
    }

    m_stream.Close();
}
having the azure web application skip that code worked (simple):
(so these usual tasks work again)
List directories;
set active folder;
download file;

There were no more exceptions thrown outwards over my process of scanning expected folders, scanning the input and downloading the files.
I have a few more tests to include like upload, writing into a file, but it seems to be doing what it should.

Overall i don't keep the FtpClient available to the application for long so it is very unlikely to find timeouts outside of connectivity problems. It rushes through a small portion known work within a using statement and restarts everything if there is more work.
m_stream.SetSocketOption(Sockets.SocketOptionLevel.Socket, Sockets.SocketOptionName.KeepAlive, m_keepAlive);
didn't appear to cause/throw any problems and it is called quite early so i should of observed it if it had.

Thanks for you help here.
Mar 4, 2014 at 4:24 PM
No problem, I'll add a property that forces the Execute() method to skip over that code which should make it easier for you guys to merge any future changes or fixes.
Mar 4, 2014 at 4:49 PM
Alright, the latest commit has a new property StaleDataCheck, set it to false and it will skip that code.
Mar 4, 2014 at 4:57 PM
@Matt : thanks for your investigation
@jptrosclair : Thx for providing a workaround so quickly

However, the culprit seems to be Socket.Available property itself, since the following simple code throws the same error :
        let socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        socket.Connect("ftp.free.fr", 21)
        socket.Available
I'm waiting for an answer from Microsoft Support though, I'll keep you informed.
Mar 7, 2014 at 5:58 PM
I just deployed a new feature in my website for uploading files to an FTP site. I'm using the latest release nuget. Unfortunately, this feature is dead in the water because of this issue. Is there any workaround at this point?
Mar 7, 2014 at 6:18 PM
Use the code from the latest revision in the master branch. Set the StaleDataCheck property = false. Until Microsoft does something to address the Socket.Available property triggering that exception when accessed the only solution is to skip over the block of code in System.Net.FtpClient that uses it. Fortunately it's not a critical piece of code; things will still work without it. The new StaleDataCheck property affects whether or not that code is executed.
Mar 10, 2014 at 6:57 PM
Edited Mar 10, 2014 at 7:13 PM
Thanks, I deployed with latest and still got the error. LOL, after looking at the source, that set property doesn't look too good to me. :)
        public bool StaleDataCheck {
            get { return m_staleDataTest; }
            set { m_staleDataTest = true; }
        }
Even after fixing to "m_staleDataTest = value", I'm still getting the following exception in Azure only:
There was an error uploading the file to the FTP server: An attempt was made to access a socket in a way forbidden by its access permissions; at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) at System.Net.FtpClient.FtpSocketStream.Connect(String host, Int32 port, FtpIpVersion ipVersions) at System.Net.FtpClient.FtpClient.Connect() at System.Net.FtpClient.FtpClient.Execute(String command) at System.Net.FtpClient.FtpClient.GetWorkingDirectory() at System.Net.FtpClient.FtpClient.DirectoryExists(String path) at System.Net.FtpClient.FtpClient.CreateDirectory(String path, Boolean force) at Lhp.EquipmentIntelligence.Web.Admin.Controllers.OtapCommandController.CreateFileCommand(NewEditModel model)
I'm running the code as follows. Upload is a simple extension method (it barfs on CreateDirectory() anyway):

using (var ftp = new FtpClient())
{
    ftp.StaleDataCheck = false; // This temporarily addresses a bug in Azure (https://netftp.codeplex.com/discussions/535879)
    ftp.Host = ftpServer.Host;
    if (ftpServer.Port.HasValue)
        ftp.Port = ftpServer.Port.Value;
    ftp.Credentials = new NetworkCredential(ftpServer.Username, ftpServer.Password);
    ftp.CreateDirectory(remoteDirectory);
    ftp.Upload(model.File.InputStream, command.RemotePath);
}
Mar 11, 2014 at 3:07 AM
My apologies, I just committed a new revision that should fix this issue.