public void Add(uint time, TransportEvent transport_event) { if(event_queue.ContainsKey(time) == false) { event_queue[time] = new List<TransportEvent>(); } event_queue[time].Add(transport_event); }
/// <summary> /// Expect to receive a PDU of any type from the remote host. /// </summary> /// <param name="timeout">Timeout of receiving PDU.</param> /// <returns>The expected PDU.</returns> /// <exception cref="System.TimeoutException">Thrown when the timeout parameter is negative.</exception> public KerberosPdu ExpectPdu(TimeSpan timeout, Type pduType = null) { this.expectedPduType = pduType; KerberosPdu pdu = null; if (UseProxy) { Debug.Assert(ProxyClient != null, "Proxy Client should be set when using proxy."); int consumedLength = 0; int expectedLength = 0; if (ProxyClient.Error == KKDCPError.STATUS_SUCCESS) { KDCProxyMessage message = ProxyClient.GetProxyResponse(); //temporarily change the tranpsort type to TCP, since all proxy messages are TCP format. var oriTransportType = Context.TransportType; Context.TransportType = TransportType.TCP; //get proxy message pdu = getExpectedPduFromBytes(message.Message.kerb_message.ByteArrayValue, out consumedLength, out expectedLength); //restore the original transport type Context.TransportType = oriTransportType; } } else { if (timeout.TotalMilliseconds < 0) { throw new TimeoutException(KerberosConstValue.TIMEOUT_EXCEPTION); } this.expectedPduType = pduType; TransportEvent eventPacket = kdcTransport.ExpectTransportEvent(timeout); pdu = (KerberosPdu)eventPacket.EventObject; this.DisConnect(); } return(pdu); }
public override bool ServerGetNextMessage(out int connectionId, out TransportEvent transportEvent, out byte[] data) { transportEvent = Mirror.TransportEvent.Disconnected; data = null; connectionId = 0; #if !UNITY_WEBGL || UNITY_EDITOR WebSocketMessage message = Server.GetNextMessage(); if (message == null) { return(false); } connectionId = message.connectionId; switch (message.Type) { case TransportEvent.Connected: transportEvent = TransportEvent.Connected; break; case TransportEvent.Data: transportEvent = TransportEvent.Data; data = message.Data; break; case TransportEvent.Disconnected: transportEvent = TransportEvent.Disconnected; break; default: break; } return(true); #else Debug.LogError(WebGLServerErrorMessage); return(false); #endif }
public bool ServerGetNextMessage(out int connectionId, out TransportEvent transportEvent, out byte[] data) { Telepathy.Message message; if (server.GetNextMessage(out message)) { switch (message.eventType) { // convert Telepathy EventType to TransportEvent case Telepathy.EventType.Connected: transportEvent = TransportEvent.Connected; break; case Telepathy.EventType.Data: transportEvent = TransportEvent.Data; break; case Telepathy.EventType.Disconnected: transportEvent = TransportEvent.Disconnected; break; default: transportEvent = TransportEvent.Disconnected; break; } // assign rest of the values and return true connectionId = message.connectionId; data = message.data; return(true); } connectionId = -1; transportEvent = TransportEvent.Disconnected; data = null; return(false); }
public void Update(INetworkCallbacks loop) { _transport.Update(); TransportEvent e = new TransportEvent(); while (_transport.NextEvent(ref e)) { switch (e.type) { case TransportEvent.Type.Connect: OnConnect(e.ConnectionId, loop); break; case TransportEvent.Type.Disconnect: OnDisconnect(e.ConnectionId, loop); break; case TransportEvent.Type.Data: OnData(e.ConnectionId, e.Data, loop); break; } } }
public bool ServerGetNextMessage(out int connectionId, out TransportEvent transportEvent, out ArraySegment <byte> data) { throw new NotImplementedException(); }
public bool ClientGetNextMessage(out TransportEvent transportEvent, out ArraySegment <byte> data) { throw new NotImplementedException(); }
/// <summary> /// The meat and vegies of the transport on the server side. This is the packet pump. /// </summary> /// <param name="connectionId">The incoming connection ID.</param> /// <param name="transportEvent">What event is this? Connection? Data? Disconnection?</param> /// <param name="data">Byte array of the data payload being received.</param> /// <returns>True if successful, False if unsuccessful.</returns> public bool ServerGetNextMessage(out int connectionId, out TransportEvent transportEvent, out byte[] data) { // The incoming Enet Event. Event incomingEvent; // Mirror's transport event and data output. transportEvent = TransportEvent.Disconnected; data = null; connectionId = -1; if (!server.IsSet) { LogWarning("Ignorance Transport: Hold on, the server is not ready yet."); return(false); } // Get the next message... server.Service(0, out incomingEvent); // What type is this? switch (incomingEvent.Type) { // Connections (Normal peer connects) case EventType.Connect: if (verboseLoggingEnabled) { Log($"Ignorance Transport: New connection with peer ID {incomingEvent.Peer.ID}, IP {incomingEvent.Peer.IP}"); } // Peer ID from ENet Wrapper will be a unsigned Int32. Since Mirror uses a signed int, we need to do a hacky work around. // This sucks, but it has to be done for now. Give the new connection a fake connection ID, but also cache the Peer. connectionId = serverConnectionCount; // The peer object will allow us to do stuff with it later. // Map them in our dictionaries knownPeersToConnIDs.Add(incomingEvent.Peer, connectionId); knownConnIDToPeers.Add(connectionId, incomingEvent.Peer); if (verboseLoggingEnabled) { Log($"Ignorance Transport: Mapped peer ID {incomingEvent.Peer.ID} (from IP {incomingEvent.Peer.IP}) => server connID {connectionId}"); } else { Log($"Ignorance Transport: New connection from IP {incomingEvent.Peer.IP}. Peer ID {incomingEvent.Peer.ID} mapped to internal connection ID {connectionId}"); } // Increment the fake connection counter by one. serverConnectionCount++; // If we're using custom timeouts, then set the timeouts too. if (useCustomPeerTimeout) { incomingEvent.Peer.Timeout(Library.throttleScale, peerBaseTimeout, peerBaseTimeout * peerBaseTimeoutMultiplier); } // Report back saying we got a connection event. transportEvent = TransportEvent.Connected; break; // Disconnections (Normal peer disconnect and timeouts) case EventType.Disconnect: case EventType.Timeout: if (verboseLoggingEnabled) { Log($"Ignorance Transport: ServerGetNextMessage(): {(incomingEvent.Type == EventType.Disconnect ? "disconnect" : "timeout")} event, peer ID {incomingEvent.Peer.ID}, IP {incomingEvent.Peer.IP}"); } Log($"Ignorance Transport: Acknowledging disconnection on connection ID {knownPeersToConnIDs[incomingEvent.Peer]}"); if (knownPeersToConnIDs.ContainsKey(incomingEvent.Peer)) { PeerDisconnectedInternal(incomingEvent.Peer); } transportEvent = TransportEvent.Disconnected; break; case EventType.Receive: transportEvent = TransportEvent.Data; if (verboseLoggingEnabled) { Log($"Ignorance Transport: ServerGetNextMessage(): Data channel {incomingEvent.ChannelID} receiving {incomingEvent.Packet.Length} byte payload..."); } // Only process data from known peers. if (knownPeersToConnIDs.ContainsKey(incomingEvent.Peer)) { connectionId = knownPeersToConnIDs[incomingEvent.Peer]; // Copy our data into our buffers. data = new byte[incomingEvent.Packet.Length]; incomingEvent.Packet.CopyTo(data); incomingEvent.Packet.Dispose(); if (verboseLoggingEnabled) { Log($"Ignorance Transport: ServerGetNextMessage() Payload:\n {BitConverter.ToString(data)}"); } } break; case EventType.None: // Nothing happened. Do nothing. return(false); } // We're done here. Bugger off. return(true); }
/// <summary> /// Creates a new Socket for a newly created connection and a new thread to receive packet in the loop. /// </summary> private void AcceptLoop() { while (!exitLoop) { if (this.receivingStreams.Count >= config.MaxConnections) { // not listen untill the current connections are less than the max value. // the interval to query is 1 seconds: Thread.Sleep(1000); continue; } Socket socket = null; try { socket = this.listenSock.Accept(); } catch (SocketException) { exitLoop = true; continue; } TransportEvent connectEvent; Stream receiveStream = null; Stream baseStream = new NetworkStream(socket); switch (streamType) { case SecurityStreamType.None: receiveStream = baseStream; break; case SecurityStreamType.Ssl: receiveStream = new SslStream( new ETWStream( baseStream), false ); ((SslStream)receiveStream).AuthenticateAsServer(cert); break; case SecurityStreamType.CredSsp: string targetSPN = ConstValue.CREDSSP_SERVER_NAME_PREFIX + config.LocalIpAddress; var csspServer = new CsspServer(new ETWStream(baseStream)); var credSspStream = csspServer.GetStream(); csspServer.Authenticate(cert, targetSPN); receiveStream = credSspStream; break; default: receiveStream = baseStream; break; } RdpbcgrReceiveThread receiveThread = new RdpbcgrReceiveThread( socket.RemoteEndPoint, this.packetQueue, this.decoder, receiveStream, this.config.BufferSize, this.rdpbcgrServer); connectEvent = new TransportEvent(EventType.Connected, socket.RemoteEndPoint, null); RdpbcgrServerSessionContext session = new RdpbcgrServerSessionContext(); session.Identity = connectEvent.EndPoint; session.Server = this.rdpbcgrServer; session.LocalIdentity = socket.LocalEndPoint; session.IsClientToServerEncrypted = this.rdpbcgrServer.IsClientToServerEncrypted; this.rdpbcgrServer.ServerContext.AddSession(session); this.packetQueue.AddObject(connectEvent); lock (this.receivingStreams) { this.receivingStreams.Add(socket, receiveThread); } receiveThread.Start(); } }
public static bool ReceiveSimulatedMessage(Source source, out int connectionID, out TransportEvent transportEvent, out ArraySegment <byte> data) { if (source == Source.Server) { if (simulatedServerQueue.TryDequeue(out SimulatedMessage message)) { // convert Telepathy EventType to TransportEvent transportEvent = (TransportEvent)message.eventType; // assign rest of the values and return true connectionID = message.connectionID; if (message.data != null) { data = new ArraySegment <byte>(message.data); } else { data = default; } return(true); } } if (source == Source.Client) { if (simulatedClientQueue.TryDequeue(out SimulatedMessage message)) { // convert Telepathy EventType to TransportEvent transportEvent = (TransportEvent)message.eventType; // assign rest of the values and return true connectionID = -1; if (message.data != null) { data = new ArraySegment <byte>(message.data); } else { data = default; } return(true); } } connectionID = -1; transportEvent = TransportEvent.Data; data = default; return(false); }
public bool ClientGetNextMessage(out TransportEvent transportEvent, out byte[] data) { return(client.ClientGetNextMessage(out transportEvent, out data)); }
public bool ClientGetNextMessage(out TransportEvent transportEvent, out ArraySegment <byte> data) { return(client.ClientGetNextMessage(out transportEvent, out data)); }
/// <summary> /// Add transport event to transport, TSD can invoke ExpectTransportEvent to get it. /// </summary> /// <param name="transportEvent"> /// a TransportEvent object that contains the event to add to the queue /// </param> public void AddEvent(TransportEvent transportEvent) { this.packetQueue.AddObject(transportEvent); }
/// <summary> /// Get the next client data packet. /// </summary> /// <param name="transportEvent">The transport event to report back to Mirror.</param> /// <param name="data">The byte array of the data.</param> /// <returns></returns> public bool ClientGetNextMessage(out TransportEvent transportEvent, out byte[] data) { // Setup some basic things // v1.0.1: Some minor optimization. For v1.0.0 behaviour, uncomment this. // byte[] newDataPacketContents; // The incoming Enet Event. Event incomingEvent; // Mirror's transport event and data output. transportEvent = TransportEvent.Disconnected; data = null; // Safety check: if the client isn't created, then we shouldn't do anything. ENet might be warming up. if (!client.IsSet) { Debug.LogWarning("Ignorance Transport: Hold on, the client is not ready yet."); return(false); } // Get the next message... client.Service(0, out incomingEvent); // Debugging only if (superParanoidMode) { Debug.Log("ClientGetNextMessage event: " + incomingEvent.Type); } switch (incomingEvent.Type) { // Peer connects. case EventType.Connect: if (superParanoidMode) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage() connect; real ENET peerID {0}, address {1}", incomingEvent.Peer.ID, incomingEvent.Peer.IP); } // If we're using custom timeouts, then set the timeouts too. if (useCustomPeerTimeout) { incomingEvent.Peer.Timeout(Library.throttleScale, peerBaseTimeout, peerBaseTimeout * peerBaseTimeoutMultiplier); } transportEvent = TransportEvent.Connected; break; // Peer disconnects/timeout. case EventType.Disconnect: case EventType.Timeout: if (superParanoidMode) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage() {0}; peerID {1}, address {2}", (incomingEvent.Type == EventType.Disconnect ? "disconnect" : "timeout"), incomingEvent.Peer.ID, incomingEvent.Peer.IP); } transportEvent = TransportEvent.Disconnected; break; // Peer sends data to us. case EventType.Receive: transportEvent = TransportEvent.Data; if (superParanoidMode) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage(): Data channel {0} receiving {1} byte payload...", incomingEvent.ChannelID, incomingEvent.Packet.Length); } // v1.0.1: Some minor optimization. For v1.0.0 behaviour, uncomment the next line and comment out the line below the newly uncommented line. // newDataPacketContents = new byte[incomingEvent.Packet.Length]; data = new byte[incomingEvent.Packet.Length]; incomingEvent.Packet.CopyTo(data); incomingEvent.Packet.Dispose(); // v1.0.1: Some minor optimization. For v1.0.0 behaviour, uncomment the next lines and comment out the line under the newly uncommented lines. // if (superParanoidMode) Debug.LogFormat("Ignorance rUDP Transport ClientGetNextMessage() Incoming data: {0}", BitConverter.ToString(newDataPacketContents)); // data = newDataPacketContents; if (superParanoidMode) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage() Payload data:\n{0}", BitConverter.ToString(data)); } break; case EventType.None: return(false); } // We're done here. Bugger off. return(true); }
public abstract bool ServerGetNextMessage(out int connectionId, out TransportEvent transportEvent, out byte[] data);
public abstract bool ClientGetNextMessage(out TransportEvent transportEvent, out byte[] data);
/** * Check for new network messages */ private bool Receive(out int connectionId, out TransportEvent transportEvent, out byte[] data, int chan) { data = null; //finally look for new packets uint packetSize; CSteamID clientSteamID; if (SteamNetworking.IsP2PPacketAvailable(out packetSize, chan)) { //check we have enough room for this packet if (packetSize > Transport.MaxPacketSize) { //cant read .. too big! should error here Debug.LogError("Available message is too large"); connectionId = -1; transportEvent = TransportEvent.Disconnected; return(false); } if (SteamNetworking.ReadP2PPacket(serverReceiveBuffer, packetSize, out packetSize /*actual size read*/, out clientSteamID, chan)) { SteamClient steamClient; try { //check we have a record for this connection steamClient = steamConnectionMap.fromSteamID[clientSteamID]; if (steamClient.state == SteamClient.ConnectionState.CONNECTING) { if (LogFilter.Debug) { Debug.Log("Received a new connection"); } if (packetSize > 0) { if (LogFilter.Debug) { Debug.Log("Message received with the new connection - postponed message"); } //we need to return the connection event but we also have data to return next time serverReceiveBufferPendingConnectionID = steamClient.connectionID; serverReceiveBufferPending = new byte[packetSize]; Array.Copy(serverReceiveBuffer, serverReceiveBufferPending, packetSize); } steamClient.state = SteamClient.ConnectionState.CONNECTED; transportEvent = TransportEvent.Connected; connectionId = steamClient.connectionID; return(true); } if (steamClient.state != SteamClient.ConnectionState.CONNECTED) { //we are not currently connected to this client - this shouldnt happen Debug.LogError("Received a message for a client thats not connected"); connectionId = -1; transportEvent = TransportEvent.Disconnected; return(false); } } catch (KeyNotFoundException) { if (packetSize == 0) { Debug.LogError("SUPPRISE New connection"); //ok so this happens when steam knows when we reconnect. we dont know about the client but steam has done the handshake before so we just have a blank hello message HandleNewConnection(clientSteamID); } else { //This shouldnt happen Debug.LogError("Totally unexpected steam ID " + clientSteamID + " sent a message size: " + packetSize + " / byte: " + serverReceiveBuffer[0]); } connectionId = -1; transportEvent = TransportEvent.Disconnected; return(false); } //received normal data packet if (packetSize == 0) { //ok so, sometimes in steam p2p we send a blank packet just to handshake.. this should just be around connect, but we seem to be already connected. //best thing we can do is call another Receive return(Receive(out connectionId, out transportEvent, out data, chan)); } else { connectionId = steamClient.connectionID; transportEvent = TransportEvent.Data; //for now allocate a new buffer TODO: do we need to do this? data = new byte[packetSize]; Array.Copy(serverReceiveBuffer, data, packetSize); return(true); } } } //nothing available connectionId = -1; transportEvent = TransportEvent.Disconnected; //they havent disconnected but this is what the LLAPITransport returns here. There is not a "nothing" event return(false); }
// 매 프레임 호출. public override void execute() { // ---------------------------------------------------------------- // // 다음 상태로 전환할지 체크. switch (this.step.do_transition()) { // 무아저씨 등장 데모. case STEP.DEMO0: { if (EventRoot.get().getCurrentEvent() == null) { this.step.set_next(STEP.SELECT_WEAPON); } } break; // 무기 아아템을 선택할 때까지. case STEP.SELECT_WEAPON: { // 무기 아이템을 선택했으면 다음으로 . if (this.player.getShotType() != SHOT_TYPE.EMPTY) { // 선택되지 않은 무기 아이템 삭제. List <ItemController> shot_items = ItemManager.get().findItems(x => x.name.StartsWith("shot")); foreach (var item in shot_items) { ItemManager.get().deleteItem(item.name); } this.select_done_players[this.player.getGlobalIndex()] = true; // 무기 아이템의 스포트 라이트를 지우고 열쇠 위치에 스포트 라이트. this.spotlight_items[0].setPosition(WeaponSelectLevelSequence.getKeyStayPosition().Y(4.0f)); this.spotlight_items[1].SetActive(false); this.step.set_next(STEP.PICKUP_KEY); } } break; // 열쇠를 주을 때까지. case STEP.PICKUP_KEY: { if (ItemManager.get().findItem(this.key_instance_name) == null) { this.spotlight_items[0].SetActive(false); this.step.set_next(STEP.ENTER_DOOR); } } break; // 문으로 들어갈 때까지. case STEP.ENTER_DOOR: { TransportEvent ev = EventRoot.get().getCurrentEvent <TransportEvent>(); if (ev != null) { ev.setEndAtHoleIn(true); this.step.set_next(STEP.TRANSPORT); } } break; // 플로어 이동 이벤트. case STEP.TRANSPORT: { TransportEvent ev = EventRoot.get().getCurrentEvent <TransportEvent>(); if (ev == null) { // 초기 장비의 동기화 대기 쿼리를 발행 . var query = new QuerySelectFinish(this.player.control.getAccountID()); // 쿼리의 타임아웃을 연장. query.timeout = 20.0f; QueryManager.get().registerQuery(query); // 선택한 무기를 게임 서버에 알림. if (this.m_network != null) { CharEquipment equip = new CharEquipment(); equip.globalId = GlobalParam.get().global_account_id; equip.shotType = (int)this.player.getShotType(); Debug.Log("[CLIENT] Send equip AccountID:" + equip.globalId + " ShotType:" + equip.shotType); EquipmentPacket packet = new EquipmentPacket(equip); int serverNode = this.m_network.GetServerNode(); this.m_network.SendReliable <CharEquipment>(serverNode, packet); } else { query.set_done(true); query.set_success(true); } this.step.set_next(STEP.WAIT_FRIEND); } } break; // 다른 플레이어 기다림. case STEP.WAIT_FRIEND: { // 던전으로 이동하는 신호 기다림. if (this.select_scene_finish) { // 만약을 위해 선택 완료가 되지 않은 아이콘을 강제로 선택 완료로 표시. // 해버린다. foreach (var icon in this.selecting_icons) { if (icon.step.get_current() == SelectingIcon.STEP.HAI) { continue; } icon.beginHai(); } this.step.set_next_delay(STEP.FINISH, 2.0f); } } break; } // ---------------------------------------------------------------- // // 상태 전환 시 초기화 while (this.step.get_next() != STEP.NONE) { switch (this.step.do_initialize()) { // 무아저씨 등장 데모. case STEP.DEMO0: { EventRoot.get().startEvent <EventWeaponSelect>(); } break; // 열쇠 줍기. case STEP.PICKUP_KEY: { // 플로어 열쇠가 외위에서 떨어진다. this.create_floor_key(); } break; // 문에 들어갈 때까지. case STEP.ENTER_DOOR: { this.spotlight_key.SetActive(true); } break; // 플로어 이동 이벤트. case STEP.TRANSPORT: { this.kabusan.onBeginTransportEvent(); } break; // 다른 플레이어 기다림. case STEP.WAIT_FRIEND: { // 다른 플레이어의 상황을 나타내는 아이콘을 표시. foreach (var icon in this.selecting_icons) { icon.setVisible(true); } } break; case STEP.FINISH: { GameRoot.get().setNextScene("GameScene"); } break; } } // ---------------------------------------------------------------- // // 각 상태에서의 실행 처리. switch (this.step.do_execution(Time.deltaTime)) { // 다른 플레이어 기다림. case STEP.WAIT_FRIEND: { foreach (var icon in this.selecting_icons) { if (icon.step.get_current() == SelectingIcon.STEP.UUN) { continue; } if (this.select_done_players[icon.player_index]) { icon.beginHai(); } } } break; } // ---------------------------------------------------------------- // this.spotlight_player.setPosition(this.player.control.getPosition().Y(4.0f)); this.spotlight_kabusan.setPosition(this.kabusan.control.getPosition().Y(8.0f)); this.update_queries(); }
private void ReceiveLoopInternal() { StackPacket[] packets = null; ReceiveStatus receiveStatus = ReceiveStatus.Success; //object endPoint = null; int bytesRecv = 0; int leftCount = 0; int expectedLength = this.maxBufferSize; while (!receiveThreadCancellationTokenSource.IsCancellationRequested) { if (expectedLength <= 0) { expectedLength = this.maxBufferSize; } byte[] receivingBuffer = new byte[expectedLength]; try { bytesRecv = this.receiveStream.Read(receivingBuffer, 0, receivingBuffer.Length); if (bytesRecv == 0) { receiveStatus = ReceiveStatus.Disconnected; } else { receiveStatus = ReceiveStatus.Success; } } catch (IOException ioException) { if (ioException.InnerException is SocketException socketException) { if (socketException.SocketErrorCode == SocketError.WouldBlock) { continue; } } // If this is an IOException, treat it as a disconnection. if (this.packetQueue != null) { TransportEvent exceptionEvent = new TransportEvent(EventType.Disconnected, this.endPointIdentity, null); this.packetQueue.AddObject(exceptionEvent); break; } else { throw; } } if (receiveStatus == ReceiveStatus.Success) { byte[] data = new byte[bytesRecv + receivedCaches.Length]; Array.Copy(receivedCaches, data, receivedCaches.Length); Array.Copy(receivingBuffer, 0, data, receivedCaches.Length, bytesRecv); while (true) { int consumedLength; try { packets = this.decoder(this.endPointIdentity, data, out consumedLength, out expectedLength); } catch (Exception e) { TransportEvent exceptionEvent = new TransportEvent(EventType.Exception, this.endPointIdentity, e); this.packetQueue.AddObject(exceptionEvent); // If decoder throw exception, we think decoder will throw exception again when it decode // subsequent received data So here we terminate the receive thread. return; } if (consumedLength > 0) { //add packet to queue if (packets != null && packets.Length > 0) { AddPacketToQueueManager(this.endPointIdentity, packets); } //check if continue the decoding leftCount = data.Length - consumedLength; if (leftCount <= 0) { receivedCaches = new byte[0]; data = new byte[0]; break; } else { // Update caches contents to the bytes which is not consumed receivedCaches = new byte[leftCount]; Array.Copy(data, consumedLength, receivedCaches, 0, leftCount); data = new byte[receivedCaches.Length]; Array.Copy(receivedCaches, data, data.Length); } } else { //if no data consumed, it means the left data cannot be decoded separately, so cache it and jump out. receivedCaches = new byte[data.Length]; Array.Copy(data, receivedCaches, receivedCaches.Length); break; } } } else if (receiveStatus == ReceiveStatus.Disconnected) { if (this.packetQueue != null) { TransportEvent disconnectEvent = new TransportEvent(EventType.Disconnected, this.endPointIdentity, null); this.packetQueue.AddObject(disconnectEvent); break; } else { throw new InvalidOperationException("The transport is disconnected by remote host."); } } else { throw new InvalidOperationException("Unknown status returned from receiving method."); } } }
/// <summary> /// The meat and vegies of the transport on the server side. This is the packet pump. /// </summary> /// <param name="connectionId">The incoming connection ID.</param> /// <param name="transportEvent">What event is this? Connection? Data? Disconnection?</param> /// <param name="data">Byte array of the data payload being received.</param> /// <returns>True if successful, False if unsuccessful.</returns> public bool ServerGetNextMessage(out int connectionId, out TransportEvent transportEvent, out byte[] data) { // The incoming Enet Event. Event incomingEvent; // Mirror's transport event and data output. transportEvent = TransportEvent.Disconnected; data = null; connectionId = -1; if (!server.IsSet) { Debug.LogWarning("Ignorance Transport: Hold on, the server is not ready yet."); return(false); } // Get the next message... server.Service(0, out incomingEvent); // What type is this? switch (incomingEvent.Type) { // Connections (Normal peer connects) case EventType.Connect: if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: New connection with peer ID {0}, IP {1}", incomingEvent.Peer.ID, incomingEvent.Peer.IP); } // Peer ID from ENet Wrapper will be a unsigned Int32. Since Mirror uses a signed int, we need to do a hacky work around. // This sucks, but it has to be done for now. Give the new connection a fake connection ID, but also cache the Peer. connectionId = serverConnectionCount; // The peer object will allow us to do stuff with it later. knownPeerConnections.Add(connectionId, incomingEvent.Peer); if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: Mapped peer ID {1} (from IP {2}) => fake connID {0}", serverConnectionCount, incomingEvent.Peer.ID, incomingEvent.Peer.IP); } else { Debug.LogFormat("Ignorance Transport: New connection from IP {0}. Peer ID {1} mapped to internal connection ID {2}", incomingEvent.Peer.IP, incomingEvent.Peer.ID, serverConnectionCount); } // Increment the fake connection counter by one. serverConnectionCount += 1; // If we're using custom timeouts, then set the timeouts too. if (useCustomPeerTimeout) { incomingEvent.Peer.Timeout(Library.throttleScale, peerBaseTimeout, peerBaseTimeout * peerBaseTimeoutMultiplier); } // Report back saying we got a connection event. transportEvent = TransportEvent.Connected; break; // Disconnections (Normal peer disconnect and timeouts) case EventType.Disconnect: case EventType.Timeout: if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: ServerGetNextMessage(): {0} event, peer ID {1}, IP {2}", (incomingEvent.Type == EventType.Disconnect ? "disconnect" : "timeout"), incomingEvent.Peer.ID, incomingEvent.Peer.IP); } // Peer ID from ENet Wrapper will be a unsigned Int32. Since Mirror uses a signed int, we need to do a hacky work around. // Since our dictionary stores fake connection IDs, we need to go through and find the real Peer ID. This could be improved. foreach (KeyValuePair <int, Peer> entry in knownPeerConnections) { if (entry.Value.ID == incomingEvent.Peer.ID) { connectionId = entry.Key; if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: Evicting peer ID {0} (fake connID {1})", incomingEvent.Peer.ID, entry.Key); } else { Debug.LogFormat("Ignorance Transport: Connection ID {0} {1}", entry.Key, (incomingEvent.Type == EventType.Disconnect ? "disconnected" : "timed out")); } knownPeerConnections.Remove(entry.Key); // No need to keep going through the list. Halt. break; } } // Report back. transportEvent = TransportEvent.Disconnected; break; case EventType.Receive: transportEvent = TransportEvent.Data; if (verboseLoggingEnabled) { Debug.LogWarningFormat("Ignorance Transport: ServerGetNextMessage(): Data channel {0} receiving {1} byte payload...", incomingEvent.ChannelID, incomingEvent.Packet.Length); } foreach (KeyValuePair <int, Peer> entry in knownPeerConnections) { if (entry.Value.ID == incomingEvent.Peer.ID) { // Debug.LogFormat("PeerID {0} maps to connection ID {1}", incomingEvent.Peer.ID, entry.Key); connectionId = entry.Key; // No need to keep going through the list. Halt. break; } } // Copy our data into our buffers. data = new byte[incomingEvent.Packet.Length]; incomingEvent.Packet.CopyTo(data); incomingEvent.Packet.Dispose(); if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: ServerGetNextMessage() Payload:\n {0}", BitConverter.ToString(data)); } break; case EventType.None: // Nothing happened. Do nothing. return(false); } // We're done here. Bugger off. return(true); }
private void AcceptLoopInternal() { listenSock = new Socket(config.LocalIpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); var streamType = config.StreamType; var endPoint = new IPEndPoint(config.LocalIpAddress, config.LocalIpPort); listenSock.Bind(endPoint); listenSock.Listen(config.MaxConnections); UpdateSocketBlockingMode(listenSock, false); while (!acceptThreadCancellationTokenSource.IsCancellationRequested) { if (this.receivingStreams.Count >= config.MaxConnections) { // not listen untill the current connections are less than the max value. // the interval to query is 1 seconds: Thread.Sleep(1000); continue; } Socket socket = null; try { socket = this.listenSock.Accept(); UpdateSocketBlockingMode(socket, true); } catch (SocketException socketException) { if (socketException.SocketErrorCode == SocketError.WouldBlock) { continue; } throw; } TransportEvent connectEvent; Stream receiveStream = null; Stream baseStream = new NetworkStream(socket); switch (streamType) { case SecurityStreamType.None: receiveStream = baseStream; break; case SecurityStreamType.CredSsp: string targetSPN = ConstValue.CREDSSP_SERVER_NAME_PREFIX + config.LocalIpAddress; var csspServer = new CsspServer(new ETWStream(baseStream)); var credSspStream = csspServer.GetStream(); csspServer.Authenticate(cert, targetSPN); receiveStream = credSspStream; break; default: receiveStream = baseStream; break; } // Start receive thread with non-blocking mode. UpdateSocketBlockingMode(socket, false); RdpbcgrReceiveThread receiveThread = new RdpbcgrReceiveThread( socket.RemoteEndPoint, this.packetQueue, this.decoder, receiveStream, this.config.BufferSize ); connectEvent = new TransportEvent(EventType.Connected, socket.RemoteEndPoint, null); RdpbcgrServerSessionContext session = new RdpbcgrServerSessionContext(); session.Identity = connectEvent.EndPoint; session.Server = this.rdpbcgrServer; session.LocalIdentity = socket.LocalEndPoint; session.IsClientToServerEncrypted = this.rdpbcgrServer.IsClientToServerEncrypted; this.rdpbcgrServer.ServerContext.AddSession(session); this.packetQueue.AddObject(connectEvent); lock (this.receivingStreams) { this.receivingStreams.Add(socket, receiveThread); } receiveThread.Start(); } }
/* * Check for messages and also deal with new connections and disconnects etc */ private bool ReceiveAndProcessEvents(out int connectionId, out TransportEvent transportEvent, out byte[] data, int chan) { data = null; //first check if we have received any new connections and return them as an event if (steamNewConnections.Count > 0) { if (LogFilter.Debug || debug) { Debug.Log("Handling a new connection from queue"); } connectionId = steamNewConnections.Dequeue(); try { SteamClient steamClient = steamConnectionMap.fromConnectionID[connectionId]; steamClient.timeIdle = 0; if (steamClient.state == SteamClient.ConnectionState.CONNECTING) { if (LogFilter.Debug || debug) { Debug.Log("Set connection state to connected"); } steamClient.state = SteamClient.ConnectionState.CONNECTED; } } catch (KeyNotFoundException) { //shouldnt happen - ignore } transportEvent = TransportEvent.Connected; return(true); } //first check if we have received any new disconnects and return them as an event if (steamDisconnectedConnections.Count > 0) { if (LogFilter.Debug || debug) { Debug.Log("Handling a disconnect from queue"); } SteamClient steamClient = steamDisconnectedConnections.Dequeue(); connectionId = steamClient.connectionID; transportEvent = TransportEvent.Disconnected; //at this point we have completly disconnected from the client so stop accepting further messages from this client SteamNetworking.CloseP2PSessionWithUser(steamClient.steamID); return(true); } //this is a buffer that may have been received at the same time as a new connection if (serverReceiveBufferPending != null) { if (LogFilter.Debug || debug) { Debug.Log("Handling a postponed message"); } //we have a packet received and already in the buffer waiting to be returned connectionId = serverReceiveBufferPendingConnectionID; transportEvent = TransportEvent.Data; data = serverReceiveBufferPending; //clear our buffered variables serverReceiveBufferPendingConnectionID = -1; serverReceiveBufferPending = null; return(true); } //finally look for new packets return(Receive(out connectionId, out transportEvent, out data, chan)); }
/// <summary> /// Get the next client data packet. /// </summary> /// <param name="transportEvent">The transport event to report back to Mirror.</param> /// <param name="data">The byte array of the data.</param> /// <returns></returns> public bool ClientGetNextMessage(out TransportEvent transportEvent, out byte[] data) { // The incoming Enet Event. Event incomingEvent; // Mirror's transport event and data output. transportEvent = TransportEvent.Disconnected; data = null; // Safety check: if the client isn't created, then we shouldn't do anything. ENet might be warming up. if (!client.IsSet) { Debug.LogWarning("Ignorance Transport: Hold on, the client is not ready yet."); return(false); } // Get the next message... client.Service(0, out incomingEvent); // Debugging only if (verboseLoggingEnabled) { Debug.Log("ClientGetNextMessage event: " + incomingEvent.Type); } switch (incomingEvent.Type) { // Peer connects. case EventType.Connect: if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage() connect; real ENET peerID {0}, address {1}", incomingEvent.Peer.ID, incomingEvent.Peer.IP); } else { Debug.LogFormat("Ignorance Transport: Connection established with {0}", incomingEvent.Peer.IP); } // If we're using custom timeouts, then set the timeouts too. if (useCustomPeerTimeout) { incomingEvent.Peer.Timeout(Library.throttleScale, peerBaseTimeout, peerBaseTimeout * peerBaseTimeoutMultiplier); } transportEvent = TransportEvent.Connected; break; // Peer disconnects/timeout. case EventType.Disconnect: case EventType.Timeout: if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage() {0}; peerID {1}, address {2}", (incomingEvent.Type == EventType.Disconnect ? "disconnect" : "timeout"), incomingEvent.Peer.ID, incomingEvent.Peer.IP); } else { Debug.LogFormat("Ignorance Transport: Client encountered {0}", (incomingEvent.Type == EventType.Disconnect ? "disconnection" : "timeout")); } transportEvent = TransportEvent.Disconnected; break; // Peer sends data to us. case EventType.Receive: transportEvent = TransportEvent.Data; if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage(): Data channel {0} receiving {1} byte payload...", incomingEvent.ChannelID, incomingEvent.Packet.Length); } data = new byte[incomingEvent.Packet.Length]; incomingEvent.Packet.CopyTo(data); incomingEvent.Packet.Dispose(); if (verboseLoggingEnabled) { Debug.LogFormat("Ignorance Transport: ClientGetNextMessage() Payload data:\n{0}", BitConverter.ToString(data)); } break; case EventType.None: return(false); } // We're done here. Bugger off. return(true); }
/** * Check for new network messages */ private bool Receive(out int connectionId, out TransportEvent transportEvent, out byte[] data, int chan) { data = null; //finally look for new packets uint packetSize; CSteamID clientSteamID; if (SteamNetworking.IsP2PPacketAvailable(out packetSize, chan)) { //check we have enough room for this packet if (packetSize > GetMaxPacketSize()) { //cant read .. too big! should error here Debug.LogError("Available message is too large"); connectionId = -1; transportEvent = TransportEvent.Disconnected; return(false); } if (SteamNetworking.ReadP2PPacket(serverReceiveBuffer, packetSize, out packetSize /*actual size read*/, out clientSteamID, chan)) { SteamClient steamClient; try { //check we have a record for this connection steamClient = steamConnectionMap.fromSteamID[clientSteamID]; if (steamClient.state != SteamClient.ConnectionState.CONNECTED) { //we are not currently connected to this client - this shouldnt happen Debug.LogError("Received a message for a client thats not connected"); connectionId = -1; transportEvent = TransportEvent.Disconnected; return(false); } steamClient.timeIdle = 0; } catch (KeyNotFoundException) { if (packetSize == 0) { Debug.LogWarning("Unexpected packet from steam client"); //ok so this happens when steam has previously accepted message from this client but they are not on our current list. This could be after quickly disconnecting a host and then starting it back up again for example. //It should be perfectly ok for this to happen in these types of circumstances HandleNewConnection(clientSteamID); } else { //This shouldnt happen Debug.LogError("Totally unexpected steam ID " + clientSteamID + " sent a message size: " + packetSize + " / byte: " + serverReceiveBuffer[0]); } connectionId = -1; transportEvent = TransportEvent.Disconnected; return(false); } //received normal data packet if (packetSize == 0) { //ok so, sometimes in steam p2p we send a blank packet just to handshake.. this should just be around connect, but we seem to be already connected. //best thing we can do is call another Receive return(Receive(out connectionId, out transportEvent, out data, chan)); } else { connectionId = steamClient.connectionID; transportEvent = TransportEvent.Data; //for now allocate a new buffer TODO: do we need to do this? data = new byte[packetSize]; Array.Copy(serverReceiveBuffer, data, packetSize); return(true); } } } //nothing available connectionId = -1; transportEvent = TransportEvent.Disconnected; //they havent disconnected but this is what the LLAPITransport returns here. There is not a "nothing" event return(false); }
/// <summary> /// Receive data, decode Packet and add them to QueueManager in the loop. /// </summary> private void ReceiveLoop() { StackPacket[] packets = null; ReceiveStatus receiveStatus = ReceiveStatus.Success; //object endPoint = null; int bytesRecv = 0; int leftCount = 0; int expectedLength = this.maxBufferSize; byte[] receivedCaches = new byte[0]; while (!exitLoop) { if (expectedLength <= 0) { expectedLength = this.maxBufferSize; } byte[] receivingBuffer = new byte[expectedLength]; try { bytesRecv = this.receiveStream.Read(receivingBuffer, 0, receivingBuffer.Length); if (bytesRecv == 0) { receiveStatus = ReceiveStatus.Disconnected; } else { receiveStatus = ReceiveStatus.Success; } } catch (System.IO.IOException) { // If this is an IOException, treat it as a disconnection. if (!exitLoop) { if (this.packetQueue != null) { TransportEvent exceptionEvent = new TransportEvent(EventType.Disconnected, this.endPointIdentity, null); this.packetQueue.AddObject(exceptionEvent); break; } else { throw; } } } catch (Exception e) { if (!exitLoop) { if (this.packetQueue != null) { TransportEvent exceptionEvent = new TransportEvent(EventType.Exception, this.endPointIdentity, e); this.packetQueue.AddObject(exceptionEvent); break; } else { throw; } } } if (receiveStatus == ReceiveStatus.Success) { byte[] data = new byte[bytesRecv + receivedCaches.Length]; Array.Copy(receivedCaches, data, receivedCaches.Length); Array.Copy(receivingBuffer, 0, data, receivedCaches.Length, bytesRecv); while (true) { int consumedLength; try { packets = this.decoder(this.endPointIdentity, data, out consumedLength, out expectedLength); } catch (Exception e) { TransportEvent exceptionEvent = new TransportEvent(EventType.Exception, this.endPointIdentity, e); this.packetQueue.AddObject(exceptionEvent); // If decoder throw exception, we think decoder will throw exception again when it decode // subsequent received data So here we terminate the receive thread. return; } if (consumedLength > 0) { //add packet to queue if (packets != null && packets.Length > 0) { AddPacketToQueueManager(this.endPointIdentity, packets); bytesRecv = 0; foreach (StackPacket pdu in packets) { if (pdu.GetType() == typeof(Client_X_224_Connection_Request_Pdu)) { // Block the thread if received a Client X224 Connection Request PDU // the main thread will resume the thread after it send X224 Connection confirm PDU and other necessary process, such as TLS Handshake rdpbcgrServer.ReceiveThreadControlEvent.WaitOne(); } } } //check if continue the decoding leftCount = data.Length - consumedLength; if (leftCount <= 0) { receivedCaches = new byte[0]; data = new byte[0]; break; } else { // Update caches contents to the bytes which is not consumed receivedCaches = new byte[leftCount]; Array.Copy(data, consumedLength, receivedCaches, 0, leftCount); data = new byte[receivedCaches.Length]; Array.Copy(receivedCaches, data, data.Length); } } else { //if no data consumed, it means the left data cannot be decoded separately, so cache it and jump out. receivedCaches = new byte[data.Length]; Array.Copy(data, receivedCaches, receivedCaches.Length); break; } } } else if (receiveStatus == ReceiveStatus.Disconnected) { if (this.packetQueue != null) { TransportEvent disconnectEvent = new TransportEvent(EventType.Disconnected, this.endPointIdentity, null); this.packetQueue.AddObject(disconnectEvent); break; } else { throw new InvalidOperationException("The transport is disconnected by remote host."); } } else { throw new InvalidOperationException("Unknown status returned from receiving method."); } } }
void Update() { // ---------------------------------------------------------------- // // 다음 상태로 전환할지 체크한다. switch (this.step.do_transition()) { case STEP.WAIT_ENTER: { if (this.is_unlocked) { if (this.keyItemName == null) { if (this.entered_players.Count >= PartyControl.get().getPlayerCount()) { this.step.set_next(STEP.EVENT_IN_ACTION); PartyControl.get().clearDoorState(this.keyItemName); } } else { if (this.entered_players.Count > 0 && PartyControl.get().isDoorOpen(this.keyItemName)) { this.step.set_next(STEP.EVENT_IN_ACTION); PartyControl.get().clearDoorState(this.keyItemName); } } } } break; case STEP.EVENT_IN_ACTION: { } break; case STEP.WAIT_LEAVE: { if (this.entered_players.Count == 0) { this.step.set_next(STEP.WAIT_ENTER); } } break; } // ---------------------------------------------------------------- // // 상태 전환 시 초기화. while (this.step.get_next() != STEP.NONE) { switch (this.step.do_initialize()) { case STEP.SLEEP: { if (this.moji_effect != null) { this.moji_effect.gameObject.destroy(); this.moji_effect = null; } } break; case STEP.WAIT_ENTER: { if (this.is_unlocked) { if (this.moji_effect == null) { this.moji_effect = EffectRoot.get().createDoorMojisEffect(this.transform.position); } } } break; case STEP.WAIT_LEAVE: { if (this.moji_effect != null) { this.moji_effect.gameObject.destroy(); this.moji_effect = null; } } break; case STEP.EVENT_IN_ACTION: { TransportEvent transport_event = EventRoot.get().startEvent <TransportEvent>(); if (transport_event != null) { transport_event.setDoor(this); } else { Debug.LogWarning("Can't begin Transport Event"); } // 다음 방을 설정해 둔다. if (this.connect_to != null) { PartyControl.get().setNextRoom(this.connect_to.room); } } break; } } // ---------------------------------------------------------------- // // 각 상태에서의 실행 처리. switch (this.step.do_execution(Time.deltaTime)) { case STEP.WAIT_ENTER: { } break; } // ---------------------------------------------------------------- // }