#region License /* * WebSocketService.cs * * The MIT License * * Copyright (c) 2012-2013 sta.blockhead * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #endregion using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Threading; using WebSocketSharp.Net; using WebSocketSharp.Net.WebSockets; namespace WebSocketSharp.Server { /// /// Provides the basic functions of the WebSocket service. /// /// /// The WebSocketService class is an abstract class. /// public abstract class WebSocketService { #region Private Fields private WebSocketContext _context; private WebSocketServiceManager _sessions; private WebSocket _websocket; #endregion #region Public Constructors /// /// Initializes a new instance of the class. /// public WebSocketService () { ID = String.Empty; IsBound = false; } #endregion #region Internal Properties internal WebSocket WebSocket { get { return _websocket; } } #endregion #region Protected Properties /// /// Gets or sets the logging functions. /// /// /// If you want to change the current logger to the service own logger, you set this property /// to a new instance that you created. /// /// /// A that provides the logging functions. /// protected Logger Log { get { return IsBound ? _websocket.Log : null; } set { if (!IsBound) return; _websocket.Log = value; } } /// /// Gets the collection of query string variables used in the WebSocket connection request. /// /// /// A that contains the collection of query string variables. /// protected NameValueCollection QueryString { get { return IsBound ? _context.QueryString : null; } } /// /// Gets the sessions to the instances. /// /// /// A that contains the sessions to /// the instances. /// protected WebSocketServiceManager Sessions { get { return IsBound ? _sessions : null; } } #endregion #region Public Properties /// /// Gets the ID of the current instance. /// /// /// A that contains an ID. /// public string ID { get; private set; } /// /// Gets a value indicating whether the current instance /// has been bound to a . /// /// /// true if the current instance has been bound to /// a ; otherwise, false. /// public bool IsBound { get; private set; } #endregion #region Private Methods private void onClose (object sender, CloseEventArgs e) { _sessions.Remove (ID); OnClose (e); } private void onError (object sender, ErrorEventArgs e) { OnError (e); } private void onMessage (object sender, MessageEventArgs e) { OnMessage (e); } private void onOpen (object sender, EventArgs e) { ID = _sessions.Add (this); OnOpen (); } #endregion #region Internal Methods internal void Bind (WebSocketContext context, WebSocketServiceManager sessions) { if (IsBound) return; _context = context; _sessions = sessions; _websocket = context.WebSocket; _websocket.CookiesValidation = ValidateCookies; _websocket.OnOpen += onOpen; _websocket.OnMessage += onMessage; _websocket.OnError += onError; _websocket.OnClose += onClose; IsBound = true; } internal void SendAsync (byte [] data, Action completed) { _websocket.SendAsync (data, completed); } internal void SendAsync (string data, Action completed) { _websocket.SendAsync (data, completed); } #endregion #region Protected Methods /// /// Is called when the WebSocket connection has been closed. /// /// /// A that contains an event data associated with /// an inner event. /// protected virtual void OnClose (CloseEventArgs e) { } /// /// Is called when the inner gets an error. /// /// /// An that contains an event data associated with /// an inner event. /// protected virtual void OnError (ErrorEventArgs e) { } /// /// Is called when the inner receives a data frame. /// /// /// A that contains an event data associated with /// an inner event. /// protected virtual void OnMessage (MessageEventArgs e) { } /// /// Is called when the WebSocket connection has been established. /// protected virtual void OnOpen () { } /// /// Validates the cookies used in the WebSocket connection request. /// /// /// This method is called when the inner validates /// the WebSocket connection request. /// /// /// true if the cookies is valid; otherwise, false. /// The default returns true. /// /// /// A that contains a collection of the HTTP Cookies /// to validate. /// /// /// A that receives the HTTP Cookies to send to the client. /// protected virtual bool ValidateCookies (CookieCollection request, CookieCollection response) { return true; } #endregion #region Public Methods /// /// Broadcasts the specified array of to the clients of /// every instances in the . /// /// /// An array of to broadcast. /// public void Broadcast (byte [] data) { if (IsBound) _sessions.Broadcast (data); } /// /// Broadcasts the specified to the clients of /// every instances in the . /// /// /// A to broadcast. /// public void Broadcast (string data) { if (IsBound) _sessions.Broadcast (data); } /// /// Sends Pings to the clients of every instances /// in the . /// /// /// A Dictionary<string, bool> that contains the collection of IDs and values /// indicating whether the each instances received a Pong in a time. /// public Dictionary Broadping () { return Broadping (String.Empty); } /// /// Sends Pings with the specified to the clients of /// every instances in the . /// /// /// A Dictionary<string, bool> that contains the collection of IDs and values /// indicating whether the each instances received a Pong in a time. /// /// /// A that contains a message to send. /// public Dictionary Broadping (string message) { return IsBound ? _sessions.Broadping (message) : null; } /// /// Sends a Ping to the client of the current instance. /// /// /// true if the current instance receives a Pong in a time; /// otherwise, false. /// public bool Ping () { return Ping (String.Empty); } /// /// Sends a Ping with the specified to the client of /// the current instance. /// /// /// true if the current instance receives a Pong in a time; /// otherwise, false. /// /// /// A that contains a message to send. /// public bool Ping (string message) { return IsBound ? _websocket.Ping (message) : false; } /// /// Sends a Ping to the client of the instance /// associated with the specified . /// /// /// true if the instance receives a Pong in a time; /// otherwise, false. /// /// /// A that contains an ID that represents the destination for the Ping. /// public bool PingTo (string id) { return PingTo (id, String.Empty); } /// /// Sends a Ping with the specified to the client of /// the instance associated with the specified . /// /// /// true if the instance receives a Pong in a time; /// otherwise, false. /// /// /// A that contains an ID that represents the destination for the Ping. /// /// /// A that contains a message to send. /// public bool PingTo (string id, string message) { if (!IsBound) return false; WebSocketService service; return _sessions.TryGetWebSocketService (id, out service) ? service.Ping (message) : false; } /// /// Sends a binary data to the client of the current instance. /// /// /// An array of that contains a binary data to send. /// public void Send (byte [] data) { if (IsBound) _websocket.Send (data); } /// /// Sends a text data to the client of the current instance. /// /// /// A that contains a text data to send. /// public void Send (string data) { if (IsBound) _websocket.Send (data); } /// /// Sends a binary data to the client of the instance /// associated with the specified . /// /// /// A that contains an ID that represents the destination for the data. /// /// /// An array of that contains a binary data to send. /// public void SendTo (string id, byte [] data) { if (!IsBound) return; WebSocketService service; if (_sessions.TryGetWebSocketService (id, out service)) service.Send (data); } /// /// Sends a text data to the client of the instance /// associated with the specified . /// /// /// A that contains an ID that represents the destination for the data. /// /// /// A that contains a text data to send. /// public void SendTo (string id, string data) { if (!IsBound) return; WebSocketService service; if (_sessions.TryGetWebSocketService (id, out service)) service.Send (data); } /// /// Starts a instance. /// public void Start () { if (IsBound) _websocket.Connect (); } /// /// Stops the current instance. /// public void Stop () { if (!IsBound) return; _websocket.Close (); } /// /// Stops the current instance with the specified /// and . /// /// /// A that contains a status code indicating the reason for stop. /// /// /// A that contains the reason for stop. /// public void Stop (ushort code, string reason) { if (!IsBound) return; _websocket.Close (code, reason); } /// /// Stops the current instance with the specified /// and . /// /// /// One of the values that indicates a status code /// indicating the reason for stop. /// /// /// A that contains the reason for stop. /// public void Stop (CloseStatusCode code, string reason) { Stop ((ushort) code, reason); } #endregion } }