All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibasco.agql.protocols.valve.source.query.SourceQueryClient Maven / Gradle / Ivy

/*
 * Copyright (c) 2022 Asynchronous Game Query Library
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ibasco.agql.protocols.valve.source.query;

import com.ibasco.agql.core.NettyMessenger;
import com.ibasco.agql.core.NettySocketClient;
import com.ibasco.agql.core.util.OptionBuilder;
import com.ibasco.agql.core.util.Options;
import com.ibasco.agql.protocols.valve.source.query.challenge.SourceQueryChallengeRequest;
import com.ibasco.agql.protocols.valve.source.query.challenge.SourceQueryChallengeResponse;
import com.ibasco.agql.protocols.valve.source.query.common.enums.SourceChallengeType;
import com.ibasco.agql.protocols.valve.source.query.common.exceptions.SourceChallengeException;
import com.ibasco.agql.protocols.valve.source.query.common.message.SourceQueryRequest;
import com.ibasco.agql.protocols.valve.source.query.common.message.SourceQueryResponse;
import com.ibasco.agql.protocols.valve.source.query.info.SourceQueryInfoRequest;
import com.ibasco.agql.protocols.valve.source.query.info.SourceQueryInfoResponse;
import com.ibasco.agql.protocols.valve.source.query.players.SourceQueryPlayerRequest;
import com.ibasco.agql.protocols.valve.source.query.players.SourceQueryPlayerResponse;
import com.ibasco.agql.protocols.valve.source.query.rules.SourceQueryRulesRequest;
import com.ibasco.agql.protocols.valve.source.query.rules.SourceQueryRulesResponse;
import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;

/**
 * 

* A query client for retreiving information on Source servers. Based on the Valve Source Server Query Protocol *

* * Example: * *

Asynchronous (non-blocking)

* *
 * try (SourceQueryClient client = new SourceQueryClient()) {
 *     CompletableFuture<Source> resultFuture = client.getInfo(new InetSocketAddress("192.168.1.10", 27015);
 *     if (resultFuture.isDone()) {
 *         SourceQueryInfoResponse infoResponse = resultFuture.getNow(null);
 *         assert infoResponse != null;
 *         System.out.printf("INFO: %s\n", infoResponse.getResult());
 *     } else {
 *         //we have not yet received a response, register a callback once we do
 *         resultFuture.whenComplete((response, error) -> {
 *             if (error != null) {
 *                 error.printStackTrace(System.err);
 *                 return;
 *             }
 *             assert response != null;
 *             System.out.printf("INFO: %s\n", response);
 *         });
 *     }
 * }
 * 
* *

Synchronous (blocking)

* *
 * try (SourceQueryClient client = new SourceQueryClient()) {
 *     SourceQueryInfoResponse infoResponse = client.getInfo(new InetSocketAddress("192.168.1.10", 27015);
 *     assert infoResponse != null;
 *     System.out.printf("INFO: %s\n", infoResponse.getResult());
 * } catch (Exception error) {
 *     error.printStackTrace(System.err);
 * }
 * 
* *

Modifying client configuration parameters

* *

Enable rate-limiting (disabled by default)

* *
 * SourceQueryOptions options = SourceQueryOptions.builder().option(SourceQueryOptions.FAILSAFE_RATELIMIT_ENABLED, true)
 *                                             .option(SourceQueryOptions.FAILSAFE_RATELIMIT_TYPE, RateLimitType.SMOOTH)
 *                                             .build();
 *
 * //pass options to client's constructor
 * try (SourceQueryClient client = new SourceQueryClient(options)) {
 *     InetSocketAddress address = new InetSocketAddress("192.168.1.10", 27015);
 *
 *     //execute query 100 times
 *     for (int i=0; i<100; i++) {
 *         CompletableFuture<Source> resultFuture = client.getInfo(address);
 *         if (resultFuture.isDone()) {
 *             SourceQueryInfoResponse infoResponse = resultFuture.getNow(null);
 *             assert infoResponse != null;
 *             System.out.printf("INFO: %s\n", infoResponse.getResult());
 *         } else {
 *             //we have not yet received a response, register a callback once we do
 *             resultFuture.whenComplete((response, error) -> {
 *                 if (error != null) {
 *                     error.printStackTrace(System.err);
 *                     return;
 *                 }
 *                 assert response != null;
 *                 System.out.printf("INFO: %s\n", response);
 *             });
 *         }
 *     }
 * }
 * 
* * @author Rafael Luis Ibasco * @see Valve Source Server Query Protocol * @see SourceQueryOptions */ public final class SourceQueryClient extends NettySocketClient> { // /** * Create a new {@link com.ibasco.agql.protocols.valve.source.query.SourceQueryClient} instance using the pre-defined configuration {@link com.ibasco.agql.core.util.Options} for this client */ public SourceQueryClient() { this(null); } /** * Create a new {@link com.ibasco.agql.protocols.valve.source.query.SourceQueryClient} instance using the provided {@link SourceQueryOptions} * * @param options * A {@link SourceQueryOptions} object containing all the user-defined configuration values to be used by the client. * * @see Options * @see OptionBuilder */ public SourceQueryClient(SourceQueryOptions options) { super(options); } // /** *

Retrieves information about the Source server. A challengenumber will automatically be obtained if required by the server.

* * @param address * The {@link java.net.InetSocketAddress} containing the ip address and port number information of the target server * * @return A {@link java.util.concurrent.CompletableFuture} that is notified once a response has been received from the server. If successful, the {@link java.util.concurrent.CompletableFuture} returns a value of {@link com.ibasco.agql.protocols.valve.source.query.info.SourceQueryInfoResponse} which provides additional details on the server. * * @see #getInfo(InetSocketAddress, Integer) */ public CompletableFuture getInfo(InetSocketAddress address) { return getInfo(address, null); } /** *

Retrieves information about the Source server using the provided challenge number (optional)

* * @param address * The {@link java.net.InetSocketAddress} containing the IP address and port number information of the target server * @param challenge * (optional) A 32-bit signed integer anti-spoofing challenge. Set to {@code null} to let the library obtain one automatically. Passing a non-null integer will implicitly disable auto-update. This means that the library will not automatically send a new challenge request if the server requires a new one. Instead, it will throw a {@link SourceChallengeException} where a valid challenge number can be obtained via {@link SourceChallengeException#getChallenge()}. This is similar to calling {@link #getInfo(InetSocketAddress)}. * * @return A {@link java.util.concurrent.CompletableFuture} that is notified once a response has been received from the server. If successful, the {@link java.util.concurrent.CompletableFuture} returns a value of {@link com.ibasco.agql.protocols.valve.source.query.info.SourceQueryInfoResponse} which provides additional details on the server * * @throws SourceChallengeException * If auto-update is disabled (challenge argument is {@code null}) and the current challenge number has been invalidated. * @see Changes to A2S_INFO protocol * @see Steam Client Updates as of 12/08/2020 */ public CompletableFuture getInfo(InetSocketAddress address, Integer challenge) { return send(address, new SourceQueryInfoRequest(challenge), SourceQueryInfoResponse.class); } /** *

Retrieve rules from the Source server

* * @param address * The {@link java.net.InetSocketAddress} containing the IP address and port number information of the target server. * * @return A {@link java.util.concurrent.CompletableFuture} that is notified once a response has been received from the server. If successful, the {@link java.util.concurrent.CompletableFuture} returns a value of {@link com.ibasco.agql.protocols.valve.source.query.rules.SourceQueryRulesResponse} which provides additional details on the response. * * @see #getRules(InetSocketAddress, Integer) * @see #getChallenge(InetSocketAddress, SourceChallengeType) */ public CompletableFuture getRules(InetSocketAddress address) { return getRules(address, null); } /** *

Retrieve rules from the Source server

* *
* Note: This method requires a valid challenge number which can be obtained via {@link #getChallenge(InetSocketAddress, SourceChallengeType)} *
* * @param address * The {@link java.net.InetSocketAddress} containing the IP address and port number information of the target server * @param challenge * (optional) A 32-bit signed integer anti-spoofing challenge. Set to {@code null} to let the library obtain one automatically. Passing a non-null integer will implicitly disable auto-update. This means that the library will not automatically send a new challenge request if the server requires a new one. Instead, it will throw a {@link SourceChallengeException} where a valid challenge number can be obtained via {@link SourceChallengeException#getChallenge()}. This is similar to calling {@link #getRules(InetSocketAddress)}. * * @return A {@link java.util.concurrent.CompletableFuture} that is notified once a response has been received from the server. If successful, the future returns a value of {@link com.ibasco.agql.protocols.valve.source.query.rules.SourceQueryRulesResponse} which provides additional details on the response. * * @throws SourceChallengeException * If auto-update is disabled (challenge argument is {@code null}) and the current challenge number has been invalidated. * @see #getRules(InetSocketAddress, Integer) */ public CompletableFuture getRules(InetSocketAddress address, Integer challenge) { return send(address, new SourceQueryRulesRequest(challenge), SourceQueryRulesResponse.class); } /** *

* Retrieve a list of active players in the server. *

* * @param address * The {@link java.net.InetSocketAddress} containing the IP address and port number information of the target server * * @return A {@link java.util.concurrent.CompletableFuture} that contains a {@link java.util.List} of {@link com.ibasco.agql.protocols.valve.source.query.players.SourcePlayer} currently residing on * the server * * @see #getPlayers(InetSocketAddress, Integer) */ public CompletableFuture getPlayers(InetSocketAddress address) { return send(address, new SourceQueryPlayerRequest(), SourceQueryPlayerResponse.class); } /** *

Retrieve a list of active players in the server. You need to obtain a valid challenge number from the server * first via {@link #getChallenge(InetSocketAddress, SourceChallengeType)}

* * @param address * The {@link java.net.InetSocketAddress} containing the IP address and port number information of the target server * @param challenge * (optional) A 32-bit signed integer anti-spoofing challenge. Set to {@code null} to let the library obtain one automatically. Passing a non-null integer will implicitly disable auto-update. This means that the library will not automatically send a new challenge request if the server requires a new one. Instead, it will throw a {@link SourceChallengeException} where a valid challenge number can be obtained via {@link SourceChallengeException#getChallenge()}. This is similar to calling {@link #getPlayers(InetSocketAddress)}. * * @return A {@link java.util.concurrent.CompletableFuture} that contains a {@link java.util.List} of {@link com.ibasco.agql.protocols.valve.source.query.players.SourcePlayer} currently residing on * the server * * @throws SourceChallengeException * If auto-update is disabled (challenge argument is {@code null}) and the current challenge number has been invalidated. * @see #getPlayers(InetSocketAddress) * @see #getChallenge(InetSocketAddress, SourceChallengeType) */ public CompletableFuture getPlayers(InetSocketAddress address, Integer challenge) { return send(address, new SourceQueryPlayerRequest(challenge), SourceQueryPlayerResponse.class); } /** *

Obtains a 4-byte (32-bit) anti-spoofing integer from the server. This is used for queries (such as PLAYERS, RULES or INFO) that requires a challenge number.

* * @param address * The {@link java.net.InetSocketAddress} containing the IP address and port number information of the target server * @param type * The {@link com.ibasco.agql.protocols.valve.source.query.common.enums.SourceChallengeType} enumeration which identifies the type of server challenge. * * @return A {@link java.util.concurrent.CompletableFuture} returning a value of {@link java.lang.Integer} representing the server challenge number */ public CompletableFuture getChallenge(InetSocketAddress address, SourceChallengeType type) { return send(address, new SourceQueryChallengeRequest(type), SourceQueryChallengeResponse.class); } /** {@inheritDoc} */ @Override protected NettyMessenger> createMessenger(Options options) { return new SourceQueryMessenger(options); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy