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:
- PublishingPointRequested — a client or publisher requests a publishing point that does not exist yet
- Authorize — the connection type and parameters are known; user code decides whether to accept or reject
- PublisherConnected or ClientConnected — the authorized connection is fully established
- Error — an unrecoverable error occurs on the connection
- PublishingPointDisposing — the publishing point is about to be removed
- 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
- Sample Applications — overview of all demo projects
- .NET Server Demo — parent page with setup instructions, license key configuration, and access URL reference
- Multi-Protocol Server — overview
- Initialization — server creation and protocol configuration
- VAST.Network Library — StreamingServer API reference