internal bool OnPreProcessUdpRawData(byte[] data, int size, NetPacket cachedPacket, IPEndPoint endPoint) { Interlocked.Increment(ref _statistic.UdpReceivedCount); Interlocked.Add(ref _statistic.UdpReceivedBytes, size); try { switch (cachedPacket.Property) { case PacketProperty.RequestConnection: { } break; case PacketProperty.ResponseConnection: { ushort sessionId = cachedPacket.SessionIdForConnection; var session = FindSession(sessionId); if (session != null && session.UdpChannel != null) { if (session.UdpChannel.SetPunchedEndPoint(endPoint) == true) { _udpSocket.AddSession(session); } if (session == this) { // 서버응답이라면 특수처리를 해주자 // 더이상 연결메시지를 보내지 않아도 됨 // 연결이 완료되었음을 알림 _isUdpConnected = true; } } } break; case PacketProperty.HolePunchingStart: { ushort sessionId = cachedPacket.SessionIdForConnection; var session = FindSession(sessionId); if (session != null && session.UdpChannel != null) { NetDataReader reader = new NetDataReader(cachedPacket); IPEndPoint ep = reader.ReadIPEndPoint(); session.UdpChannel.TempEndPoint = endPoint; /////////////////////////////////////////////////////////////////////////////////////////////// var writer = NetPool.DataWriterPool.Alloc(); try { writer.Write(ep); NetPacket sendPacket = NetPool.PacketPool.Alloc(PacketProperty.HolePunchingEnd, writer); try { sendPacket.SessionIdForConnection = SessionId; sendPacket.DeliveryMethod = DeliveryMethod.Unreliable; SocketError error = SocketError.Success; UdpSocket.SendTo(sendPacket.RawData, 0, sendPacket.Size, endPoint, ref error); var ep1 = session.UdpChannel.LocalEndPoint; var ep2 = session.UdpChannel.RemoteEndPoint; if (endPoint.Equals(ep1) == false) { UdpSocket.SendTo(sendPacket.RawData, 0, sendPacket.Size, ep1, ref error); } if (endPoint.Equals(ep2) == false && ep1.Equals(ep2) == false) { UdpSocket.SendTo(sendPacket.RawData, 0, sendPacket.Size, ep2, ref error); } } finally { NetPool.PacketPool.Free(sendPacket); } } finally { NetPool.DataWriterPool.Free(writer); } } } break; case PacketProperty.HolePunchingEnd: { ushort sessionId = cachedPacket.SessionIdForConnection; if (_p2pGroup != null) { var member = _p2pGroup.Find(sessionId); if (member != null) { NetDataReader reader = new NetDataReader(cachedPacket); IPEndPoint ep = reader.ReadIPEndPoint(); member.Session.UdpChannel.SetPunchedEndPoint(ep, true); // 메인소켓에 등록해줌 _udpSocket.AddSession(member.Session, endPoint); // 피어별 소켓에도 등록해줌 (member.Session.UdpChannel.Socket as UdpSocketEx)?.AddSession(member.Session, endPoint); member.SetState(P2pConnectState.BothConnected); } } } break; case PacketProperty.UserData: case PacketProperty.Ack: case PacketProperty.ViewRequest: { if (_serverUdpEndPoint.Equals(endPoint) == false) { return(false); } // 릴레이를 통해서 온 패킷 ushort sessionId = cachedPacket.P2pSessionId; if (sessionId == 0) { return(false); } if (sessionId == SessionId) { return(true); } if (_p2pGroup != null) { var member = _p2pGroup.Find(sessionId); if (member != null && member.Session != null && member.Session.UdpChannel != null) { SocketError error = SocketError.Success; member.Session.UdpChannel.OnReceivedRawUdpData(data, size, cachedPacket, error, endPoint); } } } break; default: return(false); } } catch (Exception ex) { OnError(ex); return(true); } return(true); }
private bool OnPreProcessUdpRawData(byte[] data, int size, NetPacket cachedPacket, IPEndPoint endPoint) { Interlocked.Increment(ref _statistic.UdpReceivedCount); Interlocked.Add(ref _statistic.UdpReceivedBytes, size); try { switch (cachedPacket.Property) { case PacketProperty.UserData: case PacketProperty.Ack: case PacketProperty.ViewRequest: { // P2p 데이터를 릴레이하자 try { ushort sessionId = cachedPacket.P2pSessionId; // 0이라면 서버와의 udp 통신 if (sessionId == 0) { return(false); } Interlocked.Increment(ref _statistic.RelayServCount); Interlocked.Add(ref _statistic.RelayServBytes, size); var targetSession = _sessionManager.FindSession(sessionId) as ServerSession; if (targetSession == null) { return(true); } var targetEp = targetSession.UdpChannel.PunchedEndPoint; if (targetEp == null) { return(true); } ISession senderSession; _udpSocket.TryGetSession(endPoint, out senderSession); if (senderSession == null) { return(true); } //_logger.LogInformation($"Relay to {sessionId} {targetSession.UdpChannel.PunchedEndPoint} from {senderSession.SessionId}"); // 보낸이를 수정해서 보내주자 cachedPacket.P2pSessionId = senderSession.SessionId; SocketError error = SocketError.Success; _udpSocket.SendTo(data, 0, size, targetEp, ref error); } catch { } } break; case PacketProperty.RequestConnection: { ushort sessionId = cachedPacket.SessionIdForConnection; NetDataReader reader = new NetDataReader(cachedPacket); long connectId = reader.ReadInt64(); IPEndPoint localEp = reader.ReadIPEndPoint(); var session = _sessionManager.FindSession(sessionId) as ServerSession; if (session != null && session.ConnectId == connectId) { session.UdpChannel.LocalEndPoint = localEp; session.UdpChannel.RemoteEndPoint = endPoint; if (session.UdpChannel.SetPunchedEndPoint(endPoint) == true) { _udpSocket.AddSession(session); //_logger.LogInformation($"Connect Udp {session.SessionId} {endPoint}"); } // 응답을 보내자 NetPacket sendPacket = NetPool.PacketPool.Alloc(PacketProperty.ResponseConnection); try { // 서버는 0번임 sendPacket.SessionIdForConnection = 0; sendPacket.DeliveryMethod = DeliveryMethod.Unreliable; SocketError error = SocketError.Success; _udpSocket.SendTo(sendPacket.RawData, 0, sendPacket.Size, endPoint, ref error); //_logger.LogInformation($"send ResponseConnection to {endPoint}"); } finally { NetPool.PacketPool.Free(sendPacket); } } } break; case PacketProperty.ResponseConnection: { } break; default: return(false); } } catch (Exception ex) { OnErrored?.Invoke(ex); return(true); } return(true); }