using System; using System.Collections.Generic; using System.Linq; using System.Text; using SuperSocket.SocketBase; using SuperSocket.SocketBase.Command; using SuperWebSocket.Protocol; namespace SuperWebSocket.Command { /// /// The command handling close fragment /// /// The type of the web socket session. class Close : FragmentCommand where TWebSocketSession : WebSocketSession, new() { /// /// Gets the name. /// public override string Name { get { return OpCode.CloseTag; } } /// /// Executes the command. /// /// The session. /// The request info. public override void ExecuteCommand(TWebSocketSession session, IWebSocketFragment requestInfo) { var frame = requestInfo as WebSocketDataFrame; if (!CheckControlFrame(frame)) { session.Close(); return; } //the close handshake started from server side, now received a handshake response if (session.InClosing) { //Close the underlying socket directly session.Close(CloseReason.ClientClosing); return; } var data = GetWebSocketData(frame); var closeStatusCode = session.ProtocolProcessor.CloseStatusClode.NormalClosure; //var reasonText = string.Empty; if (data != null && data.Length > 0) { if (data.Length == 1) { session.Close(CloseReason.ProtocolError); return; } else { var code = data[0] * 256 + data[1]; if (!session.ProtocolProcessor.IsValidCloseCode(code)) { session.Close(CloseReason.ProtocolError); return; } closeStatusCode = code; //if (data.Length > 2) //{ // reasonText = this.Utf8Encoding.GetString(data, 2, data.Length - 2); //} } } //Send handshake response session.SendCloseHandshakeResponse(closeStatusCode); //Don't include close reason the close handshake response for now //session.SendCloseHandshakeResponse(closeStatusCode, reasonText); //After both sending and receiving a Close message, the server MUST close the underlying TCP connection immediately session.Close(CloseReason.ClientClosing); } } }