Plugin Documentation

SocketGate
API Gateway WebSockets for Blueprints and C++

A realtime client for Amazon API Gateway WebSocket APIs: IAM (SigV4) or token authorization, automatic reconnect with back-off, keep-alive, request/reply messaging and server-side connection management, built on the official AWS SDK for C++.

v1.0
UE 4.27 & 5.8
Win64, Linux & Android
Category Networking
Alpha XP

Overview

SocketGate connects Unreal Engine 4.27 and 5.8 games to Amazon API Gateway WebSocket APIs (wss://<api-id>.execute-api.<region>.amazonaws.com/<stage>). It is useful for chat, lobbies, live events, notifications, turn-based play and anything else your backend pushes to players. The socket uses the engine's own WebSocket client; AWS signing and the management API use the bundled AWS SDK for C++. Every event arrives on the game thread.

  • Socket Connection object: On Connected, On Message, On Closed, On Error, On Reconnecting; Send Text, Send Json Action, Close.
  • $connect authorization: None, IAM (a presigned SigV4 URL from Cognito identity pool credentials) or Token (header or query parameter for a Lambda authorizer), plus extra headers and query parameters.
  • Auto-reconnect with exponential back-off and jitter. Every attempt signs a fresh URL, because presigned URLs expire.
  • Keep-alive: API Gateway closes connections after 10 minutes without traffic, so SocketGate sends a message whenever the client has been quiet.
  • Send And Wait For Reply: request/response over the socket, matched by a generated requestId.
  • Post To Connection, Get Connection, Delete Connection for dedicated servers and tools.

Requirements

RequirementDetails
Unreal Engine4.27 and 5.8
PlatformsWin64, Linux and Android
ModulesSocketGate (Runtime), SocketGateSdk (prebuilt AWS SDK for C++ 1.11.916 in Source/ThirdParty)
DependenciesNo other plugins. Uses the engine's WebSockets module. On Linux and Android the SDK uses the engine's libcurl, OpenSSL and certificate store.
AWSAn AWS account with an API Gateway WebSocket API. API Gateway, Lambda and Cognito usage is billed by AWS.

Installation

  1. Install SocketGate from Fab into your engine, or copy the SocketGate folder into your project's Plugins folder.
  2. Enable SocketGate in Edit > Plugins and restart the editor.
  3. Open Project Settings > Plugins > SocketGate and set Default WebSocket Url and Auth Mode. For IAM mode also set Region and Identity Pool Id.
  4. C++ only: add PublicDependencyModuleNames.Add("SocketGate"); to your Build.cs.
Several AWS plugins in one projectEach Alpha XP cloud plugin carries its own copy of the SDK under a plugin-specific name, so they install side by side without conflicts.

Setting up AWS

1. The WebSocket API

  1. In the API Gateway console create a WebSocket API with the route selection expression $request.body.action.
  2. Add the routes $connect, $disconnect, $default and your own routes (for example sendmessage), usually with Lambda integrations.
  3. Add a ping route with a Mock integration for the keep-alive message {"action":"ping"}, or let $default handle it.
  4. Deploy to a stage (for example production). The stage page shows the WebSocket URL; copy it into Default WebSocket Url.

2. Protect $connect with IAM (recommended for game clients)

In the console open Routes > $connect > Route request and set Authorization to AWS_IAM, then deploy the API again. With the AWS CLI:

aws apigatewayv2 get-routes --api-id abc123
aws apigatewayv2 update-route --api-id abc123 --route-id r1s2t3 --authorization-type AWS_IAM
aws apigatewayv2 create-deployment --api-id abc123 --stage-name production

On WebSocket APIs, authorization only applies to $connect. Once a client is connected it can use every route.

3. The Cognito identity pool role

Create an Amazon Cognito identity pool. Enable guest access if players may connect before signing in, and add your identity providers. Then allow the pool's IAM role (authenticated and/or guest) to open connections to your API and nothing else:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "execute-api:Invoke",
    "Resource": "arn:aws:execute-api:us-east-1:123456789012:abc123/production/$connect"
  }]
}

Replace the region, account id (123456789012), API id (abc123) and stage with your own. Use abc123/*/$connect to allow every stage.

4. The server role (connection management)

Code that pushes messages to clients (your Lambda functions, or a dedicated server using Post To Connection) needs execute-api:ManageConnections:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "execute-api:ManageConnections",
    "Resource": "arn:aws:execute-api:us-east-1:123456789012:abc123/production/*/@connections/*"
  }]
}

The * after the stage covers POST (Post To Connection), GET (Get Connection) and DELETE (Delete Connection). Never give this permission to the players' identity pool role.

Never ship access keysStatic keys in the settings end up in DefaultGame.ini and in packaged games. Use them only for development and dedicated servers; players should always use the identity pool. Shipping builds refuse settings keys unless Allow Static Keys In Shipping is enabled.

Quick start

  1. Call Create Socket Connection (leave Url empty to use the settings) and promote the result to a variable.
  2. From the variable, bind On Connected, On Message, On Closed and On Error, then call Connect.
  3. In On Connected call Send Json Action with Route sendmessage and Payload Json {"text": "hi"}. This sends {"action":"sendmessage","text":"hi"}.
  4. In On Message read the text, for example with Get JSON Field (Path text) or JSON To Struct.
  5. Call Close when the player leaves.
No need to keep a referenceWhile a connection is connecting, connected or reconnecting, SocketGate keeps it alive: it is held by the game instance or rooted. It is closed automatically when the game instance shuts down, including at the end of Play In Editor.

Connection object

USocketGateConnection is a Blueprint type. Its options are copied from the project settings when it is created; change them on the object before calling Connect.

MemberKindDescription
ConnectCallableOpens the connection, signing the URL first in IAM mode. Returns false if the connection is already active or the URL is not ws:// / wss://.
CloseCallableCloses the connection and stops reconnecting. Status Code is 1000 (normal) or 3000-4999; Reason is optional. On Closed fires when the server confirms, or after 5 seconds.
Send TextCallableSends a text frame. Returns false when the connection is not open or the text is larger than API Gateway's 128 KB limit.
Send Json ActionCallableSends {"action": Route, ...fields of Payload Json}. Payload Json must be a JSON object or empty. The field name comes from Route Field.
Is ConnectedPureTrue while the socket is open.
Get StatePureNot Connected, Connecting, Connected, Reconnecting or Closing.
On ConnectedEventThe connection is open. Also fires after every successful reconnect.
On MessageEvent(Message) A text message arrived. Replies to Send And Wait For Reply arrive here too.
On ClosedEvent(Status Code, Reason, Was Clean) The connection closed or dropped. If Get State returns Reconnecting, the next attempt is already scheduled.
On ErrorEvent(Error) A connection attempt failed (handshake, signing, token, timeout), or reconnecting gave up (ReconnectFailed).
On ReconnectingEvent(Attempt, Delay Seconds) A reconnect attempt was scheduled.

Options (read / write on the object)

Url, Auth Mode, Auth Token, Token Location, Token Header Name, Token Query Name, Headers, Query Parameters, Protocols, Signing Region, Presign Expiry Seconds, Connect Timeout Seconds, Auto Reconnect, Max Reconnect Attempts, Reconnect Base Delay Seconds, Reconnect Max Delay Seconds, Keep Alive Interval Seconds, Keep Alive Message, Route Field, Request Id Field. The Settings section explains each one.

SubprotocolsLeave Protocols empty for API Gateway. If the client asks for a subprotocol, the $connect integration has to answer with the Sec-WebSocket-Protocol header, or the handshake fails.

Authorization

Auth ModeAPI Gateway setupWhat SocketGate sends
None$connect with authorization NONEThe URL with your Query Parameters, plus your Headers.
IAM (SigV4)$connect with authorization AWS_IAMThe URL presigned with AWS Signature Version 4 (service execute-api) using the plugin's credentials. Query Parameters are signed too. The signing region comes from the execute-api host name; set Signing Region for a custom domain.
Token$connect with a Lambda REQUEST authorizer, identity source route.request.header.Authorization or route.request.querystring.tokenAuth Token (or, if empty, the token last passed to Set Login Token) in the header Token Header Name or the query parameter Token Query Name. Your authorizer verifies it, for example a Cognito user pool ID token.

Signing runs on a background worker, because credentials may need a network round trip. The socket itself is created and used on the game thread. URLs are presigned for Presign Expiry Seconds (default 300). Once a connection is open it no longer needs the URL; API Gateway keeps connections open for up to 2 hours.

Device clockA presigned URL contains the signing time. If a device's clock is several minutes wrong, API Gateway rejects the handshake with 403.

Reconnect & keep-alive

  • Auto Reconnect (default on) reacts to failed attempts and to connections the server or network dropped. It does not reconnect after you call Close, or after a normal close (1000) from the server, for example Delete Connection.
  • The delay starts at Reconnect Base Delay Seconds (1 s) and doubles with every attempt up to Reconnect Max Delay Seconds (30 s), with plus or minus 20% jitter so clients do not reconnect all at once. A successful connection resets the count.
  • After Max Reconnect Attempts failed attempts in a row (default 10, 0 = never give up) On Error fires with ReconnectFailed and the state becomes Not Connected.
  • Every IAM attempt signs a new URL, so expired signatures and refreshed Cognito credentials are handled for you. API Gateway ends every connection after 2 hours; the reconnect brings it back.
  • Keep-alive: when the client has sent nothing for Keep Alive Interval Seconds (default 300, 0 = off), it sends Keep Alive Message (default {"action":"ping"}). API Gateway closes connections that are idle for 10 minutes.
  • The handshake times out after Socket Connect Timeout Seconds (default 15) and counts as a failed attempt.

Request / reply

Send And Wait For Reply (Connection, Route, Payload Json, Timeout Seconds, Request Id Field Name) sends {"action": Route, "requestId": "<32 hex digits>", ...}. It fires On Reply (Reply = the whole message) when a message with the same top-level requestId string arrives. Otherwise it fires On Timeout after the timeout (0 = Default Reply Timeout Seconds), or On Failure if the connection is not open or closes while waiting. You can stop waiting with Cancel.

Your backend only has to echo the id. In a Lambda integration (Node.js):

import { ApiGatewayManagementApiClient, PostToConnectionCommand } from "@aws-sdk/client-apigatewaymanagementapi";

export const handler = async (event) => {
  const { domainName, stage, connectionId } = event.requestContext;
  const body = JSON.parse(event.body);
  const api = new ApiGatewayManagementApiClient({ endpoint: `https://${domainName}/${stage}` });
  await api.send(new PostToConnectionCommand({
    ConnectionId: connectionId,
    Data: JSON.stringify({ requestId: body.requestId, score: 1200 })
  }));
  return { statusCode: 200 };
};

Another way: give the route a route response. API Gateway then sends the integration's response body straight back to the client.

Server side: connection management

Dedicated servers and tools with IAM credentials (Static Keys or the Default Credential Chain, with the server role above) can push to clients and manage them through the API Gateway management API. The connection id is $context.connectionId / event.requestContext.connectionId in your route integrations.

NodeInputsOutputsDescription
Post To ConnectionConnection Id, Data, EndpointOn Success / On Failure (Info, Error)Sends Data (up to 128 KB) to one client. Error.Code GoneException means the client is no longer connected.
Get ConnectionConnection Id, EndpointOn Success / On Failure (Info, Error)Returns Connected At, Last Active At, Source Ip and User Agent.
Delete ConnectionConnection Id, EndpointOn Success / On Failure (Info, Error)Disconnects a client.
Resolve IdentityForce RefreshOn Success / On Failure (Identity Id, Error)Fetches the Cognito identity and credentials now, for example right after login, so problems show up before the first IAM connection.

Endpoint is https://<api-id>.execute-api.<region>.amazonaws.com/<stage>. When it is empty, SocketGate uses Default Management Endpoint, and if that is empty too it uses Default WebSocket Url with wss:// changed to https://. The signing region comes from the host name.

Functions

NodeDescription
Create Socket ConnectionCreates a connection with the options from the project settings. Url empty = Default WebSocket Url.
Make WebSocket UrlBuilds wss://<api-id>.execute-api.<region>.amazonaws.com/<stage>.
Set RegionSwitches the AWS region for every following request.
Set Credential ModeOverrides the credential mode from the settings at runtime.
Set Login TokenSigns the player in to the identity pool with a provider token (Cognito user pool, Google, Apple, Facebook, OpenID). Token mode connections without their own Auth Token send this token.
Clear Login TokensForgets all login tokens and the cached identity; the player becomes a guest.
Set Static CredentialsUses the given keys from now on (Static Keys mode), for example temporary keys handed out by your backend.
Get Identity IdThe player's Cognito identity id; empty until credentials were resolved once.
Make User Pool Provider NameBuilds the login key of a Cognito user pool: cognito-idp.<region>.amazonaws.com/<pool id>.
Is ConfiguredReturns false and a reason when the credential settings are incomplete (needed for IAM mode and the management nodes).
Struct To JSONConverts any struct to a JSON object string, for example a Payload Json.
JSON To StructFills a struct from a JSON object string; missing fields keep their defaults.
Get JSON FieldReads one value with a path such as player.stats[2].score.
CancelOn a latent node's return value: none of its pins fire any more.
Is FinishedOn a latent node's return value: true after it finished or was cancelled.

Credentials

Credentials are only needed for IAM mode and for the management nodes. None and Token modes do not use AWS credentials at all.

ModeUse forHow
Cognito Identity PoolGame clientsGuests get unauthenticated credentials; after Set Login Token the player gets the authenticated role. Credentials refresh automatically before they expire.
Static KeysDevelopment, dedicated servers, keys from your backendSettings keys or Set Static Credentials (with an optional session token).
Default Credential ChainServers and toolsEnvironment variables, the ~/.aws profile, ECS and EC2 instance roles.

C++ API

// Build.cs: PublicDependencyModuleNames.Add("SocketGate");
#include "SocketGateConnection.h"
#include "SocketGateLibrary.h"

// UPROPERTY() USocketGateConnection* Connection;
Connection = USocketGateLibrary::CreateSocketConnection(this, FString());
Connection->AuthMode = ESocketGateAuthMode::Iam;
Connection->OnConnected.AddDynamic(this, &AMyActor::HandleConnected);   // UFUNCTION() void HandleConnected();
Connection->OnMessage.AddDynamic(this, &AMyActor::HandleMessage);       // UFUNCTION() void HandleMessage(const FString& Message);
Connection->Connect();

void AMyActor::HandleConnected()
{
    Connection->SendJsonAction(TEXT("sendmessage"), TEXT("{\"text\":\"hi\"}"));
}

The latent node classes (USocketGateReplyAction, USocketGateManageAction, USocketGateIdentityAction) can also be created from C++ through their static factory functions; bind the delegates, then call Activate().

Types

TypeKindMembers
USocketGateConnectionObjectSee Connection object
FSocketGateErrorStructCode, Message, Http Status, Retryable
FSocketGateConnectionInfoStructConnection Id, Connected At, Last Active At, Source Ip, User Agent
ESocketGateAuthModeEnumNone, IAM (SigV4), Token
ESocketGateTokenLocationEnumHeader, Query Parameter
ESocketGateStateEnumNot Connected, Connecting, Connected, Reconnecting, Closing
ESocketGateCredentialModeEnumCognito Identity Pool, Static Keys, Default Credential Chain

Settings

Project Settings > Plugins > SocketGate (saved to DefaultGame.ini). WebSocket, reconnect, keep-alive and reply options are copied into each connection when it is created.

SettingDefaultDescription
Regionus-east-1Region of your API and identity pool. URLs on execute-api.<region>.amazonaws.com sign with their own region.
Request Timeout Ms / Connect Timeout Ms30000 / 5000Time limits of AWS requests (credentials, management calls).
Max Retries3Automatic retries of AWS requests for throttling and transient errors.
Worker Threads2Background threads that sign URLs and run management calls.
Verify SSL / Log Sdk WarningsOn / OnTLS verification of AWS requests; SDK warnings in LogSocketGate.
Credential ModeCognito Identity PoolCognito Identity Pool, Static Keys or Default Credential Chain.
Identity Pool Id(empty)For example us-east-1:01234567-89ab-cdef-0123-456789abcdef.
Allow Guest AccessOnUnauthenticated identities before Set Login Token. The pool must allow guest access too.
Access Key Id / Secret Access Key(empty)Static Keys mode. Saved in DefaultGame.ini - development and servers only.
Allow Static Keys In ShippingOffStatic keys from the settings are refused in Shipping builds unless enabled (dedicated servers).
Default WebSocket Url(empty)wss://<api-id>.execute-api.<region>.amazonaws.com/<stage>, used when Create Socket Connection gets no Url.
Auth ModeIAM (SigV4)None, IAM (SigV4) or Token.
Token Location / Token Header Name / Token Query NameHeader / Authorization / tokenWhere Token mode sends the token.
Presign Expiry Seconds300Lifetime of each presigned URL (10-3600).
Route FieldactionField that carries the route in Send Json Action ($request.body.action).
Socket Connect Timeout Seconds15Time allowed for the WebSocket handshake.
Auto ReconnectOnReconnect after errors and dropped connections.
Max Reconnect Attempts10Failed attempts in a row before giving up; 0 = never give up.
Reconnect Base / Max Delay Seconds1 / 30Exponential back-off range (plus or minus 20% jitter).
Keep Alive Interval Seconds300Send Keep Alive Message after this long without sending; 0 = off. Keep it under 600.
Keep Alive Message{"action":"ping"}The keep-alive text.
Request Id FieldrequestIdField used by Send And Wait For Reply.
Default Reply Timeout Seconds10Used when Send And Wait For Reply has Timeout Seconds 0.
Default Management Endpoint(empty)https://<api-id>.execute-api.<region>.amazonaws.com/<stage> for the management nodes; empty = derived from Default WebSocket Url.

Troubleshooting

Error codeCause and fix
InvalidUrlUrl (or Default WebSocket Url) is empty or does not start with wss:// or ws://.
ConnectFailedThe handshake failed. In IAM mode the usual cause is a 403: the role lacks execute-api:Invoke on .../<stage>/$connect, the API was not redeployed after switching $connect to AWS_IAM, the region is wrong (set Signing Region for custom domains), or the device clock is off. In Token mode the authorizer denied the token. Check the API's CloudWatch logs.
ConnectTimeoutNo answer within Socket Connect Timeout Seconds: network problem or wrong host.
NoTokenToken mode without Auth Token and without Set Login Token.
NotConfigured / NotAuthorizedExceptionIAM mode: set the Identity Pool Id, enable guest access on the pool, or call Set Login Token with a fresh token.
ReconnectFailedMax Reconnect Attempts failed attempts in a row. Call Connect again later.
NotConnected / TimeoutSend And Wait For Reply: the connection was not open, or no message with the same requestId arrived. Make sure your backend copies requestId into its reply.
GoneExceptionPost To Connection / Get Connection: the client has disconnected. Remove the connection id from your records.
ForbiddenException / AccessDeniedExceptionManagement calls: the server credentials lack execute-api:ManageConnections on .../<stage>/*/@connections/*.
NoEndpointManagement calls: set Endpoint on the node, Default Management Endpoint or Default WebSocket Url.
UnavailableThe SDK library could not be loaded or the engine is shutting down. Check the Output Log for LogSocketGate errors. None and Token modes keep working without it.
Messages to a route never arriveThe message must be JSON with the route field ({"action":"sendmessage"}); unknown routes go to $default, or API Gateway answers with an error message if there is none.

Credits

© 2026 Alpha XP — alphaxp.net · Support: support@alphaxp.net. Includes the AWS SDK for C++ and the AWS Common Runtime (Apache License 2.0). Built and verified warning-free for Unreal Engine 4.27 and 5.8.