|
|
|
@ -83,6 +83,7 @@ namespace WebSocketSharp
|
|
|
|
private string _extensions;
|
|
|
|
private string _extensions;
|
|
|
|
private AutoResetEvent _exitReceiving;
|
|
|
|
private AutoResetEvent _exitReceiving;
|
|
|
|
private object _forClose;
|
|
|
|
private object _forClose;
|
|
|
|
|
|
|
|
private object _forConnect;
|
|
|
|
private object _forSend;
|
|
|
|
private object _forSend;
|
|
|
|
private volatile Logger _logger;
|
|
|
|
private volatile Logger _logger;
|
|
|
|
private uint _nonceCount;
|
|
|
|
private uint _nonceCount;
|
|
|
|
@ -206,7 +207,7 @@ namespace WebSocketSharp
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
/// <value>
|
|
|
|
/// <value>
|
|
|
|
/// One of the <see cref="CompressionMethod"/> values that represents the
|
|
|
|
/// One of the <see cref="CompressionMethod"/> values that represents the
|
|
|
|
/// compression method to use.
|
|
|
|
/// compression method used to compress.
|
|
|
|
/// The default value is <see cref="CompressionMethod.NONE"/>.
|
|
|
|
/// The default value is <see cref="CompressionMethod.NONE"/>.
|
|
|
|
/// </value>
|
|
|
|
/// </value>
|
|
|
|
public CompressionMethod Compression {
|
|
|
|
public CompressionMethod Compression {
|
|
|
|
@ -215,20 +216,22 @@ namespace WebSocketSharp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
set {
|
|
|
|
set {
|
|
|
|
var msg = !_client
|
|
|
|
lock (_forConnect) {
|
|
|
|
? "Set operation of Compression isn't available as a server."
|
|
|
|
var msg = !_client
|
|
|
|
: IsOpened
|
|
|
|
? "Set operation of Compression isn't available as a server."
|
|
|
|
? "A WebSocket connection has already been established."
|
|
|
|
: IsOpened
|
|
|
|
: null;
|
|
|
|
? "A WebSocket connection has already been established."
|
|
|
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
|
|
if (msg != null) {
|
|
|
|
if (msg != null) {
|
|
|
|
_logger.Error (msg);
|
|
|
|
_logger.Error (msg);
|
|
|
|
error (msg);
|
|
|
|
error (msg);
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_compression = value;
|
|
|
|
_compression = value;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -315,9 +318,6 @@ namespace WebSocketSharp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal set {
|
|
|
|
internal set {
|
|
|
|
if (value == null)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_logger = value;
|
|
|
|
_logger = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -347,30 +347,32 @@ namespace WebSocketSharp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
set {
|
|
|
|
set {
|
|
|
|
string msg = null;
|
|
|
|
lock (_forConnect) {
|
|
|
|
if (!_client)
|
|
|
|
string msg = null;
|
|
|
|
msg = "Set operation of Origin isn't available as a server.";
|
|
|
|
if (!_client)
|
|
|
|
else if (IsOpened)
|
|
|
|
msg = "Set operation of Origin isn't available as a server.";
|
|
|
|
msg = "A WebSocket connection has already been established.";
|
|
|
|
else if (IsOpened)
|
|
|
|
else if (value.IsNullOrEmpty ()) {
|
|
|
|
msg = "A WebSocket connection has already been established.";
|
|
|
|
_origin = value;
|
|
|
|
else if (value.IsNullOrEmpty ()) {
|
|
|
|
return;
|
|
|
|
_origin = value;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
else {
|
|
|
|
}
|
|
|
|
Uri origin;
|
|
|
|
else {
|
|
|
|
if (!Uri.TryCreate (value, UriKind.Absolute, out origin) ||
|
|
|
|
Uri origin;
|
|
|
|
origin.Segments.Length > 1)
|
|
|
|
if (!Uri.TryCreate (value, UriKind.Absolute, out origin) ||
|
|
|
|
msg = "The syntax of Origin must be '<scheme>://<host>[:<port>]'.";
|
|
|
|
origin.Segments.Length > 1)
|
|
|
|
}
|
|
|
|
msg = "The syntax of Origin must be '<scheme>://<host>[:<port>]'.";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (msg != null) {
|
|
|
|
if (msg != null) {
|
|
|
|
_logger.Error (msg);
|
|
|
|
_logger.Error (msg);
|
|
|
|
error (msg);
|
|
|
|
error (msg);
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_origin = value.TrimEnd ('/');
|
|
|
|
_origin = value.TrimEnd ('/');
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -419,20 +421,22 @@ namespace WebSocketSharp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
set {
|
|
|
|
set {
|
|
|
|
var msg = !_client
|
|
|
|
lock (_forConnect) {
|
|
|
|
? "Set operation of ServerCertificateValidationCallback isn't available as a server."
|
|
|
|
var msg = !_client
|
|
|
|
: IsOpened
|
|
|
|
? "Set operation of ServerCertificateValidationCallback isn't available as a server."
|
|
|
|
? "A WebSocket connection has already been established."
|
|
|
|
: IsOpened
|
|
|
|
: null;
|
|
|
|
? "A WebSocket connection has already been established."
|
|
|
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
|
|
if (msg != null) {
|
|
|
|
if (msg != null) {
|
|
|
|
_logger.Error (msg);
|
|
|
|
_logger.Error (msg);
|
|
|
|
error (msg);
|
|
|
|
error (msg);
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_certValidationCallback = value;
|
|
|
|
_certValidationCallback = value;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -645,11 +649,26 @@ namespace WebSocketSharp
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool connect ()
|
|
|
|
private void connect ()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return _client
|
|
|
|
lock (_forConnect) {
|
|
|
|
? doHandshake ()
|
|
|
|
if (IsOpened) {
|
|
|
|
: acceptHandshake ();
|
|
|
|
var msg = "A WebSocket connection has already been established.";
|
|
|
|
|
|
|
|
_logger.Error (msg);
|
|
|
|
|
|
|
|
error (msg);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
if (_client ? doHandshake () : acceptHandshake ())
|
|
|
|
|
|
|
|
open ();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex) {
|
|
|
|
|
|
|
|
processException (
|
|
|
|
|
|
|
|
ex, "An exception has occurred while connecting or opening.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// As client
|
|
|
|
// As client
|
|
|
|
@ -804,6 +823,7 @@ namespace WebSocketSharp
|
|
|
|
_cookies = new CookieCollection ();
|
|
|
|
_cookies = new CookieCollection ();
|
|
|
|
_extensions = String.Empty;
|
|
|
|
_extensions = String.Empty;
|
|
|
|
_forClose = new object ();
|
|
|
|
_forClose = new object ();
|
|
|
|
|
|
|
|
_forConnect = new object ();
|
|
|
|
_forSend = new object ();
|
|
|
|
_forSend = new object ();
|
|
|
|
_protocol = String.Empty;
|
|
|
|
_protocol = String.Empty;
|
|
|
|
_readyState = WebSocketState.CONNECTING;
|
|
|
|
_readyState = WebSocketState.CONNECTING;
|
|
|
|
@ -1353,6 +1373,19 @@ namespace WebSocketSharp
|
|
|
|
OnClose.Emit (this, args);
|
|
|
|
OnClose.Emit (this, args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// As server
|
|
|
|
|
|
|
|
internal void ConnectAsServer ()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
if (acceptHandshake ())
|
|
|
|
|
|
|
|
open ();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex) {
|
|
|
|
|
|
|
|
processException (
|
|
|
|
|
|
|
|
ex, "An exception has occurred while connecting or opening.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal bool Ping (byte [] frameAsBytes, int timeOut)
|
|
|
|
internal bool Ping (byte [] frameAsBytes, int timeOut)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return send (frameAsBytes) &&
|
|
|
|
return send (frameAsBytes) &&
|
|
|
|
@ -1530,8 +1563,7 @@ namespace WebSocketSharp
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public void Connect ()
|
|
|
|
public void Connect ()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (IsOpened)
|
|
|
|
if (IsOpened) {
|
|
|
|
{
|
|
|
|
|
|
|
|
var msg = "A WebSocket connection has already been established.";
|
|
|
|
var msg = "A WebSocket connection has already been established.";
|
|
|
|
_logger.Error (msg);
|
|
|
|
_logger.Error (msg);
|
|
|
|
error (msg);
|
|
|
|
error (msg);
|
|
|
|
@ -1539,13 +1571,24 @@ namespace WebSocketSharp
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
connect ();
|
|
|
|
if (connect ())
|
|
|
|
}
|
|
|
|
open ();
|
|
|
|
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
|
|
catch (Exception ex) {
|
|
|
|
/// Establishes a WebSocket connection asynchronously.
|
|
|
|
processException (ex, "An exception has occurred while connecting or opening.");
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public void ConnectAsync ()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (IsOpened) {
|
|
|
|
|
|
|
|
var msg = "A WebSocket connection has already been established.";
|
|
|
|
|
|
|
|
_logger.Error (msg);
|
|
|
|
|
|
|
|
error (msg);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Action connector = connect;
|
|
|
|
|
|
|
|
connector.BeginInvoke (ar => connector.EndInvoke (ar), null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
@ -1840,23 +1883,25 @@ namespace WebSocketSharp
|
|
|
|
/// </param>
|
|
|
|
/// </param>
|
|
|
|
public void SetCookie (Cookie cookie)
|
|
|
|
public void SetCookie (Cookie cookie)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var msg = !_client
|
|
|
|
lock (_forConnect) {
|
|
|
|
? "SetCookie isn't available as a server."
|
|
|
|
var msg = !_client
|
|
|
|
: IsOpened
|
|
|
|
? "SetCookie isn't available as a server."
|
|
|
|
? "A WebSocket connection has already been established."
|
|
|
|
: IsOpened
|
|
|
|
: cookie == null
|
|
|
|
? "A WebSocket connection has already been established."
|
|
|
|
? "'cookie' must not be null."
|
|
|
|
: cookie == null
|
|
|
|
: null;
|
|
|
|
? "'cookie' must not be null."
|
|
|
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
|
|
if (msg != null) {
|
|
|
|
if (msg != null) {
|
|
|
|
_logger.Error (msg);
|
|
|
|
_logger.Error (msg);
|
|
|
|
error (msg);
|
|
|
|
error (msg);
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
lock (_cookies.SyncRoot) {
|
|
|
|
lock (_cookies.SyncRoot) {
|
|
|
|
_cookies.SetOrRemove (cookie);
|
|
|
|
_cookies.SetOrRemove (cookie);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1877,36 +1922,38 @@ namespace WebSocketSharp
|
|
|
|
/// </param>
|
|
|
|
/// </param>
|
|
|
|
public void SetCredentials (string username, string password, bool preAuth)
|
|
|
|
public void SetCredentials (string username, string password, bool preAuth)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
string msg = null;
|
|
|
|
lock (_forConnect) {
|
|
|
|
if (!_client)
|
|
|
|
string msg = null;
|
|
|
|
msg = "SetCredentials isn't available as a server.";
|
|
|
|
if (!_client)
|
|
|
|
else if (IsOpened)
|
|
|
|
msg = "SetCredentials isn't available as a server.";
|
|
|
|
msg = "A WebSocket connection has already been established.";
|
|
|
|
else if (IsOpened)
|
|
|
|
else if (username.IsNullOrEmpty ()) {
|
|
|
|
msg = "A WebSocket connection has already been established.";
|
|
|
|
_credentials = null;
|
|
|
|
else if (username.IsNullOrEmpty ()) {
|
|
|
|
_preAuth = false;
|
|
|
|
_credentials = null;
|
|
|
|
_logger.Warn ("Credentials was set back to the default.");
|
|
|
|
_preAuth = false;
|
|
|
|
|
|
|
|
_logger.Warn ("Credentials was set back to the default.");
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
msg = username.Contains (':') || !username.IsText ()
|
|
|
|
msg = username.Contains (':') || !username.IsText ()
|
|
|
|
? "'username' contains an invalid character."
|
|
|
|
? "'username' contains an invalid character."
|
|
|
|
: !password.IsNullOrEmpty () && !password.IsText ()
|
|
|
|
: !password.IsNullOrEmpty () && !password.IsText ()
|
|
|
|
? "'password' contains an invalid character."
|
|
|
|
? "'password' contains an invalid character."
|
|
|
|
: null;
|
|
|
|
: null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (msg != null) {
|
|
|
|
if (msg != null) {
|
|
|
|
_logger.Error (msg);
|
|
|
|
_logger.Error (msg);
|
|
|
|
error (msg);
|
|
|
|
error (msg);
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_credentials = new NetworkCredential (
|
|
|
|
_credentials = new NetworkCredential (
|
|
|
|
username, password, _uri.PathAndQuery);
|
|
|
|
username, password, _uri.PathAndQuery);
|
|
|
|
_preAuth = preAuth;
|
|
|
|
_preAuth = preAuth;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
|