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(); } } }
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; } }
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; } }
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; } }
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); }
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; } }
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 { } } } }
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); }