Noble Connect
Add relays and punchthrough to Mirror or UNet
NobleConnect.Stun.Controller Class Reference

The Stun Controller is used by Stun Clients and Peers to communicate with a Stun Server More...

Inherits IDisposable.

Public Member Functions

delegate void DataHandler (AttributeData data, IPEndPoint source, bool fromRelay)
 Defines the format for a DataHandler method. More...
 
 Controller (ControllerConfig config, Socket s=null, Action< string > onFatalError=null)
 Construct a Stun Controller to communicate with a Stun Server at the specificed address and port, optionally using the specified credentials. More...
 
void AddRemoteCredentials (Credentials c, IPEndPoint endPoint, IPEndPoint from, IPEndPoint allocation=null)
 
Credentials GetRemoteCredentials (IPEndPoint endPoint, IPEndPoint from, IPEndPoint allocation=null)
 
void AddLocalCredentials (Credentials c)
 
bool SendMessage (Message message, IPEndPoint target, IPEndPoint source)
 
void SocketSend (byte[] data, int offset, int count, IPEndPoint destination)
 
void ReceiveBytes (byte[] buffer, int index, int count, IPEndPoint source, IPEndPoint receivedAt, bool fromRelay)
 
void HandleResponse (Transaction< Message > transaction, Message response, IPEndPoint source, IPEndPoint receivedAt)
 
Message ReadMessage (byte[] buffer, ref int bufferIndex, int bufferLength)
 Transform some bytes into a Stun Message More...
 
void RevokeAllBindings ()
 
void RevokeBinding (IPEndPoint target, IPEndPoint source)
 
Transaction< MessageAddTransaction (Message message, Action< Transaction< Message >> onComplete, Action< Transaction< Message >> onFail, IPEndPoint target, IPEndPoint source, IPEndPoint associatedAllocation=null, int overrideRetransmissionCount=-1, int overrideTimeout=1)
 Add a transaction for an outgoing Request. More...
 
GetExtension< T > ()
 
void AddExtension (IStunExtension extension)
 
void SendBindRequest (Action< Transaction< Message >> onBindComplete, Action< Transaction< Message >> onBindError)
 
void SendBindRequest (Action< Transaction< Message >> onBindComplete, Action< Transaction< Message >> onBindError, List< Attribute > attributes, IPEndPoint target, IPEndPoint source, int overrideMaxResend=-1)
 Send a Bind Request to the Stun server. Call onBindComplete when the Response is received. More...
 
Message ConstructBindRequest (List< Attribute > attributes, IPEndPoint target, IPEndPoint source)
 
void OnBindComplete (Transaction< Message > transaction, Action< Transaction< Message >> callback=null, Action< Transaction< Message >> errorCallback=null)
 
void SendBindIndication (IPEndPoint target, IPEndPoint source)
 
void QueueRebind (IPEndPoint target, IPEndPoint source)
 
void ReSend (Transaction< Message > transaction)
 Re-send a request from a failed transaction More...
 
Transaction< MessageSendRequest (Message message, IPEndPoint target, IPEndPoint source, IPEndPoint associatedAllocation=null, Action< Transaction< Message >> onResponse=null, Action< Transaction< Message >> onFail=null, int overrideMaxResend=-1, int overrideTimeout=-1)
 
Transaction< MessageSend (Message message, IPEndPoint target, IPEndPoint source, IPEndPoint associatedAllocation=null, Action< Transaction< Message >> onResponse=null, Action< Transaction< Message >> onFail=null, int overrideMaxResend=-1, int overrideTimeout=-1)
 Send a message to the Stun server. Optionally call onResponse when a response is received. More...
 
void HandleIndication (Message message, IPEndPoint source, IPEndPoint receivedAt)
 Handle an INDICATION Message from the Stun server. More...
 
void HandleSuccessResponse (Transaction< Message > transaction, Message response, IPEndPoint source, IPEndPoint receivedAt)
 Handle a SUCCESS_RESPONSE Message from the Stun server More...
 
void HandleRequest (Message request, byte[] buffer, IPEndPoint source, IPEndPoint receivedAt)
 Handle a SUCCESS_RESPONSE Message from the Stun server More...
 
bool ValidateMessage (Message request, byte[] buffer)
 
void HandleBindRequest (Message request, IPEndPoint source, IPEndPoint receivedAt)
 
void SendBindSuccessResponse (IPEndPoint target, IPEndPoint receivedAt, Message request)
 
void SendBindErrorResponse (IPEndPoint target, IPEndPoint receivedAt, Message request)
 
Message ConstructErrorResponse (MessageMethod method, ushort errorCode, string errorMessage, ReadOnlyByteArray transactionID)
 
void SendErrorResponse (MessageMethod method, ushort errorCode, string errorMessage, IPEndPoint target, IPEndPoint receivedAt, Message request)
 
void HandleErrorResponse (Transaction< Message > transaction, Message response, IPEndPoint source, IPEndPoint receivedAt)
 Handle an ERROR_RESPONSE Message from the Stun server More...
 
bool HandleErrorAlternateServer (Transaction< Message > transaction, Message response, IPEndPoint source)
 
bool HandleErrorUnauthorizedRequest (Transaction< Message > transaction, Message response, IPEndPoint source)
 Handle unauthorised request error More...
 
void Dispose ()
 Dispose of the Controller and all extensions and timers, and close the socket More...
 

Public Attributes

readonly TransactionList< MessageopenTransactions = new TransactionList<Message>()
 
BufferPool bufferPool
 
byte[] receiveBuffer = new byte[4096]
 
Dictionary< IPSet, CredentialscredentialsForEndPoint = new Dictionary<IPSet, Credentials>()
 The set of credentials to send with Requests that requires authentication. More...
 
Dictionary< string, CredentialslocalCredentials = new Dictionary<string, Credentials>()
 The credentials to use when authenticating requests made to this client. More...
 
readonly ControllerConfig config
 
object bandwidthLock = new object()
 
int bandwidthUsedThisSecond = 0
 
Timer bandwidthTimer
 
readonly IPEndPoint localEndPoint
 
DataHandler multiplexedDataHandler
 The DataHandler to use for handling multiplxed data More...
 

Static Public Attributes

const int BINDING_EXPIRATION_TIME = 2 * 60 * 1000
 How often to refresh bindings More...
 
const uint COOKIE = 0x2112A442
 This magic constant is included in every Stun message to identify it as a Stun message. More...
 
static readonly uint COOKIE_N
 This is the same thing as the COOKIE but stored in network byte order. More...
 
static ReadOnlyByteArray COOKIE_BYTES
 
static ReadOnlyByteArray COOKIE_BYTES_N
 

Detailed Description

The Stun Controller is used by Stun Clients and Peers to communicate with a Stun Server

The Stun Controller uses a Socket to communicate with a Stun Server over UDP. The behaviour of the controller and the format of the messages are specified in RFC 5389 and RFC 5780. The main purpose of the controller is to use a Bind Request to get this Peer's server reflexive address. It can also be used to perform NAT Behaviour Discovery.

The controller handles authentication, but authentication is not needed for Bind Requests so it is ok to leave the username and password blank if that's all you need to do.

Constructor & Destructor Documentation

◆ Controller()

NobleConnect.Stun.Controller.Controller ( ControllerConfig  config,
Socket  s = null,
Action< string >  onFatalError = null 
)

Construct a Stun Controller to communicate with a Stun Server at the specificed address and port, optionally using the specified credentials.

This creates the Socket and starts listening for Messages from the Stun server.

Member Function Documentation

◆ AddExtension()

void NobleConnect.Stun.Controller.AddExtension ( IStunExtension  extension)

◆ AddLocalCredentials()

void NobleConnect.Stun.Controller.AddLocalCredentials ( Credentials  c)

◆ AddRemoteCredentials()

void NobleConnect.Stun.Controller.AddRemoteCredentials ( Credentials  c,
IPEndPoint  endPoint,
IPEndPoint  from,
IPEndPoint  allocation = null 
)

◆ AddTransaction()

Transaction<Message> NobleConnect.Stun.Controller.AddTransaction ( Message  message,
Action< Transaction< Message >>  onComplete,
Action< Transaction< Message >>  onFail,
IPEndPoint  target,
IPEndPoint  source,
IPEndPoint  associatedAllocation = null,
int  overrideRetransmissionCount = -1,
int  overrideTimeout = 1 
)

Add a transaction for an outgoing Request.

Transactions are used to keep track of which Request and Respone belongs to. They also store the callback so we can pass the Response on to the application to do something useful with.

Parameters
message
onComplete

◆ ConstructBindRequest()

Message NobleConnect.Stun.Controller.ConstructBindRequest ( List< Attribute attributes,
IPEndPoint  target,
IPEndPoint  source 
)

◆ ConstructErrorResponse()

Message NobleConnect.Stun.Controller.ConstructErrorResponse ( MessageMethod  method,
ushort  errorCode,
string  errorMessage,
ReadOnlyByteArray  transactionID 
)

◆ DataHandler()

delegate void NobleConnect.Stun.Controller.DataHandler ( AttributeData  data,
IPEndPoint  source,
bool  fromRelay 
)

Defines the format for a DataHandler method.

This format is used for both the multiplexedDataHandler and for handling Data messages in Turn.

Parameters
data
source

◆ Dispose()

void NobleConnect.Stun.Controller.Dispose ( )

Dispose of the Controller and all extensions and timers, and close the socket

◆ GetExtension< T >()

T NobleConnect.Stun.Controller.GetExtension< T > ( )
Type Constraints
T :IStunExtension 

◆ GetRemoteCredentials()

Credentials NobleConnect.Stun.Controller.GetRemoteCredentials ( IPEndPoint  endPoint,
IPEndPoint  from,
IPEndPoint  allocation = null 
)

◆ HandleBindRequest()

void NobleConnect.Stun.Controller.HandleBindRequest ( Message  request,
IPEndPoint  source,
IPEndPoint  receivedAt 
)

◆ HandleErrorAlternateServer()

bool NobleConnect.Stun.Controller.HandleErrorAlternateServer ( Transaction< Message transaction,
Message  response,
IPEndPoint  source 
)

◆ HandleErrorResponse()

void NobleConnect.Stun.Controller.HandleErrorResponse ( Transaction< Message transaction,
Message  response,
IPEndPoint  source,
IPEndPoint  receivedAt 
)

Handle an ERROR_RESPONSE Message from the Stun server

The error code is retrieved from the Message and used to look up the approrite error handling method.

Parameters
response
transaction

◆ HandleErrorUnauthorizedRequest()

bool NobleConnect.Stun.Controller.HandleErrorUnauthorizedRequest ( Transaction< Message transaction,
Message  response,
IPEndPoint  source 
)

Handle unauthorised request error

<rmarks> This error is part of the normal authentication flow which goes something like: Send a request without credentials Get this error as a response, which includes the realm and the nonce Use the realm and the nonce to create credentials and message integrity attribute Resend the original request with credentials </rmarks>

Parameters
transaction
response

◆ HandleIndication()

void NobleConnect.Stun.Controller.HandleIndication ( Message  message,
IPEndPoint  source,
IPEndPoint  receivedAt 
)

Handle an INDICATION Message from the Stun server.

This does nothing in the Stun Controller but may do things in extensions

Parameters
message
transaction

◆ HandleRequest()

void NobleConnect.Stun.Controller.HandleRequest ( Message  request,
byte[]  buffer,
IPEndPoint  source,
IPEndPoint  receivedAt 
)

Handle a SUCCESS_RESPONSE Message from the Stun server

Messages whose transaction ID do not match an open Transaction are ignored. Valid messages are passed to the onComplete handler of the corresponding Transaction.

Parameters
message
transaction

◆ HandleResponse()

void NobleConnect.Stun.Controller.HandleResponse ( Transaction< Message transaction,
Message  response,
IPEndPoint  source,
IPEndPoint  receivedAt 
)

◆ HandleSuccessResponse()

void NobleConnect.Stun.Controller.HandleSuccessResponse ( Transaction< Message transaction,
Message  response,
IPEndPoint  source,
IPEndPoint  receivedAt 
)

Handle a SUCCESS_RESPONSE Message from the Stun server

Messages whose transaction ID do not match an open Transaction are ignored. Valid messages are passed to the onComplete handler of the corresponding Transaction.

Parameters
response
transaction

◆ OnBindComplete()

void NobleConnect.Stun.Controller.OnBindComplete ( Transaction< Message transaction,
Action< Transaction< Message >>  callback = null,
Action< Transaction< Message >>  errorCallback = null 
)

◆ QueueRebind()

void NobleConnect.Stun.Controller.QueueRebind ( IPEndPoint  target,
IPEndPoint  source 
)

◆ ReadMessage()

Message NobleConnect.Stun.Controller.ReadMessage ( byte[]  buffer,
ref int  bufferIndex,
int  bufferLength 
)

Transform some bytes into a Stun Message

Parameters
buffer
bufferIndex
bufferLength
Returns

◆ ReceiveBytes()

void NobleConnect.Stun.Controller.ReceiveBytes ( byte[]  buffer,
int  index,
int  count,
IPEndPoint  source,
IPEndPoint  receivedAt,
bool  fromRelay 
)

◆ ReSend()

void NobleConnect.Stun.Controller.ReSend ( Transaction< Message transaction)

Re-send a request from a failed transaction

Parameters
transaction

◆ RevokeAllBindings()

void NobleConnect.Stun.Controller.RevokeAllBindings ( )

◆ RevokeBinding()

void NobleConnect.Stun.Controller.RevokeBinding ( IPEndPoint  target,
IPEndPoint  source 
)

◆ Send()

Transaction<Message> NobleConnect.Stun.Controller.Send ( Message  message,
IPEndPoint  target,
IPEndPoint  source,
IPEndPoint  associatedAllocation = null,
Action< Transaction< Message >>  onResponse = null,
Action< Transaction< Message >>  onFail = null,
int  overrideMaxResend = -1,
int  overrideTimeout = -1 
)

Send a message to the Stun server. Optionally call onResponse when a response is received.

This method automatically adds a Transaction for the message if it is a request.

Parameters
message
onResponse

◆ SendBindErrorResponse()

void NobleConnect.Stun.Controller.SendBindErrorResponse ( IPEndPoint  target,
IPEndPoint  receivedAt,
Message  request 
)

◆ SendBindIndication()

void NobleConnect.Stun.Controller.SendBindIndication ( IPEndPoint  target,
IPEndPoint  source 
)

◆ SendBindRequest() [1/2]

void NobleConnect.Stun.Controller.SendBindRequest ( Action< Transaction< Message >>  onBindComplete,
Action< Transaction< Message >>  onBindError 
)

◆ SendBindRequest() [2/2]

void NobleConnect.Stun.Controller.SendBindRequest ( Action< Transaction< Message >>  onBindComplete,
Action< Transaction< Message >>  onBindError,
List< Attribute attributes,
IPEndPoint  target,
IPEndPoint  source,
int  overrideMaxResend = -1 
)

Send a Bind Request to the Stun server. Call onBindComplete when the Response is received.

Parameters
onBindComplete

◆ SendBindSuccessResponse()

void NobleConnect.Stun.Controller.SendBindSuccessResponse ( IPEndPoint  target,
IPEndPoint  receivedAt,
Message  request 
)

◆ SendErrorResponse()

void NobleConnect.Stun.Controller.SendErrorResponse ( MessageMethod  method,
ushort  errorCode,
string  errorMessage,
IPEndPoint  target,
IPEndPoint  receivedAt,
Message  request 
)

◆ SendMessage()

bool NobleConnect.Stun.Controller.SendMessage ( Message  message,
IPEndPoint  target,
IPEndPoint  source 
)

◆ SendRequest()

Transaction<Message> NobleConnect.Stun.Controller.SendRequest ( Message  message,
IPEndPoint  target,
IPEndPoint  source,
IPEndPoint  associatedAllocation = null,
Action< Transaction< Message >>  onResponse = null,
Action< Transaction< Message >>  onFail = null,
int  overrideMaxResend = -1,
int  overrideTimeout = -1 
)

◆ SocketSend()

void NobleConnect.Stun.Controller.SocketSend ( byte[]  data,
int  offset,
int  count,
IPEndPoint  destination 
)

◆ ValidateMessage()

bool NobleConnect.Stun.Controller.ValidateMessage ( Message  request,
byte[]  buffer 
)

Member Data Documentation

◆ bandwidthLock

object NobleConnect.Stun.Controller.bandwidthLock = new object()

◆ bandwidthTimer

Timer NobleConnect.Stun.Controller.bandwidthTimer

◆ bandwidthUsedThisSecond

int NobleConnect.Stun.Controller.bandwidthUsedThisSecond = 0

◆ BINDING_EXPIRATION_TIME

const int NobleConnect.Stun.Controller.BINDING_EXPIRATION_TIME = 2 * 60 * 1000
static

How often to refresh bindings

Bindings do not last forever on nat devices, so they must be refreshed periodically. RFC 4787 Section 12 REQ-5 specifies that bindings must not expire in less than 2 minutes, so as long as this refresh time is less than 2 minutes it is guaranteed that bindings will stay alive on any complient nat device.

◆ bufferPool

BufferPool NobleConnect.Stun.Controller.bufferPool

◆ config

readonly ControllerConfig NobleConnect.Stun.Controller.config

◆ COOKIE

const uint NobleConnect.Stun.Controller.COOKIE = 0x2112A442
static

This magic constant is included in every Stun message to identify it as a Stun message.

It is stored as an unsigned integer in host byte order.

◆ COOKIE_BYTES

ReadOnlyByteArray NobleConnect.Stun.Controller.COOKIE_BYTES
static

◆ COOKIE_BYTES_N

ReadOnlyByteArray NobleConnect.Stun.Controller.COOKIE_BYTES_N
static

◆ COOKIE_N

readonly uint NobleConnect.Stun.Controller.COOKIE_N
static

This is the same thing as the COOKIE but stored in network byte order.

We pre-compute this one time in the static constructor since it will never change.

◆ credentialsForEndPoint

Dictionary<IPSet, Credentials> NobleConnect.Stun.Controller.credentialsForEndPoint = new Dictionary<IPSet, Credentials>()

The set of credentials to send with Requests that requires authentication.

◆ localCredentials

Dictionary<string, Credentials> NobleConnect.Stun.Controller.localCredentials = new Dictionary<string, Credentials>()

The credentials to use when authenticating requests made to this client.

◆ localEndPoint

readonly IPEndPoint NobleConnect.Stun.Controller.localEndPoint

◆ multiplexedDataHandler

DataHandler NobleConnect.Stun.Controller.multiplexedDataHandler

The DataHandler to use for handling multiplxed data

◆ openTransactions

readonly TransactionList<Message> NobleConnect.Stun.Controller.openTransactions = new TransactionList<Message>()

◆ receiveBuffer

byte [] NobleConnect.Stun.Controller.receiveBuffer = new byte[4096]