using System;
using System.Net;
using System.Text;
namespace NetCoreServer
{
///
/// WebSocket secure server
///
/// WebSocket secure server is used to communicate with clients using WebSocket protocol. Thread-safe.
public class WssServer : HttpsServer, IWebSocket
{
internal readonly WebSocket WebSocket;
///
/// Initialize WebSocket server with a given IP address and port number
///
/// SSL context
/// IP address
/// Port number
public WssServer(SslContext context, IPAddress address, int port) : base(context, address, port) { WebSocket = new WebSocket(this); }
///
/// Initialize WebSocket server with a given IP address and port number
///
/// SSL context
/// IP address
/// Port number
public WssServer(SslContext context, string address, int port) : base(context, address, port) { WebSocket = new WebSocket(this); }
///
/// Initialize WebSocket server with a given DNS endpoint
///
/// SSL context
/// DNS endpoint
public WssServer(SslContext context, DnsEndPoint endpoint) : base(context, endpoint) { WebSocket = new WebSocket(this); }
///
/// Initialize WebSocket server with a given IP endpoint
///
/// SSL context
/// IP endpoint
public WssServer(SslContext context, IPEndPoint endpoint) : base(context, endpoint) { WebSocket = new WebSocket(this); }
#region Session management
public virtual bool CloseAll() => CloseAll(0, Span.Empty);
public virtual bool CloseAll(int status) => CloseAll(status, Span.Empty);
public virtual bool CloseAll(int status, string text) => CloseAll(status, Encoding.UTF8.GetBytes(text));
public virtual bool CloseAll(int status, ReadOnlySpan text) => CloseAll(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool CloseAll(int status, byte[] buffer) => CloseAll(status, buffer.AsSpan());
public virtual bool CloseAll(int status, byte[] buffer, long offset, long size) => CloseAll(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool CloseAll(int status, ReadOnlySpan buffer)
{
lock (WebSocket.WsSendLock)
{
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, buffer, status);
if (!Multicast(WebSocket.WsSendBuffer.AsSpan()))
return false;
return base.DisconnectAll();
}
}
#endregion
#region Multicasting
public override bool Multicast(ReadOnlySpan buffer)
{
if (!IsStarted)
return false;
if (buffer.IsEmpty)
return true;
// Multicast data to all WebSocket sessions
foreach (var session in Sessions.Values)
{
if (session is WssSession wsSession)
{
if (wsSession.WebSocket.WsHandshaked)
wsSession.SendAsync(buffer);
}
}
return true;
}
#endregion
#region WebSocket multicast text methods
public bool MulticastText(string text) => MulticastText(Encoding.UTF8.GetBytes(text));
public bool MulticastText(ReadOnlySpan text) => MulticastText(Encoding.UTF8.GetBytes(text.ToArray()));
public bool MulticastText(byte[] buffer) => MulticastText(buffer.AsSpan());
public bool MulticastText(byte[] buffer, long offset, long size) => MulticastText(buffer.AsSpan((int)offset, (int)size));
public bool MulticastText(ReadOnlySpan buffer)
{
lock (WebSocket.WsSendLock)
{
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_TEXT, false, buffer);
return Multicast(WebSocket.WsSendBuffer.AsSpan());
}
}
#endregion
#region WebSocket multicast binary methods
public bool MulticastBinary(string text) => MulticastBinary(Encoding.UTF8.GetBytes(text));
public bool MulticastBinary(ReadOnlySpan text) => MulticastBinary(Encoding.UTF8.GetBytes(text.ToArray()));
public bool MulticastBinary(byte[] buffer) => MulticastBinary(buffer.AsSpan());
public bool MulticastBinary(byte[] buffer, long offset, long size) => MulticastBinary(buffer.AsSpan((int)offset, (int)size));
public bool MulticastBinary(ReadOnlySpan buffer)
{
lock (WebSocket.WsSendLock)
{
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_BINARY, false, buffer);
return Multicast(WebSocket.WsSendBuffer.AsSpan());
}
}
#endregion
#region WebSocket multicast ping methods
public bool MulticastPing(string text) => MulticastPing(Encoding.UTF8.GetBytes(text));
public bool MulticastPing(ReadOnlySpan text) => MulticastPing(Encoding.UTF8.GetBytes(text.ToArray()));
public bool MulticastPing(byte[] buffer) => MulticastPing(buffer.AsSpan());
public bool MulticastPing(byte[] buffer, long offset, long size) => MulticastPing(buffer.AsSpan((int)offset, (int)size));
public bool MulticastPing(ReadOnlySpan buffer)
{
lock (WebSocket.WsSendLock)
{
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_PING, false, buffer);
return Multicast(WebSocket.WsSendBuffer.AsSpan());
}
}
#endregion
protected override SslSession CreateSession() { return new WssSession(this); }
}
}