websocket-server – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Security.Cryptography;
5 using System.Text;
6 using System.Net.Sockets;
7 using System.Text.RegularExpressions;
8 using System.Diagnostics;
9 using System.Threading;
10 using WebSockets.Common;
11 using WebSockets.Exceptions;
12 using WebSockets.Server.Http;
13 using System.IO;
14 using WebSockets.Events;
15  
16 namespace WebSockets.Server.WebSocket
17 {
18 public class WebSocketService : WebSocketBase, IService
19 {
20 private readonly Stream _stream;
21 private readonly string _header;
22 private readonly IWebSocketLogger _logger;
23 private readonly TcpClient _tcpClient;
24 private bool _isDisposed = false;
25  
26 public WebSocketService(Stream stream, TcpClient tcpClient, string header, bool noDelay, IWebSocketLogger logger)
27 : base(logger)
28 {
29 _stream = stream;
30 _header = header;
31 _logger = logger;
32 _tcpClient = tcpClient;
33  
34 // send requests immediately if true (needed for small low latency packets but not a long stream).
35 // Basically, dont wait for the buffer to be full before before sending the packet
36 tcpClient.NoDelay = noDelay;
37 }
38  
39 public void Respond()
40 {
41 base.OpenBlocking(_stream, _tcpClient.Client);
42 }
43  
44 protected override void PerformHandshake(Stream stream)
45 {
46 string header = _header;
47  
48 try
49 {
50 Regex webSocketKeyRegex = new Regex("Sec-WebSocket-Key: (.*)");
51 Regex webSocketVersionRegex = new Regex("Sec-WebSocket-Version: (.*)");
52  
53 // check the version. Support version 13 and above
54 const int WebSocketVersion = 13;
55 int secWebSocketVersion = Convert.ToInt32(webSocketVersionRegex.Match(header).Groups[1].Value.Trim());
56 if (secWebSocketVersion < WebSocketVersion)
57 {
58 throw new WebSocketVersionNotSupportedException(string.Format("WebSocket Version {0} not suported. Must be {1} or above", secWebSocketVersion, WebSocketVersion));
59 }
60  
61 string secWebSocketKey = webSocketKeyRegex.Match(header).Groups[1].Value.Trim();
62 string setWebSocketAccept = base.ComputeSocketAcceptString(secWebSocketKey);
63 string response = ("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
64 + "Connection: Upgrade" + Environment.NewLine
65 + "Upgrade: websocket" + Environment.NewLine
66 + "Sec-WebSocket-Accept: " + setWebSocketAccept);
67  
68 HttpHelper.WriteHttpHeader(response, stream);
69 _logger.Information(this.GetType(), "Web Socket handshake sent");
70 }
71 catch (WebSocketVersionNotSupportedException ex)
72 {
73 string response = "HTTP/1.1 426 Upgrade Required" + Environment.NewLine + "Sec-WebSocket-Version: 13";
74 HttpHelper.WriteHttpHeader(response, stream);
75 throw;
76 }
77 catch (Exception ex)
78 {
79 HttpHelper.WriteHttpHeader("HTTP/1.1 400 Bad Request", stream);
80 throw;
81 }
82 }
83  
84 private static void CloseConnection(Socket socket)
85 {
86 socket.Shutdown(SocketShutdown.Both);
87 socket.Close();
88 }
89  
90 public virtual void Dispose()
91 {
92 // send special web socket close message. Don't close the network stream, it will be disposed later
93 if (_stream.CanWrite && !_isDisposed)
94 {
95 using (MemoryStream stream = new MemoryStream())
96 {
97 // set the close reason to Normal
98 BinaryReaderWriter.WriteUShort((ushort) WebSocketCloseCode.Normal, stream, false);
99  
100 // send close message to client to begin the close handshake
101 Send(WebSocketOpCode.ConnectionClose, stream.ToArray());
102 }
103  
104 _isDisposed = true;
105 _logger.Information(this.GetType(), "Sent web socket close message to client");
106 CloseConnection(_tcpClient.Client);
107 }
108 }
109  
110 protected override void OnConnectionClose(byte[] payload)
111 {
112 Send(WebSocketOpCode.ConnectionClose, payload);
113 _logger.Information(this.GetType(), "Sent response close message to client");
114 _isDisposed = true;
115  
116 base.OnConnectionClose(payload);
117 }
118 }
119 }