From b4c08dbdf84ab2c7f84bcb21f8773153aa25df4d Mon Sep 17 00:00:00 2001 From: regzo2 Date: Sat, 8 Feb 2025 21:38:35 -0500 Subject: [PATCH 1/3] refactor(osc): Optimized marshalling and threading on OscRecvService --- VRCFaceTracking.Core/OSC/OSCMessage.cs | 13 ++++++++++++- VRCFaceTracking.Core/Services/OscRecvService.cs | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/VRCFaceTracking.Core/OSC/OSCMessage.cs b/VRCFaceTracking.Core/OSC/OSCMessage.cs index 92c2f47c..70753fd9 100644 --- a/VRCFaceTracking.Core/OSC/OSCMessage.cs +++ b/VRCFaceTracking.Core/OSC/OSCMessage.cs @@ -98,9 +98,20 @@ public OscMessage(byte[] bytes, int len, ref int messageIndex) _metaPtr = fti_osc.parse_osc(bytes, len, ref messageIndex); if (_metaPtr != IntPtr.Zero) { - _meta = Marshal.PtrToStructure(_metaPtr); + //var meta1 = Marshal.PtrToStructure(_metaPtr); + ParseToOscMessageMeta(_metaPtr); } } + private void ParseToOscMessageMeta(IntPtr ptr) + { + _meta.Address = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(ptr)); + ptr += IntPtr.Size; + + _meta.ValueLength = Marshal.ReadInt32(ptr); + ptr += IntPtr.Size; + + _meta.Value = Marshal.ReadIntPtr(ptr); + } /// /// Encodes stored osc meta into raw bytes using fti_osc lib diff --git a/VRCFaceTracking.Core/Services/OscRecvService.cs b/VRCFaceTracking.Core/Services/OscRecvService.cs index 48a6a256..fb5a5fe3 100644 --- a/VRCFaceTracking.Core/Services/OscRecvService.cs +++ b/VRCFaceTracking.Core/Services/OscRecvService.cs @@ -112,7 +112,7 @@ protected async override Task ExecuteAsync(CancellationToken stoppingToken) { var bytesReceived = await _recvSocket.ReceiveAsync(_recvBuffer, _linkedToken.Token); var offset = 0; - var newMsg = await Task.Run(() => OscMessage.TryParseOsc(_recvBuffer, bytesReceived, ref offset), stoppingToken); + var newMsg = OscMessage.TryParseOsc(_recvBuffer, bytesReceived, ref offset); if (newMsg == null) { continue; From 52f4bb71cc2919fb36b2847cc3bc6e9927fc2de2 Mon Sep 17 00:00:00 2001 From: regzo2 Date: Sun, 9 Feb 2025 20:25:45 -0500 Subject: [PATCH 2/3] fix(osc): Limit buffer size to match max messages size. --- VRCFaceTracking.Core/Services/OscRecvService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VRCFaceTracking.Core/Services/OscRecvService.cs b/VRCFaceTracking.Core/Services/OscRecvService.cs index fb5a5fe3..4ffcc652 100644 --- a/VRCFaceTracking.Core/Services/OscRecvService.cs +++ b/VRCFaceTracking.Core/Services/OscRecvService.cs @@ -16,7 +16,7 @@ public class OscRecvService : BackgroundService private readonly ILocalSettingsService _settingsService; private Socket _recvSocket; - private readonly byte[] _recvBuffer = new byte[4096]; + private readonly byte[] _recvBuffer = new byte[64]; private CancellationTokenSource _cts, _linkedToken; private CancellationToken _stoppingToken; From 477c712841f893fc768bfaff0e736d3570c92f33 Mon Sep 17 00:00:00 2001 From: regzo2 Date: Sun, 9 Feb 2025 20:33:45 -0500 Subject: [PATCH 3/3] feat(osc): Added check for data available on socket. --- .../Services/OscRecvService.cs | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/VRCFaceTracking.Core/Services/OscRecvService.cs b/VRCFaceTracking.Core/Services/OscRecvService.cs index 4ffcc652..8fbdcfde 100644 --- a/VRCFaceTracking.Core/Services/OscRecvService.cs +++ b/VRCFaceTracking.Core/Services/OscRecvService.cs @@ -108,29 +108,34 @@ protected async override Task ExecuteAsync(CancellationToken stoppingToken) continue; } - try + if (_recvSocket.Available > 0) { - var bytesReceived = await _recvSocket.ReceiveAsync(_recvBuffer, _linkedToken.Token); - var offset = 0; - var newMsg = OscMessage.TryParseOsc(_recvBuffer, bytesReceived, ref offset); - if (newMsg == null) + try { - continue; - } + var bytesReceived = await _recvSocket.ReceiveAsync(_recvBuffer, SocketFlags.None, _linkedToken.Token); + var offset = 0; + var newMsg = OscMessage.TryParseOsc(_recvBuffer, bytesReceived, ref offset); + if (newMsg == null) + { + continue; + } - OnMessageReceived(newMsg); - } - catch (Exception e) - { - // We don't care about operation cancellations as they're intentional and carefully controlled - if (e.GetType() == typeof(OperationCanceledException)) + OnMessageReceived(newMsg); + } + catch (Exception e) { - continue; + // We don't care about operation cancellations as they're intentional and carefully controlled + if (e.GetType() == typeof(OperationCanceledException)) + { + continue; + } + + _logger.LogError("Error encountered in OSC Receive thread: {e}", e); + SentrySdk.CaptureException(e, scope => scope.SetExtra("recvBuffer", _recvBuffer)); } - - _logger.LogError("Error encountered in OSC Receive thread: {e}", e); - SentrySdk.CaptureException(e, scope => scope.SetExtra("recvBuffer", _recvBuffer)); } + else + await Task.Delay(100, _linkedToken.Token); } } } \ No newline at end of file