public static async Task<byte[]> PackMessageAsync(NetworkMessage message) { string serialized = await Task.Run(() => JsonConvert.SerializeObject(message, Formatting.None)); byte[] contentBytes = Encoding.UTF8.GetBytes(serialized); contentBytes = await CompressDataAsync(contentBytes); byte[] length = BitConverter.GetBytes(contentBytes.Length); // We have a fixed size of 4 bytes var returnData = new byte[length.Length + contentBytes.Length]; Buffer.BlockCopy(length, 0, returnData, 0, length.Length); Buffer.BlockCopy(contentBytes, 0, returnData, length.Length, contentBytes.Length); return returnData; }
private async Task SendMessage(NetworkMessage content) { byte[] message; using (MeasureHelper.Measure()) { message = await NetworkHelpers.PackMessageAsync(content); } await this.gate.WaitAsync(); try { await this.socket.GetStream().WriteAsync(message, 0, message.Length); } catch (Exception) { this.disconnected.OnNext(Unit.Default); } finally { this.gate.Release(); } }
private static NetworkMessage CreatePushMessage(PushAction action, JObject content) { var message = new NetworkMessage { MessageType = NetworkMessageType.Push, Payload = JObject.FromObject(new PushInfo { Content = content, PushAction = action }) }; return message; }
public void ListenAsync() { Observable.FromAsync(() => this.socket.GetStream().ReadNextMessageAsync()) .Repeat() .LoggedCatch(this, null, "Message connection was closed by the remote device or the connection failed") .TakeWhile(x => x != null) // If we don't do this, the application will throw up whenever we are manipulating a // collection that is surfaced to the UI Yes, this is astoundingly stupid .ObserveOn(RxApp.MainThreadScheduler) .SelectMany(async message => { RequestInfo request; try { request = message.Payload.ToObject<RequestInfo>(); } catch (JsonException ex) { this.Log().ErrorException(String.Format("Mobile client with access token {0} sent a malformed request", this.accessToken), ex); return Unit.Default; } var responseMessage = new NetworkMessage { MessageType = NetworkMessageType.Response }; Func<JToken, Task<ResponseInfo>> action; if (this.messageActionMap.TryGetValue(request.RequestAction, out action)) { bool isFatalRequest = false; try { ResponseInfo response = await action(request.Parameters); response.RequestId = request.RequestId; responseMessage.Payload = await Task.Run(() => JObject.FromObject(response)); await this.SendMessage(responseMessage); } catch (Exception ex) { this.Log().ErrorException(String.Format("Mobile client with access token {0} sent a request that caused an exception", this.accessToken), ex); if (Debugger.IsAttached) { Debugger.Break(); } isFatalRequest = true; } if (isFatalRequest) { ResponseInfo response = CreateResponse(ResponseStatus.Fatal); response.RequestId = request.RequestId; responseMessage.Payload = JObject.FromObject(response); // Client what are you doing? Client stahp! await this.SendMessage(responseMessage); } return Unit.Default; } return Unit.Default; }) .Finally(() => this.disconnected.OnNext(Unit.Default)) .Subscribe() .DisposeWith(this.disposable); var transfers = Observable.FromAsync(() => this.fileSocket.GetStream().ReadNextFileTransferMessageAsync()) .Repeat() .LoggedCatch(this, null, "File transfer connection was closed by the remote device or the connection failed") .TakeWhile(x => x != null) .Publish(); transfers.Connect().DisposeWith(this.disposable); this.songTransfers = transfers; }