Esempio n. 1
0
        public TcpClient(IPEndPoint RemoteEndPoint, IStreamedVirtualTransportClient VirtualTransportClient, Action <Action> QueueUserWorkItem)
        {
            this.RemoteEndPoint = RemoteEndPoint;
            Socket = new StreamedAsyncSocket(new Socket(RemoteEndPoint.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp), null, QueueUserWorkItem);
            //this.QueueUserWorkItem = QueueUserWorkItem;
            this.VirtualTransportClient          = VirtualTransportClient;
            VirtualTransportClient.ClientMethod += OnError =>
            {
                using (var h = new AutoResetEvent(false))
                {
                    var ByteArrays  = VirtualTransportClient.TakeWriteBuffer();
                    var TotalLength = ByteArrays.Sum(b => b.Length);
                    if ((WriteBuffer == null) || (TotalLength > WriteBuffer.Length))
                    {
                        WriteBuffer = new Byte[GetMinNotLessPowerOfTwo(TotalLength)];
                    }
                    var Offset = 0;
                    foreach (var b in ByteArrays)
                    {
                        Array.Copy(b, 0, WriteBuffer, Offset, b.Length);
                        Offset += b.Length;
                    }

                    Socket.SendAsync(WriteBuffer, 0, TotalLength, () => { }, OnError);
                }
            };
        }
Esempio n. 2
0
        public UdpClient(IPEndPoint RemoteEndPoint, IStreamedVirtualTransportClient VirtualTransportClient, Action <Action> QueueUserWorkItem)
        {
            this.RemoteEndPoint         = RemoteEndPoint;
            this.VirtualTransportClient = VirtualTransportClient;
            this.Socket            = new Socket(RemoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
            this.QueueUserWorkItem = QueueUserWorkItem;

            //在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;
                this.Socket.IOControl(unchecked ((int)(SIO_UDP_CONNRESET)), new byte[] { Convert.ToByte(false) }, null);
            }

            VirtualTransportClient.ClientMethod += OnError =>
            {
                OnWrite(VirtualTransportClient, () => { }, se => { throw new SocketException((int)(se)); });
            };
        }
Esempio n. 3
0
        private void OnWrite(IStreamedVirtualTransportClient vtc, Action OnSuccess, Action <SocketError> OnFailure)
        {
            var ByteArrays  = vtc.TakeWriteBuffer();
            var TotalLength = ByteArrays.Sum(b => b.Length);
            var WriteBuffer = new Byte[GetMinNotLessPowerOfTwo(TotalLength)];
            var Offset      = 0;

            foreach (var b in ByteArrays)
            {
                Array.Copy(b, 0, WriteBuffer, Offset, b.Length);
                Offset += b.Length;
            }
            var RemoteEndPoint = this.RemoteEndPoint;
            int SessionId      = 0;
            var State          = ConnectionState.Initial;

            this.ConnectionStateValue.Update(v =>
            {
                SessionId = this.SessionId;
                State     = v;
                if (v == ConnectionState.Initial)
                {
                    return(ConnectionState.Connecting);
                }
                return(v);
            });
            if (State == ConnectionState.Connecting)
            {
                throw new InvalidOperationException();
            }
            var SecureContext = this.SecureContext;
            var Indices       = new List <int>();

            RawReadingContext.DoAction(c =>
            {
                if (c.NotAcknowledgedIndices.Count == 0)
                {
                    return;
                }
                var MaxHandled   = c.Parts.MaxHandled;
                var Acknowledged = new List <int>();
                foreach (var i in c.NotAcknowledgedIndices)
                {
                    if (c.Parts.IsEqualOrAfter(MaxHandled, i))
                    {
                        Acknowledged.Add(i);
                    }
                    else if (PartContext.IsSuccessor(i, MaxHandled))
                    {
                        Acknowledged.Add(i);
                        MaxHandled = i;
                    }
                }
                foreach (var i in Acknowledged)
                {
                    c.NotAcknowledgedIndices.Remove(i);
                }
                Indices.Add(MaxHandled);
                Indices.AddRange(c.NotAcknowledgedIndices);
                c.NotAcknowledgedIndices.Clear();
            });
            if ((ByteArrays.Length == 0) && (Indices.Count == 0))
            {
                OnSuccess();
                return;
            }
            var se    = SocketError.Success;
            var Parts = new List <Byte[]>();

            CookedWritingContext.DoAction(c =>
            {
                var Time          = DateTime.UtcNow;
                var WritingOffset = 0;
                while (WritingOffset < TotalLength)
                {
                    var Index = PartContext.GetSuccessor(c.WritenIndex);

                    var NumIndex = Indices.Count;
                    if (NumIndex > 0xFFFF)
                    {
                        se = SocketError.NoBufferSpaceAvailable;
                        return;
                    }

                    var IsACK = NumIndex > 0;
                    var Flag  = 0;
                    if (State == ConnectionState.Initial)
                    {
                        Flag |= 4; //INI
                        IsACK = false;
                    }

                    var Length     = Math.Min(12 + (IsACK ? 2 + NumIndex * 2 : 0) + TotalLength - WritingOffset, MaxPacketLength);
                    var DataLength = Length - (12 + (IsACK ? 2 + NumIndex * 2 : 0));
                    if (DataLength < 0)
                    {
                        se = SocketError.NoBufferSpaceAvailable;
                        return;
                    }
                    var Buffer = new Byte[Length];
                    Buffer[0]  = (Byte)(SessionId & 0xFF);
                    Buffer[1]  = (Byte)((SessionId >> 8) & 0xFF);
                    Buffer[2]  = (Byte)((SessionId >> 16) & 0xFF);
                    Buffer[3]  = (Byte)((SessionId >> 24) & 0xFF);

                    if (IsACK)
                    {
                        Flag      |= 1; //ACK
                        Buffer[12] = (Byte)(NumIndex & 0xFF);
                        Buffer[13] = (Byte)((NumIndex >> 8) & 0xFF);
                        var j      = 0;
                        foreach (var i in Indices)
                        {
                            Buffer[14 + j * 2]     = (Byte)(i & 0xFF);
                            Buffer[14 + j * 2 + 1] = (Byte)((i >> 8) & 0xFF);
                            j += 1;
                        }
                        Indices.Clear();
                    }

                    Array.Copy(WriteBuffer, WritingOffset, Buffer, 12 + (IsACK ? 2 + NumIndex * 2 : 0), DataLength);
                    WritingOffset += DataLength;

                    if (SecureContext != null)
                    {
                        Flag |= 2; //ENC
                    }
                    Buffer[4] = (Byte)(Flag & 0xFF);
                    Buffer[5] = (Byte)((Flag >> 8) & 0xFF);
                    Buffer[6] = (Byte)(Index & 0xFF);
                    Buffer[7] = (Byte)((Index >> 8) & 0xFF);

                    var Verification = 0;
                    if (SecureContext != null)
                    {
                        var Key       = SecureContext.ClientToken.Concat(Cryptography.SHA256(Buffer.Skip(4).Take(4)));
                        var HMACBytes = Cryptography.HMACSHA256Simple(Key, Buffer).Take(4).ToArray();
                        Verification  = HMACBytes[0] | ((Int32)(HMACBytes[1]) << 8) | ((Int32)(HMACBytes[2]) << 16) | ((Int32)(HMACBytes[3]) << 24);
                    }
                    else
                    {
                        Verification = Cryptography.CRC32(Buffer);
                    }

                    Buffer[8]  = (Byte)(Verification & 0xFF);
                    Buffer[9]  = (Byte)((Verification >> 8) & 0xFF);
                    Buffer[10] = (Byte)((Verification >> 16) & 0xFF);
                    Buffer[11] = (Byte)((Verification >> 24) & 0xFF);

                    var Part = new Part {
                        Index = Index, ResendTime = Time.AddIntMilliseconds(GetTimeoutMilliseconds(0)), Data = Buffer, ResentCount = 0
                    };
                    if (!c.Parts.TryPushPart(Index, Buffer))
                    {
                        se = SocketError.NoBufferSpaceAvailable;
                        return;
                    }
                    Parts.Add(Part.Data);
                    //Debug.WriteLine(Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + " Send SessionId: " + SessionId.ToString("X8") + " Index: " + Index.ToString());

                    c.WritenIndex = Index;
                }
                if (c.Timer == null)
                {
                    c.Timer = new Timer(o => Check(), null, CheckTimeout, Timeout.Infinite);
                }
            });
            foreach (var p in Parts)
            {
                try
                {
                    SendPacket(RemoteEndPoint, p);
                }
                catch
                {
                    se = SocketError.Interrupted;
                    break;
                }
            }
            if (se != SocketError.Success)
            {
                OnFailure(se);
            }
            else
            {
                OnSuccess();
            }
        }