aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs67
1 files changed, 65 insertions, 2 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index de89e2e..c2925e3 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -28,8 +28,10 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net;
31using System.Security.Cryptography; 32using System.Security.Cryptography;
32using System.Text; 33using System.Text;
34using System.Threading;
33using HttpServer; 35using HttpServer;
34 36
35namespace OpenSim.Framework.Servers.HttpServer 37namespace OpenSim.Framework.Servers.HttpServer
@@ -98,6 +100,8 @@ namespace OpenSim.Framework.Servers.HttpServer
98 /// </summary> 100 /// </summary>
99 public ValidateHandshake HandshakeValidateMethodOverride = null; 101 public ValidateHandshake HandshakeValidateMethodOverride = null;
100 102
103 private ManualResetEvent _receiveDone = new ManualResetEvent(false);
104
101 private OSHttpRequest _request; 105 private OSHttpRequest _request;
102 private HTTPNetworkContext _networkContext; 106 private HTTPNetworkContext _networkContext;
103 private IHttpClientContext _clientContext; 107 private IHttpClientContext _clientContext;
@@ -109,6 +113,8 @@ namespace OpenSim.Framework.Servers.HttpServer
109 private bool _closing; 113 private bool _closing;
110 private bool _upgraded; 114 private bool _upgraded;
111 private int _maxPayloadBytes = 41943040; 115 private int _maxPayloadBytes = 41943040;
116 private int _initialMsgTimeout = 0;
117 private int _defaultReadTimeout = 10000;
112 118
113 private const string HandshakeAcceptText = 119 private const string HandshakeAcceptText =
114 "HTTP/1.1 101 Switching Protocols\r\n" + 120 "HTTP/1.1 101 Switching Protocols\r\n" +
@@ -131,6 +137,7 @@ namespace OpenSim.Framework.Servers.HttpServer
131 { 137 {
132 _request = preq; 138 _request = preq;
133 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing(); 139 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing();
140 _networkContext.Stream.ReadTimeout = _defaultReadTimeout;
134 _clientContext = pContext; 141 _clientContext = pContext;
135 _bufferLength = bufferlen; 142 _bufferLength = bufferlen;
136 _buffer = new byte[_bufferLength]; 143 _buffer = new byte[_bufferLength];
@@ -206,6 +213,16 @@ namespace OpenSim.Framework.Servers.HttpServer
206 } 213 }
207 214
208 /// <summary> 215 /// <summary>
216 /// Set this to the maximum amount of milliseconds to wait for the first complete message to be sent or received on the websocket after upgrading
217 /// Default, it waits forever. Use this when your Websocket consuming code opens a connection and waits for a message from the other side to avoid a Denial of Service vector.
218 /// </summary>
219 public int InitialMsgTimeout
220 {
221 get { return _initialMsgTimeout; }
222 set { _initialMsgTimeout = value; }
223 }
224
225 /// <summary>
209 /// This triggers the websocket start the upgrade process 226 /// This triggers the websocket start the upgrade process
210 /// </summary> 227 /// </summary>
211 public void HandshakeAndUpgrade() 228 public void HandshakeAndUpgrade()
@@ -245,6 +262,7 @@ namespace OpenSim.Framework.Servers.HttpServer
245 string rawaccept = string.Format(HandshakeAcceptText, acceptKey); 262 string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
246 SendUpgradeSuccess(rawaccept); 263 SendUpgradeSuccess(rawaccept);
247 264
265
248 } 266 }
249 else 267 else
250 { 268 {
@@ -258,6 +276,10 @@ namespace OpenSim.Framework.Servers.HttpServer
258 SendUpgradeSuccess(rawaccept); 276 SendUpgradeSuccess(rawaccept);
259 } 277 }
260 } 278 }
279 public IPEndPoint GetRemoteIPEndpoint()
280 {
281 return _request.RemoteIPEndPoint;
282 }
261 283
262 /// <summary> 284 /// <summary>
263 /// Generates a handshake response key string based on the client's 285 /// Generates a handshake response key string based on the client's
@@ -290,9 +312,16 @@ namespace OpenSim.Framework.Servers.HttpServer
290 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true}; 312 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true};
291 313
292 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse); 314 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse);
315
316
317
318
293 try 319 try
294 { 320 {
295 321 if (_initialMsgTimeout > 0)
322 {
323 _receiveDone.Reset();
324 }
296 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream. 325 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream.
297 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState); 326 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState);
298 327
@@ -303,6 +332,11 @@ namespace OpenSim.Framework.Servers.HttpServer
303 UpgradeCompletedDelegate d = OnUpgradeCompleted; 332 UpgradeCompletedDelegate d = OnUpgradeCompleted;
304 if (d != null) 333 if (d != null)
305 d(this, new UpgradeCompletedEventArgs()); 334 d(this, new UpgradeCompletedEventArgs());
335 if (_initialMsgTimeout > 0)
336 {
337 if (!_receiveDone.WaitOne(TimeSpan.FromMilliseconds(_initialMsgTimeout)))
338 Close(string.Empty);
339 }
306 } 340 }
307 catch (IOException) 341 catch (IOException)
308 { 342 {
@@ -489,6 +523,11 @@ namespace OpenSim.Framework.Servers.HttpServer
489 /// <param name="message">the string message that is to be sent</param> 523 /// <param name="message">the string message that is to be sent</param>
490 public void SendMessage(string message) 524 public void SendMessage(string message)
491 { 525 {
526 if (_initialMsgTimeout > 0)
527 {
528 _receiveDone.Set();
529 _initialMsgTimeout = 0;
530 }
492 byte[] messagedata = Encoding.UTF8.GetBytes(message); 531 byte[] messagedata = Encoding.UTF8.GetBytes(message);
493 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; 532 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata };
494 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text; 533 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text;
@@ -499,6 +538,11 @@ namespace OpenSim.Framework.Servers.HttpServer
499 538
500 public void SendData(byte[] data) 539 public void SendData(byte[] data)
501 { 540 {
541 if (_initialMsgTimeout > 0)
542 {
543 _receiveDone.Set();
544 _initialMsgTimeout = 0;
545 }
502 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data}; 546 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data};
503 dataMessageFrame.Header.IsEnd = true; 547 dataMessageFrame.Header.IsEnd = true;
504 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary; 548 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary;
@@ -531,6 +575,11 @@ namespace OpenSim.Framework.Servers.HttpServer
531 /// </summary> 575 /// </summary>
532 public void SendPingCheck() 576 public void SendPingCheck()
533 { 577 {
578 if (_initialMsgTimeout > 0)
579 {
580 _receiveDone.Set();
581 _initialMsgTimeout = 0;
582 }
534 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] }; 583 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] };
535 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping; 584 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping;
536 pingFrame.Header.IsEnd = true; 585 pingFrame.Header.IsEnd = true;
@@ -544,6 +593,11 @@ namespace OpenSim.Framework.Servers.HttpServer
544 /// <param name="message"></param> 593 /// <param name="message"></param>
545 public void Close(string message) 594 public void Close(string message)
546 { 595 {
596 if (_initialMsgTimeout > 0)
597 {
598 _receiveDone.Set();
599 _initialMsgTimeout = 0;
600 }
547 if (_networkContext == null) 601 if (_networkContext == null)
548 return; 602 return;
549 if (_networkContext.Stream != null) 603 if (_networkContext.Stream != null)
@@ -583,7 +637,11 @@ namespace OpenSim.Framework.Servers.HttpServer
583 WebSocketReader.Mask(psocketState.Header.Mask, unmask); 637 WebSocketReader.Mask(psocketState.Header.Mask, unmask);
584 psocketState.ReceivedBytes = new List<byte>(unmask); 638 psocketState.ReceivedBytes = new List<byte>(unmask);
585 } 639 }
586 640 if (psocketState.Header.Opcode != WebSocketReader.OpCode.Continue && _initialMsgTimeout > 0)
641 {
642 _receiveDone.Set();
643 _initialMsgTimeout = 0;
644 }
587 switch (psocketState.Header.Opcode) 645 switch (psocketState.Header.Opcode)
588 { 646 {
589 case WebSocketReader.OpCode.Ping: 647 case WebSocketReader.OpCode.Ping:
@@ -696,6 +754,11 @@ namespace OpenSim.Framework.Servers.HttpServer
696 } 754 }
697 public void Dispose() 755 public void Dispose()
698 { 756 {
757 if (_initialMsgTimeout > 0)
758 {
759 _receiveDone.Set();
760 _initialMsgTimeout = 0;
761 }
699 if (_networkContext != null && _networkContext.Stream != null) 762 if (_networkContext != null && _networkContext.Stream != null)
700 { 763 {
701 if (_networkContext.Stream.CanWrite) 764 if (_networkContext.Stream.CanWrite)