Exemplo n.º 1
0
 public void Connect()
 {
     IsRunningValue.Update
     (
         b =>
     {
         if (b)
         {
             throw new InvalidOperationException();
         }
         return(true);
     }
     );
     using (var h = new AutoResetEvent(false))
     {
         Exception Exception = null;
         Action    Completed = () =>
         {
             h.Set();
         };
         Action <Exception> Faulted = ex =>
         {
             Exception = ex;
             h.Set();
         };
         Socket.ConnectAsync(RemoteEndPoint, Completed, Faulted);
         h.WaitOne();
         if (Exception != null)
         {
             throw new AggregateException(Exception);
         }
     }
 }
Exemplo n.º 2
0
        private void OnShutdownWrite()
        {
            HttpWriteContext PairWriteContext = null;

            WriteContext.Update(c =>
            {
                PairWriteContext = c;
                return(null);
            });
            if (PairWriteContext != null)
            {
                HandleRawWrite(PairWriteContext.ListenerContext, PairWriteContext.NewSessionId, PairWriteContext.Query);
            }
        }
Exemplo n.º 3
0
        public void Stop()
        {
            StopInner();
            Boolean Done = false;

            Socket.Update
            (
                s =>
            {
                if (s != null)
                {
                    try
                    {
                        s.Shutdown(SocketShutdown.Both);
                    }
                    catch
                    {
                    }
                    try
                    {
                        s.Close();
                    }
                    catch
                    {
                    }
                    try
                    {
                        s.Dispose();
                    }
                    catch
                    {
                    }
                    Done = true;
                }
                return(null);
            }
            );
            if (Done)
            {
                Server.NotifySessionQuit((TSession)this);
            }
        }
Exemplo n.º 4
0
        private void OnShutdownRead()
        {
            HttpReadContext PairContext = null;

            ReadContext.Update(c =>
            {
                PairContext = c;
                return(null);
            });
            if (PairContext != null)
            {
                if (PairContext.ListenerContext != null)
                {
                    PairContext.ListenerContext.Response.StatusCode = 400;
                    PairContext.ListenerContext.Response.Close();
                }
                if (PairContext.OnFailure != null)
                {
                    PairContext.OnFailure();
                }
            }
        }
Exemplo n.º 5
0
 public void Connect()
 {
     IsRunningValue.Update
     (
         b =>
     {
         if (b)
         {
             throw new InvalidOperationException();
         }
         return(true);
     }
     );
     if (RemoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
     {
         Socket.Bind(new IPEndPoint(IPAddress.Any, 0));
     }
     else
     {
         Socket.Bind(new IPEndPoint(IPAddress.IPv6Any, 0));
     }
 }
Exemplo n.º 6
0
        private void HandleRawWrite(HttpListenerContext ListenerContext, String NewSessionId, Dictionary <String, String> Query)
        {
            var jo = new JObject();

            jo["commands"]  = new JArray(vts.TakeWriteBuffer());
            jo["sessionid"] = new JValue(NewSessionId);
            var Result = jo.ToString(Formatting.None);
            {
                if (Query.ContainsKey("callback"))
                {
                    var CallbackName = Query["callback"];
                    Result = "{0}({1});".Formats(CallbackName, Result);
                }
            }
            var Bytes = TextEncoding.UTF8.GetBytes(Result);

            ListenerContext.Response.StatusCode = 200;
            ListenerContext.Response.AddHeader("Accept-Ranges", "none");
            ListenerContext.Response.ContentEncoding = System.Text.Encoding.UTF8;
            ListenerContext.Response.ContentLength64 = Bytes.Length;
            ListenerContext.Response.ContentType     = "application/json; charset=utf-8";
            using (var OutputStream = ListenerContext.Response.OutputStream.AsWritable())
            {
                try
                {
                    OutputStream.Write(Bytes);
                }
                catch
                {
                }
            }
            try
            {
                ListenerContext.Response.Close();
            }
            catch
            {
            }

            LastActiveTimeValue.Update(v => DateTime.UtcNow);
        }
Exemplo n.º 7
0
        public static void TestHttpForNumUser(String UrlPrefix, String ServiceVirtualPath, int NumUser, String Title, Action <int, int, ClientContext, IApplicationClient, Action> Test, Action <int, int, ClientContext, IApplicationClient, Action> InitializeClientContext = null, Action <ClientContext[]> FinalCheck = null)
        {
            Console.Write("{0}: ", Title);
            Console.Out.Flush();

            var tl         = new List <Task>();
            var bcl        = new List <Http.HttpClient>();
            var ccl        = new List <ClientContext>();
            var vConnected = new LockedVariable <int>(0);
            var vCompleted = new LockedVariable <int>(0);
            var Check      = new AutoResetEvent(false);

            var vError = new LockedVariable <int>(0);

            for (int k = 0; k < NumUser; k += 1)
            {
                var n      = k;
                var Lockee = new Object();
                var a      = new JsonSerializationClientAdapter();
                var ac     = a.GetApplicationClient();
                var vtc    = new Http.JsonHttpPacketClient(a);
                var bc     = new Http.HttpClient(UrlPrefix, ServiceVirtualPath, vtc);
                var cc     = new ClientContext();
                ac.Error += e =>
                {
                    var m = e.Message;
                    Console.WriteLine(m);
                };
                Action Completed;
                if (Test == TestQuit)
                {
                    Completed = () =>
                    {
                        vCompleted.Update(i => i + 1);
                        Check.Set();
                    };
                }
                else
                {
                    Completed = () =>
                    {
                        ac.Quit(new QuitRequest {
                        }).ContinueWith(tt =>
                        {
                            vCompleted.Update(i => i + 1);
                            Check.Set();
                        });
                    };
                }
                if (InitializeClientContext != null)
                {
                    InitializeClientContext(NumUser, n, cc, ac, Completed);
                }
                try
                {
                    ac.ServerTime(new ServerTimeRequest {
                    }).ContinueWith(tt =>
                    {
                        vConnected.Update(i => i + 1);
                        Check.Set();
                    });
                }
                catch (Exception ex)
                {
                    Console.WriteLine(String.Format("{0}:{1}", n, ex.Message));
                    Completed();
                }
                var t = new Task
                        (
                    () =>
                {
                    try
                    {
                        Test(NumUser, n, cc, ac, Completed);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(String.Format("{0}:{1}", n, ex.Message));
                        Completed();
                    }
                }
                        );
                tl.Add(t);
                bcl.Add(bc);
                ccl.Add(cc);
            }

            while (vConnected.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }

            var Time = Environment.TickCount;

            foreach (var t in tl)
            {
                t.Start();
            }

            while (vCompleted.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }

            var TimeDiff = Environment.TickCount - Time;

            Task.WaitAll(tl.ToArray());
            foreach (var t in tl)
            {
                t.Dispose();
            }

            foreach (var bc in bcl)
            {
                bc.Dispose();
            }

            if (FinalCheck != null)
            {
                FinalCheck(ccl.ToArray());
            }

            var NumError = vError.Check(v => v);

            if (NumError > 0)
            {
                Console.WriteLine("{0} Errors", NumError);
            }
            Console.WriteLine("{0} Users, {1} ms", NumUser, TimeDiff);
        }
Exemplo n.º 8
0
        public static void TestHttpForNumUser(String UrlPrefix, String ServiceVirtualPath, int NumRequestPerUser, int NumUser, String Title, Action <int, int, ClientContext, IApplicationClient, Action> Test)
        {
            Console.Write("{0}: ", Title);
            Console.Out.Flush();

            var tll        = new Object();
            var tl         = new List <Task>();
            var bcl        = new List <Http.HttpClient>();
            var ccl        = new List <ClientContext>();
            var vConnected = new LockedVariable <int>(0);
            var vCompleted = new LockedVariable <int>(0);
            var Check      = new AutoResetEvent(false);

            var vError = new LockedVariable <int>(0);

            for (int k = 0; k < NumUser; k += 1)
            {
                Action Completed = null;

                var n      = k;
                var Lockee = new Object();
                var a      = new JsonSerializationClientAdapter();
                var ac     = a.GetApplicationClient();
                var vtc    = new Http.JsonHttpPacketClient(a);
                var bc     = new Http.HttpClient(UrlPrefix, ServiceVirtualPath, vtc);
                var cc     = new ClientContext();
                ac.Error += e =>
                {
                    var m = e.Message;
                    Console.WriteLine(m);
                };
                Action <Exception> HandleError = ex =>
                {
                    int OldValue = 0;
                    vError.Update(v =>
                    {
                        OldValue = v;
                        return(v + 1);
                    });
                    if (OldValue <= 10)
                    {
                        Console.WriteLine(String.Format("{0}:{1}", n, ex.Message));
                    }
                    vCompleted.Update(i => i + 1);
                    Check.Set();
                };
                try
                {
                    ac.ServerTime(new ServerTimeRequest {
                    }).ContinueWith(tt =>
                    {
                        vConnected.Update(i => i + 1);
                        Check.Set();
                    });
                }
                catch (Exception ex)
                {
                    HandleError(ex);
                }
                Action f = () =>
                {
                    try
                    {
                        Test(NumUser, n, cc, ac, Completed);
                    }
                    catch (Exception ex)
                    {
                        HandleError(ex);
                    }
                };
                var t = new Task(f);
                lock (tll)
                {
                    tl.Add(t);
                }
                bcl.Add(bc);
                ccl.Add(cc);

                int RequestCount = NumRequestPerUser;
                Completed = () =>
                {
                    if (RequestCount > 0)
                    {
                        RequestCount -= 1;
                        var tt = new Task(f);
                        lock (tll)
                        {
                            tl.Add(t);
                        }
                        tt.Start();
                        return;
                    }
                    ac.Quit(new QuitRequest {
                    }).ContinueWith(tt =>
                    {
                        vCompleted.Update(i => i + 1);
                        Check.Set();
                    });
                };
            }

            while (vConnected.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }

            var Time = Environment.TickCount;

            lock (tll)
            {
                foreach (var t in tl)
                {
                    t.Start();
                }
            }

            while (vCompleted.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }

            var TimeDiff = Environment.TickCount - Time;

            Task.WaitAll(tl.ToArray());
            foreach (var t in tl)
            {
                t.Dispose();
            }

            foreach (var bc in bcl)
            {
                bc.Dispose();
            }

            var NumError = vError.Check(v => v);

            if (NumError > 0)
            {
                Console.WriteLine("{0} Errors", NumError);
            }
            Console.WriteLine("{0} Users, {1} Request/User, {2} ms", NumUser, NumRequestPerUser, TimeDiff);
        }
Exemplo n.º 9
0
        public Boolean Push(IPEndPoint RemoteEndPoint, int Index, int[] Indices, Byte[] Buffer, int Offset, int Length)
        {
            var SessionId = this.SessionId;
            var Time      = DateTime.UtcNow;

            if ((Indices != null) && (Indices.Length > 0))
            {
                var l = new List <Byte[]>();
                CookedWritingContext.DoAction(c =>
                {
                    c.Parts.Acknowledge(Indices.First(), Indices.Skip(1), c.WritenIndex);
                });
            }
            {
                var l = new List <Byte[]>();
                CookedWritingContext.DoAction(c =>
                {
                    c.Parts.ForEachTimedoutPacket(SessionId, Time, (i, d, ResentCount) =>
                    {
                        l.Add(d);
                        if (Server.ServerContext.EnableLogTransport)
                        {
                            Server.ServerContext.RaiseSessionLog(new SessionLogEntry {
                                Token = SessionId.ToString("X8"), RemoteEndPoint = RemoteEndPoint, Time = DateTime.UtcNow, Type = "UdpTransport", Name = "Resend", Message = "Index: " + i.ToInvariantString() + " Length: " + d.Length.ToInvariantString() + " Count: " + ResentCount.ToInvariantString()
                            });
                        }
                    });
                });
                foreach (var p in l)
                {
                    try
                    {
                        SendPacket(RemoteEndPoint, p);
                    }
                    catch
                    {
                        return(false);
                    }
                }
            }

            var Pushed = false;
            var Parts  = new List <Part>();
            Action <StreamedVirtualTransportServerHandleResult[]> OnSuccess = null;
            Action OnFailure = null;

            RawReadingContext.DoAction(c =>
            {
                if (c.Parts.HasPart(Index))
                {
                    Pushed = true;
                    return;
                }
                Pushed = c.Parts.TryPushPart(Index, Buffer, Offset, Length);
                if (Pushed)
                {
                    c.NotAcknowledgedIndices.Add(Index);
                    var Acknowledged = new List <int>();
                    foreach (var i in c.NotAcknowledgedIndices)
                    {
                        if (c.Parts.IsEqualOrAfter(c.Parts.MaxHandled, i))
                        {
                            Acknowledged.Add(i);
                        }
                    }
                    foreach (var i in Acknowledged)
                    {
                        c.NotAcknowledgedIndices.Remove(i);
                    }

                    if ((c.OnSuccess != null) && (c.OnFailure != null))
                    {
                        while (true)
                        {
                            var p = c.Parts.TryTakeFirstPart();
                            if (p == null)
                            {
                                break;
                            }
                            Parts.Add(p);
                        }

                        if (Parts.Count > 0)
                        {
                            OnSuccess   = c.OnSuccess;
                            OnFailure   = c.OnFailure;
                            c.OnSuccess = null;
                            c.OnFailure = null;
                        }
                    }
                }
            });

            if (Pushed)
            {
                LastActiveTimeValue.Update(v => DateTime.UtcNow);
            }
            if (Parts.Count > 0)
            {
                HandleRawRead(Parts, OnSuccess, OnFailure);
            }
            return(Pushed);
        }
Exemplo n.º 10
0
        public static void TestUdpForNumUser(IPEndPoint RemoteEndPoint, SerializationProtocolType ProtocolType, int NumUser, String Title, Action <int, int, ClientContext, IApplicationClient, Action> Test, Action <int, int, ClientContext, IApplicationClient, Action> InitializeClientContext = null, Action <ClientContext[]> FinalCheck = null)
        {
            Console.Write("{0}: ", Title);
            Console.Out.Flush();

            var tl         = new List <Task>();
            var bcl        = new List <UdpClient>();
            var ccl        = new List <ClientContext>();
            var tmrl       = new List <Timer>();
            var vConnected = new LockedVariable <int>(0);
            var vCompleted = new LockedVariable <int>(0);
            var Check      = new AutoResetEvent(false);

            var bAbondon = new LockedVariable <Boolean>(false);

            var vError = new LockedVariable <int>(0);

            for (int k = 0; k < NumUser; k += 1)
            {
                var n      = k;
                var Lockee = new Object();
                IApplicationClient ac;
                IStreamedVirtualTransportClient vtc;
                if (ProtocolType == SerializationProtocolType.Binary)
                {
                    var a = new BinarySerializationClientAdapter();
                    ac  = a.GetApplicationClient();
                    vtc = new BinaryCountPacketClient(a);
                }
                else if (ProtocolType == SerializationProtocolType.Json)
                {
                    var a = new JsonSerializationClientAdapter();
                    ac  = a.GetApplicationClient();
                    vtc = new JsonLinePacketClient(a);
                }
                else
                {
                    throw new InvalidOperationException();
                }
                var    bc         = new UdpClient(RemoteEndPoint, vtc, QueueUserWorkItem);
                var    cc         = new ClientContext();
                var    bCompleted = new LockedVariable <Boolean>(false);
                Action Completed;
                Action FaultedCompleted;
                if (Test == TestQuit)
                {
                    Completed = () =>
                    {
                        bCompleted.Update(b => true);
                        vCompleted.Update(i => i + 1);
                        Check.Set();
                    };
                    FaultedCompleted = Completed;
                }
                else
                {
                    Completed = () =>
                    {
                        ac.Quit(new QuitRequest {
                        }).ContinueWith(tt =>
                        {
                            bCompleted.Update(b => true);
                            vCompleted.Update(i => i + 1);
                            Check.Set();
                        });
                    };
                    FaultedCompleted = () =>
                    {
                        bCompleted.Update(b => true);
                        vCompleted.Update(i => i + 1);
                        Check.Set();
                    };
                }

                ac.Error += e =>
                {
                    var m = e.Message;
                    Console.WriteLine(m);
                };
                if (InitializeClientContext != null)
                {
                    InitializeClientContext(NumUser, n, cc, ac, Completed);
                }
                bc.Connect();
                Action <Exception> UnknownFaulted = ex =>
                {
                    int OldValue = 0;
                    vError.Update(v =>
                    {
                        OldValue = v;
                        return(v + 1);
                    });
                    if (OldValue <= 10)
                    {
                        Console.WriteLine(String.Format("{0}:{1}", n, ex.Message));
                    }
                    FaultedCompleted();
                };
                bc.ReceiveAsync
                (
                    a =>
                {
                    a();
                },
                    UnknownFaulted
                );
                ac.ServerTime(new ServerTimeRequest {
                }).ContinueWith(tt =>
                {
                    vConnected.Update(i => i + 1);
                    Check.Set();
                });
                var t = new Task
                        (
                    () =>
                {
                    Test(NumUser, n, cc, ac, Completed);
                }
                        );
                var tmr = new Timer
                          (
                    o =>
                {
                    if (!bAbondon.Check(b => b))
                    {
                        return;
                    }
                    if (bCompleted.Check(b => b))
                    {
                        return;
                    }
                    int OldValue = 0;
                    vError.Update(v =>
                    {
                        OldValue = v;
                        return(v + 1);
                    });
                    if (OldValue <= 10)
                    {
                        Console.WriteLine(String.Format("{0}:{1}", n, "Timedout"));
                    }
                    FaultedCompleted();
                },
                    null,
                    10000,
                    10000
                          );
                tl.Add(t);
                bcl.Add(bc);
                ccl.Add(cc);
                tmrl.Add(tmr);
            }

            while (vConnected.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }

            var Time = Environment.TickCount;

            foreach (var t in tl)
            {
                t.Start();
            }

            while (vCompleted.Check(i => i != NumUser))
            {
                if (!Check.WaitOne(10000))
                {
                    if (vCompleted.Check(i => i > 0))
                    {
                        bAbondon.Update(b => true);
                        break;
                    }
                }
            }

            var NumMutualWaiting = NumUser - vCompleted.Check(i => i);

            while (vCompleted.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }
            foreach (var tmr in tmrl)
            {
                tmr.Dispose();
            }

            var TimeDiff = Environment.TickCount - Time;

            Task.WaitAll(tl.ToArray());
            foreach (var t in tl)
            {
                t.Dispose();
            }

            foreach (var bc in bcl)
            {
                bc.Dispose();
            }

            if (FinalCheck != null)
            {
                FinalCheck(ccl.ToArray());
            }

            var NumError = vError.Check(v => v);

            if (NumError > 0)
            {
                Console.WriteLine("{0} Errors", NumError);
            }
            if (NumMutualWaiting > 0)
            {
                Console.WriteLine("{0} Users, {1} ms, {2} MutualWaiting", NumUser, TimeDiff, NumMutualWaiting);
            }
            else
            {
                Console.WriteLine("{0} Users, {1} ms", NumUser, TimeDiff);
            }
        }
Exemplo n.º 11
0
        /// <summary>接收消息</summary>
        /// <param name="DoResultHandle">运行处理消息函数,应保证不多线程同时访问BinarySocketClient</param>
        /// <param name="UnknownFaulted">未知错误处理函数</param>
        public void ReceiveAsync(Action <Action> DoResultHandle, Action <Exception> UnknownFaulted)
        {
            Action <Exception> Faulted = ex =>
            {
                if (!IsRunningValue.Check(b => b) && IsSocketErrorKnown(ex))
                {
                    return;
                }
                UnknownFaulted(ex);
            };

            Action <Byte[]> CompletedSocket = Buffer =>
            {
                Action a = () =>
                {
                    if (Buffer.Length < 12)
                    {
                        return;
                    }
                    var SessionId    = Buffer[0] | ((Int32)(Buffer[1]) << 8) | ((Int32)(Buffer[2]) << 16) | ((Int32)(Buffer[3]) << 24);
                    var Flag         = Buffer[4] | ((Int32)(Buffer[5]) << 8);
                    var Index        = Buffer[6] | ((Int32)(Buffer[7]) << 8);
                    var Verification = Buffer[8] | ((Int32)(Buffer[9]) << 8) | ((Int32)(Buffer[10]) << 16) | ((Int32)(Buffer[11]) << 24);
                    Buffer[8]  = 0;
                    Buffer[9]  = 0;
                    Buffer[10] = 0;
                    Buffer[11] = 0;
                    //Debug.WriteLine(Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + " Receive SessionId: " + SessionId.ToString("X8") + " Index: " + Index.ToString());

                    var IsEncrypted   = (Flag & 2) != 0;
                    var SecureContext = this.SecureContext;
                    if ((SecureContext != null) != IsEncrypted)
                    {
                        return;
                    }

                    if (IsEncrypted)
                    {
                        var Key       = SecureContext.ServerToken.Concat(Cryptography.SHA256(Buffer.Skip(4).Take(4)));
                        var HMACBytes = Cryptography.HMACSHA256Simple(Key, Buffer).Take(4).ToArray();
                        var HMAC      = HMACBytes[0] | ((Int32)(HMACBytes[1]) << 8) | ((Int32)(HMACBytes[2]) << 16) | ((Int32)(HMACBytes[3]) << 24);
                        if (HMAC != Verification)
                        {
                            return;
                        }
                    }
                    else
                    {
                        //如果Flag中不包含ENC,则验证CRC32
                        if (Cryptography.CRC32(Buffer) != Verification)
                        {
                            return;
                        }

                        //只有尚未连接时可以设定
                        var Close = false;
                        ConnectionStateValue.Update(v =>
                        {
                            if (v == ConnectionState.Connecting)
                            {
                                this.SessionId = SessionId;
                                return(ConnectionState.Connected);
                            }
                            else
                            {
                                if (SessionId != this.SessionId)
                                {
                                    Close = true;
                                }
                                return(v);
                            }
                        });
                        if (Close)
                        {
                            return;
                        }
                    }

                    var   Offset  = 12;
                    int[] Indices = null;
                    if ((Flag & 1) != 0)
                    {
                        if (Buffer.Length < 14)
                        {
                            return;
                        }
                        var NumIndex = Buffer[Offset] | ((Int32)(Buffer[Offset + 1]) << 8);
                        if (Buffer.Length < 14 + NumIndex * 2)
                        {
                            return;
                        }
                        if (NumIndex > WritingWindowSize) //若Index数量较大,则丢弃包
                        {
                            return;
                        }
                        Offset += 2;
                        Indices = new int[NumIndex];
                        for (int k = 0; k < NumIndex; k += 1)
                        {
                            Indices[k] = Buffer[Offset + k * 2] | ((Int32)(Buffer[Offset + k * 2 + 1]) << 8);
                        }
                        Offset += NumIndex * 2;
                    }

                    var Length = Buffer.Length - Offset;

                    if ((Indices != null) && (Indices.Length > 0))
                    {
                        CookedWritingContext.DoAction(c =>
                        {
                            c.Parts.Acknowledge(Indices.First(), Indices.Skip(1), c.WritenIndex);
                        });
                    }

                    var Pushed = false;
                    var Parts  = new List <Byte[]>();
                    RawReadingContext.DoAction(c =>
                    {
                        if (c.Parts.HasPart(Index))
                        {
                            Pushed = true;
                            return;
                        }
                        Pushed = c.Parts.TryPushPart(Index, Buffer, Offset, Length);
                        if (Pushed)
                        {
                            c.NotAcknowledgedIndices.Add(Index);
                            var Acknowledged = new List <int>();
                            foreach (var i in c.NotAcknowledgedIndices)
                            {
                                if (c.Parts.IsEqualOrAfter(c.Parts.MaxHandled, i))
                                {
                                    Acknowledged.Add(i);
                                }
                            }
                            foreach (var i in Acknowledged)
                            {
                                c.NotAcknowledgedIndices.Remove(i);
                            }

                            while (true)
                            {
                                var p = c.Parts.TryTakeFirstPart();
                                if (p == null)
                                {
                                    break;
                                }
                                Parts.Add(p.Data);
                            }
                        }
                    });

                    foreach (var p in Parts)
                    {
                        var ReadBuffer       = VirtualTransportClient.GetReadBuffer();
                        var ReadBufferLength = ReadBuffer.Offset + ReadBuffer.Count;
                        if (p.Length > ReadBuffer.Array.Length - ReadBufferLength)
                        {
                            Faulted(new InvalidOperationException());
                            return;
                        }
                        Array.Copy(p, 0, ReadBuffer.Array, ReadBufferLength, p.Length);

                        var c = p.Length;
                        while (true)
                        {
                            var r = VirtualTransportClient.Handle(c);
                            if (r.OnContinue)
                            {
                                break;
                            }
                            else if (r.OnCommand)
                            {
                                DoResultHandle(r.Command.HandleResult);
                                var RemainCount = VirtualTransportClient.GetReadBuffer().Count;
                                if (RemainCount <= 0)
                                {
                                    break;
                                }
                                c = 0;
                            }
                            else
                            {
                                throw new InvalidOperationException();
                            }
                        }
                    }
                };
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    a();
                }
                else
                {
                    try
                    {
                        a();
                    }
                    catch (Exception ex)
                    {
                        UnknownFaulted(ex);
                    }
                }
            };

            Action Receive = null;
            EventHandler <SocketAsyncEventArgs> Completed = (sender, e) =>
            {
                if (e.SocketError != SocketError.Success)
                {
                    e.Dispose();
                    Faulted(new SocketException((int)(e.SocketError)));
                    return;
                }
                var Count  = e.BytesTransferred;
                var Buffer = new Byte[Count];
                Array.Copy(e.Buffer, Buffer, Count);
                e.Dispose();
                CompletedSocket(Buffer);
                Buffer = null;
                Receive();
            };

            Receive = () =>
            {
                if (!IsRunning)
                {
                    return;
                }

                var ServerEndPoint = this.RemoteEndPoint;
                var ae             = new SocketAsyncEventArgs();
                ae.RemoteEndPoint = ServerEndPoint;
                ae.SetBuffer(ReadBuffer, 0, ReadBuffer.Length);
                ae.Completed += Completed;
                try
                {
                    var willRaiseEvent = Socket.ReceiveFromAsync(ae);
                    if (!willRaiseEvent)
                    {
                        QueueUserWorkItem(() => Completed(null, ae));
                    }
                }
                catch (Exception ex)
                {
                    ae.Dispose();
                    Faulted(ex);
                    return;
                }
            };

            Receive();
        }
Exemplo n.º 12
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;

                    foreach (var Binding in BindingsValue)
                    {
                        Listener.Prefixes.Add(Binding);
                    }
                    if (SessionIdleTimeoutValue.HasValue)
                    {
                        SetTimer(Listener, SessionIdleTimeoutValue.Value);
                    }
                    Action <HttpListenerContext> PurifyContext = ListenerContext =>
                    {
                        try
                        {
                            ListenerContext.Response.Close();
                        }
                        catch
                        {
                        }
                    };

                    Action <HttpListenerContext> Accept = a =>
                    {
                        IPEndPoint e = null;
                        try
                        {
                            e = (IPEndPoint)a.Request.RemoteEndPoint;
                            var XForwardedFor = a.Request.Headers["X-Forwarded-For"];
                            var Address       = e.Address;
                            if (XForwardedFor != null)
                            {
                                try
                                {
                                    Address = IPAddress.Parse(XForwardedFor.Split(',')[0].Trim(' '));
                                }
                                catch
                                {
                                }
                            }
                            var XForwardedPort = a.Request.Headers["X-Forwarded-Port"];
                            var Port           = e.Port;
                            if (XForwardedPort != null)
                            {
                                try
                                {
                                    Port = int.Parse(XForwardedPort.Split(',')[0].Trim(' '));
                                }
                                catch
                                {
                                }
                            }
                            e = new IPEndPoint(Address, Port);

                            if (ServerContext.EnableLogSystem)
                            {
                                ServerContext.RaiseSessionLog(new SessionLogEntry {
                                    Token = "", RemoteEndPoint = e, Time = DateTime.UtcNow, Type = "Sys", Name = "RequestIn", Message = ""
                                });
                            }

                            if (a.Request.ContentLength64 < 0)
                            {
                                a.Response.StatusCode = 411;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            if (a.Request.ContentLength64 > ReadBufferSize)
                            {
                                a.Response.StatusCode = 413;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            var oRelativePath = MatchBindingNameAndGetRelativePath(a.Request.Url);
                            if (oRelativePath.OnNone)
                            {
                                a.Response.StatusCode = 404;
                                NotifyListenerContextQuit(a);
                                return;
                            }
                            var RelativePath = oRelativePath.Value;

                            var Headers = a.Request.Headers.AllKeys.ToDictionary(k => k, k => a.Request.Headers[k]);
                            if (Headers.ContainsKey("Accept-Charset"))
                            {
                                var AcceptCharsetParts = Headers["Accept-Charset"].Split(';');
                                if (AcceptCharsetParts.Length == 0)
                                {
                                    a.Response.StatusCode = 400;
                                    NotifyListenerContextQuit(a);
                                    return;
                                }
                                var EncodingNames = AcceptCharsetParts[0].Split(',').Select(n => n.Trim(' ')).ToArray();
                                if (!(EncodingNames.Contains("utf-8", StringComparer.OrdinalIgnoreCase) || EncodingNames.Contains("*", StringComparer.OrdinalIgnoreCase)))
                                {
                                    a.Response.StatusCode = 400;
                                    NotifyListenerContextQuit(a);
                                    return;
                                }
                            }

                            if (RequestHandler != null)
                            {
                                RequestHandler(RelativePath, a, e, () => NotifyListenerContextQuit(a), ex =>
                                {
                                    if (ServerContext.EnableLogSystem)
                                    {
                                        ServerContext.RaiseSessionLog(new SessionLogEntry {
                                            Token = "", RemoteEndPoint = e, Time = DateTime.UtcNow, Type = "Sys", Name = "Exception", Message = ExceptionInfo.GetExceptionInfo(ex)
                                        });
                                    }
                                    NotifyListenerContextQuit(a);
                                });
                            }
                            else
                            {
                                NotifyListenerContextQuit(a);
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ServerContext.EnableLogSystem)
                            {
                                ServerContext.RaiseSessionLog(new SessionLogEntry {
                                    Token = "", RemoteEndPoint = e ?? new IPEndPoint(IPAddress.Any, 0), Time = DateTime.UtcNow, Type = "Sys", Name = "Exception", Message = ExceptionInfo.GetExceptionInfo(ex)
                                });
                            }
                            try
                            {
                                a.Response.StatusCode = 500;
                            }
                            catch
                            {
                            }
                            NotifyListenerContextQuit(a);
                        }
                    };
                    AcceptConsumer = new AsyncConsumer <HttpListenerContext>(QueueUserWorkItem, a => { Accept(a); return(true); }, int.MaxValue);

                    ContextPurifyConsumer = new AsyncConsumer <HttpListenerContext>(QueueUserWorkItem, l => { PurifyContext(l); return(true); }, int.MaxValue);

                    try
                    {
                        Listener.Start();
                    }
                    catch (HttpListenerException ex)
                    {
                        String Message;
                        if (ex.ErrorCode == 5)
                        {
                            var l = new List <String>();
                            l.Add("Under Windows, try run the following as administrator:");
                            var UserDomainName = Environment.UserDomainName;
                            var UserName       = Environment.UserName;
                            foreach (var p in BindingsValue)
                            {
                                l.Add(@"netsh http add urlacl url={0} user={1}\{2}".Formats(p, UserDomainName, UserName));
                            }
                            l.Add("and delete it when you don't need it:");
                            foreach (var p in BindingsValue)
                            {
                                l.Add(@"netsh http delete urlacl url={0}".Formats(p));
                            }
                            Message = String.Join("\r\n", l.ToArray());
                        }
                        else
                        {
                            Message = ExceptionInfo.GetExceptionInfo(ex);
                        }
                        throw new AggregateException(Message, ex);
                    }
                    Action Listen = () =>
                    {
                        if (ListeningTaskToken.IsCancellationRequested)
                        {
                            return;
                        }
                        var l  = Listener;
                        var lc = ListenConsumer;
                        l.BeginGetContext(ar =>
                        {
                            if (!l.IsListening)
                            {
                                return;
                            }
                            try
                            {
                                var a = l.EndGetContext(ar);
                                AcceptConsumer.Push(a);
                            }
                            catch (HttpListenerException)
                            {
                            }
                            lc.Push(0);
                        }, null);
                    };
                    ListenConsumer = new AsyncConsumer <int>(QueueUserWorkItem, i => { Listen(); return(true); }, 1);

                    Listen();

                    Success = true;

                    return(true);
                }
                );
            }
            finally
            {
                if (!Success)
                {
                    Stop();
                }
            }
        }
Exemplo n.º 13
0
        private void DoAsync(SocketAsyncOperation OperationIdentifier, Func <SocketAsyncEventArgs, Boolean> Operation, Func <SocketAsyncEventArgs, Action> ResultToCompleted, Action <Exception> Faulted)
        {
            var Context = new AsyncOperationContext();

            if (!TryLockAsyncOperation(OperationIdentifier, Context))
            {
                Context.Dispose();
                Faulted(new SocketException((int)(SocketError.Shutdown)));
                return;
            }
            var Success = false;

            try
            {
                Context.ResultToCompleted = ResultToCompleted;
                Context.Faulted           = Faulted;
                var TimeoutSeconds = this.TimeoutSeconds;
                if (TimeoutSeconds.HasValue)
                {
                    var IsCompleted = new LockedVariable <Boolean>(false);
                    var Timer       = new Timer(o => { if (!IsCompleted.Check(b => b))
                                                       {
                                                           if (TimedOut != null)
                                                           {
                                                               TimedOut();
                                                           }
                                                       }
                                                }, null, TimeoutSeconds.Value * 1000, Timeout.Infinite);
                    Context.ReleaseAsyncOperation = () =>
                    {
                        IsCompleted.Update(b => true);
                        if (Timer != null)
                        {
                            Timer.Dispose();
                            Timer = null;
                        }
                        ReleaseAsyncOperation(OperationIdentifier);
                    };
                }
                else
                {
                    Context.ReleaseAsyncOperation = () => ReleaseAsyncOperation(OperationIdentifier);
                }
                Success = true;
            }
            finally
            {
                if (!Success)
                {
                    ReleaseAsyncOperation(OperationIdentifier);
                }
            }
            Success = false;
            Exception Exception = null;

            try
            {
                bool willRaiseEvent = Operation(Context.EventArgs);
                if (!willRaiseEvent)
                {
                    QueueUserWorkItem(Context.DoOnCompletion);
                }
                Success = true;
            }
            catch (ObjectDisposedException)
            {
                Exception = new SocketException((int)(SocketError.OperationAborted));
            }
            finally
            {
                if (!Success)
                {
                    Context.ReleaseAsyncOperation();
                }
            }
            if (Exception != null)
            {
                Faulted(Exception);
            }
        }
Exemplo n.º 14
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;

                    foreach (var Binding in BindingsValue)
                    {
                        Listener.Prefixes.Add(Binding);
                    }
                    if (UnauthenticatedSessionIdleTimeoutValue.HasValue)
                    {
                        SetTimer(Listener, UnauthenticatedSessionIdleTimeoutValue.Value);
                    }

                    Action <HttpListenerContext> PurifyContext = ListenerContext =>
                    {
                        try
                        {
                            ListenerContext.Response.Close();
                        }
                        catch
                        {
                        }
                    };
                    Action <HttpSession> 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);
                                }
                                var SessionId = ss.SessionToId[StoppingSession];
                                ss.SessionIdToSession.Remove(SessionId);
                                ss.SessionToId.Remove(StoppingSession);
                            }
                        }
                        );
                        StoppingSession.Dispose();
                    };

                    Action <HttpListenerContext> Accept = a =>
                    {
                        IPEndPoint e = null;
                        try
                        {
                            e = (IPEndPoint)a.Request.RemoteEndPoint;
                            var XForwardedFor = a.Request.Headers["X-Forwarded-For"];
                            var Address       = e.Address;
                            if ((XForwardedFor != null) && (XForwardedFor != ""))
                            {
                                try
                                {
                                    IPAddress addr;
                                    if (IPAddress.TryParse(XForwardedFor.Split(',')[0].Trim(' '), out addr))
                                    {
                                        Address = addr;
                                    }
                                }
                                catch
                                {
                                }
                            }
                            var XForwardedPort = a.Request.Headers["X-Forwarded-Port"];
                            var Port           = e.Port;
                            if ((XForwardedPort != null) && (XForwardedPort != ""))
                            {
                                try
                                {
                                    int p;
                                    if (int.TryParse(XForwardedPort.Split(',')[0].Trim(' '), out p))
                                    {
                                        Port = p;
                                    }
                                }
                                catch
                                {
                                }
                            }
                            e = new IPEndPoint(Address, Port);

                            if (ServerContext.EnableLogSystem)
                            {
                                ServerContext.RaiseSessionLog(new SessionLogEntry {
                                    Token = "", RemoteEndPoint = e, Time = DateTime.UtcNow, Type = "Sys", Name = "RequestIn", Message = ""
                                });
                            }

                            if (a.Request.ContentLength64 < 0)
                            {
                                a.Response.StatusCode = 411;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            if (a.Request.ContentLength64 > ReadBufferSize)
                            {
                                a.Response.StatusCode = 413;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            if (!IsMatchBindingName(a.Request.Url))
                            {
                                a.Response.StatusCode = 404;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            var Headers = a.Request.Headers.AllKeys.ToDictionary(k => k, k => a.Request.Headers[k]);
                            if (Headers.ContainsKey("Range"))
                            {
                                a.Response.StatusCode = 400;
                                NotifyListenerContextQuit(a);
                                return;
                            }
                            if (Headers.ContainsKey("Accept-Charset"))
                            {
                                var AcceptCharsetParts = Headers["Accept-Charset"].Split(';');
                                if (AcceptCharsetParts.Length == 0)
                                {
                                    a.Response.StatusCode = 400;
                                    NotifyListenerContextQuit(a);
                                    return;
                                }
                                var EncodingNames = AcceptCharsetParts[0].Split(',').Select(n => n.Trim(' ')).ToArray();
                                if (!(EncodingNames.Contains("utf-8", StringComparer.OrdinalIgnoreCase) || EncodingNames.Contains("*", StringComparer.OrdinalIgnoreCase)))
                                {
                                    a.Response.StatusCode = 400;
                                    NotifyListenerContextQuit(a);
                                    return;
                                }
                            }

                            {
                                var Query = HttpListenerRequestExtension.GetQuery(a.Request);

                                if (Query.ContainsKey("sessionid"))
                                {
                                    HttpSession s = null;

                                    var SessionId = Query["sessionid"];
                                    var Close     = false;
                                    SessionSets.DoAction
                                    (
                                        ss =>
                                    {
                                        if (!ss.SessionIdToSession.ContainsKey(SessionId))
                                        {
                                            a.Response.StatusCode = 403;
                                            Close = true;
                                            return;
                                        }
                                        var CurrentSession = ss.SessionIdToSession[SessionId];
                                        if (!CurrentSession.RemoteEndPoint.Address.Equals(e.Address))
                                        {
                                            a.Response.StatusCode = 403;
                                            Close = true;
                                            return;
                                        }
                                        s = ss.SessionIdToSession[SessionId];
                                    }
                                    );
                                    if (Close)
                                    {
                                        NotifyListenerContextQuit(a);
                                        return;
                                    }
                                    var NewSessionId = Convert.ToBase64String(Cryptography.CreateRandom(64));
                                    SessionSets.DoAction
                                    (
                                        ss =>
                                    {
                                        ss.SessionIdToSession.Remove(SessionId);
                                        ss.SessionIdToSession.Add(NewSessionId, s);
                                        ss.SessionToId[s] = NewSessionId;
                                    }
                                    );
                                    if (!s.Push(a, NewSessionId))
                                    {
                                        NotifyListenerContextQuit(a);
                                        return;
                                    }
                                    return;
                                }
                            }

                            if (MaxConnectionsValue.HasValue && (SessionSets.Check(ss => ss.Sessions.Count) >= MaxConnectionsValue.Value))
                            {
                                ContextPurifyConsumer.DoOne();
                                PurifyConsumer.DoOne();
                            }
                            if (MaxConnectionsValue.HasValue && (SessionSets.Check(ss => ss.Sessions.Count) >= MaxConnectionsValue.Value))
                            {
                                a.Response.StatusCode = 503;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            if (MaxConnectionsPerIPValue.HasValue && (SessionSets.Check(ss => ss.IpSessions.ContainsKey(e.Address) ? ss.IpSessions[e.Address].Count : 0) >= MaxConnectionsPerIPValue.Value))
                            {
                                a.Response.StatusCode = 503;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            if (MaxUnauthenticatedPerIPValue.HasValue && (SessionSets.Check(ss => ss.IpSessions.ContainsKey(e.Address) ? (ss.IpSessions[e.Address].Count - ss.IpSessions[e.Address].Authenticated.Count) : 0) >= MaxUnauthenticatedPerIPValue.Value))
                            {
                                a.Response.StatusCode = 503;
                                NotifyListenerContextQuit(a);
                                return;
                            }

                            {
                                var s = new HttpSession(this, e, VirtualTransportServerFactory, QueueUserWorkItem);

                                var SessionId = Convert.ToBase64String(Cryptography.CreateRandom(64));
                                SessionSets.DoAction
                                (
                                    ss =>
                                {
                                    ss.Sessions.Add(s);
                                    if (ss.IpSessions.ContainsKey(e.Address))
                                    {
                                        ss.IpSessions[e.Address].Count += 1;
                                    }
                                    else
                                    {
                                        var isi    = new IpSessionInfo();
                                        isi.Count += 1;
                                        ss.IpSessions.Add(e.Address, isi);
                                    }
                                    ss.SessionIdToSession.Add(SessionId, s);
                                    ss.SessionToId.Add(s, SessionId);
                                }
                                );

                                s.Start();
                                if (!s.Push(a, SessionId))
                                {
                                    NotifyListenerContextQuit(a);
                                    return;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ServerContext.EnableLogSystem)
                            {
                                ServerContext.RaiseSessionLog(new SessionLogEntry {
                                    Token = "", RemoteEndPoint = e ?? new IPEndPoint(IPAddress.Any, 0), Time = DateTime.UtcNow, Type = "Sys", Name = "Exception", Message = ExceptionInfo.GetExceptionInfo(ex)
                                });
                            }
                            try
                            {
                                a.Response.StatusCode = 500;
                            }
                            catch
                            {
                            }
                            NotifyListenerContextQuit(a);
                        }
                    };
                    AcceptConsumer = new AsyncConsumer <HttpListenerContext>(QueueUserWorkItem, a => { Accept(a); return(true); }, int.MaxValue);

                    ContextPurifyConsumer = new AsyncConsumer <HttpListenerContext>(QueueUserWorkItem, l => { PurifyContext(l); return(true); }, int.MaxValue);
                    PurifyConsumer        = new AsyncConsumer <HttpSession>(PurifierQueueUserWorkItem, s => { Purify(s); return(true); }, int.MaxValue);

                    if (UnauthenticatedSessionIdleTimeoutValue.HasValue || SessionIdleTimeoutValue.HasValue)
                    {
                        var TimePeriod           = TimeSpan.FromSeconds(Math.Max(TimeoutCheckPeriodValue, 1));
                        LastActiveTimeCheckTimer = new Timer(state =>
                        {
                            if (UnauthenticatedSessionIdleTimeoutValue.HasValue)
                            {
                                var CheckTime = DateTime.UtcNow.AddIntSeconds(-UnauthenticatedSessionIdleTimeoutValue.Value);
                                SessionSets.DoAction
                                (
                                    ss =>
                                {
                                    foreach (var s in ss.Sessions)
                                    {
                                        var IpAddress = s.RemoteEndPoint.Address;
                                        var isi       = ss.IpSessions[IpAddress];
                                        if (!isi.Authenticated.Contains(s))
                                        {
                                            if (s.LastActiveTime < CheckTime)
                                            {
                                                PurifyConsumer.Push(s);
                                            }
                                        }
                                    }
                                }
                                );
                            }

                            if (SessionIdleTimeoutValue.HasValue)
                            {
                                var CheckTime = DateTime.UtcNow.AddIntSeconds(-SessionIdleTimeoutValue.Value);
                                SessionSets.DoAction
                                (
                                    ss =>
                                {
                                    foreach (var s in ss.Sessions)
                                    {
                                        var IpAddress = s.RemoteEndPoint.Address;
                                        var isi       = ss.IpSessions[IpAddress];
                                        if (isi.Authenticated.Contains(s))
                                        {
                                            if (s.LastActiveTime < CheckTime)
                                            {
                                                PurifyConsumer.Push(s);
                                            }
                                        }
                                    }
                                }
                                );
                            }
                        }, null, TimePeriod, TimePeriod);
                    }

                    try
                    {
                        Listener.Start();
                    }
                    catch (HttpListenerException ex)
                    {
                        String Message;
                        if (ex.ErrorCode == 5)
                        {
                            var l = new List <String>();
                            l.Add("Under Windows, try run the following as administrator:");
                            var UserDomainName = Environment.UserDomainName;
                            var UserName       = Environment.UserName;
                            foreach (var p in BindingsValue)
                            {
                                l.Add(@"netsh http add urlacl url={0} user={1}\{2}".Formats(p, UserDomainName, UserName));
                            }
                            l.Add("and delete it when you don't need it:");
                            foreach (var p in BindingsValue)
                            {
                                l.Add(@"netsh http delete urlacl url={0}".Formats(p));
                            }
                            Message = String.Join("\r\n", l.ToArray());
                        }
                        else
                        {
                            Message = ExceptionInfo.GetExceptionInfo(ex);
                        }
                        throw new AggregateException(Message, ex);
                    }
                    Action Listen = () =>
                    {
                        if (ListeningTaskToken.IsCancellationRequested)
                        {
                            return;
                        }
                        var l  = Listener;
                        var lc = ListenConsumer;
                        l.BeginGetContext(ar =>
                        {
                            if (!l.IsListening)
                            {
                                return;
                            }
                            try
                            {
                                var a = l.EndGetContext(ar);
                                AcceptConsumer.Push(a);
                            }
                            catch (HttpListenerException)
                            {
                            }
                            catch (ObjectDisposedException)
                            {
                            }
                            lc.Push(0);
                        }, null);
                    };
                    ListenConsumer = new AsyncConsumer <int>(QueueUserWorkItem, i => { Listen(); return(true); }, 1);

                    Listen();

                    Success = true;

                    return(true);
                }
                );
            }
            finally
            {
                if (!Success)
                {
                    Stop();
                }
            }
        }
Exemplo n.º 15
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();
                }
            }
        }
Exemplo n.º 16
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 <UdpSession> 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);
                                }
                                var SessionId = StoppingSession.SessionId;
                                ss.SessionIdToSession.Remove(SessionId);
                            }
                        }
                        );
                        StoppingSession.Dispose();
                    };

                    Action <AcceptingInfo> Accept = a =>
                    {
                        var ep       = a.RemoteEndPoint;
                        UdpSession s = null;

                        try
                        {
                            var Buffer = a.ReadBuffer;
                            if (Buffer.Length < 12)
                            {
                                return;
                            }
                            var SessionId    = Buffer[0] | ((Int32)(Buffer[1]) << 8) | ((Int32)(Buffer[2]) << 16) | ((Int32)(Buffer[3]) << 24);
                            var Flag         = Buffer[4] | ((Int32)(Buffer[5]) << 8);
                            var Index        = Buffer[6] | ((Int32)(Buffer[7]) << 8);
                            var Verification = Buffer[8] | ((Int32)(Buffer[9]) << 8) | ((Int32)(Buffer[10]) << 16) | ((Int32)(Buffer[11]) << 24);
                            Buffer[8]        = 0;
                            Buffer[9]        = 0;
                            Buffer[10]       = 0;
                            Buffer[11]       = 0;
                            if (ServerContext.EnableLogTransport)
                            {
                                //按Flag中是否包含AUX分别生成日志
                                if ((Flag & 8) != 0)
                                {
                                    ServerContext.RaiseSessionLog(new SessionLogEntry {
                                        Token = SessionId.ToString("X8"), RemoteEndPoint = ep, Time = DateTime.UtcNow, Type = "UdpTransport", Name = "ReceiveAux", Message = "AckIndex: " + Index.ToInvariantString() + " Length: " + Buffer.Length.ToInvariantString()
                                    });
                                }
                                else
                                {
                                    ServerContext.RaiseSessionLog(new SessionLogEntry {
                                        Token = SessionId.ToString("X8"), RemoteEndPoint = ep, Time = DateTime.UtcNow, Type = "UdpTransport", Name = "Receive", Message = "Index: " + Index.ToInvariantString() + " Length: " + Buffer.Length.ToInvariantString()
                                    });
                                }
                            }

                            //如果Flag中不包含ENC,则验证CRC32
                            if ((Flag & 2) == 0)
                            {
                                if (Cryptography.CRC32(Buffer) != Verification)
                                {
                                    if (ServerContext.EnableLogTransport)
                                    {
                                        ServerContext.RaiseSessionLog(new SessionLogEntry {
                                            Token = SessionId.ToString("X8"), RemoteEndPoint = ep, Time = DateTime.UtcNow, Type = "UdpTransport", Name = "Receive", Message = "Index: " + Index.ToInvariantString() + " CRC32Failed"
                                        });
                                    }
                                    return;
                                }
                            }

                            //如果Flag中包含INI,则初始化
                            if ((Flag & 4) != 0)
                            {
                                if ((Flag & 1) != 0)
                                {
                                    return;
                                }
                                if ((Flag & 2) != 0)
                                {
                                    return;
                                }
                                if ((Flag & 8) != 0)
                                {
                                    return;
                                }
                                var Offset = 12;

                                s         = new UdpSession(this, a.Socket, ep, VirtualTransportServerFactory, QueueUserWorkItem);
                                SessionId = s.SessionId;

                                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 - ss.IpSessions[ep.Address].Authenticated.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);
                                    }
                                    while ((SessionId == 0) || ss.SessionIdToSession.ContainsKey(SessionId))
                                    {
                                        s         = new UdpSession(this, a.Socket, ep, VirtualTransportServerFactory, QueueUserWorkItem);
                                        SessionId = s.SessionId;
                                    }
                                    ss.SessionIdToSession.Add(SessionId, s);
                                }
                                );

                                s.Start();
                                s.PrePush(() =>
                                {
                                    if (!s.Push(ep, Index, null, Buffer, Offset, Buffer.Length - Offset))
                                    {
                                        PurifyConsumer.Push(s);
                                    }
                                });
                            }
                            else
                            {
                                var Close = false;
                                SessionSets.DoAction
                                (
                                    ss =>
                                {
                                    if (!ss.SessionIdToSession.ContainsKey(SessionId))
                                    {
                                        Close = true;
                                        return;
                                    }
                                    s = ss.SessionIdToSession[SessionId];
                                }
                                );
                                if (Close)
                                {
                                    return;
                                }

                                s.PrePush(() =>
                                {
                                    var IsEncrypted       = (Flag & 2) != 0;
                                    var NextSecureContext = s.NextSecureContext;
                                    var SecureContext     = s.SecureContext;
                                    if ((SecureContext == null) && (NextSecureContext != null))
                                    {
                                        s.SecureContext     = NextSecureContext;
                                        s.NextSecureContext = null;
                                        SecureContext       = NextSecureContext;
                                        NextSecureContext   = null;
                                    }
                                    if ((SecureContext != null) != IsEncrypted)
                                    {
                                        return;
                                    }
                                    if (IsEncrypted)
                                    {
                                        var Key       = SecureContext.ClientToken.Concat(Cryptography.SHA256(Buffer.Skip(4).Take(4)));
                                        var HMACBytes = Cryptography.HMACSHA256Simple(Key, Buffer).Take(4).ToArray();
                                        var HMAC      = HMACBytes[0] | ((Int32)(HMACBytes[1]) << 8) | ((Int32)(HMACBytes[2]) << 16) | ((Int32)(HMACBytes[3]) << 24);
                                        if (HMAC != Verification)
                                        {
                                            if (ServerContext.EnableLogTransport)
                                            {
                                                ServerContext.RaiseSessionLog(new SessionLogEntry {
                                                    Token = SessionId.ToString("X8"), RemoteEndPoint = ep, Time = DateTime.UtcNow, Type = "UdpTransport", Name = "Receive", Message = "Index: " + Index.ToInvariantString() + " HMACFailed"
                                                });
                                            }
                                            return;
                                        }
                                    }

                                    var Offset    = 12;
                                    int[] Indices = null;
                                    if ((Flag & 1) != 0)
                                    {
                                        if (Buffer.Length < 14)
                                        {
                                            return;
                                        }
                                        var NumIndex = Buffer[Offset] | ((Int32)(Buffer[Offset + 1]) << 8);
                                        if (Buffer.Length < 14 + NumIndex * 2)
                                        {
                                            return;
                                        }
                                        if (NumIndex > UdpSession.WritingWindowSize)     //若Index数量较大,则丢弃包
                                        {
                                            return;
                                        }
                                        Offset += 2;
                                        Indices = new int[NumIndex];
                                        for (int k = 0; k < NumIndex; k += 1)
                                        {
                                            Indices[k] = Buffer[Offset + k * 2] | ((Int32)(Buffer[Offset + k * 2 + 1]) << 8);
                                        }
                                        Offset += NumIndex * 2;
                                    }

                                    //如果Flag中包含AUX,则判断
                                    if ((Flag & 8) != 0)
                                    {
                                        if (Indices == null)
                                        {
                                            return;
                                        }
                                        if (Indices.Length < 1)
                                        {
                                            return;
                                        }
                                        if (Index != Indices[0])
                                        {
                                            return;
                                        }
                                        if (Offset != Buffer.Length)
                                        {
                                            return;
                                        }
                                    }

                                    var PreviousRemoteEndPoint = s.RemoteEndPoint;
                                    if (!PreviousRemoteEndPoint.Equals(ep))
                                    {
                                        SessionSets.DoAction
                                        (
                                            ss =>
                                        {
                                            var Authenticated = false;
                                            {
                                                var PreviousIpAddress = PreviousRemoteEndPoint.Address;
                                                var isi = ss.IpSessions[PreviousIpAddress];
                                                if (isi.Authenticated.Contains(s))
                                                {
                                                    isi.Authenticated.Remove(s);
                                                    Authenticated = true;
                                                }
                                                isi.Count -= 1;
                                                if (isi.Count == 0)
                                                {
                                                    ss.IpSessions.Remove(PreviousIpAddress);
                                                }
                                            }

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

                                            s.RemoteEndPoint = ep;
                                        }
                                        );
                                    }

                                    if ((Flag & 8) != 0)
                                    {
                                        if (!s.PushAux(ep, Indices))
                                        {
                                            PurifyConsumer.Push(s);
                                        }
                                    }
                                    else
                                    {
                                        if (!s.Push(ep, Index, Indices, Buffer, Offset, Buffer.Length - Offset))
                                        {
                                            PurifyConsumer.Push(s);
                                        }
                                    }
                                });
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ServerContext.EnableLogSystem)
                            {
                                ServerContext.RaiseSessionLog(new SessionLogEntry {
                                    Token = "", RemoteEndPoint = ep, Time = DateTime.UtcNow, Type = "Sys", Name = "Exception", Message = ExceptionInfo.GetExceptionInfo(ex)
                                });
                            }
                            if (s != null)
                            {
                                PurifyConsumer.Push(s);
                            }
                        }
                    };
                    AcceptConsumer = new AsyncConsumer <AcceptingInfo>(QueueUserWorkItem, a => { Accept(a); return(true); }, int.MaxValue);

                    var Exceptions = new List <Exception>();
                    var Bindings   = new List <IPEndPoint>();
                    //将所有默认地址换为实际的所有接口地址
                    foreach (var Binding in BindingsValue)
                    {
                        if (IPAddress.Equals(Binding.Address, IPAddress.Any) || IPAddress.Equals(Binding.Address, IPAddress.IPv6Any))
                        {
                            foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
                            {
                                foreach (var a in ni.GetIPProperties().UnicastAddresses)
                                {
                                    if (a.Address.AddressFamily == Binding.Address.AddressFamily)
                                    {
                                        Bindings.Add(new IPEndPoint(a.Address, Binding.Port));
                                    }
                                }
                            }
                        }
                        else
                        {
                            Bindings.Add(Binding);
                        }
                    }
                    foreach (var Binding in Bindings)
                    {
                        Func <Socket> CreateSocket = () =>
                        {
                            var s = new Socket(Binding.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                            //在Windows下关闭SIO_UDP_CONNRESET报告,防止接受数据出错
                            //http://support.microsoft.com/kb/263823/en-us
                            if (System.Environment.OSVersion.Platform == PlatformID.Win32NT)
                            {
                                uint IOC_IN            = 0x80000000;
                                uint IOC_VENDOR        = 0x18000000;
                                uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
                                s.IOControl(unchecked ((int)(SIO_UDP_CONNRESET)), new byte[] { Convert.ToByte(false) }, null);
                            }
                            return(s);
                        };

                        var Socket = CreateSocket();

                        try
                        {
                            Socket.Bind(Binding);
                        }
                        catch (SocketException ex)
                        {
                            Exceptions.Add(ex);
                            continue;
                        }

                        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 Count      = args.BytesTransferred;
                                    var ReadBuffer = new Byte[Count];
                                    Array.Copy(BindingInfo.ReadBuffer, ReadBuffer, Count);
                                    var a = new AcceptingInfo {
                                        Socket = BindingInfo.Socket.Check(s => s), ReadBuffer = ReadBuffer, RemoteEndPoint = (IPEndPoint)(args.RemoteEndPoint)
                                    };
                                    AcceptConsumer.Push(a);
                                }
                                else
                                {
                                    BindingInfo.Socket.Update
                                    (
                                        OriginalSocket =>
                                    {
                                        try
                                        {
                                            OriginalSocket.Dispose();
                                        }
                                        catch (Exception)
                                        {
                                        }
                                        var NewSocket = CreateSocket();
                                        NewSocket.Bind(Binding);
                                        return(NewSocket);
                                    }
                                    );
                                }
                            }
                            finally
                            {
                                args.Dispose();
                            }
                            BindingInfo.Start();
                            return(true);
                        };
                        BindingInfo.ListenConsumer = new AsyncConsumer <SocketAsyncEventArgs>(QueueUserWorkItem, Completed, 1);
                        BindingInfo.Start          = () =>
                        {
                            var EventArgs            = new SocketAsyncEventArgs();
                            EventArgs.RemoteEndPoint = new IPEndPoint(Binding.Address.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, 0);
                            EventArgs.SetBuffer(BindingInfo.ReadBuffer, 0, BindingInfo.ReadBuffer.Length);
                            var bs = BindingInfo.Socket.Check(s => s);
                            EventArgs.Completed += (o, args) => BindingInfo.ListenConsumer.Push(args);
                            try
                            {
                                if (!bs.ReceiveFromAsync(EventArgs))
                                {
                                    BindingInfo.ListenConsumer.Push(EventArgs);
                                }
                            }
                            catch (ObjectDisposedException)
                            {
                            }
                        };

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

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

                    if (UnauthenticatedSessionIdleTimeoutValue.HasValue || SessionIdleTimeoutValue.HasValue)
                    {
                        var TimePeriod           = TimeSpan.FromSeconds(Math.Max(TimeoutCheckPeriodValue, 1));
                        LastActiveTimeCheckTimer = new Timer(state =>
                        {
                            if (UnauthenticatedSessionIdleTimeoutValue.HasValue)
                            {
                                var CheckTime = DateTime.UtcNow.AddIntSeconds(-UnauthenticatedSessionIdleTimeoutValue.Value);
                                SessionSets.DoAction
                                (
                                    ss =>
                                {
                                    foreach (var s in ss.Sessions)
                                    {
                                        var IpAddress = s.RemoteEndPoint.Address;
                                        var isi       = ss.IpSessions[IpAddress];
                                        if (!isi.Authenticated.Contains(s))
                                        {
                                            if (s.LastActiveTime < CheckTime)
                                            {
                                                PurifyConsumer.Push(s);
                                            }
                                        }
                                    }
                                }
                                );
                            }

                            if (SessionIdleTimeoutValue.HasValue)
                            {
                                var CheckTime = DateTime.UtcNow.AddIntSeconds(-SessionIdleTimeoutValue.Value);
                                SessionSets.DoAction
                                (
                                    ss =>
                                {
                                    foreach (var s in ss.Sessions)
                                    {
                                        var IpAddress = s.RemoteEndPoint.Address;
                                        var isi       = ss.IpSessions[IpAddress];
                                        if (isi.Authenticated.Contains(s))
                                        {
                                            if (s.LastActiveTime < CheckTime)
                                            {
                                                PurifyConsumer.Push(s);
                                            }
                                        }
                                    }
                                }
                                );
                            }
                        }, null, TimePeriod, TimePeriod);
                    }

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

                    Success = true;

                    return(true);
                }
                );
            }
            finally
            {
                if (!Success)
                {
                    Stop();
                }
            }
        }
Exemplo n.º 17
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();
                    AcceptingTaskTokenSource   = new CancellationTokenSource();
                    AcceptingTaskNotifier      = new AutoResetEvent(false);
                    PurifieringTaskTokenSource = new CancellationTokenSource();
                    PurifieringTaskNotifier    = new AutoResetEvent(false);

                    var ListeningTaskToken   = ListeningTaskTokenSource.Token;
                    var AcceptingTaskToken   = AcceptingTaskTokenSource.Token;
                    var PurifieringTaskToken = PurifieringTaskTokenSource.Token;

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

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

                        var BindingInfo = new BindingInfo
                        {
                            Socket = new LockedVariable <Socket>(Socket),
                            Task   = null
                        };
                        var Task = new Task
                                   (
                            () =>
                        {
                            try
                            {
                                while (true)
                                {
                                    if (ListeningTaskToken.IsCancellationRequested)
                                    {
                                        return;
                                    }
                                    try
                                    {
                                        var a = BindingInfo.Socket.Check(s => s).Accept();
                                        AcceptedSockets.Add(a);
                                        AcceptingTaskNotifier.Set();
                                    }
                                    catch (SocketException)
                                    {
                                        if (ListeningTaskToken.IsCancellationRequested)
                                        {
                                            return;
                                        }
                                        BindingInfo.Socket.Update
                                        (
                                            OriginalSocket =>
                                        {
                                            try
                                            {
                                                OriginalSocket.Close();
                                            }
                                            catch (Exception)
                                            {
                                            }
                                            try
                                            {
                                                OriginalSocket.Dispose();
                                            }
                                            catch (Exception)
                                            {
                                            }
                                            var NewSocket = new Socket(Binding.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                                            NewSocket.Bind(Binding);
                                            NewSocket.Listen(MaxConnectionsValue.HasValue ? (MaxConnectionsValue.Value + 1) : 128);
                                            Socket = NewSocket;
                                            return(NewSocket);
                                        }
                                        );
                                    }
                                }
                            }
                            catch (ObjectDisposedException)
                            {
                            }
                        },
                            TaskCreationOptions.LongRunning
                                   );

                        BindingInfo.Task = Task;

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

                    AcceptingTask = new Task
                                    (
                        () =>
                    {
                        while (true)
                        {
                            if (AcceptingTaskToken.IsCancellationRequested)
                            {
                                return;
                            }
                            AcceptingTaskNotifier.WaitOne();
                            while (true)
                            {
                                Socket a;
                                if (!AcceptedSockets.TryTake(out a))
                                {
                                    break;
                                }

                                var s = new TSession()
                                {
                                    Server         = (TServer)this,
                                    RemoteEndPoint = (IPEndPoint)(a.RemoteEndPoint)
                                };
                                if (SessionIdleTimeoutValue.HasValue)
                                {
                                    a.ReceiveTimeout = SessionIdleTimeoutValue.Value * 1000;
                                }
                                s.SetSocket(a);

                                if (MaxConnectionsValue.HasValue && (Sessions.Check(ss => ss.Count) >= MaxConnectionsValue.Value))
                                {
                                    try
                                    {
                                        s.Start();
                                        if (MaxConnectionsExceeded != null)
                                        {
                                            MaxConnectionsExceeded(s);
                                        }
                                    }
                                    finally
                                    {
                                        s.Stop();
                                        s.Dispose();
                                    }
                                    continue;
                                }

                                IPEndPoint e = (IPEndPoint)(a.RemoteEndPoint);
                                if (MaxConnectionsPerIPValue.HasValue && (IpSessions.Check(iss => iss.ContainsKey(e.Address) ? iss[e.Address] : 0) >= MaxConnectionsPerIPValue.Value))
                                {
                                    try
                                    {
                                        s.Start();
                                        if (MaxConnectionsPerIPExceeded != null)
                                        {
                                            MaxConnectionsPerIPExceeded(s);
                                        }
                                    }
                                    finally
                                    {
                                        s.Stop();
                                        s.Dispose();
                                    }
                                    continue;
                                }

                                Sessions.DoAction
                                (
                                    ss =>
                                {
                                    ss.Add(s);
                                }
                                );
                                IpSessions.DoAction
                                (
                                    iss =>
                                {
                                    if (iss.ContainsKey(e.Address))
                                    {
                                        iss[e.Address] += 1;
                                    }
                                    else
                                    {
                                        iss.Add(e.Address, 1);
                                    }
                                }
                                );

                                s.Start();
                            }
                        }
                    },
                        AcceptingTaskToken,
                        TaskCreationOptions.LongRunning
                                    );

                    PurifieringTask = new Task
                                      (
                        () =>
                    {
                        while (true)
                        {
                            if (PurifieringTaskToken.IsCancellationRequested)
                            {
                                return;
                            }

                            PurifieringTaskNotifier.WaitOne();
                            TSession StoppingSession;
                            while (StoppingSessions.TryTake(out StoppingSession))
                            {
                                var Removed = false;
                                Sessions.DoAction
                                (
                                    ss =>
                                {
                                    if (ss.Contains(StoppingSession))
                                    {
                                        ss.Remove(StoppingSession);
                                        Removed = true;
                                    }
                                }
                                );
                                if (Removed)
                                {
                                    var IpAddress = StoppingSession.RemoteEndPoint.Address;
                                    IpSessions.DoAction
                                    (
                                        iss =>
                                    {
                                        if (iss.ContainsKey(IpAddress))
                                        {
                                            iss[IpAddress] -= 1;
                                            if (iss[IpAddress] == 0)
                                            {
                                                iss.Remove(IpAddress);
                                            }
                                        }
                                    }
                                    );
                                }
                                StoppingSession.Stop();
                                StoppingSession.Dispose();
                            }
                        }
                    },
                        PurifieringTaskToken,
                        TaskCreationOptions.LongRunning
                                      );

                    AcceptingTask.Start();
                    PurifieringTask.Start();

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

                    Success = true;

                    return(true);
                }
                );
            }
            finally
            {
                if (!Success)
                {
                    Stop();
                }
            }
        }
Exemplo n.º 18
0
        public static void TestTcpForNumUser(IPEndPoint RemoteEndPoint, SerializationProtocolType ProtocolType, int NumRequestPerUser, int NumUser, String Title, Action <int, int, ClientContext, IApplicationClient, Action> Test)
        {
            Console.Write("{0}: ", Title);
            Console.Out.Flush();

            var tll        = new Object();
            var tl         = new List <Task>();
            var bcl        = new List <TcpClient>();
            var ccl        = new List <ClientContext>();
            var vConnected = new LockedVariable <int>(0);
            var vCompleted = new LockedVariable <int>(0);
            var Check      = new AutoResetEvent(false);

            var vError = new LockedVariable <int>(0);

            for (int k = 0; k < NumUser; k += 1)
            {
                Action Completed = null;

                var n      = k;
                var Lockee = new Object();
                IApplicationClient ac;
                IStreamedVirtualTransportClient vtc;
                if (ProtocolType == SerializationProtocolType.Binary)
                {
                    var a = new BinarySerializationClientAdapter();
                    ac  = a.GetApplicationClient();
                    vtc = new BinaryCountPacketClient(a);
                }
                else if (ProtocolType == SerializationProtocolType.Json)
                {
                    var a = new JsonSerializationClientAdapter();
                    ac  = a.GetApplicationClient();
                    vtc = new JsonLinePacketClient(a);
                }
                else
                {
                    throw new InvalidOperationException();
                }
                var bc = new TcpClient(RemoteEndPoint, vtc, QueueUserWorkItem);
                var cc = new ClientContext();
                ac.Error += e =>
                {
                    var m = e.Message;
                    Console.WriteLine(m);
                };
                bc.Connect();
                Action <Exception> UnknownFaulted = ex =>
                {
                    int OldValue = 0;
                    vError.Update(v =>
                    {
                        OldValue = v;
                        return(v + 1);
                    });
                    if (OldValue <= 10)
                    {
                        Console.WriteLine(String.Format("{0}:{1}", n, ex.Message));
                    }
                    vCompleted.Update(i => i + 1);
                    Check.Set();
                };
                bc.ReceiveAsync
                (
                    a =>
                {
                    a();
                },
                    UnknownFaulted
                );
                ac.ServerTime(new ServerTimeRequest {
                }).ContinueWith(tt =>
                {
                    vConnected.Update(i => i + 1);
                    Check.Set();
                });
                Action f = () =>
                {
                    Test(NumUser, n, cc, ac, Completed);
                };
                var t = new Task(f);
                lock (tll)
                {
                    tl.Add(t);
                }
                bcl.Add(bc);
                ccl.Add(cc);

                int RequestCount = NumRequestPerUser;
                Completed = () =>
                {
                    if (RequestCount > 0)
                    {
                        RequestCount -= 1;
                        var tt = new Task(f);
                        lock (tll)
                        {
                            tl.Add(t);
                        }
                        tt.Start();
                        return;
                    }
                    vCompleted.Update(i => i + 1);
                    Check.Set();
                };
            }

            while (vConnected.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }

            var Time = Environment.TickCount;

            lock (tll)
            {
                foreach (var t in tl)
                {
                    t.Start();
                }
            }

            while (vCompleted.Check(i => i != NumUser))
            {
                Check.WaitOne();
            }

            var TimeDiff = Environment.TickCount - Time;

            Task.WaitAll(tl.ToArray());
            foreach (var t in tl)
            {
                t.Dispose();
            }

            foreach (var bc in bcl)
            {
                bc.Dispose();
            }

            var NumError = vError.Check(v => v);

            if (NumError > 0)
            {
                Console.WriteLine("{0} Errors", NumError);
            }
            Console.WriteLine("{0} Users, {1} Request/User, {2} ms", NumUser, NumRequestPerUser, TimeDiff);
        }
Exemplo n.º 19
0
        public static void Run(Configuration c)
        {
            Console.WriteLine(Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + @"  服务器进程启动。");

            var ProcessorCount  = Environment.ProcessorCount;
            var WorkThreadCount = c.NumThread.OnSome ? Math.Max(1, c.NumThread.Value) : ProcessorCount;

            Console.WriteLine(@"逻辑处理器数量: " + ProcessorCount.ToString());
            Console.WriteLine(@"工作线程数量: {0}".Formats(WorkThreadCount));

            using (var tp = new CountedThreadPool("Worker", WorkThreadCount))
                using (var tpPurifier = new CountedThreadPool("Purifier", 2))
                    using (var tpLog = new CountedThreadPool("Log", 1))
                        using (var ExitEvent = new AutoResetEvent(false))
                            using (var Logger = new ConsoleLogger(tpLog.QueueUserWorkItem))
                            {
                                Logger.Start();

                                LockedVariable <ConsoleCancelEventHandler> CancelKeyPressInner = null;
                                CancelKeyPressInner = new LockedVariable <ConsoleCancelEventHandler>((sender, e) =>
                                {
                                    CancelKeyPressInner.Update(v => { return(null); });
                                    e.Cancel = true;
                                    Console.WriteLine(Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + @"  命令行中断退出。");
                                    ExitEvent.Set();
                                });
                                ConsoleCancelEventHandler CancelKeyPress = (sender, e) =>
                                {
                                    var f = CancelKeyPressInner.Check(v => v);
                                    if (f == null)
                                    {
                                        return;
                                    }
                                    f(sender, e);
                                };
                                Console.CancelKeyPress += CancelKeyPress;

                                var ChatContexts = new List <ServerContext>();

                                var ServerCloses = new List <Action>();

                                try
                                {
                                    foreach (var s in c.Servers)
                                    {
                                        if (s.OnChat)
                                        {
                                            var ss            = s.Chat;
                                            var ServerContext = new ServerContext();
                                            ChatContexts.Add(ServerContext);

                                            ServerContext.EnableLogNormalIn      = c.EnableLogNormalIn;
                                            ServerContext.EnableLogNormalOut     = c.EnableLogNormalOut;
                                            ServerContext.EnableLogUnknownError  = c.EnableLogUnknownError;
                                            ServerContext.EnableLogCriticalError = c.EnableLogCriticalError;
                                            ServerContext.EnableLogPerformance   = c.EnableLogPerformance;
                                            ServerContext.EnableLogSystem        = c.EnableLogSystem;
                                            ServerContext.EnableLogTransport     = c.EnableLogTransport;
                                            ServerContext.ServerDebug            = c.ServerDebug;
                                            ServerContext.ClientDebug            = c.ClientDebug;

                                            ServerContext.Shutdown += () =>
                                            {
                                                Console.WriteLine(Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + @"  远程命令退出。");
                                                ExitEvent.Set();
                                            };
                                            if (c.EnableLogConsole)
                                            {
                                                ServerContext.SessionLog += Logger.Push;
                                            }

                                            var Protocols       = new List <IServer>();
                                            var Factory         = new TaskFactory(tp);
                                            var PurifierFactory = new TaskFactory(tp);
                                            foreach (var p in ss.Protocols)
                                            {
                                                if (System.Diagnostics.Debugger.IsAttached)
                                                {
                                                    Protocols.Add(StartProtocol(c, p, ServerContext, Factory, PurifierFactory));
                                                }
                                                else
                                                {
                                                    try
                                                    {
                                                        Protocols.Add(StartProtocol(c, p, ServerContext, Factory, PurifierFactory));
                                                    }
                                                    catch (Exception ex)
                                                    {
                                                        var Message = Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + "\r\n" + ExceptionInfo.GetExceptionInfo(ex);
                                                        Console.WriteLine(Message);
                                                        FileLoggerSync.WriteLog("Error.log", Message);
                                                    }
                                                }
                                            }

                                            ServerCloses.Add(() =>
                                            {
                                                foreach (var Session in ServerContext.Sessions.AsParallel())
                                                {
                                                    Session.SessionLock.EnterReadLock();;
                                                    try
                                                    {
                                                        if (Session.EventPump != null)
                                                        {
                                                            Session.EventPump.ServerShutdown(new Communication.ServerShutdownEvent {
                                                            });
                                                        }
                                                    }
                                                    finally
                                                    {
                                                        Session.SessionLock.ExitReadLock();
                                                    }
                                                }

                                                foreach (var p in Protocols)
                                                {
                                                    if (System.Diagnostics.Debugger.IsAttached)
                                                    {
                                                        StopProtocol(p);
                                                    }
                                                    else
                                                    {
                                                        try
                                                        {
                                                            StopProtocol(p);
                                                        }
                                                        catch (Exception ex)
                                                        {
                                                            var Message = Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + "\r\n" + ExceptionInfo.GetExceptionInfo(ex);
                                                            Console.WriteLine(Message);
                                                            FileLoggerSync.WriteLog("Error.log", Message);
                                                        }
                                                    }
                                                }

                                                if (c.EnableLogConsole)
                                                {
                                                    ServerContext.SessionLog -= Logger.Push;
                                                }

                                                Console.WriteLine(@"ChatServerContext.RequestCount = {0}".Formats(ServerContext.RequestCount));
                                                Console.WriteLine(@"ChatServerContext.ReplyCount = {0}".Formats(ServerContext.ReplyCount));
                                                Console.WriteLine(@"ChatServerContext.EventCount = {0}".Formats(ServerContext.EventCount));
                                            });
                                        }
                                        else
                                        {
                                            throw new InvalidOperationException("未知服务器类型: " + s._Tag.ToString());
                                        }
                                    }

                                    ExitEvent.WaitOne();
                                    Console.CancelKeyPress -= CancelKeyPress;
                                }
                                finally
                                {
                                    foreach (var a in ServerCloses)
                                    {
                                        a();
                                    }
                                }
                            }

            Console.WriteLine(Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + @"  服务器进程退出完成。");
        }