Beispiel #1
0
        private static void ReadUnsignedVarint(
            Stream stream,
            Bcp.ReadState readState,
            ProcessReadVarint processReadVarint,
            BcpDelegate.ExceptionHandler exceptionHandler)
        {
            var           buffer        = new byte[1];
            var           i             = 0;
            uint          result        = 0U;
            AsyncCallback asyncCallback = null;

            asyncCallback = asyncResult =>
            {
                try
                {
                    int numBytesRead = stream.EndRead(asyncResult);
                    if (numBytesRead != 1)
                    {
                        exceptionHandler(new EndOfStreamException());
                    }
                    uint b = buffer[0];
                    if (i < 32)
                    {
                        if (b >= 0x80)
                        {
                            result |= ((b & 0x7f) << i);
                            i      += 7;
                            stream.BeginRead(buffer, 0, 1, asyncCallback, readState);
                        }
                        else
                        {
                            result |= (b << i);
                            processReadVarint(result);
                        }
                    }
                    else
                    {
                        exceptionHandler(new BcpException.VarintTooBig());
                    }
                }
                catch (Exception e)
                {
                    exceptionHandler(e);
                }
            };
            try
            {
                stream.BeginRead(buffer, 0, 1, asyncCallback, readState);
            }
            catch (Exception e)
            {
                exceptionHandler(e);
            }
        }
Beispiel #2
0
        internal Timer StartReadTimer(Stream stream, BcpDelegate.ExceptionHandler exceptionHandler)
        {
            TimerCallback readTimeoutCallback = delegate(Object source)
            {
                stream.Dispose();
                exceptionHandler(new Exception());
            };
            var readTimer = new Timer(readTimeoutCallback, null, Bcp.ReadingTimeoutMilliseconds, Bcp.ReadingTimeoutMilliseconds);

            return(readTimer);
        }
Beispiel #3
0
        private static void ReadAll(
            Stream stream,
            Bcp.ReadState readState,
            byte[] buffer,
            int offset,
            int count,
            ProcessReadAll processReadAll,
            BcpDelegate.ExceptionHandler exceptionHandler)
        {
            AsyncCallback asyncCallback = null;

            asyncCallback = asyncResult =>
            {
                try
                {
                    int numBytesRead = stream.EndRead(asyncResult);
                    if (numBytesRead == 0)
                    {
                        exceptionHandler(new EndOfStreamException());
                    }
                    else
                    {
                        offset += numBytesRead;

                        if (offset < count)
                        {
                            stream.BeginRead(buffer, offset, count, asyncCallback, readState);
                        }
                        else
                        {
                            processReadAll();
                        }
                    }
                }
                catch (Exception e)
                {
                    exceptionHandler(e);
                }
            };
            try
            {
                stream.BeginRead(buffer, offset, count, asyncCallback, readState);
            }
            catch (Exception e)
            {
                exceptionHandler(e);
            }
        }
Beispiel #4
0
        protected void AddIncomingSocket(Stream stream)
        {
            BcpDelegate.ProcessReadHead processReadHead = delegate(Bcp.ConnectionHead connectionHead)
            {
                var    sessionId    = connectionHead.SessionId;
                string sessionKey   = Convert.ToBase64String(sessionId);
                var    connectionId = connectionHead.ConnectionId;
                Debug.WriteLine("BcpServer add incomming socket, sessionId: " + sessionId + ", connectionId: " + connectionId);
                lock (serverLock)
                {
                    BcpServer.Session session;
                    if (sessions.TryGetValue(sessionKey, out session))
                    {
                    }
                    else
                    {
                        session = NewSession(sessionId);
                        sessions.Add(sessionKey, session);
                        session.RaiseAccepted();
                    }
                    if (connectionHead.IsRenew)
                    {
                        session.RenewSession();
                    }
                    session.AddStream(connectionId, stream);
                    Debug.WriteLine("Server added stream!");
                }
            };
            BcpDelegate.ExceptionHandler exceptionHandler = delegate(Exception e)
            {
                Debug.WriteLine("BcpServer add incomming stream exception: " + e.Message);
            };
            TimerCallback readTimeoutCallback = delegate(Object source)
            {
                stream.Dispose();
                exceptionHandler(new Exception());
            };

            Bcp.ReadState readState = new Bcp.ReadState();
            readState.readTimeoutTimer = new Timer(readTimeoutCallback, null, Bcp.ReadingTimeoutMilliseconds, Bcp.ReadingTimeoutMilliseconds);
            BcpIO.ReadHead(stream, readState, processReadHead, exceptionHandler);
        }
Beispiel #5
0
        public static void ReadHead(Stream stream,
                                    Bcp.ReadState readState,
                                    BcpDelegate.ProcessReadHead processReadHead,
                                    BcpDelegate.ExceptionHandler exceptionHandler)
        {
            var            sessionId      = new byte[Bcp.NumBytesSessionId];
            ProcessReadAll processReadAll = delegate()
            {
                ProcessReadVarint processReadIsRenew = delegate(uint isRenew)
                {
                    ProcessReadVarint processReadConnectionId = delegate(uint connectionId)
                    {
                        readState.Cancel();
                        processReadHead(new Bcp.ConnectionHead(sessionId, Convert.ToBoolean(isRenew), connectionId));
                    };
                    ReadUnsignedVarint(stream, readState, processReadConnectionId, exceptionHandler);
                };
                ReadUnsignedVarint(stream, readState, processReadIsRenew, exceptionHandler);
            };

            ReadAll(stream, readState, sessionId, 0, Bcp.NumBytesSessionId, processReadAll, exceptionHandler);
        }
Beispiel #6
0
        public static void Read(Stream stream, Bcp.ReadState readState, BcpDelegate.ProcessRead processRead, BcpDelegate.ExceptionHandler exceptionHandler)
        {
            var           headBuffer    = new byte[1];
            AsyncCallback asyncCallback = null;

            asyncCallback = asyncResult =>
            {
                try
                {
                    int numBytesRead = stream.EndRead(asyncResult);
                    if (numBytesRead != 1)
                    {
                        throw new EndOfStreamException();
                    }
                    switch (headBuffer[0])
                    {
                    case Bcp.Data.HeadByte:
                    {
                        ProcessReadVarint processReadLength = delegate(uint length)
                        {
                            if (length > Bcp.MaxDataSize)
                            {
                                throw new BcpException.DataTooBig();
                            }
                            var            buffer         = new byte[length];
                            ProcessReadAll processReadAll = delegate()
                            {
                                processRead(new Bcp.Data(new[] { (new ArraySegment <byte>(buffer)) }));
                            };
                            ReadAll(stream, readState, buffer, 0, (int)length, processReadAll, exceptionHandler);
                        };
                        ReadUnsignedVarint(stream, readState, processReadLength, exceptionHandler);
                        break;
                    }

                    case Bcp.RetransmissionData.HeadByte:
                    {
                        ProcessReadVarint processReadConnectionId = delegate(uint connectionId)
                        {
                            ProcessReadVarint processReadPackId = delegate(uint packId)
                            {
                                ProcessReadVarint processReadLength = delegate(uint length)
                                {
                                    if (length > Bcp.MaxDataSize)
                                    {
                                        throw new BcpException.DataTooBig();
                                    }
                                    var            buffer         = new byte[length];
                                    ProcessReadAll processReadAll = delegate()
                                    {
                                        processRead(new Bcp.RetransmissionData(connectionId, packId, new[] { (new ArraySegment <byte>(buffer)) }));
                                    };
                                    ReadAll(stream, readState, buffer, 0, (int)length, processReadAll, exceptionHandler);
                                };
                                ReadUnsignedVarint(stream, readState, processReadLength, exceptionHandler);
                            };
                            ReadUnsignedVarint(stream, readState, processReadPackId, exceptionHandler);
                        };
                        ReadUnsignedVarint(stream, readState, processReadConnectionId, exceptionHandler);
                        break;
                    }

                    case Bcp.RetransmissionFinish.HeadByte:
                    {
                        ProcessReadVarint processReadConnectionId = delegate(uint connectionId)
                        {
                            ProcessReadVarint processReadPackId = delegate(uint packId)
                            {
                                processRead(new Bcp.RetransmissionFinish(connectionId, packId));
                            };
                            ReadUnsignedVarint(stream, readState, processReadPackId, exceptionHandler);
                        };
                        ReadUnsignedVarint(stream, readState, processReadConnectionId, exceptionHandler);
                        break;
                    }

                    case Bcp.Acknowledge.HeadByte:
                        processRead(new Bcp.Acknowledge());
                        break;

                    case Bcp.Finish.HeadByte:
                        processRead(new Bcp.Finish());
                        break;

                    case Bcp.ShutDown.HeadByte:
                        processRead(new Bcp.ShutDown());
                        break;

                    case Bcp.HeartBeat.HeadByte:
                        processRead(new Bcp.HeartBeat());
                        break;

                    default:
                        throw new BcpException.UnknownHeadByte();
                    }
                }
                catch (Exception e)
                {
                    exceptionHandler(e);
                }
            };
            try
            {
                stream.BeginRead(headBuffer, 0, 1, asyncCallback, readState);
            }
            catch (Exception e)
            {
                exceptionHandler(e);
            }
        }
Beispiel #7
0
        private void StartReceive(uint connectionId, Connection connection)
        {
            BcpDelegate.ProcessRead processRead = delegate(Bcp.IPacket packet)
            {
                var readTimer = connection.readState.readTimeoutTimer;
                readTimer.Change(Timeout.Infinite, Timeout.Infinite);
                readTimer.Dispose();
                readTimer = null;
                if (packet is Bcp.HeartBeat)
                {
                    Debug.WriteLine("Receive heart beat!");
                    StartReceive(connectionId, connection);
                }
                else if (packet is Bcp.Data)
                {
                    Debug.WriteLine("Receive data: " + packet);
                    lock (sessionLock)
                    {
                        BcpIO.Write(connection.stream, new Bcp.Acknowledge());
                        var data   = (Bcp.Data)packet;
                        var buffer = data.Buffers;
                        ResetHeartBeatTimer(connection);
                        var packId = connection.numDataReceived;
                        connection.numDataReceived = packId + 1;
                        DataReceived(connectionId, connection, packId, buffer);
                        connection.stream.Flush();
                    }
                    StartReceive(connectionId, connection);
                }
                else if (packet is Bcp.RetransmissionData)
                {
                    Debug.WriteLine("Receive retransmission data: " + packet);
                    lock (sessionLock)
                    {
                        BcpIO.Write(connection.stream, new Bcp.Acknowledge());
                        var retransmissionData = (Bcp.RetransmissionData)packet;
                        var dataConnectionId   = retransmissionData.ConnectionId;
                        var packId             = retransmissionData.PackId;
                        var data = retransmissionData.Buffers;
                        ResetHeartBeatTimer(connection);
                        Connection dataConnection;
                        if (connections.TryGetValue(dataConnectionId, out dataConnection))
                        {
                            DataReceived(dataConnectionId, dataConnection, packId, data);
                        }
                        else
                        {
                            var oldLastConnectionId = lastConnectionId;
                            if (dataConnectionId - oldLastConnectionId + connections.Count >= Bcp.MaxConnectionsPerSession)
                            {
                                InternalInterrupt();
                            }
                            else
                            {
                                if (oldLastConnectionId <= dataConnectionId)
                                {
                                    lastConnectionId = dataConnectionId;
                                    for (var id = oldLastConnectionId + 1; id < dataConnectionId; ++id)
                                    {
                                        Connection c = NewConnection();
                                        connections.Add(id, c);
                                    }
                                    DataReceived(dataConnectionId, GetLastConnection(), packId, data);
                                }
                                else
                                {
                                }
                            }
                        }
                        connection.stream.Flush();
                    }
                    StartReceive(connectionId, connection);
                }
                else if (packet is Bcp.Acknowledge)
                {
                    lock (sessionLock)
                    {
                        Debug.WriteLine("Before receive acknowledge, sendingConnectionQueue: " + sendingConnectionQueue.Count);
                        var originalPack = connection.unconfirmedPackets.Dequeue();
                        if (connection.unconfirmedPackets.Count == 0)
                        {
                            switch (connectionState)
                            {
                            case SessionState.Available:
                            {
                                foreach (var openConnections in sendingConnectionQueue)
                                {
                                    if (openConnections.Value.Contains(connection))
                                    {
                                        openConnections.Value.Remove(connection);
                                        if (openConnections.Value.Count == 0)
                                        {
                                            sendingConnectionQueue.Remove(openConnections.Key);
                                        }
                                        HashSet <Connection> allConfirmedConnections;
                                        if (sendingConnectionQueue.TryGetValue(allConfirmed, out allConfirmedConnections))
                                        {
                                            allConfirmedConnections.Add(connection);
                                        }
                                        else
                                        {
                                            allConfirmedConnections = new HashSet <Connection>();
                                            allConfirmedConnections.Add(connection);
                                            sendingConnectionQueue.Add(allConfirmed, allConfirmedConnections);
                                        }
                                        break;
                                    }
                                }
                                break;
                            }

                            case SessionState.Unavailable:
                                break;
                            }
                            Idle(connection);
                        }
                        if (originalPack is Bcp.Data)
                        {
                            connection.numAcknowledgeReceivedForData += 1;
                        }
                        else if (originalPack is Bcp.RetransmissionData ||
                                 originalPack is Bcp.Finish || originalPack is Bcp.RetransmissionFinish)
                        {
                        }
                        CheckConnectionFinish(connectionId, connection);
                        Debug.WriteLine("After receive acknowledge, sendingConnectionQueue: " + sendingConnectionQueue.Count);
                    }
                    StartReceive(connectionId, connection);
                }
                else if (packet is Bcp.Finish)
                {
                    Debug.WriteLine("receive finish, connectionId: " + connectionId.ToString());
                    lock (sessionLock)
                    {
                        BcpIO.Write(connection.stream, new Bcp.Acknowledge());
                        if (!connection.isFinishSent)
                        {
                            EnqueueFinish(connection);
                        }
                        var packId = connection.numDataReceived;
                        connection.finishID = packId;
                        CleanUp(connectionId, connection);
                        connection.stream.Dispose();
                        connection.stream = null;
                    }
                }
                else if (packet is Bcp.RetransmissionFinish)
                {
                    lock (sessionLock)
                    {
                        Debug.WriteLine("Before receive retransmission finish, sendingConnectionQueue: " + sendingConnectionQueue.Count);
                        BcpIO.Write(connection.stream, new Bcp.Acknowledge());
                        var retransmissionFinishPack = (Bcp.RetransmissionFinish)packet;
                        var finishConnectionId       = retransmissionFinishPack.ConnectionId;
                        var packId = retransmissionFinishPack.PackId;
                        ResetHeartBeatTimer(connection);
                        Connection finishConnection;
                        if (connections.TryGetValue(finishConnectionId, out finishConnection))
                        {
                            RetransmissionFinishReceived(finishConnectionId, finishConnection, packId);
                            CleanUp(finishConnectionId, finishConnection);
                        }
                        else
                        {
                            var oldLastConnectionId = lastConnectionId;
                            if (finishConnectionId - oldLastConnectionId + connections.Count >= Bcp.MaxConnectionsPerSession)
                            {
                                InternalInterrupt();
                            }
                            else
                            {
                                if (oldLastConnectionId < finishConnectionId)
                                {
                                    lastConnectionId = finishConnectionId;
                                    for (var id = oldLastConnectionId + 1; id <= finishConnectionId; ++id)
                                    {
                                        Connection c = NewConnection();
                                        connections.Add(id, c);
                                    }
                                    RetransmissionFinishReceived(finishConnectionId, GetLastConnection(), packId);
                                    CleanUp(finishConnectionId, GetLastConnection());
                                }
                                else
                                {
                                }
                            }
                        }
                        connection.stream.Flush();
                        Debug.WriteLine("After receive retransmission finish, sendingConnectionQueue: " + sendingConnectionQueue.Count);
                    }
                    StartReceive(connectionId, connection);
                }
                else if (packet is Bcp.ShutDown)
                {
                    Debug.WriteLine("Receive shut down!");
                    lock (sessionLock)
                    {
                        CheckShutDown();
                    }
                }
            };
            BcpDelegate.ExceptionHandler exceptionHandler = delegate(Exception e)
            {
                lock (sessionLock)
                {
                    if (!connection.readState.isCancel)
                    {
                        connection.readState.Cancel();
                        Console.WriteLine("Received exception: " + e.Message);
                        if (connection.stream != null)
                        {
                            connection.stream.Dispose();
                        }
                        CleanUp(connectionId, connection);
                    }
                }
            };
            connection.readState.readTimeoutTimer = StartReadTimer(connection.stream, exceptionHandler);
            BcpIO.Read(connection.stream, connection.readState, processRead, exceptionHandler);
        }