Exemple #1
0
 public void NotifySessionQuit(TcpSession s)
 {
     PurifyConsumer.Push(s);
 }
Exemple #2
0
 private static async Task onCron(UInt16 id, TcpSession session, byte[] buffer)
 {
     String buf = System.Text.Encoding.Default.GetString(buffer);
     await session.send(buf, id);
 }
Exemple #3
0
        public void Start()
        {
            var Success = false;

            try
            {
                IsRunningValue.Update
                (
                    b =>
                {
                    if (b)
                    {
                        throw new InvalidOperationException();
                    }

                    if (BindingsValue.Length == 0)
                    {
                        throw new Exception("NoValidBinding");
                    }

                    ListeningTaskTokenSource = new CancellationTokenSource();

                    var ListeningTaskToken = ListeningTaskTokenSource.Token;

                    Action <TcpSession> Purify = StoppingSession =>
                    {
                        SessionSets.DoAction
                        (
                            ss =>
                        {
                            if (ss.Sessions.Contains(StoppingSession))
                            {
                                ss.Sessions.Remove(StoppingSession);
                                var IpAddress = StoppingSession.RemoteEndPoint.Address;
                                var isi       = ss.IpSessions[IpAddress];
                                if (isi.Authenticated.Contains(StoppingSession))
                                {
                                    isi.Authenticated.Remove(StoppingSession);
                                }
                                isi.Count -= 1;
                                if (isi.Count == 0)
                                {
                                    ss.IpSessions.Remove(IpAddress);
                                }
                            }
                        }
                        );
                        StoppingSession.Dispose();
                    };

                    Action <Socket> Accept = a =>
                    {
                        IPEndPoint ep;
                        try
                        {
                            ep = (IPEndPoint)(a.RemoteEndPoint);
                        }
                        catch
                        {
                            a.Dispose();
                            return;
                        }
                        var s = new TcpSession(this, new StreamedAsyncSocket(a, UnauthenticatedSessionIdleTimeoutValue, QueueUserWorkItem), ep, VirtualTransportServerFactory, QueueUserWorkItem);

                        if (MaxConnectionsValue.HasValue && (SessionSets.Check(ss => ss.Sessions.Count) >= MaxConnectionsValue.Value))
                        {
                            PurifyConsumer.DoOne();
                        }
                        if (MaxConnectionsValue.HasValue && (SessionSets.Check(ss => ss.Sessions.Count) >= MaxConnectionsValue.Value))
                        {
                            try
                            {
                                s.Start();
                                OnMaxConnectionsExceeded(s);
                            }
                            finally
                            {
                                s.Dispose();
                            }
                            return;
                        }

                        if (MaxConnectionsPerIPValue.HasValue && (SessionSets.Check(ss => ss.IpSessions.ContainsKey(ep.Address) ? ss.IpSessions[ep.Address].Count : 0) >= MaxConnectionsPerIPValue.Value))
                        {
                            try
                            {
                                s.Start();
                                OnMaxConnectionsPerIPExceeded(s);
                            }
                            finally
                            {
                                PurifyConsumer.Push(s);
                            }
                            return;
                        }

                        if (MaxUnauthenticatedPerIPValue.HasValue && (SessionSets.Check(ss => ss.IpSessions.ContainsKey(ep.Address) ? ss.IpSessions[ep.Address].Count : 0) >= MaxUnauthenticatedPerIPValue.Value))
                        {
                            try
                            {
                                s.Start();
                                OnMaxConnectionsPerIPExceeded(s);
                            }
                            finally
                            {
                                PurifyConsumer.Push(s);
                            }
                            return;
                        }

                        SessionSets.DoAction
                        (
                            ss =>
                        {
                            ss.Sessions.Add(s);
                            if (ss.IpSessions.ContainsKey(ep.Address))
                            {
                                ss.IpSessions[ep.Address].Count += 1;
                            }
                            else
                            {
                                var isi    = new IpSessionInfo();
                                isi.Count += 1;
                                ss.IpSessions.Add(ep.Address, isi);
                            }
                        }
                        );

                        s.Start();
                    };
                    AcceptConsumer = new AsyncConsumer <Socket>(QueueUserWorkItem, a => { Accept(a); return(true); }, int.MaxValue);

                    var Exceptions = new List <Exception>();
                    foreach (var Binding in BindingsValue)
                    {
                        Func <Socket> CreateSocket = () =>
                        {
                            var s = new Socket(Binding.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                            return(s);
                        };

                        var Socket = CreateSocket();

                        try
                        {
                            Socket.Bind(Binding);
                        }
                        catch (SocketException ex)
                        {
                            Exceptions.Add(ex);
                            continue;
                        }
                        Socket.Listen(MaxConnectionsValue.HasValue ? (MaxConnectionsValue.Value + 1) : 128);

                        var BindingInfo      = new BindingInfo();
                        BindingInfo.EndPoint = Binding;
                        BindingInfo.Socket   = new LockedVariable <Socket>(Socket);
                        Func <SocketAsyncEventArgs, Boolean> Completed = args =>
                        {
                            try
                            {
                                if (ListeningTaskToken.IsCancellationRequested)
                                {
                                    return(false);
                                }
                                if (args.SocketError == SocketError.Success)
                                {
                                    var a = args.AcceptSocket;
                                    AcceptConsumer.Push(a);
                                }
                                else
                                {
                                    BindingInfo.Socket.Update
                                    (
                                        OriginalSocket =>
                                    {
                                        try
                                        {
                                            OriginalSocket.Dispose();
                                        }
                                        catch (Exception)
                                        {
                                        }
                                        var NewSocket = CreateSocket();
                                        NewSocket.Bind(Binding);
                                        NewSocket.Listen(MaxConnectionsValue.HasValue ? (MaxConnectionsValue.Value + 1) : 128);
                                        return(NewSocket);
                                    }
                                    );
                                }
                            }
                            finally
                            {
                                args.Dispose();
                            }
                            BindingInfo.Start();
                            return(true);
                        };
                        BindingInfo.ListenConsumer = new AsyncConsumer <SocketAsyncEventArgs>(QueueUserWorkItem, Completed, 1);
                        BindingInfo.Start          = () =>
                        {
                            var EventArgs        = new SocketAsyncEventArgs();
                            var bs               = BindingInfo.Socket.Check(s => s);
                            EventArgs.Completed += (o, args) =>
                            {
                                if (ListeningTaskToken.IsCancellationRequested)
                                {
                                    return;
                                }
                                BindingInfo.ListenConsumer.Push(args);
                            };
                            try
                            {
                                if (!bs.AcceptAsync(EventArgs))
                                {
                                    BindingInfo.ListenConsumer.Push(EventArgs);
                                }
                            }
                            catch (ObjectDisposedException)
                            {
                            }
                        };

                        BindingInfos.Add(BindingInfo);
                    }
                    if (BindingInfos.Count == 0)
                    {
                        throw new AggregateException(Exceptions);
                    }

                    PurifyConsumer = new AsyncConsumer <TcpSession>(PurifierQueueUserWorkItem, s => { Purify(s); return(true); }, int.MaxValue);

                    foreach (var BindingInfo in BindingInfos)
                    {
                        BindingInfo.Start();
                    }

                    Success = true;

                    return(true);
                }
                );
            }
            finally
            {
                if (!Success)
                {
                    Stop();
                }
            }
        }
Exemple #4
0
 private static void connectCallback(TcpSession session)
 {
     System.Console.WriteLine("connect close : {0}", session.ID);
 }