Example #1
0
 /// <summary>
 /// This should be called in connection thread. Real send data to server. The sending will NOT be done immediately, and we should NOT reuse data before onComplete.
 /// </summary>
 /// <param name="data">data to send.</param>
 /// <param name="cnt">data count in bytes.</param>
 /// <param name="onComplete">this will be called in some other thread.</param>
 public void SendRaw(byte[] data, int cnt, Action <bool> onComplete)
 {
     _LastSendTick = System.Environment.TickCount;
     if (_Socket != null)
     {
         try
         {
             if (_BroadcastEP != null)
             {
                 _Socket.BeginSendTo(data, 0, cnt, SocketFlags.None, _BroadcastEP, ar =>
                 {
                     bool success = false;
                     try
                     {
                         _Socket.EndSendTo(ar);
                         success = true;
                     }
                     catch (Exception e)
                     {
                         PlatDependant.LogError(e);
                     }
                     if (onComplete != null)
                     {
                         onComplete(success);
                     }
                 }, null);
                 return;
             }
             else
             {
                 _Socket.BeginSend(data, 0, cnt, SocketFlags.None, ar =>
                 {
                     bool success = false;
                     try
                     {
                         _Socket.EndSend(ar);
                         success = true;
                     }
                     catch (Exception e)
                     {
                         PlatDependant.LogError(e);
                     }
                     if (onComplete != null)
                     {
                         onComplete(success);
                     }
                 }, null);
                 return;
             }
         }
         catch (Exception e)
         {
             PlatDependant.LogError(e);
         }
     }
     if (onComplete != null)
     {
         onComplete(false);
     }
 }
Example #2
0
 /// <summary>
 /// This should be called in connection thread. Real send data to server. The sending will NOT be done immediately, and we should NOT reuse data before onComplete.
 /// </summary>
 /// <param name="data">data to send.</param>
 /// <param name="cnt">data count in bytes.</param>
 /// <param name="onComplete">this will be called in some other thread.</param>
 public void SendRaw(byte[] data, int cnt, Action <bool> onComplete)
 {
     if (_Socket != null)
     {
         try
         {
             _Socket.BeginSend(data, 0, cnt, SocketFlags.None, ar =>
             {
                 bool success = false;
                 try
                 {
                     _Socket.EndSend(ar);
                     success = true;
                 }
                 catch (Exception e)
                 {
                     PlatDependant.LogError(e);
                 }
                 if (onComplete != null)
                 {
                     onComplete(success);
                 }
             }, null);
             return;
         }
         catch (Exception e)
         {
             PlatDependant.LogError(e);
         }
     }
     if (onComplete != null)
     {
         onComplete(false);
     }
 }
 public object Read(out uint seq, out uint sseq, out uint type)
 {
     try
     {
         while (_Client != null && _Client.IsConnectionAlive)
         {
             _Splitter.ReadBlock();
             if (_PendingRead.Obj != null)
             {
                 var obj = _PendingRead.Obj;
                 seq              = _PendingRead.Seq;
                 sseq             = _PendingRead.SSeq;
                 type             = _PendingRead.Type;
                 _PendingRead.Obj = null;
                 return(obj);
             }
         }
     }
     catch (Exception e)
     {
         PlatDependant.LogError(e);
     }
     seq  = 0;
     sseq = 0;
     type = 0;
     return(null);
 }
Example #4
0
        protected void FireReceiveBlock(NativeBufferStream buffer, int size, uint type, uint flags, uint seq, uint sseq)
        {
#if DEBUG_PERSIST_CONNECT
            PlatDependant.LogInfo(string.Format("Data Received, length {0}, type {1}, flags {2:x}, seq {3}, sseq {4}. (from {5})", size, type, flags, seq, sseq, this.GetType().Name));
#endif
            //buffer.Seek(0, SeekOrigin.Begin);
            OnReceiveBlock(buffer, size, type, flags, seq, sseq);
        }
Example #5
0
 public void StartConnect()
 {
     if (!IsConnectionAlive)
     {
         _ConnectWorkRunning = true;
         PlatDependant.RunBackground(prog => ConnectWork());
     }
 }
Example #6
0
        protected override void ConnectWork()
        {
            try
            {
                var address4 = IPAddress.Any;
                _Socket = new Socket(address4.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                _Socket.Bind(new IPEndPoint(address4, _Port));
                _Socket.Listen(CONST.MAX_SERVER_PENDING_CONNECTIONS);

                var address6 = IPAddress.IPv6Any;
                _Socket6 = new Socket(address6.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                _Socket6.Bind(new IPEndPoint(address6, _Port));
                _Socket6.Listen(CONST.MAX_SERVER_PENDING_CONNECTIONS);

                BeginAccept4();
                BeginAccept6();

                while (!_ConnectWorkCanceled)
                {
                    _HaveDataToSend.WaitOne();
                }

                //_Socket.Shutdown(SocketShutdown.Both);
                //_Socket6.Shutdown(SocketShutdown.Both);
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception e)
            {
                PlatDependant.LogError(e);
            }
            finally
            {
                _ConnectWorkRunning  = false;
                _ConnectWorkCanceled = false;
                if (_PreDispose != null)
                {
                    _PreDispose(this);
                }
                if (_Socket != null)
                {
                    _Socket.Close();
                    _Socket = null;
                }
                if (_Socket6 != null)
                {
                    _Socket6.Close();
                    _Socket6 = null;
                }
                // set handlers to null.
                _OnReceive      = null;
                _OnSend         = null;
                _OnSendComplete = null;
                _PreDispose     = null;
            }
        }
Example #7
0
        private void Init(string url, uint conv)
        {
            if (conv == 0)
            {
                PlatDependant.LogError("KCP conversation id should not be 0.");
            }
            _Connection       = new UDPClient(url);
            _Conv             = conv;
            _ConnectionHandle = GCHandle.Alloc(_Connection);
            _KCP = KCPLib.kcp_create(conv, (IntPtr)_ConnectionHandle);

            _KCP.kcp_setoutput(Func_KCPOutput);
            _KCP.kcp_nodelay(1, 10, 2, 1);
            // set minrto to 10?

            _Connection.UpdateInterval = 10;
            _Connection.PreDispose     = _con => DisposeSelf();
            _Connection.OnReceive      = (data, cnt, sender) => _KCP.kcp_input(data, cnt);
            _Connection.OnSend         = (data, cnt) =>
            {
                if (cnt > CONST.MTU)
                {
                    int offset = 0;
                    var buffer = BufferPool.GetBufferFromPool();
                    while (cnt > CONST.MTU)
                    {
                        Buffer.BlockCopy(data, offset, buffer, 0, CONST.MTU);
                        _KCP.kcp_send(buffer, CONST.MTU);
                        cnt    -= CONST.MTU;
                        offset += CONST.MTU;
                    }
                    if (cnt > 0)
                    {
                        Buffer.BlockCopy(data, offset, buffer, 0, cnt);
                        _KCP.kcp_send(buffer, cnt);
                    }
                    BufferPool.ReturnBufferToPool(buffer);
                }
                else
                {
                    _KCP.kcp_send(data, cnt);
                }
                return(true);
            };
            _Connection.OnUpdate = _con =>
            {
                _KCP.kcp_update((uint)Environment.TickCount);
                int recvcnt = _KCP.kcp_recv(_RecvBuffer, CONST.MTU);
                if (_OnReceive != null)
                {
                    if (recvcnt > 0)
                    {
                        _OnReceive(_RecvBuffer, recvcnt, _Connection.RemoteEndPoint);
                    }
                }
            };
        }
        public KCPConsultClient(string url) : base(url, 1)
        {
            _Conv = 0;
            _Connection.OnUpdate = _con =>
            {
                _KCP.kcp_update((uint)Environment.TickCount);
                int recvcnt = _KCP.kcp_recv(_RecvBuffer, CONST.MTU);
                if (_Conv == 0)
                {
                    if (recvcnt >= 4)
                    {
                        uint conv = 0;
                        if (BitConverter.IsLittleEndian)
                        {
                            conv = BitConverter.ToUInt32(_RecvBuffer, 0);
                        }
                        else
                        {
                            for (int i = 0; i < 4; ++i)
                            {
                                conv <<= 8;
                                conv  += _RecvBuffer[i];
                            }
                        }
                        if (conv == 0 || conv == 1)
                        {
                            PlatDependant.LogError("KCP conversation id should not be 0 or 1 (with Consult).");
                            throw new ArgumentException("KCP conversation id should not be 0 or 1 (with Consult).");
                        }
                        _KCP.kcp_release();

                        _Conv = conv;
                        _KCP  = KCPLib.kcp_create(conv, (IntPtr)_ConnectionHandle);
                        _KCP.kcp_setoutput(Func_KCPOutput);
                        _KCP.kcp_nodelay(1, 10, 2, 1);
                        _Connection.HoldSending = false;
                    }
                }
                else
                {
                    if (_OnReceive != null)
                    {
                        if (recvcnt > 0)
                        {
                            _OnReceive(_RecvBuffer, recvcnt, _Connection.RemoteEndPoint);
                        }
                    }
                }
            };
            _Connection.PreStart = _con =>
            {
                var guid = _ConnectionGUID.ToByteArray();
                _KCP.kcp_send(guid, guid.Length);
            };
            _Connection.HoldSending = true;
        }
            public void SetConv(uint conv)
            {
                if (_Ready)
                {
                    PlatDependant.LogError("Can not change conv. Please create another one.");
                }
                else
                {
                    _Conv  = conv;
                    _KCP   = KCPLib.kcp_create(conv, (IntPtr)_InfoHandle);
                    _Ready = true;

                    _KCP.kcp_setoutput(Func_KCPOutput);
                    _KCP.kcp_nodelay(1, 10, 2, 1);
                    // set minrto to 10?
                }
            }
 private static int KCPOutput(IntPtr buf, int len, KCPLib.Connection kcp, IntPtr user)
 {
     try
     {
         var gchandle = (GCHandle)user;
         var info     = gchandle.Target as KCPServerConnectionInfo;
         if (info != null && info.EP != null)
         {
             var buffer = BufferPool.GetBufferFromPool(len);
             Marshal.Copy(buf, buffer, 0, len);
             info.Server._Connection.SendRaw(buffer, len, info.EP, success => BufferPool.ReturnBufferToPool(buffer));
         }
     }
     catch (Exception e)
     {
         PlatDependant.LogError(e);
     }
     return(0);
 }
Example #11
0
 private static int KCPOutput(IntPtr buf, int len, KCPLib.Connection kcp, IntPtr user)
 {
     try
     {
         var gchandle   = (GCHandle)user;
         var connection = gchandle.Target as UDPClient;
         if (connection != null)
         {
             var buffer = BufferPool.GetBufferFromPool(len);
             Marshal.Copy(buf, buffer, 0, len);
             connection.SendRaw(buffer, len, success => BufferPool.ReturnBufferToPool(buffer));
         }
     }
     catch (Exception e)
     {
         PlatDependant.LogError(e);
     }
     return(0);
 }
 protected void WriteWork(TaskProgress prog)
 {
     try
     {
         while (_HaveDataToSend.WaitOne())
         {
             try
             {
                 if (_Connection == null || !_Connection.IsConnectionAlive || _WriteDone)
                 {
                     return;
                 }
                 PendingSendData pending;
                 while (_PendingSend.TryDequeue(out pending))
                 {
                     if (pending._Req != null)
                     {
                         pending._Req.Send(_Connection);
                     }
                     else if (pending._Raw != null)
                     {
                         _Connection.Write(pending._Raw);
                     }
                 }
             }
             catch (ThreadAbortException)
             {
             }
             catch (Exception e)
             {
                 PlatDependant.LogError(e);
             }
         }
     }
     catch (ThreadAbortException)
     {
         Thread.ResetAbort();
     }
     catch (Exception e)
     {
         PlatDependant.LogError(e);
     }
 }
 public void BeginReceive()
 {
     ReceiveCount  = 0;
     ReceiveResult = LocalSocket.BeginReceiveFrom(ReceiveData, 0, CONST.MTU, SocketFlags.None, ref RemoteEP, ar =>
     {
         try
         {
             ReceiveCount = LocalSocket.EndReceiveFrom(ar, ref RemoteEP);
         }
         catch (Exception e)
         {
             if (ParentServer.IsConnectionAlive)
             {
                 ParentServer._ConnectWorkCanceled = true;
                 PlatDependant.LogError(e);
             }
         }
         ParentServer._HaveDataToSend.Set();
     }, null);
 }
Example #14
0
 public override object Read(uint type, NativeBufferStream buffer, int offset, int cnt)
 {
     Google.Protobuf.MessageParser parser;
     DataParsers.TryGetValue(type, out parser);
     if (parser != null)
     {
         try
         {
             buffer.Seek(offset, SeekOrigin.Begin);
             buffer.SetLength(offset + cnt);
             var rv = parser.ParseFrom(buffer);
             return(rv);
         }
         catch (Exception e)
         {
             PlatDependant.LogError(e);
         }
     }
     return(null);
 }
Example #15
0
 public override void ReadBlock()
 {
     while (true)
     { // Read Each Tag-Field
         if (_CodedInputStream.IsAtEnd)
         {
             return;
         }
         if (_Type == 0)
         { // Determine the start of a message.
             while (_Tag == 0)
             {
                 try
                 {
                     if (_CodedInputStream.IsAtEnd)
                     {
                         return;
                     }
                     _Tag = _CodedInputStream.ReadTag();
                 }
                 catch (Google.Protobuf.InvalidProtocolBufferException e)
                 {
                     PlatDependant.LogError(e);
                 }
                 catch (InvalidOperationException e)
                 {
                     // this means the stream is closed. so we ignore the exception.
                     //PlatDependant.LogError(e);
                     return;
                 }
                 catch (Exception e)
                 {
                     PlatDependant.LogError(e);
                     return;
                 }
             }
         }
         else
         { // The Next tag must follow
             try
             {
                 _Tag = _CodedInputStream.ReadTag();
                 if (_Tag == 0)
                 {
                     ResetReadBlockContext();
                     continue;
                 }
             }
             catch (Exception e)
             {
                 PlatDependant.LogError(e);
                 ResetReadBlockContext();
                 continue;
             }
         }
         try
         { // Tag got.
             int seq   = Google.Protobuf.WireFormat.GetTagFieldNumber(_Tag);
             var ttype = Google.Protobuf.WireFormat.GetTagWireType(_Tag);
             if (seq == 1 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
             {
                 ResetReadBlockContext();
                 _Type = _CodedInputStream.ReadUInt32();
             }
             else if (_Type != 0)
             {
                 if (seq == 2 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
                 {
                     _Flags = _CodedInputStream.ReadUInt32();
                 }
                 else if (seq == 3 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
                 {
                     _Seq = _CodedInputStream.ReadUInt32();
                 }
                 else if (seq == 4 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
                 {
                     _SSeq = _CodedInputStream.ReadUInt32();
                 }
                 else if (seq == 5 && ttype == Google.Protobuf.WireFormat.WireType.LengthDelimited)
                 {
                     _Size = _CodedInputStream.ReadLength();
                     if (_Size >= 0)
                     {
                         if (_Size > CONST.MAX_MESSAGE_LENGTH)
                         {
                             PlatDependant.LogError("We got a too long message. We will drop this message and treat it as an error message.");
                             _CodedInputStream.SkipRawBytes(_Size);
                             FireReceiveBlock(null, 0, _Type, _Flags, _Seq, _SSeq);
                         }
                         else
                         {
                             _ReadBuffer.Clear();
                             _CodedInputStream.ReadRawBytes(_ReadBuffer, _Size);
                             FireReceiveBlock(_ReadBuffer, _Size, _Type, _Flags, _Seq, _SSeq);
                         }
                     }
                     else
                     {
                         FireReceiveBlock(null, 0, _Type, _Flags, _Seq, _SSeq);
                     }
                     ResetReadBlockContext();
                     return;
                 }
             }
             // else means the first field(type) has not been read yet.
             _Tag = 0;
         }
         catch (InvalidOperationException e)
         {
             // this means the stream is closed. so we ignore the exception.
             //PlatDependant.LogError(e);
             return;
         }
         catch (Exception e)
         {
             PlatDependant.LogError(e);
             ResetReadBlockContext();
         }
     }
 }
 public PersistentConnectionRequestFactory(ObjClient con) : base(con)
 {
     _ShouldLock = true;
     PlatDependant.RunBackground(ReadWork);
     PlatDependant.RunBackground(WriteWork);
 }
        protected void Update()
        {
            object readobj = null;
            uint   type, seq, sseq;

            while ((readobj = Read(out seq, out sseq, out type)) != null)
            {
                uint reqseq;
                uint respseq;
                if (_Connection.IsServer)
                {
                    reqseq  = sseq;
                    respseq = seq;
                }
                else
                {
                    reqseq  = seq;
                    respseq = sseq;
                }
                if (reqseq != 0)
                {
                    if (_ShouldLock)
                    {
                        lock (_PendingRequests)
                        {
                            CheckPendingRequests(readobj, type, reqseq, respseq);
                        }
                    }
                    else
                    {
                        CheckPendingRequests(readobj, type, reqseq, respseq);
                    }
                }
                else
                {
                    if (PushMessageCount >= CONST.MAX_QUEUED_MESSAGE)
                    {
                        PlatDependant.LogError("To many unhandled push messages. Do you forget to check push messages?");
                        while (PushMessageCount >= CONST.MAX_QUEUED_MESSAGE)
                        {
                            PersistentConnectionResponseData oldmess;
                            if (!TryDequeuePushMessage(out oldmess))
                            {
                                break;
                            }
                        }
                    }
                    //else
                    {
                        if (OnFilterMessage == null || OnFilterMessage(type, respseq, readobj))
                        {
                            EnqueuePushMessage(new PersistentConnectionResponseData()
                            {
                                RespDataType = type,
                                RespSeq      = respseq,
                                Result       = readobj,
                            });
                        }
                    }
                }
            }
        }
 public void SendRaw(byte[] data, int cnt, IPEndPoint ep, Action <bool> onComplete)
 {
     if (_ListenBroadcast)
     {
         int curVer = 0;
         if (_KnownRemotesS != null)
         {
             curVer = _KnownRemotesS.Version;
         }
         int rver = 0;
         if (_KnownRemotes != null)
         {
             rver = _KnownRemotes.Version;
         }
         if (rver > curVer)
         {
             _KnownRemotesS = System.Threading.Interlocked.Exchange(ref _KnownRemotes, _KnownRemotesS);
         }
         Socket knowSocket = null;
         if (_KnownRemotesS != null)
         {
             KnownRemote remote;
             if (_KnownRemotesS.Remotes.TryGetValue(ep.Address, out remote))
             {
                 knowSocket      = remote.LocalSocket;
                 remote.LastTick = Environment.TickCount;
                 _KnownRemotesS.Remotes[ep.Address] = remote;
             }
         }
         if (knowSocket != null)
         {
             try
             {
                 knowSocket.BeginSendTo(data, 0, cnt, SocketFlags.None, ep, ar =>
                 {
                     bool success = false;
                     try
                     {
                         knowSocket.EndSendTo(ar);
                         success = true;
                     }
                     catch (Exception e)
                     {
                         PlatDependant.LogError(e);
                     }
                     if (onComplete != null)
                     {
                         onComplete(success);
                     }
                 }, null);
                 return;
             }
             catch (Exception e)
             {
                 PlatDependant.LogError(e);
             }
         }
     }
     else
     {
         if (ep.AddressFamily == AddressFamily.InterNetworkV6)
         {
             if (_Socket6 != null)
             {
                 try
                 {
                     _Socket6.BeginSendTo(data, 0, cnt, SocketFlags.None, ep, ar =>
                     {
                         bool success = false;
                         try
                         {
                             _Socket6.EndSendTo(ar);
                             success = true;
                         }
                         catch (Exception e)
                         {
                             PlatDependant.LogError(e);
                         }
                         if (onComplete != null)
                         {
                             onComplete(success);
                         }
                     }, null);
                     return;
                 }
                 catch (Exception e)
                 {
                     PlatDependant.LogError(e);
                 }
             }
         }
         else
         {
             if (_Socket != null)
             {
                 try
                 {
                     _Socket.BeginSendTo(data, 0, cnt, SocketFlags.None, ep, ar =>
                     {
                         bool success = false;
                         try
                         {
                             _Socket.EndSendTo(ar);
                             success = true;
                         }
                         catch (Exception e)
                         {
                             PlatDependant.LogError(e);
                         }
                         if (onComplete != null)
                         {
                             onComplete(success);
                         }
                     }, null);
                     return;
                 }
                 catch (Exception e)
                 {
                     PlatDependant.LogError(e);
                 }
             }
         }
     }
     if (onComplete != null)
     {
         onComplete(false);
     }
 }
Example #19
0
        protected virtual void ConnectWork()
        {
            try
            {
                if (_Url != null)
                {
                    bool isMulticastOrBroadcast = false;
                    int  port = 0;

                    Uri uri = new Uri(_Url);
                    port = uri.Port;
                    var addresses = Dns.GetHostAddresses(uri.DnsSafeHost);
                    if (addresses != null && addresses.Length > 0)
                    {
                        var address = addresses[0];
                        if (address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            if (address.Equals(IPAddress.Broadcast))
                            {
                                isMulticastOrBroadcast = true;
                            }
                            else
                            {
                                var firstb = address.GetAddressBytes()[0];
                                if (firstb >= 224 && firstb < 240)
                                {
                                    isMulticastOrBroadcast = true;
                                }
                            }
                        }
                        else if (address.AddressFamily == AddressFamily.InterNetworkV6)
                        {
                            if (address.IsIPv6Multicast)
                            {
                                isMulticastOrBroadcast = true;
                            }
                        }
                        _Socket = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                        if (isMulticastOrBroadcast)
                        {
                            _Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
                            if (address.AddressFamily == AddressFamily.InterNetworkV6)
                            {
#if NET_STANDARD_2_0 || NET_4_6
                                // Notice: it is a pitty that unity does not support ipv6 multicast. (Unity 5.6)
                                _Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(address));
                                _Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, 5);
#endif
                                _Socket.Bind(new IPEndPoint(IPAddress.IPv6Any, 0));
                            }
                            else
                            {
                                if (!address.Equals(IPAddress.Broadcast))
                                {
                                    _Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(address, IPAddress.Any));
                                    _Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 5);
                                }
                                _Socket.Bind(new IPEndPoint(IPAddress.Any, 0));
                            }
                            _BroadcastEP = new IPEndPoint(address, port);
                        }
                        else
                        {
                            _Socket.Connect(address, port);
                        }
                    }
                }
                if (_Socket != null)
                {
                    if (_PreStart != null)
                    {
                        _PreStart(this);
                    }
                    byte[]   receivebuffer = new byte[CONST.MTU];
                    int      receivecnt    = 0;
                    EndPoint broadcastRespEP;
                    if (_BroadcastEP != null && _BroadcastEP.AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        broadcastRespEP = new IPEndPoint(IPAddress.IPv6Any, 0);
                    }
                    else
                    {
                        broadcastRespEP = new IPEndPoint(IPAddress.Any, 0);
                    }
                    Action BeginReceive = () =>
                    {
                        if (_BroadcastEP != null)
                        {
                            _Socket.BeginReceiveFrom(receivebuffer, 0, CONST.MTU, SocketFlags.None, ref broadcastRespEP, ar =>
                            {
                                try
                                {
                                    receivecnt = _Socket.EndReceiveFrom(ar, ref broadcastRespEP);
                                }
                                catch (Exception e)
                                {
                                    if (IsConnectionAlive)
                                    {
                                        _ConnectWorkCanceled = true;
                                        PlatDependant.LogError(e);
                                    }
                                }
                                _HaveDataToSend.Set();
                            }, null);
                        }
                        else
                        {
                            _Socket.BeginReceive(receivebuffer, 0, CONST.MTU, SocketFlags.None, ar =>
                            {
                                try
                                {
                                    receivecnt = _Socket.EndReceive(ar);
                                }
                                catch (Exception e)
                                {
                                    if (IsConnectionAlive)
                                    {
                                        _ConnectWorkCanceled = true;
                                        PlatDependant.LogError(e);
                                    }
                                }
                                _HaveDataToSend.Set();
                            }, null);
                        }
                    };
                    if (_OnReceive != null)
                    {
                        BeginReceive();
                    }
                    while (!_ConnectWorkCanceled)
                    {
                        if (_OnReceive != null)
                        {
                            if (receivecnt > 0)
                            {
                                if (_BroadcastEP != null && _WaitForBroadcastResp)
                                {
                                    _OnReceive(receivebuffer, receivecnt, broadcastRespEP);
                                    receivecnt = 0;
                                    BeginReceive();
                                }
                                else
                                {
                                    if (_BroadcastEP != null)
                                    {
                                        _Socket.Connect(broadcastRespEP);
                                        _BroadcastEP = null;
                                    }
                                    _OnReceive(receivebuffer, receivecnt, _Socket.RemoteEndPoint);
                                    receivecnt = 0;
                                    BeginReceive();
                                }
                            }
                        }

                        if (!HoldSending)
                        {
                            BufferInfo binfo;
                            while (_PendingSendMessages.TryDequeue(out binfo))
                            {
                                var message = binfo.Buffer;
                                int cnt     = binfo.Count;
                                if (_OnSend != null && _OnSend(message, cnt))
                                {
                                    if (_OnSendComplete != null)
                                    {
                                        _OnSendComplete(message, true);
                                    }
                                }
                                else
                                {
                                    SendRaw(message, cnt, success =>
                                    {
                                        if (_OnSendComplete != null)
                                        {
                                            _OnSendComplete(message, success);
                                        }
                                    });
                                }
                            }
                        }

                        if (_OnUpdate != null)
                        {
                            _OnUpdate(this);
                        }

                        var waitinterval = _UpdateInterval;
                        var easeratio    = _EaseUpdateRatio;
                        if (waitinterval > 0 && easeratio > 0)
                        {
                            var easeinterval = waitinterval * easeratio;
                            if (_LastSendTick + easeinterval <= System.Environment.TickCount)
                            {
                                waitinterval = easeinterval;
                            }
                        }
                        _HaveDataToSend.WaitOne(waitinterval);
                    }
                }
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception e)
            {
                PlatDependant.LogError(e);
            }
            finally
            {
                _ConnectWorkRunning  = false;
                _ConnectWorkCanceled = false;
                if (_PreDispose != null)
                {
                    _PreDispose(this);
                }
                if (_Socket != null)
                {
                    _Socket.Close();
                    _Socket = null;
                }
                // set handlers to null.
                _OnReceive      = null;
                _OnSend         = null;
                _OnSendComplete = null;
                _OnUpdate       = null;
                _PreDispose     = null;
            }
        }
Example #20
0
 public override bool TryReadBlock() // TODO: BufferedSize < 1 -> actual size... may be we need to peek(n) or get and put back.
 {
     if (_BufferedStream == null)
     {
         ReadBlock();
         return(true);
     }
     else
     {
         while (true)
         {
             if (_Type == 0)
             { // Determine the start of a message.
                 while (_Tag == 0)
                 {
                     if (BufferedSize < 1)
                     {
                         return(false);
                     }
                     try
                     {
                         _Tag = _CodedInputStream.ReadTag();
                     }
                     catch (Exception e)
                     {
                         PlatDependant.LogError(e);
                     }
                 }
             }
             else
             { // The Next tag must follow
                 if (_Tag == 0)
                 {
                     if (BufferedSize < 1)
                     {
                         return(false);
                     }
                     try
                     {
                         _Tag = _CodedInputStream.ReadTag();
                         if (_Tag == 0)
                         {
                             ResetReadBlockContext();
                             continue;
                         }
                     }
                     catch (Exception e)
                     {
                         PlatDependant.LogError(e);
                         ResetReadBlockContext();
                         continue;
                     }
                 }
             }
             try
             {
                 int seq   = Google.Protobuf.WireFormat.GetTagFieldNumber(_Tag);
                 var ttype = Google.Protobuf.WireFormat.GetTagWireType(_Tag);
                 if (seq == 1 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
                 {
                     if (BufferedSize < 1)
                     {
                         return(false);
                     }
                     ResetReadBlockContext();
                     _Type = _CodedInputStream.ReadUInt32();
                 }
                 else if (_Type != 0)
                 {
                     if (seq == 2 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
                     {
                         if (BufferedSize < 1)
                         {
                             return(false);
                         }
                         _Flags = _CodedInputStream.ReadUInt32();
                     }
                     else if (seq == 3 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
                     {
                         if (BufferedSize < 1)
                         {
                             return(false);
                         }
                         _Seq = _CodedInputStream.ReadUInt32();
                     }
                     else if (seq == 4 && ttype == Google.Protobuf.WireFormat.WireType.Varint)
                     {
                         if (BufferedSize < 1)
                         {
                             return(false);
                         }
                         _SSeq = _CodedInputStream.ReadUInt32();
                     }
                     else if (seq == 5 && ttype == Google.Protobuf.WireFormat.WireType.LengthDelimited)
                     {
                         if (!_SizeReady)
                         {
                             if (BufferedSize < 1)
                             {
                                 return(false);
                             }
                             _Size      = _CodedInputStream.ReadLength();
                             _SizeReady = true;
                         }
                         if (_Size >= 0)
                         {
                             if (BufferedSize < _Size)
                             {
                                 return(false);
                             }
                             if (_Size > CONST.MAX_MESSAGE_LENGTH)
                             {
                                 PlatDependant.LogError("We got a too long message. We will drop this message and treat it as an error message.");
                                 _CodedInputStream.SkipRawBytes(_Size);
                                 FireReceiveBlock(null, 0, _Type, _Flags, _Seq, _SSeq);
                             }
                             else
                             {
                                 _ReadBuffer.Clear();
                                 _CodedInputStream.ReadRawBytes(_ReadBuffer, _Size);
                                 FireReceiveBlock(_ReadBuffer, _Size, _Type, _Flags, _Seq, _SSeq);
                             }
                         }
                         else
                         {
                             FireReceiveBlock(null, 0, _Type, _Flags, _Seq, _SSeq);
                         }
                         ResetReadBlockContext();
                         return(true);
                     }
                 }
                 _Tag = 0;
             }
             catch (Exception e)
             {
                 PlatDependant.LogError(e);
                 ResetReadBlockContext();
             }
         }
     }
 }
Example #21
0
        protected virtual void ConnectWork()
        {
            try
            {
                PrepareSocket();
                if (_Socket != null)
                {
                    byte[] receivebuffer = new byte[CONST.MTU];
                    int    receivecnt    = 0;
                    Action BeginReceive  = () =>
                    {
                        _Socket.BeginReceive(receivebuffer, 0, 1, SocketFlags.None, ar =>
                        {
                            try
                            {
                                receivecnt = _Socket.EndReceive(ar);
                                if (receivecnt > 0)
                                {
                                    var bytesRemaining = _Socket.Available;
                                    if (bytesRemaining > 0)
                                    {
                                        if (bytesRemaining > CONST.MTU - 1)
                                        {
                                            bytesRemaining = CONST.MTU - 1;
                                        }
                                        receivecnt += _Socket.Receive(receivebuffer, 1, bytesRemaining, SocketFlags.None);
                                    }
                                }
                                else
                                {
                                    if (_ConnectWorkRunning)
                                    {
                                        _ConnectWorkCanceled = true;
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                if (IsConnectionAlive)
                                {
                                    _ConnectWorkCanceled = true;
                                    PlatDependant.LogError(e);
                                }
                            }
                            _HaveDataToSend.Set();
                        }, null);
                    };
                    BeginReceive();
                    while (!_ConnectWorkCanceled)
                    {
                        if (receivecnt > 0)
                        {
                            if (_OnReceive != null)
                            {
                                _OnReceive(receivebuffer, receivecnt, _Socket.RemoteEndPoint);
                            }
                            receivecnt = 0;
                            BeginReceive();
                        }

                        BufferInfo binfo;
                        while (_PendingSendMessages.TryDequeue(out binfo))
                        {
                            var message = binfo.Buffer;
                            int cnt     = binfo.Count;
                            if (_OnSend != null && _OnSend(message, cnt))
                            {
                                if (_OnSendComplete != null)
                                {
                                    _OnSendComplete(message, true);
                                }
                            }
                            else
                            {
                                SendRaw(message, cnt, success =>
                                {
                                    if (_OnSendComplete != null)
                                    {
                                        _OnSendComplete(message, success);
                                    }
                                });
                            }
                        }

                        _HaveDataToSend.WaitOne();
                    }
                    _Socket.Shutdown(SocketShutdown.Both);
                }
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception e)
            {
                PlatDependant.LogError(e);
            }
            finally
            {
                _ConnectWorkRunning  = false;
                _ConnectWorkCanceled = false;
                if (_PreDispose != null)
                {
                    _PreDispose(this);
                }
                if (_Socket != null)
                {
                    _Socket.Close();
                    _Socket = null;
                }
                // set handlers to null.
                _OnReceive      = null;
                _OnSend         = null;
                _OnSendComplete = null;
                _PreDispose     = null;
            }
        }
        protected override void ConnectWork()
        {
            try
            {
                KnownRemotes remotes = null;
                if (_ListenBroadcast)
                {
                    IPAddressInfo.Refresh();
                    _SocketsBroadcast = new List <BroadcastSocketReceiveInfo>();
                    remotes           = new KnownRemotes();
                    _KnownRemotes     = new KnownRemotes();
                    _KnownRemotesR    = new KnownRemotes();
                    _KnownRemotesS    = new KnownRemotes();
                }

                if (_ListenBroadcast)
                {
                    var ipv4addrs = IPAddressInfo.LocalIPv4Addresses;
                    for (int i = 0; i < ipv4addrs.Length; ++i)
                    {
                        try
                        {
                            var address = ipv4addrs[i];
                            var socket  = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                            socket.Bind(new IPEndPoint(address, _Port));
                            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
                            socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddressInfo.IPv4MulticastAddress, address));
                            socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 5);
                            _SocketsBroadcast.Add(new BroadcastSocketReceiveInfo(this, socket, new IPEndPoint(IPAddress.Any, _Port)));
                            if (_Socket == null)
                            {
                                _Socket = socket;
                            }
                        }
                        catch (Exception e)
                        {
                            PlatDependant.LogError(ipv4addrs[i]);
                            PlatDependant.LogError(e);
                        }
                    }
                }
                if (_Socket == null)
                {
                    var address4 = IPAddress.Any;
                    _Socket = new Socket(address4.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                    _Socket.Bind(new IPEndPoint(address4, _Port));
                }

#if NET_STANDARD_2_0 || NET_4_6
                // Notice: it is a pitty that unity does not support ipv6 multicast. (Unity 5.6)
                if (_ListenBroadcast)
                {
                    var ipv6addrs = IPAddressInfo.LocalIPv6Addresses;
                    for (int i = 0; i < ipv6addrs.Length; ++i)
                    {
                        try
                        {
                            var address = ipv6addrs[i];
                            var maddr   = IPAddressInfo.IPv6MulticastAddressOrganization;
                            if (address.IsIPv6SiteLocal)
                            {
                                maddr = IPAddressInfo.IPv6MulticastAddressSiteLocal;
                            }
                            else if (address.IsIPv6LinkLocal)
                            {
                                maddr = IPAddressInfo.IPv6MulticastAddressLinkLocal;
                            }
                            var socket = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                            socket.Bind(new IPEndPoint(address, _Port));
                            var iindex = IPAddressInfo.GetInterfaceIndex(address);
                            if (iindex == 0)
                            {
                                socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(maddr));
                            }
                            else
                            {
                                socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(maddr, iindex));
                            }
                            socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, 5);
                            _SocketsBroadcast.Add(new BroadcastSocketReceiveInfo(this, socket, new IPEndPoint(IPAddress.IPv6Any, _Port)));
                            if (_Socket6 == null)
                            {
                                _Socket6 = socket;
                            }
                        }
                        catch (Exception e)
                        {
                            PlatDependant.LogError(ipv6addrs[i]);
                            PlatDependant.LogError(e);
                        }
                    }
                }
#endif
                if (_Socket6 == null)
                {
                    var address6 = IPAddress.IPv6Any;
                    _Socket6 = new Socket(address6.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                    _Socket6.Bind(new IPEndPoint(address6, _Port));
                }

                if (_ListenBroadcast)
                {
                    for (int i = 0; i < _SocketsBroadcast.Count; ++i)
                    {
                        var bsinfo = _SocketsBroadcast[i];
                        bsinfo.BeginReceive();
                    }
                    int knownRemotesVersion = 0;
                    while (!_ConnectWorkCanceled)
                    {
                        bool knownRemotesChanged = false;
                        var  curTick             = Environment.TickCount;
                        for (int i = 0; i < _SocketsBroadcast.Count; ++i)
                        {
                            var bsinfo = _SocketsBroadcast[i];
                            if (bsinfo.ReceiveCount > 0)
                            {
                                var ep = bsinfo.RemoteEP as IPEndPoint;
                                //var remote = new IPEndPoint(ep.Address, ep.Port);
                                remotes.Remotes[ep.Address] = new KnownRemote()
                                {
                                    Address = ep.Address, LocalSocket = bsinfo.LocalSocket, LastTick = curTick
                                };
                                knownRemotesChanged = true;
                            }
                        }
                        if (remotes.Remotes.Count > 100)
                        {
                            KnownRemote[] aremotes = new KnownRemote[remotes.Remotes.Count];
                            remotes.Remotes.Values.CopyTo(aremotes, 0);
                            Array.Sort(aremotes, (ra, rb) => ra.LastTick - rb.LastTick);
                            for (int i = 0; i < aremotes.Length - 100; ++i)
                            {
                                var remote = aremotes[i];
                                if (remote.LastTick + 15000 <= curTick)
                                {
                                    remotes.Remotes.Remove(remote.Address);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                        // TODO: check dead knownRemotes...
                        if (knownRemotesChanged)
                        {
                            _KnownRemotesR.Remotes.Clear();
                            foreach (var kvp in remotes.Remotes)
                            {
                                _KnownRemotesR.Remotes[kvp.Key] = kvp.Value;
                            }
                            _KnownRemotesR.Version = ++knownRemotesVersion;
                            _KnownRemotesR         = System.Threading.Interlocked.Exchange(ref _KnownRemotes, _KnownRemotesR);
                        }

                        if (_OnReceive != null)
                        {
                            for (int i = 0; i < _SocketsBroadcast.Count; ++i)
                            {
                                var bsinfo = _SocketsBroadcast[i];
                                if (bsinfo.ReceiveCount > 0)
                                {
                                    _OnReceive(bsinfo.ReceiveData, bsinfo.ReceiveCount, bsinfo.RemoteEP);
                                }
                            }
                        }
                        for (int i = 0; i < _SocketsBroadcast.Count; ++i)
                        {
                            var bsinfo = _SocketsBroadcast[i];
                            if (bsinfo.ReceiveResult.IsCompleted)
                            {
                                bsinfo.BeginReceive();
                            }
                        }

                        if (_OnUpdate != null)
                        {
                            _OnUpdate(this);
                        }

                        _HaveDataToSend.WaitOne(_UpdateInterval);
                    }
                }
                else
                {
                    EndPoint sender4 = new IPEndPoint(IPAddress.Any, _Port);
                    EndPoint sender6 = new IPEndPoint(IPAddress.IPv6Any, _Port);

                    byte[]       data4   = new byte[CONST.MTU];
                    byte[]       data6   = new byte[CONST.MTU];
                    int          dcnt4   = 0;
                    int          dcnt6   = 0;
                    IAsyncResult readar4 = null;
                    IAsyncResult readar6 = null;

                    Action BeginReceive4 = () =>
                    {
                        readar4 = _Socket.BeginReceiveFrom(data4, 0, CONST.MTU, SocketFlags.None, ref sender4, ar =>
                        {
                            try
                            {
                                dcnt4 = _Socket.EndReceiveFrom(ar, ref sender4);
                            }
                            catch (Exception e)
                            {
                                if (IsConnectionAlive)
                                {
                                    _ConnectWorkCanceled = true;
                                    PlatDependant.LogError(e);
                                }
                            }
                            _HaveDataToSend.Set();
                        }, null);
                    };
                    Action BeginReceive6 = () =>
                    {
                        readar6 = _Socket6.BeginReceiveFrom(data6, 0, CONST.MTU, SocketFlags.None, ref sender6, ar =>
                        {
                            try
                            {
                                dcnt6 = _Socket6.EndReceiveFrom(ar, ref sender6);
                            }
                            catch (Exception e)
                            {
                                if (IsConnectionAlive)
                                {
                                    _ConnectWorkCanceled = true;
                                    PlatDependant.LogError(e);
                                }
                            }
                            _HaveDataToSend.Set();
                        }, null);
                    };
                    BeginReceive4();
                    BeginReceive6();
                    while (!_ConnectWorkCanceled)
                    {
                        if (_OnReceive != null)
                        {
                            if (dcnt4 > 0)
                            {
                                _OnReceive(data4, dcnt4, sender4);
                                dcnt4 = 0;
                            }
                            if (dcnt6 > 0)
                            {
                                _OnReceive(data6, dcnt6, sender6);
                                dcnt6 = 0;
                            }
                        }
                        if (readar4.IsCompleted)
                        {
                            BeginReceive4();
                        }
                        if (readar6.IsCompleted)
                        {
                            BeginReceive6();
                        }

                        if (_OnUpdate != null)
                        {
                            _OnUpdate(this);
                        }

                        _HaveDataToSend.WaitOne(_UpdateInterval);
                    }
                }
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception e)
            {
                PlatDependant.LogError(e);
            }
            finally
            {
                _ConnectWorkRunning  = false;
                _ConnectWorkCanceled = false;
                if (_PreDispose != null)
                {
                    _PreDispose(this);
                }
                if (_Socket != null)
                {
                    _Socket.Close();
                    _Socket = null;
                }
                if (_Socket6 != null)
                {
                    _Socket6.Close();
                    _Socket6 = null;
                }
                if (_SocketsBroadcast != null)
                {
                    for (int i = 0; i < _SocketsBroadcast.Count; ++i)
                    {
                        var bsinfo = _SocketsBroadcast[i];
                        if (bsinfo != null && bsinfo.LocalSocket != null)
                        {
                            bsinfo.LocalSocket.Close();
                        }
                    }
                    _SocketsBroadcast = null;
                }
                // set handlers to null.
                _OnReceive      = null;
                _OnSend         = null;
                _OnSendComplete = null;
                _OnUpdate       = null;
                _PreDispose     = null;
            }
        }