Modified some Send and Broadcast methods (e.g. Send (stream, length, dispose) -> Send (stream, length))

master
sta 12 years ago
parent cbf73e9865
commit f6610352e2

@ -147,7 +147,13 @@ ws.Send (data);
The `Send` method is overloaded.
The types of `data` are `string`, `byte []` and `FileInfo` class.
The types of `data` are `string`, `byte []` and `System.IO.FileInfo` class.
In addition, the `Send (stream, length)` method exists, too.
These methods don't wait for the send to be complete. This means that these methods behave asynchronously.
If you want to do something when the send is complete, you use any of some `Send (data, completed)` methods.
#### Step 6 ####
@ -159,9 +165,11 @@ ws.Close (code, reason);
If you want to close the WebSocket connection explicitly, you use the `Close` method.
The `Close` method is overloaded. The types of `code` are `WebSocketSharp.CloseStatusCode` and `ushort`, the type of `reason` is `string`.
The `Close` method is overloaded.
The types of `code` are `WebSocketSharp.CloseStatusCode` and `ushort`, and the type of `reason` is `string`.
In addition, the `Close ()` and `Close (code)` methods exist.
In addition, the `Close ()` and `Close (code)` methods exist, too.
### WebSocket Server ###

@ -140,22 +140,22 @@ namespace WebSocketSharp
private static byte [] readBytes (this Stream stream, byte [] buffer, int offset, int length)
{
var readLen = stream.Read (buffer, offset, length);
if (readLen < 1)
var len = stream.Read (buffer, offset, length);
if (len < 1)
return buffer.SubArray (0, offset);
var tmpLen = 0;
while (readLen < length)
var tmp = 0;
while (len < length)
{
tmpLen = stream.Read (buffer, offset + readLen, length - readLen);
if (tmpLen < 1)
tmp = stream.Read (buffer, offset + len, length - len);
if (tmp < 1)
break;
readLen += tmpLen;
len += tmp;
}
return readLen < length
? buffer.SubArray (0, offset + readLen)
return len < length
? buffer.SubArray (0, offset + len)
: buffer;
}
@ -536,15 +536,15 @@ namespace WebSocketSharp
AsyncCallback callback = ar =>
{
try {
var readLen = stream.EndRead (ar);
var result = readLen < 1
? new byte []{}
: readLen < length
? stream.readBytes (buffer, readLen, length - readLen)
: buffer;
var len = stream.EndRead (ar);
var bytes = len < 1
? new byte []{}
: len < length
? stream.readBytes (buffer, len, length - len)
: buffer;
if (completed != null)
completed (result);
completed (bytes);
}
catch (Exception ex) {
if (error != null)

@ -316,35 +316,35 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a text <paramref name="data"/> to the client of the current
/// <see cref="WebSocketService"/> instance.
/// Sends a binary data from the specified <see cref="FileInfo"/> to
/// the client of the current <see cref="WebSocketService"/> instance.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// </param>
protected void Send (string data)
protected void Send (FileInfo file)
{
if (_websocket != null)
_websocket.Send (data, null);
_websocket.Send (file, null);
}
/// <summary>
/// Sends a binary data from the specified <see cref="FileInfo"/> to
/// the client of the current <see cref="WebSocketService"/> instance.
/// Sends a text <paramref name="data"/> to the client of the current
/// <see cref="WebSocketService"/> instance.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// </param>
protected void Send (FileInfo file)
protected void Send (string data)
{
if (_websocket != null)
_websocket.Send (file, null);
_websocket.Send (data, null);
}
/// <summary>
@ -370,14 +370,14 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a text <paramref name="data"/> to the client of the current
/// <see cref="WebSocketService"/> instance.
/// Sends a binary data from the specified <see cref="FileInfo"/> to
/// the client of the current <see cref="WebSocketService"/> instance.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
@ -385,21 +385,21 @@ namespace WebSocketSharp.Server
/// A <see cref="bool"/> passed to this delegate is <c>true</c> if the send is
/// complete successfully; otherwise, <c>false</c>.
/// </param>
protected void Send (string data, Action<bool> completed)
protected void Send (FileInfo file, Action<bool> completed)
{
if (_websocket != null)
_websocket.Send (data, completed);
_websocket.Send (file, completed);
}
/// <summary>
/// Sends a binary data from the specified <see cref="FileInfo"/> to
/// the client of the current <see cref="WebSocketService"/> instance.
/// Sends a text <paramref name="data"/> to the client of the current
/// <see cref="WebSocketService"/> instance.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
@ -407,10 +407,10 @@ namespace WebSocketSharp.Server
/// A <see cref="bool"/> passed to this delegate is <c>true</c> if the send is
/// complete successfully; otherwise, <c>false</c>.
/// </param>
protected void Send (FileInfo file, Action<bool> completed)
protected void Send (string data, Action<bool> completed)
{
if (_websocket != null)
_websocket.Send (file, completed);
_websocket.Send (data, completed);
}
/// <summary>
@ -426,14 +426,10 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
protected void Send (Stream stream, int length, bool dispose)
protected void Send (Stream stream, int length)
{
if (_websocket != null)
_websocket.Send (stream, length, dispose, null);
_websocket.Send (stream, length, null);
}
/// <summary>
@ -449,20 +445,16 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
/// the send is complete.
/// A <see cref="bool"/> passed to this delegate is <c>true</c> if the send is
/// complete successfully; otherwise, <c>false</c>.
/// </param>
protected void Send (Stream stream, int length, bool dispose, Action<bool> completed)
protected void Send (Stream stream, int length, Action<bool> completed)
{
if (_websocket != null)
_websocket.Send (stream, length, dispose, completed);
_websocket.Send (stream, length, completed);
}
/// <summary>

@ -470,13 +470,9 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to broadcast.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data broadcasted;
/// otherwise, <c>false</c>.
/// </param>
public void Broadcast (Stream stream, int length, bool dispose)
public void Broadcast (Stream stream, int length)
{
Broadcast (stream, length, dispose, null);
Broadcast (stream, length, null);
}
/// <summary>
@ -492,15 +488,11 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to broadcast.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data broadcasted;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="completed">
/// A <see cref="Action"/> delegate that references the method(s) called when
/// the broadcast is complete.
/// </param>
public void Broadcast (Stream stream, int length, bool dispose, Action completed)
public void Broadcast (Stream stream, int length, Action completed)
{
var msg = _state.CheckIfStarted () ??
stream.CheckIfCanRead () ??
@ -512,36 +504,32 @@ namespace WebSocketSharp.Server
return;
}
Action<byte []> result = data =>
{
var readLen = data.Length;
if (readLen == 0)
stream.ReadBytesAsync (
length,
data =>
{
_logger.Error ("A data cannot be read from 'stream'.");
return;
}
if (readLen != length)
_logger.Warn (String.Format (
"A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
length,
readLen));
if (dispose)
stream.Dispose ();
if (readLen <= WebSocket.FragmentLength)
broadcast (Opcode.BINARY, data, completed);
else
broadcast (Opcode.BINARY, new MemoryStream (data), completed);
};
Action<Exception> exception = ex =>
{
_logger.Fatal (ex.ToString ());
};
stream.ReadBytesAsync (length, result, exception);
var len = data.Length;
if (len == 0)
{
_logger.Error ("A data cannot be read from 'stream'.");
return;
}
if (len < length)
_logger.Warn (String.Format (
"A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
length,
len));
if (len <= WebSocket.FragmentLength)
broadcast (Opcode.BINARY, data, completed);
else
broadcast (Opcode.BINARY, new MemoryStream (data), completed);
},
ex =>
{
_logger.Fatal (ex.ToString ());
});
}
/// <summary>
@ -644,13 +632,9 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to broadcast.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data broadcasted;
/// otherwise, <c>false</c>.
/// </param>
public void BroadcastTo (string servicePath, Stream stream, int length, bool dispose)
public void BroadcastTo (string servicePath, Stream stream, int length)
{
BroadcastTo (servicePath, stream, length, dispose, null);
BroadcastTo (servicePath, stream, length, null);
}
/// <summary>
@ -669,20 +653,16 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to broadcast.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data broadcasted;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="completed">
/// A <see cref="Action"/> delegate that references the method(s) called when
/// the broadcast is complete.
/// </param>
public void BroadcastTo (
string servicePath, Stream stream, int length, bool dispose, Action completed)
string servicePath, Stream stream, int length, Action completed)
{
WebSocketServiceHost host;
if (TryGetServiceHost (servicePath, out host))
host.Sessions.Broadcast (stream, length, dispose, completed);
host.Sessions.Broadcast (stream, length, completed);
}
/// <summary>
@ -1011,13 +991,9 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
public void SendTo (string servicePath, string id, Stream stream, int length, bool dispose)
public void SendTo (string servicePath, string id, Stream stream, int length)
{
SendTo (servicePath, id, stream, length, dispose, null);
SendTo (servicePath, id, stream, length, null);
}
/// <summary>
@ -1040,10 +1016,6 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
/// the send is complete.
@ -1051,11 +1023,11 @@ namespace WebSocketSharp.Server
/// successfully; otherwise, <c>false</c>.
/// </param>
public void SendTo (
string servicePath, string id, Stream stream, int length, bool dispose, Action<bool> completed)
string servicePath, string id, Stream stream, int length, Action<bool> completed)
{
WebSocketServiceHost host;
if (TryGetServiceHost (servicePath, out host))
host.Sessions.SendTo (id, stream, length, dispose, completed);
host.Sessions.SendTo (id, stream, length, completed);
}
/// <summary>

@ -504,13 +504,9 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to broadcast.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data broadcasted;
/// otherwise, <c>false</c>.
/// </param>
public void Broadcast (Stream stream, int length, bool dispose)
public void Broadcast (Stream stream, int length)
{
Broadcast (stream, length, dispose, null);
Broadcast (stream, length, null);
}
/// <summary>
@ -526,15 +522,11 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to broadcast.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data broadcasted;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="completed">
/// A <see cref="Action"/> delegate that references the method(s) called when
/// the broadcast is complete.
/// </param>
public void Broadcast (Stream stream, int length, bool dispose, Action completed)
public void Broadcast (Stream stream, int length, Action completed)
{
var msg = _state.CheckIfStarted () ??
stream.CheckIfCanRead () ??
@ -546,36 +538,32 @@ namespace WebSocketSharp.Server
return;
}
Action<byte []> result = data =>
{
var readLen = data.Length;
if (readLen == 0)
stream.ReadBytesAsync (
length,
data =>
{
_logger.Error ("A data cannot be read from 'stream'.");
return;
}
if (readLen != length)
_logger.Warn (String.Format (
"A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
length,
readLen));
if (dispose)
stream.Dispose ();
if (readLen <= WebSocket.FragmentLength)
Broadcast (Opcode.BINARY, data, completed);
else
Broadcast (Opcode.BINARY, new MemoryStream (data), completed);
};
Action<Exception> exception = ex =>
{
_logger.Fatal (ex.ToString ());
};
var len = data.Length;
if (len == 0)
{
_logger.Error ("A data cannot be read from 'stream'.");
return;
}
stream.ReadBytesAsync (length, result, exception);
if (len < length)
_logger.Warn (String.Format (
"A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
length,
len));
if (len <= WebSocket.FragmentLength)
Broadcast (Opcode.BINARY, data, completed);
else
Broadcast (Opcode.BINARY, new MemoryStream (data), completed);
},
ex =>
{
_logger.Fatal (ex.ToString ());
});
}
/// <summary>
@ -826,13 +814,9 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
public void SendTo (string id, Stream stream, int length, bool dispose)
public void SendTo (string id, Stream stream, int length)
{
SendTo (id, stream, length, dispose, null);
SendTo (id, stream, length, null);
}
/// <summary>
@ -852,10 +836,6 @@ namespace WebSocketSharp.Server
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
/// the send is complete.
@ -863,11 +843,11 @@ namespace WebSocketSharp.Server
/// successfully; otherwise, <c>false</c>.
/// </param>
public void SendTo (
string id, Stream stream, int length, bool dispose, Action<bool> completed)
string id, Stream stream, int length, Action<bool> completed)
{
IWebSocketSession session;
if (TryGetSession (id, out session))
session.Context.WebSocket.Send (stream, length, dispose, completed);
session.Context.WebSocket.Send (stream, length, completed);
}
/// <summary>

@ -202,7 +202,7 @@ namespace WebSocketSharp
/// <paramref name="url"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="url"/> is not valid WebSocket URL.
/// <paramref name="url"/> is invalid.
/// </exception>
public WebSocket (
string url,
@ -1603,32 +1603,32 @@ namespace WebSocketSharp
}
/// <summary>
/// Sends a text <paramref name="data"/> using the WebSocket connection.
/// Sends a binary data from the specified <see cref="FileInfo"/>
/// using the WebSocket connection.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// </param>
public void Send (string data)
public void Send (FileInfo file)
{
Send (data, null);
Send (file, null);
}
/// <summary>
/// Sends a binary data from the specified <see cref="FileInfo"/>
/// using the WebSocket connection.
/// Sends a text <paramref name="data"/> using the WebSocket connection.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// </param>
public void Send (FileInfo file)
public void Send (string data)
{
Send (file, null);
Send (data, null);
}
/// <summary>
@ -1664,13 +1664,14 @@ namespace WebSocketSharp
}
/// <summary>
/// Sends a text <paramref name="data"/> using the WebSocket connection.
/// Sends a binary data from the specified <see cref="FileInfo"/>
/// using the WebSocket connection.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
@ -1678,9 +1679,11 @@ namespace WebSocketSharp
/// A <see cref="bool"/> passed to this delegate is <c>true</c> if the send is complete
/// successfully; otherwise, <c>false</c>.
/// </param>
public void Send (string data, Action<bool> completed)
public void Send (FileInfo file, Action<bool> completed)
{
var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData ();
var msg = _readyState.CheckIfOpen () ??
(file == null ? "'file' must not be null." : null);
if (msg != null)
{
_logger.Error (msg);
@ -1689,22 +1692,17 @@ namespace WebSocketSharp
return;
}
var rawData = Encoding.UTF8.GetBytes (data);
if (rawData.LongLength <= FragmentLength)
send (Opcode.TEXT, rawData, completed);
else
send (Opcode.TEXT, new MemoryStream (rawData), completed);
send (Opcode.BINARY, file.OpenRead (), completed);
}
/// <summary>
/// Sends a binary data from the specified <see cref="FileInfo"/>
/// using the WebSocket connection.
/// Sends a text <paramref name="data"/> using the WebSocket connection.
/// </summary>
/// <remarks>
/// This method does not wait for the send to be complete.
/// </remarks>
/// <param name="file">
/// A <see cref="FileInfo"/> from which contains a binary data to send.
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
@ -1712,11 +1710,9 @@ namespace WebSocketSharp
/// A <see cref="bool"/> passed to this delegate is <c>true</c> if the send is complete
/// successfully; otherwise, <c>false</c>.
/// </param>
public void Send (FileInfo file, Action<bool> completed)
public void Send (string data, Action<bool> completed)
{
var msg = _readyState.CheckIfOpen () ??
(file == null ? "'file' must not be null." : null);
var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData ();
if (msg != null)
{
_logger.Error (msg);
@ -1725,7 +1721,11 @@ namespace WebSocketSharp
return;
}
send (Opcode.BINARY, file.OpenRead (), completed);
var rawData = Encoding.UTF8.GetBytes (data);
if (rawData.LongLength <= FragmentLength)
send (Opcode.TEXT, rawData, completed);
else
send (Opcode.TEXT, new MemoryStream (rawData), completed);
}
/// <summary>
@ -1741,13 +1741,9 @@ namespace WebSocketSharp
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
public void Send (Stream stream, int length, bool dispose)
public void Send (Stream stream, int length)
{
Send (stream, length, dispose, null);
Send (stream, length, null);
}
/// <summary>
@ -1763,17 +1759,13 @@ namespace WebSocketSharp
/// <param name="length">
/// An <see cref="int"/> that contains the number of bytes to send.
/// </param>
/// <param name="dispose">
/// <c>true</c> if <paramref name="stream"/> is disposed after a binary data read;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="completed">
/// An Action&lt;bool&gt; delegate that references the method(s) called when
/// the send is complete.
/// A <see cref="bool"/> passed to this delegate is <c>true</c> if the send is complete
/// successfully; otherwise, <c>false</c>.
/// A <see cref="bool"/> passed to this delegate is <c>true</c> if the send is
/// complete successfully; otherwise, <c>false</c>.
/// </param>
public void Send (Stream stream, int length, bool dispose, Action<bool> completed)
public void Send (Stream stream, int length, Action<bool> completed)
{
var msg = _readyState.CheckIfOpen () ??
stream.CheckIfCanRead () ??
@ -1787,42 +1779,38 @@ namespace WebSocketSharp
return;
}
Action<byte []> result = data =>
{
var readLen = data.Length;
if (readLen == 0)
stream.ReadBytesAsync (
length,
data =>
{
var err = "A data cannot be read from 'stream'.";
_logger.Error (err);
error (err);
return;
}
if (readLen != length)
_logger.Warn (String.Format (
"A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
length,
readLen));
if (dispose)
stream.Dispose ();
var len = data.Length;
if (len == 0)
{
var err = "A data cannot be read from 'stream'.";
_logger.Error (err);
error (err);
var sent = readLen <= FragmentLength
? send (Opcode.BINARY, data)
: send (Opcode.BINARY, new MemoryStream (data));
return;
}
if (completed != null)
completed (sent);
};
if (len < length)
_logger.Warn (String.Format (
"A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
length,
len));
Action<Exception> exception = ex =>
{
_logger.Fatal (ex.ToString ());
error ("An exception has occured.");
};
var sent = len <= FragmentLength
? send (Opcode.BINARY, data)
: send (Opcode.BINARY, new MemoryStream (data));
stream.ReadBytesAsync (length, result, exception);
if (completed != null)
completed (sent);
},
ex =>
{
_logger.Fatal (ex.ToString ());
error ("An exception has occured.");
});
}
/// <summary>

Loading…
Cancel
Save