using System;
using System.Collections.Generic;
using System.Text;
using WebSocketSharp;
using WebSocketSharp.Frame;
namespace Taobao.Top.Link.Channel.WebSocket
{
/// websocket clientchannel via websocket-sharp impl
///
public class WebSocketClientChannel : IClientChannel
{
private WebSocketSharp.WebSocket _socket;
private ResetableTimer _timer;
private EventHandler _onMessage;
private EventHandler _onError;
private EventHandler _onClosed;
public EventHandler OnMessage
{
get { this.DelayPing(); return this._onMessage; }
set { this._onMessage = value; }
}
public EventHandler OnError
{
get { this.DelayPing(); return this._onError; }
set { this._onError = value; }
}
public EventHandler OnClosed
{
get { return this._onClosed; }
set { this._onClosed = value; }
}
public Uri Uri { get; set; }
public bool IsConnected { get { return this._socket.ReadyState == WsState.OPEN; } }
public WebSocketClientChannel(WebSocketSharp.WebSocket socket)
{
this._socket = socket;
this._onClosed += (o, e) =>
{
this.Close(e.Reason);
};
}
public void Send(byte[] data)
{
this.CheckChannel();
this._socket.Send(data);
}
public void Close(string reason)
{
this._socket.Close(CloseStatusCode.NORMAL, reason);
if (this._timer != null)
{
this._timer.Cancel();
this._timer = null;
#if DEBUG
Console.WriteLine("TMC: Info@close: " + reason);
#endif
}
}
public ResetableTimer HeartbeatTimer
{
set
{
this._timer = value;
this._timer.Elapsed += (s, e) =>
{
if (this.IsConnected)
//websocket-sharp's ping is sync
this._socket.Ping();
};
}
}
private void CheckChannel()
{
if (!this.IsConnected)
{
if (this._timer != null)
this._timer.Cancel();
throw new LinkException("websocket channel closed");
}
this.DelayPing();
}
private void DelayPing()
{
try
{
if (this._timer != null)
this._timer.Delay();
}
catch (Exception)
{
}
}
}
}