예제 #1
0
        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;
        }
예제 #2
0
        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();
            }
        }
예제 #3
0
        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;
        }
예제 #4
0
        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;
        }