Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 45 additions & 6 deletions Source/RemObjects.InternetPack/Bindings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ public Boolean ShouldSerializePort()

public class ServerBinding : Binding
{
ManualResetEvent _accepted;

public ServerBinding()
{
this.fListenerThreadCount = 1;
Expand Down Expand Up @@ -235,12 +237,16 @@ public virtual void Unbind(Boolean block)
if (this.fListeningSocket == null)
return;

this.fListeningSocket.Close();
using (this.fListeningSocket)
{
this.fListeningSocket.Close();
#if FULLFRAMEWORK
if (block && this.fListenThreads != null)
for (Int32 i = 0; i < this.fListenThreads.Length; i++)
this.fListenThreads[i].Join();
if (block && this.fListenThreads != null)
for (Int32 i = 0; i < this.fListenThreads.Length; i++)
this.fListenThreads[i].Join();
#endif
this.fListeningSocket = null;
}
}

public virtual void BindUnthreaded()
Expand All @@ -249,12 +255,45 @@ public virtual void BindUnthreaded()
this.fListeningSocket = new Socket(this.AddressFamily, this.SocketType, this.Protocol);
if (!this.EnableNagle)
this.fListeningSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1);
this.fListeningSocket.Bind(this.fEndPoint);

try
{
this.fListeningSocket.Bind(this.fEndPoint);
}
catch (SocketException)
{
using (this.fListeningSocket)
{
this.fListeningSocket = null;
}
this.fEndPoint = null;
throw;
}
}

public virtual Connection Accept()
{
return new Connection(this.fListeningSocket.Accept());
using (_accepted = new ManualResetEvent(false))
{
var cancelThread = new Thread(CancelAccept);
cancelThread.Start();

var socket = this.fListeningSocket.Accept();

_accepted.Set();
cancelThread.Join();
_accepted = null;

return new Connection(socket);
}
}

void CancelAccept()
{
if (_accepted.WaitOne(TimeSpan.FromSeconds(20)))
return;

fListeningSocket.Close();
}
}

Expand Down
10 changes: 7 additions & 3 deletions Source/RemObjects.InternetPack/FtpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,16 +1161,20 @@ public static void Cmd_PASV(Object sender, CommandEventArgs e)
lSession.PassiveServer = new SimpleServer();

lSession.PassiveServer.Binding.Address = ((IPEndPoint)e.Connection.LocalEndPoint).Address;
lSession.PassiveServer.Open();
if (!lSession.PassiveServer.Open())
{
e.Connection.WriteLine("421 Can't create socket");
return;
}
}
lSession.Passive = true;

Byte[] lAddress;
#if FULLFRAMEWORK
lAddress = ((IPEndPoint)lSession.PassiveServer.Binding.ListeningSocket.LocalEndPoint).Address.GetAddressBytes();
lAddress = lSession.PassiveServer.GetLocalEndpointAddress().GetAddressBytes();
#endif
#if COMPACTFRAMEWORK
IPAddress lIPAddress = ((IPEndPoint)lSession.PassiveServer.Binding.ListeningSocket.LocalEndPoint).Address;
IPAddress lIPAddress = lSession.PassiveServer.GetLocalEndpointAddress();
String[] lIPAddressstr = lIPAddress.ToString().Split(new Char[] {'.'});
lAddress = new Byte[lIPAddressstr.Length];
for (Int32 i = 0; i < lIPAddressstr.Length; i++)
Expand Down
68 changes: 65 additions & 3 deletions Source/RemObjects.InternetPack/SimpleServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ Using this code requires a valid license of the RemObjects Internet Pack
which can be obtained at http://www.remobjects.com?ip.
---------------------------------------------------------------------------*/

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;

namespace RemObjects.InternetPack
{
public class SimpleServer
{
public static readonly SimplePortPool Pool = new SimplePortPool();
public static IPAddress LocalEndpointIpAddress;
public SimpleServer()
{
this.fBinding = new ServerBinding();
Expand All @@ -29,10 +34,27 @@ public ServerBinding Binding
private ServerBinding fBinding;
#endregion

public void Open()
public bool Open()
{
this.Binding.BindUnthreaded();
this.Binding.ListeningSocket.Listen(this.Binding.MaxWaitConnections);
var retries = 3;
while (retries > 0)
{
try
{
this.Binding.Port = Pool.GetNextSocketPort();
this.Binding.BindUnthreaded();
this.Binding.ListeningSocket.Listen(this.Binding.MaxWaitConnections);
break;
}
catch (SocketException)
{
this.Binding.Unbind();
}

--retries;
}

return retries > 0;
}

public void Close()
Expand All @@ -44,5 +66,45 @@ public Connection WaitForConnection()
{
return this.Binding.Accept();
}

public IPAddress GetLocalEndpointAddress()
{
return LocalEndpointIpAddress ?? ((IPEndPoint)Binding.ListeningSocket.LocalEndPoint).Address;
}

public Int32 GetLocalEndpointPort()
{
return ((IPEndPoint) Binding.ListeningSocket.LocalEndPoint).Port;
}
}

public class SimplePortPool
{
int _minPort = 5000;
int _maxPort = 5010;
int _nextPort;

public void SetPortRange(int min, int max)
{
if (min >= max)
throw new InvalidOperationException();

_minPort = min;
_maxPort = max;

}

[MethodImpl(MethodImplOptions.Synchronized)]
public int GetNextSocketPort()
{
if (_minPort > _maxPort)
throw new InvalidOperationException("Max port should be greater than min port");

if (_nextPort < _minPort || _maxPort < _nextPort)
_nextPort = _minPort;
var port = _nextPort;
++_nextPort;
return port;
}
}
}