예제 #1
0
 void WebSocketOpen(string[] args)
 {
     // new websocket connection with conntionID, uri, and optional UTF16 arguments
     try
     {
         int    connectionID = Int32.Parse(args[2]);
         string uriDecoded   = Encoding.Unicode.GetString(Convert.FromBase64String(args[3]));
         Uri    webUri;
         try
         {
             webUri = new Uri(uriDecoded);
         }
         catch (UriFormatException e)
         {
             Console.WriteLine("URI incorrectly formatted: " + e.Message);
             Console.WriteLine("Closing websocket connection " + connectionID);
             midiManager.SendWebSocketClosedResponse(connectionID);
             return;
         }
         bool autoConvertResponse = false;
         if (args.Length > 4)
         {
             autoConvertResponse = args[4] == "UTF16";
         }
         Console.WriteLine("Opening websocket (" + connectionID + "): " + uriDecoded);
         webManager.OpenWebSocketConnection(connectionID, webUri, autoConvertResponse);
     }
     catch (Exception e)
     {
         Console.WriteLine("Error parsing web request: " + e.Message);
     }
 }
예제 #2
0
        public async void OpenWebSocketConnection(int connectionID, Uri webUri, bool autoConvertResponses)
        {
            // Block all non-internet IP address
            if (HostnameIsPrivateIPAddress(webUri))
            {
                Console.WriteLine("Closing websocket connection " + connectionID);
                midiManager.SendWebSocketClosedResponse(connectionID);
                return;
            }

            if (webUri.Scheme != "ws" && webUri.Scheme != "wss")
            {
                Console.WriteLine("Error: World attempted to open unsupported URI: " + webUri.Scheme);
                Console.WriteLine("Closing websocket connection " + connectionID);
                midiManager.SendWebSocketClosedResponse(connectionID);
                return;
            }

            // Block all rate limited domain+path combos
            var hostAndPath = new HostnameAndPath(webUri.Host, "");

            if (rateLimitedURIs.ContainsKey(hostAndPath))
            {
                if (DateTime.Now < rateLimitedURIs[hostAndPath])
                {
                    Console.WriteLine("ERROR: Could not open websocket connection, currently rate limited.");
                    Console.WriteLine("Closing websocket connection " + connectionID);
                    midiManager.SendWebSocketClosedResponse(connectionID);
                    return;
                }
                else
                {
                    rateLimitedURIs.Remove(hostAndPath);
                }
            }

            webSockets[connectionID] = new ClientWebSocket();
            ClientWebSocket cws = webSockets[connectionID];

            try
            {
                await cws.ConnectAsync(webUri, ctSource.Token);
            }
            catch (WebSocketException e)
            {
                rateLimitedURIs.Add(hostAndPath, DateTime.Now.AddSeconds(RATE_LIMIT_TIMEOUT_SECONDS));
                Console.WriteLine("Failed to open websocket: " + e.Message);
                Console.WriteLine("Closing websocket connection " + connectionID);
                midiManager.SendWebSocketClosedResponse(connectionID);
                webSockets[connectionID] = null;
                return;
            }
            catch (OperationCanceledException)
            {
                return;
            }

            while (cws.State == WebSocketState.Connecting)
            {
                ;
            }
            if (cws.State == WebSocketState.Open)
            {
                midiManager.SendWebSocketOpenedResponse(connectionID);
            }

            wsBuffers[connectionID]             = new ArraySegment <byte>(new byte[WEBSOCKET_BUFFER_SIZE]);
            wsAutoConvertMessages[connectionID] = autoConvertResponses;
            while (cws.State == WebSocketState.Open)
            {
                WebSocketReceiveResult wssr = null;
                try
                {
                    wssr = await cws.ReceiveAsync(wsBuffers[connectionID], ctSource.Token);
                }
                catch (WebSocketException e)
                {
                    // Aborted state.  To or to not rate limit, because twitch likes to
                    // abort any connection when a nickname is already taken...
                    Console.WriteLine("WebSocketException: " + e.Message);
                    Console.WriteLine("Closing websocket connection " + connectionID);
                    midiManager.SendWebSocketClosedResponse(connectionID);
                    webSockets[connectionID] = null;
                    break;
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: " + e.Message);
                    Console.WriteLine("Closing websocket connection " + connectionID);
                    midiManager.SendWebSocketClosedResponse(connectionID);
                    webSockets[connectionID] = null;
                    break;
                }

                // Copy data to an intermediate array in case it needs to be converted from UTF8 to UTF16
                byte[] message = new byte[wssr.Count];
                Array.Copy(wsBuffers[connectionID].Array, 0, message, 0, wssr.Count);
                Console.WriteLine("Received websocket message: " + Encoding.UTF8.GetString(message));
                if (wsAutoConvertMessages[connectionID] && (wssr.MessageType == WebSocketMessageType.Text))
                {
                    message = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, message);
                }

                // Send 4 bytes for response length, 1 bytes for txt/bin flag, and then response data
                byte[] responseData = new byte[4 + 1 + message.Length];
                Array.Copy(BitConverter.GetBytes(message.Length + 1), 0, responseData, 0, 4);
                responseData[4] = wssr.MessageType == WebSocketMessageType.Text ? (byte)0x0 :(byte)0x1;
                Array.Copy(message, 0, responseData, 5, message.Length);
                midiManager.AddConnectionResponse((byte)connectionID, responseData);
            }
        }