/// <summary>
        /// Logs the client into the Steam3 network as an anonymous game server.
        /// The client should already have been connected at this point.
        /// Results are returned in a <see cref="SteamUser.LoggedOnCallback"/>.
        /// </summary>
        /// <param name="appId">The AppID served by this game server, or 0 for the default.</param>
        public void LogOnAnonymous(uint appId = 0)
        {
            var logon = new ClientMsgProtobuf <CMsgClientLogon>(EMsg.ClientLogonGameServer);

            SteamID gsId = new SteamID(0, 0, Client.ConnectedUniverse, EAccountType.AnonGameServer);

            logon.ProtoHeader.client_sessionid = 0;
            logon.ProtoHeader.steamid          = gsId.ConvertToUInt64();

            uint localIp = NetHelpers.GetIPAddress(this.Client.LocalIP);

            logon.Body.obfustucated_private_ip = localIp ^ MsgClientLogon.ObfuscationMask;

            logon.Body.protocol_version = MsgClientLogon.CurrentProtocol;

            logon.Body.client_os_type     = ( uint )Utils.GetOSType();
            logon.Body.game_server_app_id = ( int )appId;
            logon.Body.machine_id         = Utils.GenerateMachineID();

            this.Client.Send(logon);
        }
Beispiel #2
0
        void HandleUserJoinedLobby(IPacketMsg packetMsg)
        {
            var userJoinedLobby = new ClientMsgProtobuf <CMsgClientMMSUserJoinedLobby>(packetMsg);
            var body            = userJoinedLobby.Body;

            var lobby = lobbyCache.GetLobby(body.app_id, body.steam_id_lobby);

            if (lobby != null && lobby.Members.Count > 0)
            {
                var joiningMember = lobbyCache.AddLobbyMember(body.app_id, lobby, body.steam_id_user, body.persona_name);

                if (joiningMember != null)
                {
                    Client.PostCallback(new UserJoinedLobbyCallback(
                                            body.app_id,
                                            body.steam_id_lobby,
                                            joiningMember
                                            ));
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Invites a user to a chat room.
        /// The results of this action will be available through the <see cref="ChatActionResultCallback"/> callback.
        /// </summary>
        /// <param name="steamIdUser">The SteamID of the user to invite.</param>
        /// <param name="steamIdChat">The SteamID of the chat room to invite the user to.</param>
        public void InviteUserToChat(SteamID steamIdUser, SteamID steamIdChat)
        {
            SteamID chatId = steamIdChat.ConvertToUInt64(); // copy the steamid so we don't modify it

            if (chatId.IsClanAccount)
            {
                // this steamid is incorrect, so we'll fix it up
                chatId.AccountInstance = (uint)SteamID.ChatInstanceFlags.Clan;
                chatId.AccountType     = EAccountType.Chat;
            }

            var inviteMsg = new ClientMsgProtobuf <CMsgClientChatInvite>(EMsg.ClientChatInvite);

            inviteMsg.Body.steam_id_chat    = chatId;
            inviteMsg.Body.steam_id_invited = steamIdUser;
            // steamclient also sends the steamid of the user that did the invitation
            // we'll mimic that behavior
            inviteMsg.Body.steam_id_patron = Client.SteamID;

            this.Client.Send(inviteMsg);
        }
Beispiel #4
0
        void HandleSetLobbyOwnerResponse(IPacketMsg packetMsg)
        {
            var setLobbyOwnerResponse = new ClientMsgProtobuf <CMsgClientMMSSetLobbyOwnerResponse>(packetMsg);
            var body = setLobbyOwnerResponse.Body;

            if (lobbyManipulationRequests.TryRemove(setLobbyOwnerResponse.TargetJobID, out var request))
            {
                if (body.eresult == ( int )EResult.OK && request != null)
                {
                    var setLobbyOwner = ( CMsgClientMMSSetLobbyOwner )request;
                    lobbyCache.UpdateLobbyOwner(body.app_id, body.steam_id_lobby, setLobbyOwner.steam_id_new_owner);
                }
            }

            Client.PostCallback(new SetLobbyOwnerCallback(
                                    setLobbyOwnerResponse.TargetJobID,
                                    body.app_id,
                                    ( EResult )body.eresult,
                                    body.steam_id_lobby
                                    ));
        }
Beispiel #5
0
        void HandleCreateLobbyResponse(IPacketMsg packetMsg)
        {
            var lobbyListResponse = new ClientMsgProtobuf <CMsgClientMMSCreateLobbyResponse>(packetMsg);
            var body = lobbyListResponse.Body;

            if (lobbyManipulationRequests.TryRemove(lobbyListResponse.TargetJobID, out var request))
            {
                if (body.eresult == ( int )EResult.OK && request != null)
                {
                    var createLobby = ( CMsgClientMMSCreateLobby )request;
                    var members     = new List <Lobby.Member>(1)
                    {
                        new Lobby.Member(Client.SteamID, createLobby.persona_name_owner)
                    };

                    lobbyCache.CacheLobby(
                        createLobby.app_id,
                        new Lobby(
                            body.steam_id_lobby,
                            ( ELobbyType )createLobby.lobby_type,
                            createLobby.lobby_flags,
                            Client.SteamID,
                            Lobby.DecodeMetadata(createLobby.metadata),
                            createLobby.max_members,
                            1,
                            members.AsReadOnly(),
                            null,
                            null
                            )
                        );
                }
            }

            Client.PostCallback(new CreateLobbyCallback(
                                    lobbyListResponse.TargetJobID,
                                    body.app_id,
                                    ( EResult )body.eresult,
                                    body.steam_id_lobby
                                    ));
        }
Beispiel #6
0
        /// <summary>
        /// Requests a list of servers from the Steam game master server.
        /// Results are returned in a <see cref="QueryCallback"/>.
        /// </summary>
        /// <param name="details">The details for the request.</param>
        /// <returns>The Job ID of the request. This can be used to find the appropriate <see cref="QueryCallback"/>.</returns>
        public JobID ServerQuery(QueryDetails details)
        {
            var query = new ClientMsgProtobuf <CMsgClientGMSServerQuery>(EMsg.ClientGMSServerQuery);

            query.SourceJobID = Client.GetNextJobID();

            query.Body.app_id = details.AppID;

            if (details.GeoLocatedIP != null)
            {
                query.Body.geo_location_ip = NetHelpers.GetIPAddress(details.GeoLocatedIP);
            }

            query.Body.filter_text = details.Filter;
            query.Body.region_code = ( uint )details.Region;

            query.Body.max_servers = details.MaxServers;

            this.Client.Send(query);

            return(query.SourceJobID);
        }
        /// <summary>
        /// Logs onto the Steam network as a persistent game server.
        /// The client should already have been connected at this point.
        /// Results are return in a <see cref="SteamUser.LoggedOnCallback"/>.
        /// </summary>
        /// <param name="details">The details to use for logging on.</param>
        /// <exception cref="System.ArgumentNullException">No logon details were provided.</exception>
        /// <exception cref="System.ArgumentException">Username or password are not set within <paramref name="details"/>.</exception>
        public void LogOn(LogOnDetails details)
        {
            if (details == null)
            {
                throw new ArgumentNullException("details");
            }

            if (string.IsNullOrEmpty(details.Token))
            {
                throw new ArgumentException("LogOn requires a game server token to be set in 'details'.");
            }

            if (!this.Client.IsConnected)
            {
                this.Client.PostCallback(new SteamUser.LoggedOnCallback(EResult.NoConnection));
                return;
            }

            var logon = new ClientMsgProtobuf <CMsgClientLogon>(EMsg.ClientLogonGameServer);

            SteamID gsId = new SteamID(0, 0, Client.Universe, EAccountType.GameServer);

            logon.ProtoHeader.client_sessionid = 0;
            logon.ProtoHeader.steamid          = gsId.ConvertToUInt64();

            uint localIp = NetHelpers.GetIPAddress(this.Client.LocalIP);

            logon.Body.obfustucated_private_ip = localIp ^ MsgClientLogon.ObfuscationMask;

            logon.Body.protocol_version = MsgClientLogon.CurrentProtocol;

            logon.Body.client_os_type     = ( uint )Utils.GetOSType();
            logon.Body.game_server_app_id = ( int )details.AppID;
            logon.Body.machine_id         = HardwareUtils.GetMachineID();

            logon.Body.game_server_token = details.Token;

            this.Client.Send(logon);
        }
Beispiel #8
0
        /// <summary>
        /// Uploads the actual contents of a file to the UFS.
        /// The <see cref="UFSClient"/> should be logged on before this point, and the previous request to upload a file must have completed successfully.
        /// Results are returned in a <see cref="UploadFileFinishedCallback"/>.
        /// </summary>
        /// <param name="details">The details to use for uploading the file.</param>
        /// <returns>The Job ID of the request. This can be used to find the appropriate <see cref="UploadFileFinishedCallback"/>.</returns>
        public void UploadFile(UploadDetails details)
        {
            if (details == null)
            {
                throw new ArgumentNullException(nameof(details));
            }

            const uint MaxBytesPerChunk = 10240;

            byte[] compressedData = ZipUtil.Compress(details.FileData);
            byte[] fileHash       = CryptoHelper.SHAHash(details.FileData);

            var buffer = new byte[MaxBytesPerChunk];

            using (var ms = new MemoryStream(compressedData))
            {
                for (long readIndex = 0; readIndex < ms.Length; readIndex += buffer.Length)
                {
                    var msg = new ClientMsgProtobuf <CMsgClientUFSFileChunk>(EMsg.ClientUFSUploadFileChunk);
                    msg.TargetJobID = details.RemoteJobID;

                    var bytesRead = ms.Read(buffer, 0, buffer.Length);

                    if (bytesRead < buffer.Length)
                    {
                        msg.Body.data = buffer.Take(bytesRead).ToArray();
                    }
                    else
                    {
                        msg.Body.data = buffer;
                    }

                    msg.Body.file_start = ( uint )readIndex;
                    msg.Body.sha_file   = fileHash;

                    Send(msg);
                }
            }
        }
Beispiel #9
0
        /// <summary>
        /// Enumerates the list of all published files on the Steam workshop.
        /// Results are returned in a <see cref="PublishedFilesCallback"/> from a <see cref="SteamClient.JobCallback&lt;T&gt;"/>.
        /// </summary>
        /// <param name="details">The specific details of the request.</param>
        /// <returns>The Job ID of the request. This can be used to find the appropriate <see cref="SteamClient.JobCallback&lt;T&gt;"/>.</returns>
        public JobID EnumeratePublishedFiles(EnumerationDetails details)
        {
            var enumRequest = new ClientMsgProtobuf <CMsgCREEnumeratePublishedFiles>(EMsg.CREEnumeratePublishedFiles);

            enumRequest.SourceJobID = Client.GetNextJobID();

            enumRequest.Body.app_id = details.AppID;

            enumRequest.Body.query_type = ( int )details.Type;

            enumRequest.Body.start_index = details.StartIndex;

            enumRequest.Body.days  = details.Days;
            enumRequest.Body.count = details.Count;

            enumRequest.Body.tags.AddRange(details.Tags);
            enumRequest.Body.user_tags.AddRange(details.UserTags);

            Client.Send(enumRequest);

            return(enumRequest.SourceJobID);
        }
Beispiel #10
0
        /// <summary>
        /// Attempt to logon to the UFS and authorize the client for the given AppIDs.
        /// The <see cref="UFSClient"/> should be connected before this point.
        /// Results are returned in a <see cref="LoggedOnCallback"/>.
        /// </summary>
        /// <param name="appIds">The AppIDs to authorize when connecting to the UFS.</param>
        /// <returns>The Job ID of the request. This can be used to find the appropriate <see cref="LoggedOnCallback"/>.</returns>
        public JobID Logon(IEnumerable <uint> appIds)
        {
            var jobId = steamClient.GetNextJobID();

            if (!steamClient.IsConnected)
            {
                var callback = new LoggedOnCallback(jobId, EResult.NoConnection);
                steamClient.PostCallback(callback);
                return(jobId);
            }

            var loginReq = new ClientMsgProtobuf <CMsgClientUFSLoginRequest>(EMsg.ClientUFSLoginRequest);

            loginReq.SourceJobID = jobId;

            loginReq.Body.apps.AddRange(appIds);
            loginReq.Body.protocol_version = MsgClientLogon.CurrentProtocol;
            loginReq.Body.am_session_token = steamClient.SessionToken;

            Send(loginReq);

            return(loginReq.SourceJobID);
        }
Beispiel #11
0
        /// <summary>
        /// Sends a request to update a lobby.
        /// </summary>
        /// <param name="appId">ID of app the lobby belongs to.</param>
        /// <param name="lobbySteamId">The SteamID of the lobby that should be updated.</param>
        /// <param name="lobbyType">The new lobby type.</param>
        /// <param name="maxMembers">The new maximum number of members that may occupy the lobby.</param>
        /// <param name="lobbyFlags">The new lobby flags. Defaults to 0.</param>
        /// <param name="metadata">The new metadata for the lobby. Defaults to <c>null</c> (treated as an empty dictionary).</param>
        /// <returns>An <see cref="AsyncJob{SetLobbyDataCallback}"/>.</returns>
        public AsyncJob <SetLobbyDataCallback> SetLobbyData(uint appId, SteamID lobbySteamId, ELobbyType lobbyType, int maxMembers, int lobbyFlags = 0,
                                                            IReadOnlyDictionary <string, string> metadata = null)
        {
            var setLobbyData = new ClientMsgProtobuf <CMsgClientMMSSetLobbyData>(EMsg.ClientMMSSetLobbyData)
            {
                Body =
                {
                    app_id          = appId,
                    steam_id_lobby  = lobbySteamId,
                    steam_id_member =                              0,
                    lobby_type      = ( int )lobbyType,
                    max_members     = maxMembers,
                    lobby_flags     = lobbyFlags,
                    metadata        = Lobby.EncodeMetadata(metadata),
                },
                SourceJobID = Client.GetNextJobID()
            };

            Send(setLobbyData, appId);

            lobbyManipulationRequests[setLobbyData.SourceJobID] = setLobbyData.Body;
            return(AttachIncompleteManipulationHandler(new AsyncJob <SetLobbyDataCallback>(Client, setLobbyData.SourceJobID)));
        }
Beispiel #12
0
        void HandleUserLeftLobby(IPacketMsg packetMsg)
        {
            var userLeftLobby = new ClientMsgProtobuf <CMsgClientMMSUserLeftLobby>(packetMsg);
            var body          = userLeftLobby.Body;

            var lobby = lobbyCache.GetLobby(body.app_id, body.steam_id_lobby);

            if (lobby != null && lobby.Members.Count > 0)
            {
                var leavingMember = lobbyCache.RemoveLobbyMember(body.app_id, lobby, body.steam_id_user);

                if (leavingMember?.SteamID == Client.SteamID)
                {
                    lobbyCache.ClearLobbyMembers(body.app_id, body.steam_id_lobby);
                }

                Client.PostCallback(new UserLeftLobbyCallback(
                                        body.app_id,
                                        body.steam_id_lobby,
                                        leavingMember
                                        ));
            }
        }
Beispiel #13
0
        /// <summary>
        /// Sends a request to update the current user's lobby metadata.
        /// </summary>
        /// <param name="appId">ID of app the lobby belongs to.</param>
        /// <param name="lobbySteamId">The SteamID of the lobby that should be updated.</param>
        /// <param name="metadata">The new metadata for the lobby.</param>
        /// <returns><c>null</c>, if the request could not be submitted i.e. not yet logged in. Otherwise, an <see cref="AsyncJob{SetLobbyDataCallback}"/>.</returns>
        public AsyncJob <SetLobbyDataCallback> SetLobbyMemberData(uint appId, SteamID lobbySteamId, IReadOnlyDictionary <string, string> metadata)
        {
            if (Client.SteamID == null)
            {
                return(null);
            }

            var setLobbyData = new ClientMsgProtobuf <CMsgClientMMSSetLobbyData>(EMsg.ClientMMSSetLobbyData)
            {
                Body =
                {
                    app_id          = appId,
                    steam_id_lobby  = lobbySteamId,
                    steam_id_member = Client.SteamID,
                    metadata        = Lobby.EncodeMetadata(metadata)
                }
            };

            Send(setLobbyData, appId);

            lobbyManipulationRequests[setLobbyData.SourceJobID] = setLobbyData.Body;
            return(AttachIncompleteManipulationHandler(new AsyncJob <SetLobbyDataCallback>(Client, setLobbyData.SourceJobID)));
        }
Beispiel #14
0
        void HandleGetLobbyListResponse(IPacketMsg packetMsg)
        {
            var lobbyListResponse = new ClientMsgProtobuf <CMsgClientMMSGetLobbyListResponse>(packetMsg);
            var body = lobbyListResponse.Body;

            var lobbyList =
                body.lobbies.ConvertAll(lobby =>
            {
                var existingLobby = lobbyCache.GetLobby(body.app_id, lobby.steam_id);
                var members       = existingLobby?.Members;

                return(new Lobby(
                           lobby.steam_id,
                           ( ELobbyType )lobby.lobby_type,
                           lobby.lobby_flags,
                           existingLobby?.OwnerSteamID,
                           Lobby.DecodeMetadata(lobby.metadata),
                           lobby.max_members,
                           lobby.num_members,
                           members,
                           lobby.distance,
                           lobby.weight
                           ));
            });

            foreach (var lobby in lobbyList)
            {
                lobbyCache.CacheLobby(body.app_id, lobby);
            }

            Client.PostCallback(new GetLobbyListCallback(
                                    body.app_id,
                                    ( EResult )body.eresult,
                                    lobbyList
                                    ));
        }
Beispiel #15
0
        /// <summary>
        /// Sends a request to join a lobby.
        /// </summary>
        /// <param name="appId">ID of app the lobby belongs to.</param>
        /// <param name="lobbySteamId">The SteamID of the lobby that should be joined.</param>
        /// <returns><c>null</c>, if the request could not be submitted i.e. not yet logged in. Otherwise, an <see cref="AsyncJob{JoinLobbyCallback}"/>.</returns>
        public AsyncJob <JoinLobbyCallback> JoinLobby(uint appId, SteamID lobbySteamId)
        {
            var personaName = Client.GetHandler <SteamFriends>()?.GetPersonaName();

            if (personaName == null)
            {
                return(null);
            }

            var joinLobby = new ClientMsgProtobuf <CMsgClientMMSJoinLobby>(EMsg.ClientMMSJoinLobby)
            {
                Body =
                {
                    app_id         = appId,
                    persona_name   = personaName,
                    steam_id_lobby = lobbySteamId
                },
                SourceJobID = Client.GetNextJobID()
            };

            Send(joinLobby, appId);

            return(new AsyncJob <JoinLobbyCallback>(Client, joinLobby.SourceJobID));
        }
Beispiel #16
0
        /// <summary>
        /// Sends a machine auth response.
        /// This should normally be used in response to a <see cref="UpdateMachineAuthCallback"/>.
        /// </summary>
        /// <param name="details">The details pertaining to the response.</param>
        public void SendMachineAuthResponse(MachineAuthDetails details)
        {
            var response = new ClientMsgProtobuf <CMsgClientUpdateMachineAuthResponse>(EMsg.ClientUpdateMachineAuthResponse);

            // so we respond to the correct message
            response.ProtoHeader.jobid_target = details.JobID;

            response.Body.cubwrote = ( uint )details.BytesWritten;
            response.Body.eresult  = ( uint )details.Result;

            response.Body.filename = details.FileName;
            response.Body.filesize = ( uint )details.FileSize;

            response.Body.getlasterror = ( uint )details.LastError;
            response.Body.offset       = ( uint )details.Offset;

            response.Body.sha_file = details.SentryFileHash;

            response.Body.otp_identifier = details.OneTimePassword.Identifier;
            response.Body.otp_type       = ( int )details.OneTimePassword.Type;
            response.Body.otp_value      = details.OneTimePassword.Value;

            this.Client.Send(response);
        }
Beispiel #17
0
        /// <summary>
        /// Logs the client into the Steam3 network as an anonymous user.
        /// The client should already have been connected at this point.
        /// Results are returned in a <see cref="LoggedOnCallback"/>.
        /// </summary>
        /// <param name="details">The details to use for logging on.</param>
        public void LogOnAnonymous(AnonymousLogOnDetails details)
        {
            if (!this.Client.IsConnected)
            {
                this.Client.PostCallback(new LoggedOnCallback(EResult.NoConnection));
                return;
            }

            var logon = new ClientMsgProtobuf <CMsgClientLogon>(EMsg.ClientLogon);

            SteamID auId = new SteamID(0, 0, Client.ConnectedUniverse, EAccountType.AnonUser);

            logon.ProtoHeader.client_sessionid = 0;
            logon.ProtoHeader.steamid          = auId.ConvertToUInt64();

            logon.Body.protocol_version = MsgClientLogon.CurrentProtocol;
            logon.Body.client_os_type   = ( uint )details.ClientOSType;
            logon.Body.client_language  = details.ClientLanguage;
            logon.Body.cell_id          = details.CellID;

            logon.Body.machine_id = HardwareUtils.GetMachineID();

            this.Client.Send(logon);
        }
Beispiel #18
0
        /// <summary>
        /// Logs the client into the Steam3 network as an anonymous user.
        /// The client should already have been connected at this point.
        /// Results are returned in a <see cref="LoggedOnCallback"/>.
        /// </summary>
        public void LogOnAnonymous()
        {
            if (!this.Client.IsConnected)
            {
                this.Client.PostCallback(new LoggedOnCallback(EResult.NoConnection));
                return;
            }

            var logon = new ClientMsgProtobuf <CMsgClientLogon>(EMsg.ClientLogon);

            SteamID auId = new SteamID(0, 0, Client.ConnectedUniverse, EAccountType.AnonUser);

            logon.ProtoHeader.client_sessionid = 0;
            logon.ProtoHeader.steamid          = auId.ConvertToUInt64();

            logon.Body.protocol_version = MsgClientLogon.CurrentProtocol;
            logon.Body.client_os_type   = ( uint )Utils.GetOSType();

            // this is not a proper machine id that Steam accepts
            // but it's good enough for identifying a machine
            logon.Body.machine_id = Utils.GenerateMachineID();

            this.Client.Send(logon);
        }
Beispiel #19
0
        void HandlePlayingSessionState(IPacketMsg packetMsg)
        {
            var playingSessionState = new ClientMsgProtobuf <CMsgClientPlayingSessionState>(packetMsg);

            this.Client.PostCallback(new PlayingSessionStateCallback(packetMsg.TargetJobID, playingSessionState.Body));
        }
Beispiel #20
0
        /// <summary>
        /// Logs the client into the Steam3 network.
        /// The client should already have been connected at this point.
        /// Results are returned in a <see cref="LoggedOnCallback"/>.
        /// </summary>
        /// <param name="details">The details to use for logging on.</param>
        /// <exception cref="ArgumentNullException">No logon details were provided.</exception>
        /// <exception cref="ArgumentException">Username or password are not set within <paramref name="details"/>.</exception>
        public void LogOn(LogOnDetails details)
        {
            if (details == null)
            {
                throw new ArgumentNullException("details");
            }
            if (string.IsNullOrEmpty(details.Username) || (string.IsNullOrEmpty(details.Password) && string.IsNullOrEmpty(details.LoginKey)))
            {
                throw new ArgumentException("LogOn requires a username and password to be set in 'details'.");
            }
            if (!string.IsNullOrEmpty(details.LoginKey) && !details.ShouldRememberPassword)
            {
                // Prevent consumers from screwing this up.
                // If should_remember_password is false, the login_key is ignored server-side.
                // The inverse is not applicable (you can log in with should_remember_password and no login_key).
                throw new ArgumentException("ShouldRememberPassword is required to be set to true in order to use LoginKey.");
            }
            if (!this.Client.IsConnected)
            {
                this.Client.PostCallback(new LoggedOnCallback(EResult.NoConnection));
                return;
            }

            var logon = new ClientMsgProtobuf <CMsgClientLogon>(EMsg.ClientLogon);

            SteamID steamId = new SteamID(details.AccountID, details.AccountInstance, Client.ConnectedUniverse, EAccountType.Individual);

            if (details.LoginID.HasValue)
            {
                logon.Body.obfustucated_private_ip = details.LoginID.Value;
            }
            else
            {
                uint localIp = NetHelpers.GetIPAddress(this.Client.LocalIP);
                logon.Body.obfustucated_private_ip = localIp ^ MsgClientLogon.ObfuscationMask;
            }

            logon.ProtoHeader.client_sessionid = 0;
            logon.ProtoHeader.steamid          = steamId.ConvertToUInt64();

            logon.Body.account_name             = details.Username;
            logon.Body.password                 = details.Password;
            logon.Body.should_remember_password = details.ShouldRememberPassword;

            logon.Body.protocol_version = MsgClientLogon.CurrentProtocol;
            logon.Body.client_os_type   = ( uint )details.ClientOSType;
            logon.Body.client_language  = details.ClientLanguage;
            logon.Body.cell_id          = details.CellID;

            logon.Body.steam2_ticket_request = details.RequestSteam2Ticket;

            // we're now using the latest steamclient package version, this is required to get a proper sentry file for steam guard
            logon.Body.client_package_version = 1771; // todo: determine if this is still required
            logon.Body.machine_id             = HardwareUtils.GetMachineID();

            // steam guard
            logon.Body.auth_code       = details.AuthCode;
            logon.Body.two_factor_code = details.TwoFactorCode;

            logon.Body.login_key = details.LoginKey;

            logon.Body.sha_sentryfile     = details.SentryFileHash;
            logon.Body.eresult_sentryfile = ( int )(details.SentryFileHash != null ? EResult.OK : EResult.FileNotFound);


            this.Client.Send(logon);
        }
Beispiel #21
0
        void HandleFriendsList(IPacketMsg packetMsg)
        {
            var list = new ClientMsgProtobuf <CMsgClientFriendsList>(packetMsg);

            cache.LocalUser.SteamID = this.Client.SteamID;

            if (!list.Body.bincremental)
            {
                // if we're not an incremental update, the message contains all friends, so we should clear our current list
                lock ( listLock )
                {
                    friendList.Clear();
                    clanList.Clear();
                }
            }

            // we have to request information for all of our friends because steam only sends persona information for online friends
            var reqInfo = new ClientMsgProtobuf <CMsgClientRequestFriendData>(EMsg.ClientRequestFriendData);

            reqInfo.Body.persona_state_requested = ( uint )Client.Configuration.DefaultPersonaStateFlags;

            lock ( listLock )
            {
                List <SteamID> friendsToRemove = new List <SteamID>();
                List <SteamID> clansToRemove   = new List <SteamID>();

                foreach (var friendObj in list.Body.friends)
                {
                    SteamID friendId = friendObj.ulfriendid;

                    if (friendId.IsIndividualAccount)
                    {
                        var user = cache.GetUser(friendId);

                        user.Relationship = ( EFriendRelationship )friendObj.efriendrelationship;

                        if (friendList.Contains(friendId))
                        {
                            // if this is a friend on our list, and they removed us, mark them for removal
                            if (user.Relationship == EFriendRelationship.None)
                            {
                                friendsToRemove.Add(friendId);
                            }
                        }
                        else
                        {
                            // we don't know about this friend yet, lets add them
                            friendList.Add(friendId);
                        }
                    }
                    else if (friendId.IsClanAccount)
                    {
                        var clan = cache.Clans.GetAccount(friendId);

                        clan.Relationship = ( EClanRelationship )friendObj.efriendrelationship;

                        if (clanList.Contains(friendId))
                        {
                            // mark clans we were removed/kicked from
                            // note: not actually sure about the kicked relationship, but i'm using it for good measure
                            if (clan.Relationship == EClanRelationship.None || clan.Relationship == EClanRelationship.Kicked)
                            {
                                clansToRemove.Add(friendId);
                            }
                        }
                        else
                        {
                            // don't know about this clan, add it
                            clanList.Add(friendId);
                        }
                    }

                    if (!list.Body.bincremental)
                    {
                        // request persona state for our friend & clan list when it's a non-incremental update
                        reqInfo.Body.friends.Add(friendId);
                    }
                }

                // remove anything we marked for removal
                friendsToRemove.ForEach(f => friendList.Remove(f));
                clansToRemove.ForEach(c => clanList.Remove(c));
            }

            if (reqInfo.Body.friends.Count > 0)
            {
                this.Client.Send(reqInfo);
            }

            var callback = new FriendsListCallback(list.Body);

            this.Client.PostCallback(callback);
        }
Beispiel #22
0
        /// <summary>
        /// Requests all offline messages.
        /// This also marks them as read server side.
        /// Results are returned in a <see cref="FriendMsgHistoryCallback"/>.
        /// </summary>
        public void RequestOfflineMessages()
        {
            var request = new ClientMsgProtobuf <CMsgClientChatGetFriendMessageHistoryForOfflineMessages>(EMsg.ClientFSGetFriendMessageHistoryForOfflineMessages);

            this.Client.Send(request);
        }
Beispiel #23
0
        void HandleAccountInfo(IPacketMsg packetMsg)
        {
            var accInfo = new ClientMsgProtobuf <CMsgClientAccountInfo>(packetMsg);

            cache.LocalUser.Name = accInfo.Body.persona_name;
        }
Beispiel #24
0
        void HandlePersonaState(IPacketMsg packetMsg)
        {
            var perState = new ClientMsgProtobuf <CMsgClientPersonaState>(packetMsg);

            EClientPersonaStateFlag flags = ( EClientPersonaStateFlag )perState.Body.status_flags;

            foreach (var friend in perState.Body.friends)
            {
                SteamID friendId = friend.friendid;

                SteamID sourceId = friend.steamid_source;

                if (friendId.IsIndividualAccount)
                {
                    User cacheFriend = cache.GetUser(friendId);

                    if ((flags & EClientPersonaStateFlag.PlayerName) == EClientPersonaStateFlag.PlayerName)
                    {
                        cacheFriend.Name = friend.player_name;
                    }

                    if ((flags & EClientPersonaStateFlag.Presence) == EClientPersonaStateFlag.Presence)
                    {
                        cacheFriend.AvatarHash        = friend.avatar_hash;
                        cacheFriend.PersonaState      = ( EPersonaState )friend.persona_state;
                        cacheFriend.PersonaStateFlags = ( EPersonaStateFlag )friend.persona_state_flags;
                    }

                    if ((flags & EClientPersonaStateFlag.GameExtraInfo) == EClientPersonaStateFlag.GameExtraInfo)
                    {
                        cacheFriend.GameName  = friend.game_name;
                        cacheFriend.GameID    = friend.gameid;
                        cacheFriend.GameAppID = friend.game_played_app_id;
                    }
                }
                else if (friendId.IsClanAccount)
                {
                    Clan cacheClan = cache.Clans.GetAccount(friendId);

                    if ((flags & EClientPersonaStateFlag.PlayerName) == EClientPersonaStateFlag.PlayerName)
                    {
                        cacheClan.Name = friend.player_name;
                    }

                    if ((flags & EClientPersonaStateFlag.Presence) == EClientPersonaStateFlag.Presence)
                    {
                        cacheClan.AvatarHash = friend.avatar_hash;
                    }
                }
                else
                {
                }

                // todo: cache other details/account types?
            }

            foreach (var friend in perState.Body.friends)
            {
                var callback = new PersonaStateCallback(friend);
                this.Client.PostCallback(callback);
            }
        }
Beispiel #25
0
        void HandleCMList(IPacketMsg packetMsg)
        {
            var cmMsg = new ClientMsgProtobuf <CMsgClientCMList>(packetMsg);

            PostCallback(new CMListCallback(cmMsg.Body));
        }
Beispiel #26
0
        /// <summary>
        /// Logs the user off of the Steam3 network.
        /// This method does not disconnect the client.
        /// Results are returned in a <see cref="LoggedOffCallback"/>.
        /// </summary>
        public void LogOff()
        {
            var logOff = new ClientMsgProtobuf <CMsgClientLogOff>(EMsg.ClientLogOff);

            this.Client.Send(logOff);
        }
Beispiel #27
0
        void HandleServerList(IPacketMsg packetMsg)
        {
            var listMsg = new ClientMsgProtobuf <CMsgClientServerList>(packetMsg);

            PostCallback(new ServerListCallback(listMsg.Body));
        }