Exemple #1
0
        /// <summary>
        /// Guarda una reservacion ficticia en Opera para clientes Outhouse
        /// </summary>
        /// <param name="hotel"></param>
        /// <param name="folio"></param>
        /// <param name="FirstName"></param>
        /// <param name="LastName"></param>
        /// <param name="Company"></param>
        /// <param name="Application"></param>
        /// <param name="MembershipType"></param>
        /// <returns></returns>
        /// <history>
        /// [vipacheco] 27/Mayo/2016 Created
        /// </history>
        public static long Origos_reservas_ficticias_Guardar(string hotel, int folio, string FirstName, string LastName)
        {
            IntegerResponse Response = null;

            // Configuramos el Request
            origos_reservas_ficticiasRequest Request = new origos_reservas_ficticiasRequest()
            {
                data = new origos_reservas_ficticias
                {
                    hotel     = hotel,
                    folio     = folio,
                    FirstName = FirstName,
                    LastName  = LastName
                }
            };

            // Invocamos al servicio web
            Response = Current.Origos_reservas_ficticias_Guardar(Request);

            // Si ocurrio un error
            if (Response.HasErrors)
            {
                MessageBox.Show(Response.ExceptionInfo.Message, "Origos_reservas_ficticias_Guardar");
            }


            return(Response.Numero);
        }
        //
        // Write a object instance to data output stream
        //
        public override void LooseMarshal(OpenWireFormat wireFormat, Object o, BinaryWriter dataOut)
        {
            IntegerResponse info = (IntegerResponse)o;

            base.LooseMarshal(wireFormat, o, dataOut);
            dataOut.Write(info.Result);
        }
        //
        // Write a object instance to data output stream
        //
        public override void TightMarshal2(OpenWireFormat wireFormat, Object o, BinaryWriter dataOut, BooleanStream bs)
        {
            base.TightMarshal2(wireFormat, o, dataOut, bs);

            IntegerResponse info = (IntegerResponse)o;
            dataOut.Write(info.Result);
        }
        //
        // Un-marshal an object instance from the data input stream
        //
        public override void LooseUnmarshal(OpenWireFormat wireFormat, Object o, BinaryReader dataIn)
        {
            base.LooseUnmarshal(wireFormat, o, dataIn);

            IntegerResponse info = (IntegerResponse)o;
            info.Result = dataIn.ReadInt32();
        }
        //
        // Un-marshal an object instance from the data input stream
        //
        public override void TightUnmarshal(OpenWireFormat wireFormat, Object o, BinaryReader dataIn, BooleanStream bs)
        {
            base.TightUnmarshal(wireFormat, o, dataIn, bs);

            IntegerResponse info = (IntegerResponse)o;
            info.Result = dataIn.ReadInt32();
        }
        //
        // Write the booleans that this object uses to a BooleanStream
        //
        public override int TightMarshal1(OpenWireFormat wireFormat, Object o, BooleanStream bs)
        {
            IntegerResponse info = (IntegerResponse)o;

            int rc = base.TightMarshal1(wireFormat, info, bs);

            return(rc + 4);
        }
        public override Task <IntegerResponse> GetTeamID(NameRequest request, ServerCallContext context)
        {
            var tmp = new IntegerResponse
            {
                Number = GetTeamIdFromName(request.TeamName)
            };

            return(System.Threading.Tasks.Task.FromResult(tmp));
        }
        public override Task <IntegerResponse> GetTeamID(NameRequest request, ServerCallContext context)
        {
            IntegerResponse tmp = new IntegerResponse();

            DBConnection.Open();
            tmp.Number = GetTeamIdFromName(request.TeamName);
            DBConnection.Close();
            return(System.Threading.Tasks.Task.FromResult(tmp));
        }
        public IntegerResponse GetVolumeState()
        {
            var response = new IntegerResponse()
            {
                Data = ITunesService.Instance.Volume,
                Name = nameof(ITunesService.Instance.Volume)
            };

            return(response);
        }
Exemple #10
0
        public void Parse_Throws_MessageReadException_On_Missing_Data()
        {
            var msg = new MessageBuilder()
                      .WriteCode(MessageCode.Server.GetPeerAddress)
                      .Build();

            var ex = Record.Exception(() => IntegerResponse.FromByteArray <MessageCode.Server>(msg));

            Assert.NotNull(ex);
            Assert.IsType <MessageReadException>(ex);
        }
Exemple #11
0
        public void Parse_Returns_Expected_Data()
        {
            var num = new Random().Next();

            var msg = new MessageBuilder()
                      .WriteCode(MessageCode.Server.GetPeerAddress)
                      .WriteInteger(num)
                      .Build();

            var response = IntegerResponse.FromByteArray <MessageCode.Server>(msg);

            Assert.Equal(num, response);
        }
        public IActionResult PostVolumeState([FromBody] IntegerRequest volumeParameter)
        {
            if (volumeParameter.Name == null || !volumeParameter.Name.Equals("Volume"))
            {
                return(BadRequest(volumeParameter));
            }

            if (!ITunesService.Instance.IsActive)
            {
                return(new StatusCodeResult((int)HttpStatusCode.ServiceUnavailable));
            }

            var newVolume   = ITunesService.Instance.ChangeVolume(volumeParameter.Data);
            var volumeValue = newVolume ?? 0;
            var response    = new IntegerResponse()
            {
                Data = volumeValue,
                Name = nameof(ITunesService.Instance.Volume)
            };

            return(Ok(response));
        }
Exemple #13
0
        /// <summary>
        ///     Handles incoming messages.
        /// </summary>
        /// <param name="sender">The <see cref="IMessageConnection"/> instance from which the message originated.</param>
        /// <param name="message">The message.</param>
        public async void HandleMessage(object sender, byte[] message)
        {
            var code = new MessageReader <MessageCode.Server>(message).ReadCode();

            Diagnostic.Debug($"Server message received: {code}");

            try
            {
                switch (code)
                {
                case MessageCode.Server.ParentMinSpeed:
                case MessageCode.Server.ParentSpeedRatio:
                case MessageCode.Server.WishlistInterval:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), IntegerResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.Login:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), LoginResponse.FromByteArray(message));
                    break;

                case MessageCode.Server.RoomList:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), RoomList.FromByteArray(message));
                    break;

                case MessageCode.Server.PrivilegedUsers:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), PrivilegedUserList.FromByteArray(message));
                    break;

                case MessageCode.Server.NetInfo:
                    var netInfo = NetInfo.FromByteArray(message);

                    try
                    {
                        await SoulseekClient.DistributedConnectionManager.AddParentConnectionAsync(netInfo.Parents).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling NetInfo message: {ex.Message}");
                    }

                    break;

                case MessageCode.Server.ConnectToPeer:
                    ConnectToPeerResponse connectToPeerResponse = default;

                    try
                    {
                        connectToPeerResponse = ConnectToPeerResponse.FromByteArray(message);

                        if (connectToPeerResponse.Type == Constants.ConnectionType.Transfer)
                        {
                            // ensure that we are expecting at least one file from this user before we connect. the response
                            // doesn't contain any other identifying information about the file.
                            if (!SoulseekClient.Downloads.IsEmpty && SoulseekClient.Downloads.Values.Any(d => d.Username == connectToPeerResponse.Username))
                            {
                                var(connection, remoteToken) = await SoulseekClient.PeerConnectionManager.GetTransferConnectionAsync(connectToPeerResponse).ConfigureAwait(false);

                                var download = SoulseekClient.Downloads.Values.FirstOrDefault(v => v.RemoteToken == remoteToken && v.Username == connectToPeerResponse.Username);

                                if (download != default(Transfer))
                                {
                                    SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.IndirectTransfer, download.Username, download.Filename, download.RemoteToken), connection);
                                }
                            }
                            else
                            {
                                throw new SoulseekClientException($"Unexpected transfer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPAddress}:{connectToPeerResponse.Port}); Ignored");
                            }
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Peer)
                        {
                            await SoulseekClient.PeerConnectionManager.GetOrAddMessageConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Distributed)
                        {
                            await SoulseekClient.DistributedConnectionManager.AddChildConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else
                        {
                            throw new MessageException($"Unknown Connect To Peer connection type '{connectToPeerResponse.Type}'");
                        }
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling ConnectToPeer response from {connectToPeerResponse?.Username} ({connectToPeerResponse?.IPAddress}:{connectToPeerResponse.Port}): {ex.Message}");
                    }

                    break;

                case MessageCode.Server.AddUser:
                    var addUserResponse = AddUserResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, addUserResponse.Username), addUserResponse);
                    break;

                case MessageCode.Server.GetStatus:
                    var statsResponse = GetStatusResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, statsResponse.Username), statsResponse);
                    UserStatusChanged?.Invoke(this, new UserStatusChangedEventArgs(statsResponse));
                    break;

                case MessageCode.Server.PrivateMessage:
                    var pm = PrivateMessage.FromByteArray(message);
                    PrivateMessageReceived?.Invoke(this, pm);

                    if (SoulseekClient.Options.AutoAcknowledgePrivateMessages)
                    {
                        await SoulseekClient.AcknowledgePrivateMessageAsync(pm.Id, CancellationToken.None).ConfigureAwait(false);
                    }

                    break;

                case MessageCode.Server.GetPeerAddress:
                    var peerAddressResponse = GetPeerAddressResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, peerAddressResponse.Username), peerAddressResponse);
                    break;

                default:
                    Diagnostic.Debug($"Unhandled server message: {code}; {message.Length} bytes");
                    break;
                }
            }
            catch (Exception ex)
            {
                Diagnostic.Warning($"Error handling server message: {code}; {ex.Message}", ex);
            }
        }
        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            try
            {
                dtcControlEvent.Reset();

                Tracer.Debug("Prepare notification received for TX id: " + this.transactionId);

                BeforeEnd();

                // Before sending the request to the broker, log the recovery bits, if
                // this fails we can't prepare and the TX should be rolled back.
                RecoveryLogger.LogRecoveryInfo(this.transactionId as XATransactionId,
                                               preparingEnlistment.RecoveryInformation());

                // Inform the broker that work on the XA'sh TX Branch is complete.
                TransactionInfo info = new TransactionInfo();
                info.ConnectionId  = this.connection.ConnectionId;
                info.TransactionId = this.transactionId;
                info.Type          = (int)TransactionType.End;

                this.connection.CheckConnected();
                this.connection.SyncRequest(info);

                // Prepare the Transaction for commit.
                info.Type = (int)TransactionType.Prepare;
                IntegerResponse response = (IntegerResponse)this.connection.SyncRequest(info);
                if (response.Result == XA_READONLY)
                {
                    Tracer.Debug("Transaction Prepare done and doesn't need a commit, TX id: " + this.transactionId);

                    this.transactionId     = null;
                    this.currentEnlistment = null;

                    // Read Only means there's nothing to recover because there was no
                    // change on the broker.
                    RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                    // if server responds that nothing needs to be done, then reply prepared
                    // but clear the current state data so we appear done to the commit method.
                    preparingEnlistment.Prepared();

                    // Done so commit won't be called.
                    AfterCommit();
                }
                else
                {
                    Tracer.Debug("Transaction Prepare succeeded TX id: " + this.transactionId);

                    // If work finished correctly, reply prepared
                    preparingEnlistment.Prepared();
                }
            }
            catch (Exception ex)
            {
                Tracer.DebugFormat("Transaction[{0}] Prepare failed with error: {1}",
                                   this.transactionId, ex.Message);

                AfterRollback();
                preparingEnlistment.ForceRollback();
                try
                {
                    this.connection.OnException(ex);
                }
                catch (Exception error)
                {
                    Tracer.Error(error.ToString());
                }

                this.currentEnlistment = null;
                this.transactionId     = null;
            }
            finally
            {
                this.dtcControlEvent.Set();
            }
        }
Exemple #15
0
        /// <summary>
        ///     Handles incoming messages.
        /// </summary>
        /// <param name="sender">The <see cref="IMessageConnection"/> instance from which the message originated.</param>
        /// <param name="message">The message.</param>
        public async void HandleMessageRead(object sender, byte[] message)
        {
            var code = new MessageReader <MessageCode.Server>(message).ReadCode();

            if (code != MessageCode.Server.SearchRequest)
            {
                Diagnostic.Debug($"Server message received: {code}");
            }

            try
            {
                switch (code)
                {
                case MessageCode.Server.ParentMinSpeed:
                case MessageCode.Server.ParentSpeedRatio:
                case MessageCode.Server.WishlistInterval:
                case MessageCode.Server.CheckPrivileges:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), IntegerResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.NewPassword:
                    var confirmedPassword = NewPassword.FromByteArray(message).Password;
                    SoulseekClient.Waiter.Complete(new WaitKey(code), confirmedPassword);
                    break;

                case MessageCode.Server.GlobalAdminMessage:
                    var msg = GlobalMessageNotification.FromByteArray(message);
                    GlobalMessageReceived?.Invoke(this, new GlobalMessageReceivedEventArgs(msg));
                    break;

                case MessageCode.Server.Ping:
                    SoulseekClient.Waiter.Complete(new WaitKey(code));
                    break;

                case MessageCode.Server.Login:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), LoginResponse.FromByteArray(message));
                    break;

                case MessageCode.Server.RoomList:
                    var roomList = RoomListResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code), roomList);
                    RoomListReceived?.Invoke(this, new RoomListReceivedEventArgs(roomList));
                    break;

                case MessageCode.Server.PrivilegedUsers:
                    var privilegedUserList = PrivilegedUserListNotification.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code), privilegedUserList);
                    PrivilegedUserListReceived?.Invoke(this, new PrivilegedUserListReceivedEventArgs(privilegedUserList));
                    break;

                case MessageCode.Server.AddPrivilegedUser:
                    PrivilegeNotificationReceived?.Invoke(this, new PrivilegeNotificationReceivedEventArgs(PrivilegedUserNotification.FromByteArray(message)));
                    break;

                case MessageCode.Server.NotifyPrivileges:
                    var pn = PrivilegeNotification.FromByteArray(message);
                    PrivilegeNotificationReceived?.Invoke(this, new PrivilegeNotificationReceivedEventArgs(pn.Username, pn.Id));

                    if (SoulseekClient.Options.AutoAcknowledgePrivilegeNotifications)
                    {
                        await SoulseekClient.AcknowledgePrivilegeNotificationAsync(pn.Id, CancellationToken.None).ConfigureAwait(false);
                    }

                    break;

                case MessageCode.Server.UserPrivileges:
                    var privilegeResponse = UserPrivilegeResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privilegeResponse.Username), privilegeResponse.IsPrivileged);
                    break;

                case MessageCode.Server.NetInfo:
                    var netInfo = NetInfoNotification.FromByteArray(message);

                    try
                    {
                        var parents = netInfo.Parents.Select(parent => (parent.Username, new IPEndPoint(parent.IPAddress, parent.Port)));
                        await SoulseekClient.DistributedConnectionManager.AddParentConnectionAsync(parents).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling NetInfo message: {ex.Message}");
                    }

                    break;

                case MessageCode.Server.ConnectToPeer:
                    ConnectToPeerResponse connectToPeerResponse = default;

                    try
                    {
                        connectToPeerResponse = ConnectToPeerResponse.FromByteArray(message);

                        if (connectToPeerResponse.Type == Constants.ConnectionType.Transfer)
                        {
                            Diagnostic.Debug($"Received transfer ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}) for remote token {connectToPeerResponse.Token}");

                            // ensure that we are expecting at least one file from this user before we connect. the response
                            // doesn't contain any other identifying information about the file.
                            if (!SoulseekClient.Downloads.IsEmpty && SoulseekClient.Downloads.Values.Any(d => d.Username == connectToPeerResponse.Username))
                            {
                                var(connection, remoteToken) = await SoulseekClient.PeerConnectionManager.GetTransferConnectionAsync(connectToPeerResponse).ConfigureAwait(false);

                                var download = SoulseekClient.Downloads.Values.FirstOrDefault(v => v.RemoteToken == remoteToken && v.Username == connectToPeerResponse.Username);

                                if (download != default(TransferInternal))
                                {
                                    Diagnostic.Debug($"Solicited inbound transfer connection to {download.Username} ({connection.IPEndPoint}) for token {download.Token} (remote: {download.RemoteToken}) established. (id: {connection.Id})");
                                    SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.IndirectTransfer, download.Username, download.Filename, download.RemoteToken), connection);
                                }
                                else
                                {
                                    Diagnostic.Debug($"Transfer ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}) for remote token {connectToPeerResponse.Token} does not match any waiting downloads, discarding.");
                                    connection.Disconnect($"Unknown transfer");
                                }
                            }
                            else
                            {
                                throw new SoulseekClientException($"Unexpected transfer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}); Ignored");
                            }
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Peer)
                        {
                            Diagnostic.Debug($"Received message ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint})");
                            await SoulseekClient.PeerConnectionManager.GetOrAddMessageConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Distributed)
                        {
                            Diagnostic.Debug($"Received distributed ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint})");
                            await SoulseekClient.DistributedConnectionManager.AddChildConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else
                        {
                            throw new MessageException($"Unknown Connect To Peer connection type '{connectToPeerResponse.Type}'");
                        }
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling ConnectToPeer response from {connectToPeerResponse?.Username} ({connectToPeerResponse?.IPEndPoint}): {ex.Message}");
                    }

                    break;

                case MessageCode.Server.AddUser:
                    var addUserResponse = AddUserResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, addUserResponse.Username), addUserResponse);
                    break;

                case MessageCode.Server.GetStatus:
                    var statsResponse = UserStatusResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, statsResponse.Username), statsResponse);
                    UserStatusChanged?.Invoke(this, new UserStatusChangedEventArgs(statsResponse));
                    break;

                case MessageCode.Server.PrivateMessage:
                    var pm = PrivateMessageNotification.FromByteArray(message);
                    PrivateMessageReceived?.Invoke(this, new PrivateMessageReceivedEventArgs(pm));

                    if (SoulseekClient.Options.AutoAcknowledgePrivateMessages)
                    {
                        await SoulseekClient.AcknowledgePrivateMessageAsync(pm.Id, CancellationToken.None).ConfigureAwait(false);
                    }

                    break;

                case MessageCode.Server.GetPeerAddress:
                    var peerAddressResponse = UserAddressResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, peerAddressResponse.Username), peerAddressResponse);
                    break;

                case MessageCode.Server.JoinRoom:
                    var roomData = RoomJoinResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, roomData.Name), roomData);
                    break;

                case MessageCode.Server.LeaveRoom:
                    var leaveRoomResponse = RoomLeaveResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, leaveRoomResponse.RoomName));
                    break;

                case MessageCode.Server.SayInChatRoom:
                    var roomMessage = RoomMessageNotification.FromByteArray(message);
                    RoomMessageReceived?.Invoke(this, new RoomMessageReceivedEventArgs(roomMessage));
                    break;

                case MessageCode.Server.UserJoinedRoom:
                    var joinNotification = RoomJoinedNotification.FromByteArray(message);
                    RoomJoined?.Invoke(this, new RoomJoinedEventArgs(joinNotification));
                    break;

                case MessageCode.Server.UserLeftRoom:
                    var leftNotification = RoomLeftNotification.FromByteArray(message);
                    RoomLeft?.Invoke(this, new RoomLeftEventArgs(leftNotification));
                    break;

                case MessageCode.Server.KickedFromServer:
                    KickedFromServer?.Invoke(this, EventArgs.Empty);
                    break;

                case MessageCode.Server.FileSearch:
                    var searchRequest = ServerSearchRequest.FromByteArray(message);

                    // sometimes (most of the time?) a room search will result in a request to ourselves (assuming we are
                    // joined to it)
                    if (searchRequest.Username == SoulseekClient.Username)
                    {
                        break;
                    }

                    SearchResponse searchResponse;

                    if (SoulseekClient.Options.SearchResponseResolver == default)
                    {
                        break;
                    }

                    try
                    {
                        searchResponse = await SoulseekClient.Options.SearchResponseResolver(searchRequest.Username, searchRequest.Token, SearchQuery.FromText(searchRequest.Query)).ConfigureAwait(false);

                        if (searchResponse != null && searchResponse.FileCount + searchResponse.LockedFileCount > 0)
                        {
                            var endpoint = await SoulseekClient.GetUserEndPointAsync(searchRequest.Username).ConfigureAwait(false);

                            var peerConnection = await SoulseekClient.PeerConnectionManager.GetOrAddMessageConnectionAsync(searchRequest.Username, endpoint, CancellationToken.None).ConfigureAwait(false);

                            await peerConnection.WriteAsync(searchResponse.ToByteArray()).ConfigureAwait(false);
                        }
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Warning($"Error resolving search response for query '{searchRequest.Query}' requested by {searchRequest.Username} with token {searchRequest.Token}: {ex.Message}", ex);
                    }

                    break;

                // if we fail to connect to a distributed parent in a timely manner, the server will begin to send us distributed search requests directly.
                // forward these to the distributed message handler.
                case MessageCode.Server.SearchRequest:
                    SoulseekClient.DistributedMessageHandler.HandleMessageRead(SoulseekClient.ServerConnection, message);
                    break;

                default:
                    Diagnostic.Debug($"Unhandled server message: {code}; {message.Length} bytes");
                    break;
                }
            }
            catch (Exception ex)
            {
                Diagnostic.Warning($"Error handling server message: {code}; {ex.Message}", ex);
            }
        }
Exemple #16
0
        /// <summary>
        ///     Handles incoming messages.
        /// </summary>
        /// <param name="sender">The <see cref="IMessageConnection"/> instance from which the message originated.</param>
        /// <param name="message">The message.</param>
        public async void HandleMessageRead(object sender, byte[] message)
        {
            var code = new MessageReader <MessageCode.Server>(message).ReadCode();

            if (code != MessageCode.Server.EmbeddedMessage)
            {
                Diagnostic.Debug($"Server message received: {code}");
            }

            try
            {
                switch (code)
                {
                case MessageCode.Server.ParentMinSpeed:
                case MessageCode.Server.ParentSpeedRatio:
                case MessageCode.Server.WishlistInterval:
                case MessageCode.Server.CheckPrivileges:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), IntegerResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.PrivateRoomAdded:
                    PrivateRoomMembershipAdded?.Invoke(this, StringResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.PrivateRoomRemoved:
                    var privateRoomRemoved = StringResponse.FromByteArray <MessageCode.Server>(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomRemoved));
                    PrivateRoomMembershipRemoved?.Invoke(this, privateRoomRemoved);
                    break;

                case MessageCode.Server.PrivateRoomOperatorAdded:
                    PrivateRoomModerationAdded?.Invoke(this, StringResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.PrivateRoomOperatorRemoved:
                    var privateRoomOperatorRemoved = StringResponse.FromByteArray <MessageCode.Server>(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomOperatorRemoved));
                    PrivateRoomModerationRemoved?.Invoke(this, privateRoomOperatorRemoved);
                    break;

                case MessageCode.Server.NewPassword:
                    var confirmedPassword = NewPassword.FromByteArray(message).Password;
                    SoulseekClient.Waiter.Complete(new WaitKey(code), confirmedPassword);
                    break;

                case MessageCode.Server.PrivateRoomToggle:
                    var acceptInvitations = PrivateRoomToggle.FromByteArray(message).AcceptInvitations;
                    SoulseekClient.Waiter.Complete(new WaitKey(code), acceptInvitations);
                    break;

                case MessageCode.Server.GlobalAdminMessage:
                    var msg = GlobalMessageNotification.FromByteArray(message);
                    GlobalMessageReceived?.Invoke(this, msg);
                    break;

                case MessageCode.Server.Ping:
                    SoulseekClient.Waiter.Complete(new WaitKey(code));
                    break;

                case MessageCode.Server.Login:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), LoginResponse.FromByteArray(message));
                    break;

                case MessageCode.Server.RoomList:
                    var roomList = RoomListResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code), roomList);
                    RoomListReceived?.Invoke(this, roomList);
                    break;

                case MessageCode.Server.PrivateRoomOwned:
                    var moderatedRoomInfo = PrivateRoomOwnedListNotification.FromByteArray(message);
                    PrivateRoomModeratedUserListReceived?.Invoke(this, moderatedRoomInfo);
                    break;

                case MessageCode.Server.PrivateRoomUsers:
                    var roomInfo = PrivateRoomUserListNotification.FromByteArray(message);
                    PrivateRoomUserListReceived?.Invoke(this, roomInfo);
                    break;

                case MessageCode.Server.PrivilegedUsers:
                    var privilegedUserList = PrivilegedUserListNotification.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code), privilegedUserList);
                    PrivilegedUserListReceived?.Invoke(this, privilegedUserList);
                    break;

                case MessageCode.Server.AddPrivilegedUser:
                    PrivilegeNotificationReceived?.Invoke(this, new PrivilegeNotificationReceivedEventArgs(PrivilegedUserNotification.FromByteArray(message)));
                    break;

                case MessageCode.Server.NotifyPrivileges:
                    var pn = PrivilegeNotification.FromByteArray(message);
                    PrivilegeNotificationReceived?.Invoke(this, new PrivilegeNotificationReceivedEventArgs(pn.Username, pn.Id));

                    if (SoulseekClient.Options.AutoAcknowledgePrivilegeNotifications)
                    {
                        await SoulseekClient.AcknowledgePrivilegeNotificationAsync(pn.Id, CancellationToken.None).ConfigureAwait(false);
                    }

                    break;

                case MessageCode.Server.UserPrivileges:
                    var privilegeResponse = UserPrivilegeResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privilegeResponse.Username), privilegeResponse.IsPrivileged);
                    break;

                case MessageCode.Server.NetInfo:
                    var netInfo = NetInfoNotification.FromByteArray(message);

                    try
                    {
                        var parents = netInfo.Parents.Select(parent => (parent.Username, new IPEndPoint(parent.IPAddress, parent.Port)));
                        await SoulseekClient.DistributedConnectionManager.AddParentConnectionAsync(parents).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling NetInfo message: {ex.Message}");
                    }

                    break;

                case MessageCode.Server.CannotConnect:
                    var cannotConnect = CannotConnect.FromByteArray(message);
                    Diagnostic.Debug($"Received CannotConnect message for token {cannotConnect.Token}{(!string.IsNullOrEmpty(cannotConnect.Username) ? $" from user {cannotConnect.Username}" : string.Empty)}");

                    SoulseekClient.SearchResponder.TryDiscard(cannotConnect.Token);

                    if (!string.IsNullOrEmpty(cannotConnect.Username))
                    {
                        UserCannotConnect?.Invoke(this, new UserCannotConnectEventArgs(cannotConnect));
                    }

                    break;

                case MessageCode.Server.CannotJoinRoom:
                    var cannotJoinRoom = CannotJoinRoom.FromByteArray(message);
                    SoulseekClient.Waiter.Throw(
                        new WaitKey(MessageCode.Server.JoinRoom, cannotJoinRoom.RoomName),
                        new RoomJoinForbiddenException($"The server rejected the request to join room {cannotJoinRoom.RoomName}"));

                    break;

                case MessageCode.Server.ConnectToPeer:
                    var connectToPeerResponse = ConnectToPeerResponse.FromByteArray(message);

                    try
                    {
                        if (connectToPeerResponse.Type == Constants.ConnectionType.Transfer)
                        {
                            Diagnostic.Debug($"Received transfer ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}) for remote token {connectToPeerResponse.Token}");

                            // ensure that we are expecting at least one file from this user before we connect. the response
                            // doesn't contain any other identifying information about the file.
                            if (!SoulseekClient.Downloads.IsEmpty && SoulseekClient.Downloads.Values.Any(d => d.Username == connectToPeerResponse.Username))
                            {
                                var(connection, remoteToken) = await SoulseekClient.PeerConnectionManager.GetTransferConnectionAsync(connectToPeerResponse).ConfigureAwait(false);

                                var download = SoulseekClient.Downloads.Values.FirstOrDefault(v => v.RemoteToken == remoteToken && v.Username == connectToPeerResponse.Username);

                                if (download != default(TransferInternal))
                                {
                                    Diagnostic.Debug($"Solicited inbound transfer connection to {download.Username} ({connection.IPEndPoint}) for token {download.Token} (remote: {download.RemoteToken}) established. (id: {connection.Id})");
                                    SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.IndirectTransfer, download.Username, download.Filename, download.RemoteToken), connection);
                                }
                                else
                                {
                                    Diagnostic.Debug($"Transfer ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}) for remote token {connectToPeerResponse.Token} does not match any waiting downloads, discarding.");
                                    connection.Disconnect("Unknown transfer");
                                }
                            }
                            else
                            {
                                throw new SoulseekClientException($"Unexpected transfer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}); Ignored");
                            }
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Peer)
                        {
                            Diagnostic.Debug($"Received message ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint})");
                            await SoulseekClient.PeerConnectionManager.GetOrAddMessageConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Distributed)
                        {
                            Diagnostic.Debug($"Received distributed ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint})");
                            await SoulseekClient.DistributedConnectionManager.GetOrAddChildConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else
                        {
                            throw new MessageException($"Unknown Connect To Peer connection type '{connectToPeerResponse.Type}'");
                        }
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling ConnectToPeer response from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}): {ex.Message}");
                    }

                    break;

                case MessageCode.Server.AddUser:
                    var addUserResponse = AddUserResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, addUserResponse.Username), addUserResponse);
                    break;

                case MessageCode.Server.GetStatus:
                    var statsResponse = UserStatusResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, statsResponse.Username), statsResponse);
                    UserStatusChanged?.Invoke(this, new UserStatusChangedEventArgs(statsResponse));
                    break;

                case MessageCode.Server.PrivateMessage:
                    var pm = PrivateMessageNotification.FromByteArray(message);
                    PrivateMessageReceived?.Invoke(this, new PrivateMessageReceivedEventArgs(pm));

                    if (SoulseekClient.Options.AutoAcknowledgePrivateMessages)
                    {
                        await SoulseekClient.AcknowledgePrivateMessageAsync(pm.Id, CancellationToken.None).ConfigureAwait(false);
                    }

                    break;

                case MessageCode.Server.GetPeerAddress:
                    var peerAddressResponse = UserAddressResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, peerAddressResponse.Username), peerAddressResponse);
                    break;

                case MessageCode.Server.JoinRoom:
                    var roomData = JoinRoomResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, roomData.Name), roomData);
                    break;

                case MessageCode.Server.LeaveRoom:
                    var leaveRoomResponse = LeaveRoomResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, leaveRoomResponse.RoomName));
                    break;

                case MessageCode.Server.SayInChatRoom:
                    var roomMessage = RoomMessageNotification.FromByteArray(message);
                    RoomMessageReceived?.Invoke(this, new RoomMessageReceivedEventArgs(roomMessage));
                    break;

                case MessageCode.Server.PublicChat:
                    var publicChatMessage = PublicChatMessageNotification.FromByteArray(message);
                    PublicChatMessageReceived?.Invoke(this, new PublicChatMessageReceivedEventArgs(publicChatMessage));
                    break;

                case MessageCode.Server.UserJoinedRoom:
                    var joinNotification = UserJoinedRoomNotification.FromByteArray(message);
                    RoomJoined?.Invoke(this, new RoomJoinedEventArgs(joinNotification));
                    break;

                case MessageCode.Server.UserLeftRoom:
                    var leftNotification = UserLeftRoomNotification.FromByteArray(message);
                    RoomLeft?.Invoke(this, new RoomLeftEventArgs(leftNotification));
                    break;

                case MessageCode.Server.RoomTickers:
                    var roomTickers = RoomTickerListNotification.FromByteArray(message);
                    RoomTickerListReceived?.Invoke(this, new RoomTickerListReceivedEventArgs(roomTickers));
                    break;

                case MessageCode.Server.RoomTickerAdd:
                    var roomTickerAdded = RoomTickerAddedNotification.FromByteArray(message);
                    RoomTickerAdded?.Invoke(this, new RoomTickerAddedEventArgs(roomTickerAdded.RoomName, roomTickerAdded.Ticker));
                    break;

                case MessageCode.Server.RoomTickerRemove:
                    var roomTickerRemoved = RoomTickerRemovedNotification.FromByteArray(message);
                    RoomTickerRemoved?.Invoke(this, new RoomTickerRemovedEventArgs(roomTickerRemoved.RoomName, roomTickerRemoved.Username));
                    break;

                case MessageCode.Server.PrivateRoomAddUser:
                    var privateRoomAddUserResponse = PrivateRoomAddUser.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomAddUserResponse.RoomName, privateRoomAddUserResponse.Username));
                    break;

                case MessageCode.Server.PrivateRoomRemoveUser:
                    var privateRoomRemoveUserResponse = PrivateRoomRemoveUser.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomRemoveUserResponse.RoomName, privateRoomRemoveUserResponse.Username));
                    break;

                case MessageCode.Server.PrivateRoomAddOperator:
                    var privateRoomAddOperatorResponse = PrivateRoomAddOperator.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomAddOperatorResponse.RoomName, privateRoomAddOperatorResponse.Username));
                    break;

                case MessageCode.Server.PrivateRoomRemoveOperator:
                    var privateRoomRemoveOperatorResponse = PrivateRoomRemoveOperator.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomRemoveOperatorResponse.RoomName, privateRoomRemoveOperatorResponse.Username));
                    break;

                case MessageCode.Server.KickedFromServer:
                    KickedFromServer?.Invoke(this, EventArgs.Empty);
                    break;

                case MessageCode.Server.FileSearch:
                    var searchRequest = ServerSearchRequest.FromByteArray(message);

                    // sometimes (most of the time?) a room search will result in a request to ourselves (assuming we are
                    // joined to it)
                    if (searchRequest.Username == SoulseekClient.Username)
                    {
                        break;
                    }

                    await SoulseekClient.SearchResponder.TryRespondAsync(searchRequest.Username, searchRequest.Token, searchRequest.Query).ConfigureAwait(false);

                    break;

                case MessageCode.Server.EmbeddedMessage:
                    SoulseekClient.DistributedMessageHandler.HandleEmbeddedMessage(message);
                    break;

                default:
                    Diagnostic.Debug($"Unhandled server message: {code}; {message.Length} bytes");
                    break;
                }
            }
            catch (Exception ex)
            {
                Diagnostic.Warning($"Error handling server message: {code}; {ex.Message}", ex);
            }
        }
        public async Task PrepareAsync(PreparingEnlistment preparingEnlistment)
        {
            using (await this.syncObject.LockAsync().Await())
            {
                this.netTxState = TxState.Pending;

                try
                {
                    Tracer.Debug("Prepare notification received for TX id: " + this.TransactionId);

                    await BeforeEndAsync().Await();

                    // Before sending the request to the broker, log the recovery bits, if
                    // this fails we can't prepare and the TX should be rolled back.
                    RecoveryLogger.LogRecoveryInfo(this.TransactionId as XATransactionId,
                                                   preparingEnlistment.RecoveryInformation());

                    // Inform the broker that work on the XA'sh TX Branch is complete.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId  = this.connection.ConnectionId;
                    info.TransactionId = this.TransactionId;
                    info.Type          = (int)TransactionType.End;

                    await this.connection.CheckConnectedAsync().Await();

                    await this.connection.SyncRequestAsync((TransactionInfo)info.Clone()).Await();

                    // Prepare the Transaction for commit.
                    info.Type = (int)TransactionType.Prepare;
                    IntegerResponse response = (IntegerResponse)await this.connection.SyncRequestAsync(info).Await();

                    if (response.Result == XA_READONLY)
                    {
                        Tracer.Debug("Transaction Prepare done and doesn't need a commit, TX id: " + this.TransactionId);

                        this.TransactionId     = null;
                        this.currentEnlistment = null;

                        // Read Only means there's nothing to recover because there was no
                        // change on the broker.
                        RecoveryLogger.LogRecovered(this.TransactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        // otherwise the DTC will call Commit or Rollback but another transaction
                        // can already be in progress and this one would be commited or rolled back
                        // immediately.
                        preparingEnlistment.Done();

                        // Done so commit won't be called.
                        AfterCommit();

                        // A Read-Only TX is considered closed at this point, DTC won't call us again.
                        this.dtcControlEvent.Set();
                    }
                    else
                    {
                        Tracer.Debug("Transaction Prepare succeeded TX id: " + this.TransactionId);

                        // If work finished correctly, reply prepared
                        preparingEnlistment.Prepared();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Prepare failed with error: {1}",
                                       this.TransactionId, ex.Message);

                    AfterRollback();
                    preparingEnlistment.ForceRollback();
                    try
                    {
                        this.connection.OnAsyncException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }

                    this.currentEnlistment = null;
                    this.TransactionId     = null;
                    this.netTxState        = TxState.None;
                    this.dtcControlEvent.Set();
                }
            }
        }