Пример #1
0
 private void AfterConnect(Stream stream)
 {
     Debug.WriteLine("Handle after connect!");
     if (stream != null)
     {
         Debug.WriteLine("Connect Success!");
         lock (sessionLock)
         {
             if (!isShutedDown)
             {
                 var connectionId = nextConnectionId + 1;
                 nextConnectionId += 1;
                 BcpIO.WriteHead(stream, new Bcp.ConnectionHead(sessionId, isRenew, connectionId));
                 AddStream(connectionId, stream);
                 Debug.WriteLine("Client added stream!");
                 Debug.WriteLine("Connection num: " + connections.Count);
                 isConnecting = false;
                 isRenew      = false;
             }
             else
             {
                 stream.Dispose();
             }
             stream.Flush();
         }
     }
 }
Пример #2
0
        private void Enqueue(Bcp.IAcknowledgeRequired newPack)
        {
            Debug.WriteLine("Enqueue pack: " + newPack);
            switch (connectionState)
            {
            case SessionState.Available:
            {
                Debug.WriteLine("Before available enqueue sendingConnectionQueue count: " + sendingConnectionQueue.Count);
                var sendingConnectionQueueEnumerator = sendingConnectionQueue.GetEnumerator();
                sendingConnectionQueueEnumerator.MoveNext();
                long time = sendingConnectionQueueEnumerator.Current.Key;
                HashSet <Connection> openConnections = sendingConnectionQueueEnumerator.Current.Value;
                var openConnectionsEnumerator        = openConnections.GetEnumerator();
                openConnectionsEnumerator.MoveNext();
                Connection connection = openConnectionsEnumerator.Current;
                Stream     stream     = connection.stream;
                Busy(connection);
                BcpIO.Write(stream, newPack);
                stream.Flush();
                connection.unconfirmedPackets.Enqueue(newPack);
                ResetHeartBeatTimer(connection);
                long currentTimeMillis = Environment.TickCount;
                HashSet <Connection> currentOpenConnections;
                openConnections.Remove(connection);
                if (openConnections.Count == 0)
                {
                    sendingConnectionQueue.Remove(time);
                }
                if (sendingConnectionQueue.TryGetValue(currentTimeMillis, out currentOpenConnections))
                {
                    currentOpenConnections.Add(connection);
                }
                else
                {
                    currentOpenConnections = new HashSet <Connection>();
                    currentOpenConnections.Add(connection);
                    sendingConnectionQueue.Add(currentTimeMillis, currentOpenConnections);
                }
                Debug.WriteLine("After available enqueue sendingConnectionQueue count: " + sendingConnectionQueue.Count);
                break;
            }

            case SessionState.Unavailable:
            {
                Debug.WriteLine("Before Unavailable enqueue: " + packQueue.Count);
                if (packQueue.Count >= Bcp.MaxOfflinePack)
                {
                    Debug.WriteLine("Sending queue is full!");
                    Interrupt();
                }
                else
                {
                    packQueue.Enqueue(newPack);
                }
                Debug.WriteLine("After Unavailable enqueue: " + packQueue.Count);
            }
            break;
            }
        }
Пример #3
0
        private void AddOpenConnection(Connection connection)
        {
            HashSet <Connection> openConnections;

            switch (connectionState)
            {
            case SessionState.Available:
                if (sendingConnectionQueue.TryGetValue(allConfirmed, out openConnections))
                {
                    openConnections.Add(connection);
                }
                else
                {
                    openConnections = new HashSet <Connection>();
                    openConnections.Add(connection);
                    sendingConnectionQueue.Add(allConfirmed, openConnections);
                }
                break;

            case SessionState.Unavailable:
                Debug.WriteLine("Unavailable add open connection, packQueue count: " + packQueue.Count);
                Stream stream = connection.stream;
                while (packQueue.Count > 0)
                {
                    var pack = packQueue.Dequeue();
                    BcpIO.Write(stream, pack);
                    connection.unconfirmedPackets.Enqueue(pack);
                }
                stream.Flush();
                EventHandler availableEventHandler = Available;
                if (availableEventHandler != null)
                {
                    try
                    {
                        availableEventHandler(this, EventArgs.Empty);
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine("Available event occur exception: " + e);
                    }
                }
                openConnections = new HashSet <Connection>();
                openConnections.Add(connection);
                sendingConnectionQueue = NewSendingConnectionQueue();
                if (packQueue.Count == 0)
                {
                    sendingConnectionQueue.Add(allConfirmed, openConnections);
                }
                else
                {
                    sendingConnectionQueue.Add(Environment.TickCount, openConnections);
                    Busy(connection);
                }
                connectionState = SessionState.Available;
                Debug.WriteLine("After unavailable add open connection, sendingConnectionQueue count: " + sendingConnectionQueue.Count);
                break;
            }
        }
Пример #4
0
 private void EnqueueFinish(Connection connection)
 {
     if (!connection.isFinishSent)
     {
         Bcp.Finish finishPacket = new Bcp.Finish();
         connection.unconfirmedPackets.Enqueue(finishPacket);
         Stream stream = connection.stream;
         BcpIO.Write(stream, finishPacket);
         stream.Flush();
         connection.isFinishSent = true;
     }
 }
Пример #5
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);
        }
Пример #6
0
        private void TrySend(Bcp.IPacket newPack)
        {
            switch (connectionState)
            {
            case SessionState.Available:
            {
                var sendingConnectionQueueEnumerator = sendingConnectionQueue.GetEnumerator();
                sendingConnectionQueueEnumerator.MoveNext();
                long time = sendingConnectionQueueEnumerator.Current.Key;
                HashSet <Connection> openConnections = sendingConnectionQueueEnumerator.Current.Value;
                var openConnectionsEnumerator        = openConnections.GetEnumerator();
                openConnectionsEnumerator.MoveNext();
                Connection connection = openConnectionsEnumerator.Current;
                Stream     stream     = connection.stream;
                BcpIO.Write(stream, newPack);
                stream.Flush();
                ResetHeartBeatTimer(connection);
                openConnections.Remove(connection);
                long currentTimeMillis = Environment.TickCount;
                HashSet <Connection> currentOpenConnections;
                openConnections.Remove(connection);
                if (openConnections.Count == 0)
                {
                    sendingConnectionQueue.Remove(time);
                }
                if (sendingConnectionQueue.TryGetValue(currentTimeMillis, out currentOpenConnections))
                {
                    currentOpenConnections.Add(connection);
                }
                else
                {
                    currentOpenConnections = new HashSet <Connection>();
                    currentOpenConnections.Add(connection);
                    sendingConnectionQueue.Add(currentTimeMillis, currentOpenConnections);
                }
                break;
            }

            case SessionState.Unavailable:
                break;
            }
        }
Пример #7
0
        private void HeartBeatEvent(Object source)
        {
            Debug.WriteLine("Sending heart beat!");
            var connection = (Connection)source;

            lock (sessionLock)
            {
                if (connection.stream != null)
                {
                    try
                    {
                        BcpIO.Write(connection.stream, new Bcp.HeartBeat());
                        connection.stream.Flush();
                    }
                    catch
                    {
                    }
                }
            }
        }
Пример #8
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);
        }