Table of Contents

Server Event Handlers

The StreamingServer communicates with user code through events and a delegate. These handlers control authorization, react to connections and disconnections, handle file transfers, and respond to errors.

server.PublishingPointRequested += Server_PublishingPointRequested;
server.Authorize += Server_Authorize;
server.PublisherConnected += Server_PublisherConnected;
server.ClientConnected += Server_ClientConnected;
server.FileTransferRequestedHandler = Server_FileTransferRequestedHandler;
server.Error += Server_Error;
server.PublishingPointDisposing += Server_PublishingPointDisposing;
server.Disconnected += Server_Disconnected;
server.Start();

Event Lifecycle

Events fire in the following order for a typical connection:

  1. PublishingPointRequested — a client or publisher requests a publishing point that does not exist yet
  2. Authorize — the connection type and parameters are known; user code decides whether to accept or reject
  3. PublisherConnected or ClientConnected — the authorized connection is fully established
  4. Error — an unrecoverable error occurs on the connection
  5. PublishingPointDisposing — the publishing point is about to be removed
  6. Disconnected — the connection is closed (either gracefully or after an error)

FileTransferRequestedHandler is a special case — it is not related to publishing points and fires independently when an SRT file transfer is requested. It is a delegate (Func<..., Task>) rather than a C# event, representing a new generation of asynchronous callbacks that the current event model will eventually migrate to.

PublishingPointRequested

Fires when a client requests a publishing point that does not exist yet. This is the place to create on-demand publishing points.

This event is invoked for clients only. Publisher requests go straight to the Authorize event because the server creates a new publishing point automatically for each authorized publisher.

private void Server_PublishingPointRequested(
    Guid connectionId,
    VAST.Network.ConnectionInfo connectionInfo,
    VAST.Network.CreatedPublishingPointParameters createdPublishingPointParameters)
{
    // connectionInfo.PublishingPath contains the requested path
    // create the publishing point on demand if the path is recognized
    if (connectionInfo.PublishingPath == "on-demand-stream")
    {
        this.server.CreatePublishingPoint("on-demand-stream", "rtsp://192.168.0.101/stream");
    }
}

Parameters

Parameter Type Description
connectionId Guid Unique identifier of the connection
connectionInfo ConnectionInfo Connection details including PublishingPath, ConnectionType, and EndPoint
createdPublishingPointParameters CreatedPublishingPointParameters Output parameters for the created publishing point

CreatedPublishingPointParameters Properties

Property Type Description
ActualPublishingPath string Set this to redirect the connection to a different publishing path than originally requested
AdditionalUriParameters string Additional URI parameters that must persist in the sink's protocol-specific URI

If you do not create a publishing point in this handler, the connection will be rejected with the standard, protocol specific sequence for the resource not found case.

Authorize

Fires after the connection type has been determined and all connection parameters are available. User code must set connectionInfo.IsValid to accept or reject the connection.

When this event fires for a publishing request, the publishing point does not exist yet. It will be created only after user code authorizes the request by setting connectionInfo.IsValid to true.

private void Server_Authorize(
    Guid connectionId,
    VAST.Network.ConnectionInfo connectionInfo)
{
    // accept all connections
    connectionInfo.IsValid = true;
}

Rejecting Connections

Reject a connection by setting IsValid to false:

private void Server_Authorize(
    Guid connectionId,
    VAST.Network.ConnectionInfo connectionInfo)
{
    // reject publishers from unknown addresses
    if (connectionInfo.ConnectionType == VAST.Network.ConnectionType.Publisher &&
        connectionInfo.EndPoint?.Address?.ToString() != "192.168.0.100")
    {
        connectionInfo.IsValid = false;
        return;
    }

    connectionInfo.IsValid = true;
}

Asynchronous Authorization

For long-running authorization logic (e.g., database lookups), use the IsValidAwaiter property instead of setting IsValid directly:

private void Server_Authorize(
    Guid connectionId,
    VAST.Network.ConnectionInfo connectionInfo)
{
    connectionInfo.IsValidAwaiter = Task.Run(async () =>
    {
        // perform async authorization (e.g., check database)
        bool authorized = await CheckCredentialsAsync(
            connectionInfo.EndPoint?.Address?.ToString());
        return authorized;
    });
}

ConnectionInfo Properties

Property Type Description
ConnectionId Guid Unique identifier of the connection
ConnectionType ConnectionType Publisher, Client, or Undetermined
PublishingPath string Publishing point path extracted from the URI
InboundUri string Full inbound URI of the connection
EndPoint IPProtoEndPoint Remote endpoint address and port
AdditionalInfo object Protocol-specific connection data (may be null)
IsValid bool? Set to true to accept, false to reject
IsValidAwaiter Task<bool> Asynchronous authorization result
AdditionalParameters PublishingPointParameters Optional parameters for publishing point creation if it's a publisher request
UserSource INetworkSource Custom source object for user-handled connections

PublisherConnected

Fires when a publisher (or a pull source created by user code) has been connected and authorized. The publishing point is created and ready for use.

private void Server_PublisherConnected(
    Guid connectionId,
    VAST.Network.PublishingPoint publishingPoint)
{
    // the publishing point is live and can accept clients

    // optionally start forwarding to another server
    publishingPoint.StartForwarding("rtmp://cdn.example.com/live/stream-key");

    // optionally start recording to a file
    publishingPoint.StartRecording("C:\\Recordings\\stream.mp4");
}

Parameters

Parameter Type Description
connectionId Guid Unique identifier of the publisher connection
publishingPoint PublishingPoint The publishing point that was created for this publisher

PublishingPoint Key Properties

Property Type Description
PublishingPath string Path that uniquely identifies this publishing point
UniqueId Guid Unique identifier; equals to the media source's UniqueId
StreamingMode StreamingMode Live, Vod, or Event
ConnectionInfo ConnectionInfo Publisher's connection information
Streams List<MediaType> List of media streams
Created DateTime When the publishing point was created
UserData object Attach custom data to the publishing point

PublishingPoint Key Methods

Method Description
StartForwarding(uri) Re-stream to another server. Returns the Guid of the forwarding sink
StartRecording(path) Record to a file. Returns the Guid of the recording sink
StartRecording(fileType, nextUri, rotationPeriod) Record with automatic file rotation
AddSink(sink) Add a user-created sink to the publishing point
GetClients() Get list of connected clients
GetClientsCount() Get count of connected clients
GetClient(clientId) Get a specific client by its connection ID
SetBuffering(duration, bufferingType) Configure buffering (Memory, Disk, or GOP)
Resume() Resume a suspended publishing point
Disconnect(reason) Disconnect publisher and all clients

Recording with File Rotation

private void Server_PublisherConnected(
    Guid connectionId,
    VAST.Network.PublishingPoint publishingPoint)
{
    int fileNumber = 0;
    publishingPoint.StartRecording(
        "mp4",
        () => $"C:\\Recordings\\{publishingPoint.PublishingPath}_{fileNumber++:D4}.mp4",
        3600); // rotate every hour
}

ClientConnected

Fires when a new client has connected to an existing publishing point and has been authorized.

private void Server_ClientConnected(
    Guid connectionId,
    VAST.Network.ConnectedClient client)
{
    // client.ConnectionInfo contains connection details
    // client.PublishingPoint references the publishing point this client belongs to
}

Parameters

Parameter Type Description
connectionId Guid Unique identifier of the client connection
client ConnectedClient The connected client object

ConnectedClient Properties

Property Type Description
ConnectionInfo ConnectionInfo Client's connection information
ClientType ClientType Type of client
Sink IMediaSink Media sink associated with this client
PublishingPoint PublishingPoint Publishing point the client belongs to

Disconnecting a Client

To forcibly disconnect a specific client:

client.Stop();

FileTransferRequestedHandler

A delegate (not an event) that handles SRT file transfer requests. It is an async Task-returning function, allowing long-running file operations without blocking the server.

server.FileTransferRequestedHandler = Server_FileTransferRequestedHandler;
private Task Server_FileTransferRequestedHandler(
    object caller,
    VAST.Media.FileTransferRequestedArgs args)
{
    return Task.Run(() =>
    {
        switch (args.RequestedFileTransfer.Direction)
        {
            case VAST.Common.MediaFlowDirection.Input:
            {
                // remote peer wants to send a file to us
                args.IsValid = true;
                Uri u = new Uri(args.RequestedFileTransfer.Uri);
                args.RequestedFileTransfer.FilePath = $"C:\\Temp\\{u.LocalPath}";

                // execute the transfer in a separate task to avoid blocking the server
                Task.Run(async () =>
                {
                    bool result = await args.RequestedFileTransfer.ExecuteAsync();
                    // handle result
                });
                break;
            }

            case VAST.Common.MediaFlowDirection.Output:
            {
                // remote peer wants to download a file from us
                Uri u = new Uri(args.RequestedFileTransfer.Uri);
                string localPath = $"C:\\Temp\\{u.LocalPath}";

                if (System.IO.File.Exists(localPath))
                {
                    args.IsValid = true;
                    args.RequestedFileTransfer.FilePath = localPath;

                    Task.Run(async () =>
                    {
                        bool result = await args.RequestedFileTransfer.ExecuteAsync();
                        // handle result
                    });
                }
                else
                {
                    args.IsValid = false;
                }
                break;
            }
        }
    });
}

FileTransferRequestedArgs Properties

Property Type Description
ConnectionId Guid Unique identifier of the connection (equals IFileTransfer.InstanceId)
RequestedFileTransfer IFileTransfer The file transfer object — set FilePath or Stream before calling ExecuteAsync()
IsValid bool Set to true to accept the transfer, false to reject

IFileTransfer Properties

Property Type Description
Uri string URI requested by the remote peer
Direction MediaFlowDirection Input (receiving) or Output (sending)
FilePath string Local file path — set before calling ExecuteAsync()
Stream Stream Alternative to FilePath — use a custom stream
State MediaState Current transfer state
ErrorDescription string Error description if the transfer failed
Important

The ExecuteAsync call must run in a separate Task.Run() because the handler must return args.IsValid to the server before executing the actual transfer.

Note

File transfers are only available over SRT and must be enabled via AllowFileTransfers.

Error

Fires when a connection encounters an unrecoverable error. The connection will be closed shortly after this event.

private void Server_Error(
    Guid connectionId,
    string errorDescription)
{
    Console.WriteLine($"Connection {connectionId}: error - {errorDescription}");
}

Parameters

Parameter Type Description
connectionId Guid Unique identifier of the connection that encountered the error
errorDescription string Human-readable description of the error

After this event fires, the Disconnected event will follow for the same connectionId.

PublishingPointDisposing

Fires when a publishing point is about to be disposed. Use this to perform cleanup, release external resources, or log the shutdown reason.

private void Server_PublishingPointDisposing(
    Guid connectionId,
    VAST.Network.PublishingPoint publishingPoint)
{
    Console.WriteLine($"Publishing point '{publishingPoint.PublishingPath}' disposing, " +
        $"reason: {publishingPoint.ActualShutdownReason}");
}

Parameters

Parameter Type Description
connectionId Guid Unique identifier of the connection
publishingPoint PublishingPoint The publishing point being disposed

Shutdown Reasons

The ActualShutdownReason property indicates why the publishing point is being removed:

Reason Description
Unknown Reason not specified
SourceDown The media source disconnected or stopped
UserInitiated Shut down by user code via Disconnect()
DurationLimit Duration limit reached
OpeningTimeout No media received within the opening timeout
NoClients No connected clients within the configured timeout
InactivityTimeout No activity within the configured timeout

Disconnected

Fires when a connection is closed, regardless of the reason. This is the final event for any connection. It is raised for all connection types: publishers, clients, and other sinks (forwarding, recording, etc.).

Since a publisher's connectionId equals its publishing point's UniqueId, this event can also be used to detect that a publishing point has been destroyed.

private void Server_Disconnected(
    Guid connectionId,
    VAST.Network.ExtendedSocketError socketError)
{
    Console.WriteLine($"Connection {connectionId}: disconnected ({socketError})");
}

Parameters

Parameter Type Description
connectionId Guid Unique identifier of the closed connection
socketError ExtendedSocketError Reason for disconnection

Common ExtendedSocketError Values

Value Description
Success Connection closed gracefully
RemotePeerInitiatedDisconnect Remote peer closed the connection
LocalPeerInitiatedDisconnect Local server closed the connection
NotAuthorized Connection was rejected during authorization
TimedOut Connection timed out
ConnectionReset Connection reset by remote peer
ConnectionAborted Connection aborted

If Error was raised for the same connectionId before Disconnected, it means the server forcibly closed the connection due to the error.

See Also