Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

This documentation is still a work in progress, things will be missing.

Steam-vent allows using the steam client protocol to interact with steam servers.

The steam client protocol can be used to send and receive chat messages, manipulate the inventory, manage friends and more.

Discovering servers

Before we can connect to any steam servers, we first need to know what servers are available.

Servers are provided trough a ServerList, while you can manually specify a list of servers, the usual method is to use the steam web-api to discover a list of servers with ServerList::discover.

Once you have a server list you can save a copy of the server list for future use. But be aware that if you're re-using an old server list, some server in the list might no longer be functional, so be prepared with dealing with connection issues when trying to connect using a re-used ServerList.

Anonymous sessions

Note all usages of the steam client api require authentication.

For apis that don't require authentication you can start anonymous sessions using Connection::anonymous or Connection::anonymous_server to start a new session using the anonymous client or server account respectively.

Authentication

Authenticated user connections are started with Connection::login.

Besides the normal username and password, you need to provide a store for the steam guard machine data and a confirmation handler.

Steam guard machine data store

After authentication, steam provides the client with some machine specific data to allow skipping (depending on various factors) the authentication step for the next login.

For steam-vent to make use of this data, the app needs to provide a way for storing this data by providing an implementation of the GuardDataStore trait.

steam-vent bundles two implementations of the trait:

If none of these methods of storage are suitable for the specific use case, the app can provide their own implementation for the trait. For example storing the data in the application database.

Confirmation handler

When logging into steam, a user needs to provide confirmation of the login trough a second factor. Usually either trough the mobile app or by providing a TOTP token.

An app can implement this confirmation by providing one or more implementations of the AuthConfirmationHandler trait.

steam-vent bundles the following implementations of the trait:

Multiple authentication providers can be combined by using AuthConfirmationHandler::or, where the first backend that successfully completes the confirmation will be used. A common use case for apps will be combining the DeviceConfirmationHandler and one of the TOTP providers to allow users to confirm the login trough either the app or TOTP.

Alternatively apps can provide their own implementation of the trait to integrate whichever method of asking the user for the TOTP token.

Listen before authentication

Steam sends some messages to the client immediately on authentication.

If you need to listen to those messages, you can create a connection without logging in yet by using UnAuthenticatedConnection::connect.

Unauthenticated connections cannot be used to send messages, but you can use it to start listening on messages before authenticating.

Once you're started listening for all the messages you require, you can convert an UnAuthenticatedConnection into a authenticated Connection by using anonymous, anonymous_server or login.

Customizing the websocket

Sometimes it's necessary to customize the websocket that steam-vent uses, for example to change the TLS settings or configure a proxy.

To accomplish this, steam-vent allows using a custom transport with UnAuthenticatedConnection::from_sender_receiver which takes a impl Sink<BytesMut, Error = NetworkError> that will be used to send messages to steam, and a impl Stream<Item = Result<BytesMut, NetworkError>> that is used to receive messages.

The Sink/Stream pair can be acquired, for example, by spliting a websocket from tokio_tungsentite and maping it's data to/from BytesMut.

Once you've created the UnAuthenticatedConnection you can start a session by using anonymous, anonymous_server or login.

See the custom_transport example for a full example of creating a Connection with a customer transport.

Sending messages

There are three different types of messages you can send to steam:

  • One-shot messages
  • Job messages
  • Rpc messages

One-shot messages

One-shot messages are messages sent by the client where no response is expected.

You can send one-show messages with Connection::send, the returned future will complete as soon as the message has been send.

Job messages

Job messages are messages that expect a response from steam

You can send job messages with Connection::job, the returned future will complete once steam returns a response or the response times out.

Note that type of the response isn't specified in the steam protobufs, you fill thus need to manually specify the response type.

Rpc messages

Rpc messages are messages that expect a response from steam

You can send job messages with Connection::service_method, the returned future will complete once steam returns a response or the response times out.

For rpc messages, the return type of the response is specified in the protobufs and you will thus not need to specify the return type.

Rpc messages are denoted in the protobufs by being included in a service block. See for example the FriendMessages service.

In the generated code for the protobufs, rpc messages implement the ServiceMethodRequest trait.

Receiving messages

Besides the messages sent as a reply to a message, there are two categories of messages you can listen.

  • Notification messages
  • Regular messages

Notification messages

You can listen for notification messages with Connection::on_notification, this will return Stream of messages of the specified type.

Notification messages are denoted in the protobufs by being included in a service block. See for example the FriendMessagesClient service.

In the generated code for the protobufs, notification messages implement the ServiceMethodRequest trait.

Regular messages

For non-notification messages, you can use one to wait for a single messages of a specific type or on to receive a stream of messages.

Game Coordinator

Some messages need to be send to a game-specific game coordinator instead.

These messages are proxied trough the normal steam connection with a special wrapper, steam-vent can handle this proxying for you.

To send and receive messages from the game coordindator, you need to acquire an instance of the GameCoordinator with Connection::game_coordinator.

This takes an implementation of the GCHandshake trait, which specifies the specifics of initiating the game coordinator connection.

Game-specific implementations can be found the in the protobuf (e.g. GCHandshake from steam-vent-proto-csgo). Additionally there is a generic implementation GenericGCHandshake, using the game-specific handshake is recommended and will generally provide better results.

Once a GameCoordinator is aquired, you can send and receive messages from it using the same interface as your would with a Connection.