TSUSERARGS(3ts)

πŸ“¦
version 9.2.5 Β· 5 versions
, in ubuntu questing

πŸ¦‹ TSUSERARGS πŸ¦‹

okay bestie, so this is the TSUserArgs(3ts) page from the Apache Traffic Server manual β€” yes, the whole thing, and no we're not skipping a single line of it πŸ’…


🌸 NAME 🌸

TSUserArgs β€” the TSUserArgs API function ✨ like, that's the whole name, that's the whole job, periodt.


πŸŽ€ SYNOPSIS πŸŽ€

#include <ts/ts.h>

typedef enum {
  TS_USER_ARGS_TXN,   ///< Transaction based.
  TS_USER_ARGS_SSN,   ///< Session based
  TS_USER_ARGS_VCONN, ///< VConnection based
  TS_USER_ARGS_GLB,   ///< Global based
  TS_USER_ARGS_COUNT  ///< Fake enum, # of valid entries.
} TSUserArgType;

TSReturnCode TSUserArgIndexReserve(TSUserArgType type, const char *name,
const char *description, int *arg_idx)

TSReturnCode TSUserArgIndexNameLookup(TSUserArgType type, const char
*name, int *arg_idx, const char **description)

TSReturnCode TSUserArgIndexLookup(TSUserArgType type, int arg_idx, const
char **name, const char **description)

void TSUserArgSet(void *data, int arg_idx, void *arg)

void *TSUserArgGet(void *data, int arg_idx)

πŸ’– DESCRIPTION πŸ’–

okay so here's the tea β˜• β€” Traffic Server sessions, transactions, virtual connections and globally all hand you a fixed array of void pointers that plugins can use to stash information. It's giving built-in storage closet, no cap. Why would you want this? Two reasons, bestie:

  • so you don't have to go create a per-session or per-transaction continuation just to hold some data 😭
  • so plugins can talk to each other β€” the values in that array are visible to any plugin that can access the session or transaction. it's a group chat, fr fr 🫢

Now, the array values are opaque to Traffic Server itself. It will not dereference them and it will not release them. So who cleans up? You do, babes. Plugins are responsible for cleaning up any resources pointed to by the values. Or β€” if the values are just plain values with nothing hanging off them β€” there's literally no need for the plugin to remove them after the session or transaction has completed. easy ✨


🧚 reserving your spot (collision avoidance, iconic)

To avoid collisions between plugins, a plugin should first reserve an index in the array. You reserve a slot of a particular type by calling TSUserArgIndexReserve(). The arguments are:

  • type β€” the type for which the plugin intends to reserve a slot. See TSUserArgType up above πŸ‘†
  • name β€” an identifying name for the plugin that reserved the index. Required. like, mandatory mandatory πŸ™ˆ
  • description β€” an optional description of the use of the arg. This can be nullptr.
  • arg_idx β€” a pointer to an int. If an index is successfully reserved, the int pointed at by this gets set to the reserved index. It is not modified if the call is unsuccessful. no notes πŸ’…

The functions return TS_SUCCESS if an index was reserved, TS_ERROR if not β€” most likely because all of the indices have already been reserved. tragic. Generally this will be a file or library scope global which is set at plugin initialization. This function is used in the example remap plugin example/plugins/c-api/remap/remap.cc. The index is stored in the plugin global arg_index. Transaction and session plugin argument indices are reserved independently β€” two separate worlds, two separate vibes 🌈


πŸ” who owns this index anyway

To look up the owner of a reserved index, use TSUserArgIndexNameLookup(), with the appropriate type. If name is found as an owner, the function returns TS_SUCCESS and arg_index is updated with the index reserved under that name. If description is not NULL then the character pointer to which it points will be updated to point at the description for that reserved index. This enables communication between plugins where plugin "A" reserves an index under a well known name and plugin "B" locates the index by looking it up under that name. besties collaborating, we love to see it 🫢

The owner of a reserved index can be found with TSUserArgIndexLookup(). If arg_index is reserved then the function returns TS_SUCCESS and the pointers referred to by name and description are updated. name must point at a valid character pointer, but description can be NULL in which case it is ignored. (she's flexible, she's chill πŸ’œ)


πŸ“ setting and getting (the fun part)

Manipulating the array is simple, bestie. TSUserArgSet() sets the array slot at arg_idx, for the particular type based on the provided data pointer. The values can be retrieved with the value from TSUserArgGet(). Values that have not been set are NULL. πŸ‘‘

Note that both the setter and the getter are context sensitive, based on the type (or value) of the data pointer:

  • TSHttpTxn β€” the implicit context is for a transaction (TS_USER_ARGS_TXN)
  • TSHttpSsn β€” the implicit context is for a transaction (TS_USER_ARGS_SSN)
  • TSVConn β€” the implicit context is for a transaction (TS_USER_ARGS_VCONN)
  • nullptr β€” the implicit context is global (TS_USER_ARGS_GLB)
⚠️ Note that neither TSUserArgSet() nor TSUserArgGet() has any type safety on the data parameters, being a void* pointer. she does not check your receipts, she trusts you completely πŸ’€

πŸ“Œ NOTES (read these, for real)

NOTE: Session arguments persist for the entire session, which means potentially across all transactions in that session. like, she's in it for the long haul πŸ’–
NOTE: Following arg index reservations is conventional, it is not enforced. it's a lifestyle, not a rule ✨

2026, dev@trafficserver.apache.org


aaaand that's the whole page, bestie, we ate and left no crumbs πŸŽ€πŸ’…

so yeah β€” that was the TSUSERARGS(3ts) page, version 9.2, dated Feb 12, 2026, brought to you by the Apache Traffic Server girlies at dev@trafficserver.apache.org, Β© 2026. slay, bye πŸ¦‹βœ¨

πŸ“¦ where this page comes from