NAME

‘on_issue’ - event which gets invoked when connection statistics fall outside the designated range.

SYNOPSIS

#include <game-carrier/server.h>

GC_ADAPTER_EVENT
GCT_INT on_issue(
    GCT_INTPTR conn_user,
    GCT_INT id,
    GCT_COUNTER_VALUE value);

Parameters:

  • conn_user GCT_INTPTR User data associated with the connection.
  • id GCT_INT Stores the statistic id.
  • value GCT_COUNTER_VALUE Identifies the current value of the statistic.

RETURN VALUE

The on_issue function can return a value from the gc_stat_reaction enum, indicating how to handle a connection issue.

The available options are:

DESCRIPTION

The on_issue function is triggered by the gcs when connection statistics fall outside the designated range.

The on_issue event is executed within the gcs worker thread context, and as connection events are serialized, synchronization primitives are unnecessary. The connection is not tied to a specific thread in the worker thread pool, so different threads may handle connection events.

The conn_user parameter holds user data associated with the connection, which was returned by the on_connect call.

The id parameter represents the statistic ID, and it corresponds to an element from the gc_conn_stats enum. Possible values for id are:

The value parameter indicates the current value of the specific statistic.

Each statistic has two alarm levels: YELLOW and RED. If a statistic falls into the RED zone, the default action, typically connection closure, is triggered unconditionally. If it enters the YELLOW zone, the on_issue event is invoked. The application can determine the appropriate action for the connection in such cases by providing a return value.

Limit values for statistics can be configured either through a configuration file or via API calls. The conn_critical section sets the RED zone limits, while the conn_notice section sets the YELLOW zone limits. These sections are placed in the root section of the configuration file. Additionally, specific applications can override default settings by placing them in the application configuration section. Moreover, the application has the ability to override default settings using the connectionSetLimit API call.

EXAMPLE

#include <game-carrier/server.h>

#include <stdlib.h>

/*
 In the following example the application ignores the `max_msg_size` issue
 * for the first message. And closes the connection for the other messages.
*/

struct core_api gc_api;

struct connection_data {
    GCT_INTPTR handle;
    int message_count;
    /* user data asociated with connection */
};

GC_ADAPTER_EVENT
int adapter_initialize(int id, struct core_api *api, const void *load_path)
{
    gc_api = *api;
    return 0;
}

GC_ADAPTER_EVENT
GCT_INTPTR on_connect(
    GCT_INT app_id,
    GCT_INTPTR handle,
    GCT_INT pid,
    GCT_CSTR rip,
    GCT_INT rport,
    GCT_CSTR lip,
    GCT_INT lport,
    GCT_CSTR udata)
{
    /* Allocate user data */
    struct connection_data * conn = malloc(sizeof(struct connection_data));

    /* Out of memory, failed */
    if (conn == NULL) {
        return GC_DROP_CONNECTION;
    }

    /* Save connection hadnle */
    conn->handle = handle;

    /* Initialize message counter */
    conn->message_count = 0;

    /* Set limit for a connection */
    GCT_COUNTER_VALUE one_mb = 1024 * 1024;
    gc_api.connectionSetLimit(handle, GC_STAT_STATUS_YELLOW, GC_CONN_STAT_MAX_MSG_SIZE, one_mb);

    /* Initialize other fields .........  */

    /* Return a pointer to our data as user_data */
    return (GCT_INTPTR)conn;
}

GC_ADAPTER_EVENT
void on_message(
    GCT_INTPTR user,
    GCT_PTR data,
    GCT_SIZE len)
{
    struct connection_data * conn = (struct connection_data *)user;

    /* Increase message counter for a connection */
    ++conn->message_count;

    /* Continue processing message... */
}

GC_ADAPTER_EVENT
GCT_INT on_issue(
    GCT_INTPTR user,
    GCT_INT id,
    GCT_COUNTER_VALUE value)
{
    struct connection_data * conn = (struct connection_data *)user;

    if (id != GC_CONN_STAT_MAX_MSG_SIZE) {
        /* Ignore everything is not related to max_msg_size */
        return GC_STAT_REACTION_DEFAULT;
    }

    /* Check message_count to choose a behaviour */
    /* Note that on_message is not called yet! */
    if (conn->message_count <= 0) {
        /* The counter is zero, this is a first message, ignore */
        return GC_STAT_REACTION_IGNORE;
    } else {
        /* The counter is non-zero, this is not a first message, close */
        return GC_STAT_REACTION_CLOSE;
    }
}

SEE ALSO

connectionSetLimit, on_connect, on_disconnect, on_message, gc_conn_stats, gc_stat_reaction