/// <summary> /// Sends a SIP message asynchronously on a specific stream connection. /// </summary> /// <param name="connectionID">The ID of the specific web socket connection that the message must be sent on.</param> /// <param name="buffer">The data to send.</param> /// <returns>If no errors SocketError.Success otherwise an error value.</returns> public override async Task <SocketError> SendAsync(string connectionID, byte[] buffer) { if (String.IsNullOrEmpty(connectionID)) { throw new ArgumentException("connectionID", "An empty connection ID was specified for a Send in SIPWebSocketChannel."); } else if (buffer == null || buffer.Length == 0) { throw new ArgumentException("buffer", "The buffer must be set and non empty for Send in SIPWebSocketChannel."); } try { SIPMessagWebSocketBehavior client = null; m_clientConnections.TryGetValue(connectionID, out client); if (client != null) { await Task.Run(() => client.Send(buffer, 0, buffer.Length)); return(SocketError.Success); } else { return(SocketError.ConnectionReset); } } catch (SocketException sockExcp) { return(sockExcp.SocketErrorCode); } }
/// <summary> /// Attempts to get a web socket ingress connection (one where a client connected to us). /// </summary> /// <param name="destinationEndPoint">The remote end point of the connection.</param> /// <param name="connectionIDHint">Optional. A connection ID hint for the ingress connection.</param> /// <returns>Returns the client connection or null if not found.</returns> private SIPMessagWebSocketBehavior GetIngressConnection(IPEndPoint destinationEndPoint, string connectionIDHint) { SIPMessagWebSocketBehavior client = null; if (connectionIDHint != null) { // This send needs to use a specific web socket connection. If the connection has been closed // then don't attempt to re-connect (often not possible any way). m_ingressConnections.TryGetValue(connectionIDHint, out client); } if (client == null) { client = m_ingressConnections.Where(x => x.Value.Context.UserEndPoint.Equals(destinationEndPoint)).Select(x => x.Value).FirstOrDefault(); } return(client); }
/// <summary> /// Ideally sends on the web socket channel should specify the connection ID. But if there's /// a good reason not to we can check if there is an existing client connection with the /// requested remote end point and use it. /// </summary> /// <param name="destinationEndPoint">The remote destiation end point to send the data to.</param> /// <param name="buffer">The data to send.</param> /// <param name="connectionIDHint">The ID of the specific web socket connection to try and send the message on.</param> /// <returns>If no errors SocketError.Success otherwise an error value.</returns> public override async Task <SocketError> SendAsync(IPEndPoint destinationEndPoint, byte[] buffer, string connectionIDHint) { if (destinationEndPoint == null) { throw new ApplicationException("An empty destination was specified to Send in SIPWebSocketChannel."); } else if (buffer == null || buffer.Length == 0) { throw new ArgumentException("buffer", "The buffer must be set and non empty for Send in SIPWebSocketChannel."); } try { SIPMessagWebSocketBehavior client = null; if (connectionIDHint != null) { m_clientConnections.TryGetValue(connectionIDHint, out client); } if (client == null) { client = m_clientConnections.Where(x => x.Value.Context.UserEndPoint.Equals(destinationEndPoint)).Select(x => x.Value).FirstOrDefault(); } if (client != null) { await Task.Run(() => client.Send(buffer, 0, buffer.Length)); return(SocketError.Success); } else { return(SocketError.ConnectionReset); } } catch (SocketException sockExcp) { return(sockExcp.SocketErrorCode); } }
/// <summary> /// Records a new client connection in the list. This allows responses or subsequent requests to the same SIP agent /// to reuse the same connection. /// </summary> /// <param name="id">The unique ID of the client connection.</param> /// <param name="client">The web socket client.</param> private void AddClientConnection(string id, SIPMessagWebSocketBehavior client) { m_ingressConnections.TryAdd(id, client); }