示例#1
0
		public WebSocketChannel(TcpChannel source) : this() {
			if (source == null) throw new ArgumentNullException("source");
			this.messageSource = source;
			this.initSource = new HttpChannel(source);
			this.State = WebChannelState.Initializing;
		}
示例#2
0
        private void Process()
        {
            // wait for clients and process channels and changes
            var resourceListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 9242);
            //var liveListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 9234);
            var liveWire = new LiveWire.LiveWireServer();

            liveWire.Start();
            resourceListener.Start();
            //liveListener.Start();
            Console.WriteLine("Started server on port 9242");
            while (!stopSignal.WaitOne(16))
            {
                liveWire.Process();
                // accept new clients
                if (resourceListener.Pending())
                {
                    var client = resourceListener.AcceptTcpClient();
                    //client.NoDelay = true;
                    //client.ReceiveTimeout = 1;
                    //client.SendTimeout = 1;
                    var baseChannel = new TcpChannel(client);
                    var channel     = new HttpChannel(baseChannel);
                    //var channel = new WebSocketChannel(baseChannel);
                    AddChannelPrototype(channel);
                }
//				if (liveListener.Pending()) {
//					var client = liveListener.AcceptTcpClient();
//					var baseChannel = new TcpChannel(client);
//					var channel = new WebSocketChannel(baseChannel);
//					AddChannelPrototype(channel);
//				}
                List <IWebChannel> toClose = new List <IWebChannel>();
                foreach (var c in channels)
                {
                    c.Process();
                    if (c.State == WebChannelState.InitFailed || c.State == WebChannelState.Closed)
                    {
                        toClose.Add(c);
                        continue;
                    }

                    if (c.AvailableMessageNo > 0)
                    {
                        var wc = c as WebSocketChannel;
                        if (wc != null)
                        {
                            WebSocketMessage message = wc.EmitMessage();
                            string           text    = message.Text;
                            Console.WriteLine("received: " + text);
                            //string updateMsg = "{ 'type': 'request',
                            Console.WriteLine("circling that");
                            //string updateMsg = "{ 'sender': 'minority', 'type': 'config',  'update', 'content': 'sent to update division' }";
                            //Console.WriteLine("sending update: " + updateMsg);
                            //Thread.Sleep(1000);
                            JsonString str = JsonString.Parse(text);
                            str.AddTerminal("text", "tentacles");
                            wc.SendMessage(new WebSocketMessage(str.ToJsonString()));

                            wc.SendMessage(new WebSocketMessage("{\"type\":\"update\", \"subject\":\"content\"  }"));
                        }
                        var hc = c as HttpChannel;
                        if (hc != null)
                        {
                            HttpMessage message = hc.EmitMessage();
                            //Console.WriteLine("message: ");
                            //Console.WriteLine(message.Header.ToString());
                            //Console.WriteLine(Encoding.UTF8.GetString(message.Content));
                            string resource = message.Header.Resource;

                            byte[]     responseContent = new Services.ResourceWireServer().ProvideResource(resource);
                            HttpHeader responseHeader;
                            if (responseContent.Length > 0)
                            {
                                responseHeader = new HttpHeader(HttpMethod.Response, resource, message.Header.Version, HttpStatusCode.OK);

                                if (resource.EndsWith(".js"))
                                {
                                    responseHeader.Fields.Add("Content-Type", "text/javascript; charset=UTF-8");
                                }
                                else if (resource.EndsWith(".html") || resource.Equals("/"))
                                {
                                    responseHeader.Fields.Add("Content-Type", "text/html; charset=UTF-8");
                                }
                                else if (resource.EndsWith(".css"))
                                {
                                    responseHeader.Fields.Add("Content-Type", "text/css; charset=UTF-8");
                                }
                                else if (resource.EndsWith(".ico"))
                                {
                                    responseHeader.Fields.Add("Content-Type", "image/vnd.microsoft.icon");
                                }
                                else if (resource.EndsWith(".svg"))
                                {
                                    responseHeader.Fields.Add("Content-Type", "image/svg+xml");
                                }
                                else
                                {
                                    responseHeader.Fields.Add("Content-Type", "text/plain; charset=UTF-8");
                                }
                                responseHeader.Fields.Add("Content-Encoding", "identity");
                                responseHeader.Fields.Add("Content-Length", string.Format("{0}", responseContent.Length));
                                //responseHeader.Fields.Add("Transfer-Encoding", "identity");
                                responseHeader.Fields.Add("Connection", "close");
                            }
                            else
                            {
                                responseHeader = new HttpHeader(HttpMethod.Response, resource, message.Header.Version, HttpStatusCode.NotFound);
                                responseHeader.Fields.Add("Content-Length", "0");
                                //responseHeader.Fields.Add("Transfer-Encoding", "identity");
                                responseHeader.Fields.Add("Connection", "close");
                            }
                            responseHeader.Fields.Add("Server", "Irseny");
                            responseHeader.Fields.Add("Date", DateTime.UtcNow.ToString());

                            var response = new HttpMessage(responseHeader, responseContent);

                            hc.SendMessage(response);
                            hc.Close();
                        }
                    }
                }
                foreach (IWebChannel c in toClose)
                {
                    c.Close();
                    Console.WriteLine("closed client " + channels.IndexOf(c));
                    channels.Remove(c);
                }
            }
            foreach (var c in channels)
            {
                c.Close();
            }
            resourceListener.Stop();
        }
示例#3
0
		private void ProcessInit() {
			// continue initializing through the html channel
			initSource.Process();
			// stop processing if something went wrong
			if (initSource.State == WebChannelState.Closed || initSource.State == WebChannelState.InitFailed) {
				State = WebChannelState.InitFailed;
				initSource = null;
			}
			// wait for the first header to arrive
			if (initSource.AvailableMessageNo > 0) {
				HttpHeader header = initSource.EmitMessage().Header;
				string headerKey = string.Empty;
				bool headerValid = false;
				bool canRecover = false;
				bool denySubprotocol = false;
				bool denyExtension = false;
				do {
					// check the header for errors
					if (header.Method != HttpMethod.Get) {
						break;
					}
					// TODO optional origin
					string connection;
					if (!header.Fields.TryGetValue("Connection", out connection)) {
						break;
					}
					if (!connection.ToLower().Contains("upgrade")) {
						break;
					}
					string upgrade;
					if (!header.Fields.TryGetValue("Upgrade", out upgrade)) {
						break;
					}
					if (!upgrade.ToLower().Contains("websocket")) {
						break;
					}
					if (!header.Fields.TryGetValue("Sec-WebSocket-Key", out headerKey)) {
						break;
					}
					string sVersion;
					if (header.Fields.TryGetValue("Sec-WebSocket-Version", out sVersion)) {
						// TODO improve detection
						bool acceptVersion = false;
						if (sVersion.Contains("13")) {
							acceptVersion = true;

						}
						if (!acceptVersion) {
							headerValid = false;
							canRecover = true;
							HttpHeader response = new HttpHeader(header.Version, HttpStatusCode.UpgradeRequired);
							response.Fields.Add("Sec-WebSocket-Version", "13");
							initSource.SendMessage(new HttpMessage(response));
							break;
						}
					}
					// this implementation does not support subprotocols or extensions
					// send null fields if these exist in the request
					if (header.Fields.ContainsKey("Subprotocol")) {
						denySubprotocol = true;
					}
					if (header.Fields.ContainsKey("Extension")) {
						denyExtension = true;
					}
					// TODO optional handle resource or send 404 not found
					headerValid = true;
				} while (false);
				if (!headerValid) {
					if (!canRecover) {
						// set the connection on ice if the setup failed
						State = WebChannelState.InitFailed;
						initSource.Close(false);
						initSource = null;
					}
				} else {
					// send an appropriate response header
					HttpHeader response = new HttpHeader(HttpVersion.Version11, HttpStatusCode.SwitchingProtocols);
					response.Fields.Add("Upgrade", "websocket");
					response.Fields.Add("Connection", "Upgrade");
					byte[] byteKey = Encoding.UTF8.GetBytes(headerKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
					byte[] sha1Key = System.Security.Cryptography.SHA1.Create().ComputeHash(byteKey);
					string base64Key = Convert.ToBase64String(sha1Key);
					response.Fields.Add("Sec-WebSocket-Accept", base64Key);

					if (denySubprotocol) {
						response.Fields.Add("Subprotocol", "null");
					}
					if (denyExtension) {
						response.Fields.Add("Extension", "null");
					}
					initSource.SendMessage(new HttpMessage(response));
					// since the upgrade is done no more http communication is necessary
					// ACK has to be sent first so initSource can not contain any websocket messages at this point
					initSource.Flush();
					initSource.Close(false);
					initSource = null;
					// the handshake has been completed
					// messages can now be sent
					State = WebChannelState.Open;
					// continue with sending all pending messages
					foreach (WebSocketMessage send in toSend) {
						byte[] encoded = EncodeMessage(send);
						messageSource.SendMessage(encoded);
					}
					toSend.Clear();				
				} 
			}
		}