/*********** UDP request ***********/ public void InitializeRemotePlayChannel(Session session, IPEndPoint ps4Endpoint) { const int retry = 3; for (int i = 0; i < retry; i++) { Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); udpClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); udpClient.ExclusiveAddressUse = false; udpClient.ReceiveTimeout = 5500; udpClient.Connect(ps4Endpoint.Address, RemotePlayPort); RemotePlayContext remotePlayContext = SendInitControlMessages(udpClient); if (remotePlayContext == null) { udpClient.Close(); udpClient.Dispose(); Thread.Sleep(2500); continue; } remotePlayContext = SendBigBangMessages(udpClient, session, remotePlayContext); if (remotePlayContext == null) { udpClient.Close(); udpClient.Dispose(); Thread.Sleep(2500); continue; } remotePlayContext = SendStreamInfo(udpClient, session, remotePlayContext); if (remotePlayContext == null) { udpClient.Close(); udpClient.Dispose(); Thread.Sleep(2500); continue; } OnPs4LogInfo?.Invoke(this, "!!!!!!!!!!!!! Stream initialization successfully completed" + Environment.NewLine); _udpClient = udpClient; RemotePlayAsyncState remotePlayAsyncState = new RemotePlayAsyncState(remotePlayContext, session); //HandleFeedbackData(_udpClient, remotePlayContext); HandleHeartBeat(_udpClient, remotePlayContext); _udpClient.BeginReceive(remotePlayAsyncState.Buffer, 0, remotePlayAsyncState.Buffer.Length, SocketFlags.None, HandleRemotePlayStream, remotePlayAsyncState); break; } }
/*********** Stream handling ***********/ private void HandleRemotePlayStream(IAsyncResult result) { try { RemotePlayAsyncState remotePlayAsyncState = (RemotePlayAsyncState)result.AsyncState; int bytesRead = _udpClient.EndReceive(result); if (bytesRead > 0) { if (remotePlayAsyncState.Buffer[0] == 0) // Control message { // ToDo check takion_handle_packet_message ControlMessage controlMessage = new ControlMessage(); using (MemoryStream memoryStream = new MemoryStream(remotePlayAsyncState.Buffer, 0, bytesRead)) using (BinaryReader binaryWriter = new BinaryReader(memoryStream)) { controlMessage.Deserialize(binaryWriter); OnPs4LogInfo?.Invoke(this, "Received remote play stream control package, crypto " + controlMessage.Crypto + ", tagPos " + controlMessage.TagPos); } byte[] ackBangPayload = HexUtil.Unhexlify("00000000"); ushort ackBangPayloadSize = (ushort)(12 + ackBangPayload.Length); ControlMessage ackControlMessage = new ControlMessage(0, remotePlayAsyncState.RemotePlayContext.ReceiverId, 0, 0, 3, 0, ackBangPayloadSize, controlMessage.FuncIncr, 0x19000); ackControlMessage.UnParsedPayload = ackBangPayload; SendCryptedControlMessage(ackControlMessage, remotePlayAsyncState.RemotePlayContext, _udpClient); //SendData(_udpClient, GetByteArrayForControlMessage(ackControlMessage)); /*if (controlMessage.ProtoBuffFlag == 1 && controlMessage.UnParsedPayload.Length > 0 && controlMessage.UnParsedPayload.Length != 7) WIP * { * TakionMessage takionMessage = Serializer.Deserialize<TakionMessage>(new MemoryStream(controlMessage.UnParsedPayload)); * if (takionMessage.Type == TakionMessage.PayloadType.Heartbeat) * { * byte[] heartbeatPayload = HexUtil.Unhexlify("000803"); * short heartbeatPayloadSize = (short) (12 + heartbeatPayload.Length); * ControlMessage heartbeatControlMessage = new ControlMessage(0, remotePlayAsyncState.RemotePlayContext.ReceiverId, new Random().Next(), controlMessage.TagPos + 0x10, 0, 1, heartbeatPayloadSize, controlMessage.FuncIncr, 0x10000); * heartbeatControlMessage.UnParsedPayload = heartbeatPayload; * * SendData(_udpClient, GetByteArrayForControlMessage(heartbeatControlMessage)); * } * }*/ } _udpClient.BeginReceive(remotePlayAsyncState.Buffer, 0, remotePlayAsyncState.Buffer.Length, SocketFlags.None, HandleRemotePlayStream, remotePlayAsyncState); } else { // Close connection } } catch (ObjectDisposedException) { // Ignore closed from outside } catch (Exception exception) { OnPs4ConnectionError?.Invoke(this, "Connection error while handling stream data. Exception: " + exception); } }