private void broadcast(Opcode opcode, byte[] data, Action completed) { var cache = new Dictionary <CompressionMethod, byte[]> (); try { foreach (var host in Hosts) { if (_state != ServerState.Start) { _log.Error("The server is shutting down."); break; } host.Sessions.Broadcast(opcode, data, cache); } if (completed != null) { completed(); } } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); } finally { cache.Clear(); } }
private Stream GetStream(TcpClient tcpClient) { Stream stream = tcpClient.GetStream(); // we have no ssl certificate if (_sslCertificate == null) { _logger.Information("", this.GetType(), "Connection not secure"); return(stream); } try { SslStream sslStream = new SslStream(stream, false); _logger.Information("", this.GetType(), "Attempting to secure connection..."); sslStream.AuthenticateAsServer(_sslCertificate, false, SslProtocols.Tls, true); _logger.Information("", this.GetType(), "Connection successfully secured"); return(sslStream); } catch (AuthenticationException e) { // TODO: send 401 Unauthorized _logger.Error("", this.GetType(), e); throw; } }
private void HandleAsyncConnection(IAsyncResult res) { try { if (_isDisposed) { return; } // this worker thread stays alive until either of the following happens: // Client sends a close conection request OR // An unhandled exception is thrown OR // The server is disposed using (TcpClient tcpClient = _listener.EndAcceptTcpClient(res)) { // we are ready to listen for more connections (on another thread) StartAccept(); _logger.Information(this.GetType(), "Server: Connection opened"); // get a secure or insecure stream Stream stream = GetStream(tcpClient); // extract the connection details and use those details to build a connection ConnectionDetails connectionDetails = GetConnectionDetails(stream, tcpClient); using (IService service = _serviceFactory.CreateInstance(connectionDetails)) { try { // record the connection so we can close it if something goes wrong lock (_openConnections) { _openConnections.Add(service); } // respond to the http request. // Take a look at the WebSocketConnection or HttpConnection classes service.Respond(); } finally { // forget the connection, we are done with it lock (_openConnections) { _openConnections.Remove(service); } } } } _logger.Information(this.GetType(), "Server: Connection closed"); } catch (ObjectDisposedException) { // do nothing. This will be thrown if the Listener has been stopped } catch (Exception ex) { _logger.Error(this.GetType(), ex); } }
private Stream GetStream(TcpClient tcpClient) { Stream stream = tcpClient.GetStream(); // we have no ssl certificate if (_sslCertificate == null) { //_logger.Information(this.GetType(), "Connection not secure"); return(stream); } try { SslStream sslStream = new SslStream(stream, false); //_logger.Information(this.GetType(), "Attempting to secure connection..."); sslStream.AuthenticateAsServer(_sslCertificate, false, SslProtocols.Tls12, true); //_logger.Information(this.GetType(), "Connection successfully secured"); return(sslStream); } catch (AuthenticationException e) { // TODO: send 401 Unauthorized _logger.Error(typeof(WebServer), $"401 unauth on {tcpClient.Client.LocalEndPoint} with error {e.Message}"); return(null); //throw e; } }
private static void TestClient(object state) { try { string url = (string)state; using (var client = new ChatWebSocketClient(true, _logger)) { Uri uri = new Uri(url); client.TextFrame += Client_TextFrame; client.ConnectionOpened += Client_ConnectionOpened; // test the open handshake client.OpenBlocking(uri); } _logger.Information(typeof(Program), "Client finished, press any key"); } catch (Exception ex) { _logger.Error(typeof(Program), ex.ToString()); _logger.Information(typeof(Program), "Client terminated: Press any key"); } Console.ReadKey(); }
/// <summary> /// Show the progress of the download in a progressbar /// </summary> /// <param name="sender"></param> /// <param name="e"></param> /*private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) * { * // In case you don't have a progressBar Log the value instead * _logger.Information(typeof(MOTR_Moviescraper), "MOTR_Moviescraper image download: " + e.ProgressPercentage.ToString()); * }*/ //Feedback from the webclient, downloading our file to the imagestore private void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { if (e.Cancelled) { _logger.Error(typeof(MOTR_Moviescraper), "Download canceled!"); return; } if (e.Error != null) // We have an error! Retry a few times, then abort. { _logger.Error(typeof(MOTR_Moviescraper), "An error accured during download: " + e.Error.ToString()); return; } _logger.Information(typeof(MOTR_Moviescraper), "MOTR_Moviescraper image download complete"); }
private static void Main(string[] args) { _logger = new WebSocketLogger(); try { int port = 2120; string webRoot = Settings.Default.WebRoot; if (!Directory.Exists(webRoot)) { string baseFolder = AppDomain.CurrentDomain.BaseDirectory; _logger.Warning(typeof(Program), "Webroot folder {0} not found. Using application base directory: {1}", webRoot, baseFolder); webRoot = baseFolder; } // used to decide what to do with incoming connections ServiceFactory serviceFactory = new ServiceFactory(webRoot, _logger); using (WebServer server = new WebServer(serviceFactory, _logger)) { server.Listen(port); //Thread clientThread = new Thread(new ParameterizedThreadStart(TestClient)); //clientThread.IsBackground = true; //clientThread.Start("ws://localhost:2120/chat"); Console.ReadKey(); } } catch (Exception ex) { _logger.Error(typeof(Program), ex); Console.ReadKey(); } }
// The following method is invoked by the RemoteCertificateValidationDelegate. // if you want to ignore certificate errors (for debugging) then return true; public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (sslPolicyErrors == SslPolicyErrors.None) { return(true); } _globalLogger.Error(typeof(WebSocketClient), "Certificate error: {0}", sslPolicyErrors); // Do not allow this client to communicate with unauthenticated servers. return(false); }
// The following method is invoked by the RemoteCertificateValidationDelegate. // if you want to ignore certificate errors (for debugging) then return true; public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { //2019-06-28 by Salem Su If you are getting certificate errors (like name mismatch or expiries), then you can always disable the check by making the WebSocketClient.ValidateServerCertificate function always return true. return(true); if (sslPolicyErrors == SslPolicyErrors.None) { return(true); } _globalLogger.Error("", typeof(WebSocketClient), "Certificate error: {0}", sslPolicyErrors); // Do not allow this client to communicate with unauthenticated servers. return(false); }
private static void Main(string[] args) { _logger = new WebSocketLogger(); try { int port = Settings.Default.Port; string webRoot = Settings.Default.WebRoot; if (!Directory.Exists(webRoot)) { string baseFolder = AppDomain.CurrentDomain.BaseDirectory; _logger.Warning(typeof(Program), "Webroot folder {0} not found. Using application base directory: {1}", webRoot, baseFolder); webRoot = baseFolder; } // used to decide what to do with incoming connections ServiceFactory serviceFactory = new ServiceFactory(webRoot, _logger); using (WebServer server = new WebServer(serviceFactory, _logger)) { if (port == 443) { X509Certificate2 cert = GetCertificate(); server.Listen(port, cert); } else { server.Listen(port); } Thread clientThread = new Thread(new ParameterizedThreadStart(TestClient)); clientThread.IsBackground = false; // to enable ssl change the port to 443 in the settings file and use the wss schema below // clientThread.Start("wss://localhost/chat"); clientThread.Start("ws://localhost/chat"); Console.ReadKey(); } } catch (Exception ex) { _logger.Error(typeof(Program), ex); Console.ReadKey(); } }
protected override void OnTextFrame(string text) { try { string response = "Server Send: " + text; base.Send(response); // limit the log message size int length = 1024 * 16; // 16KB buffer more than enough for http header string logMessage = response.Length > length?response.Substring(0, length) + "..." : response; _logger.Information("", this.GetType(), logMessage); } catch (Exception ex) { _logger.Error("", this.GetType(), ex.Message); } }
//Here we create the webserver and starts listening public bool CreateWebServer(int iPortNumber, string webRoot, bool bSSL = false, string sCertPath = "", string sCertPassWord = "") { //Store information for recalling after a initalwizard has been launched MOTR_WebserverObject m_WebServer = new MOTR_WebserverObject(); m_WebServer.LastPortNumber = iPortNumber; m_WebServer.LastPath = webRoot; m_WebServer.LastSSL = bSSL; m_WebServer.LastCert = sCertPath; m_WebServer.LastCertPassword = sCertPassWord; try { //Get the path or set the default path of where the program was runned if (!Directory.Exists(webRoot)) { _logger.Error(typeof(WindowsService), "Webroot folder {0} not found. Directory needs to exist to start webserver", webRoot); return(false); } if (!File.Exists(sCertPath) && sCertPath.Length != 0) { _logger.Error(typeof(WindowsService), "Certificate {0} not found, needed for https on port {1}, generate by entering motrd.exe -cert.", sCertPath, iPortNumber); return(false); } //Check if there are users available. //If not, create a inital wizard mode so the user are able to create their own username and password if (_users.Count() == 0) { //Changing the root to only include the initalsetup directory m_WebServer.initalServiceFactory = new MOTR_WebserverFactoryInitalWizard(webRoot, _users, _admin, _logger); m_WebServer.initalServiceFactory.OnInitalsetupComplete += HandleEventInitalSetupComplete; m_WebServer.server = new WebServer(m_WebServer.initalServiceFactory, _logger); if (!bSSL) { m_WebServer.server.Listen(iPortNumber); } else { X509Certificate2 cert = GetCertificate(sCertPath, sCertPassWord); m_WebServer.server.Listen(iPortNumber, cert); } aWebservers.Add(m_WebServer); return(true); } //Create the servicefactory for handling each connection m_WebServer.serviceFactory = new MOTR_WebserverFactory(webRoot, _sessions, _users, _dirs, _queue, _admin, _downloads, _logger, this); m_WebServer.serviceFactory.OnRestartWebserver += HandleRestartServer; m_WebServer.server = new WebServer(m_WebServer.serviceFactory, _logger); if (!bSSL) { m_WebServer.server.Listen(iPortNumber); } else { X509Certificate2 cert = GetCertificate(sCertPath, sCertPassWord); m_WebServer.server.Listen(iPortNumber, cert); } aWebservers.Add(m_WebServer); return(true); } catch (Exception ex) { _logger.Error(typeof(WindowsService), ex); return(false); } }
protected override void OnTextFrame(string text) { string jsonText = null; // WebsocketSendClass WSTest2 = new WebsocketSendClass(); // WSTest2.command = "Do this thing"; // WSTest2.aArray = m_Dirs.GetArray(); // WSTest2.count = WSTest2.aArray.Count; // jsonText = fastJSON.JSON.ToJSON(WSTest2); //Just for debugging purposes //Console.WriteLine("Received: " + text); //Every object is linked to this //WebSocketCommandClass WSCommand = (WebSocketCommandClass)fastJSON.JSON.ToObject(text); //Every object is linked to this WebSocketCommandClass WSCommand = new WebSocketCommandClass(); //Try & catch on the parsing try { dynamic WSTemp = fastJSON.JSON.ToDynamic(text); WSCommand.command = WSTemp.command; WSCommand.parameter = WSTemp.parameter; //WSCommand.sessionid = WSTemp.sessionid; } catch (Exception ex) { _logger.Error(typeof(MOTR_AdminWebsocket), "Admin->Error parsing JSON: " + text + " - Returnstring: " + ex.ToString()); return; } //Check if the user is logged in // if (!m_Sessions.SessionLoggedIn(WSCommand.sessionid)) // return; //Just temp info // _logger.Information(typeof(MOTR_AdminWebsocket), "session: " + WSCommand.sessionid); _logger.Information(typeof(MOTR_AdminWebsocket), "command: " + WSCommand.command); //This object is used to send info WebsocketSendClass WSSend = new WebsocketSendClass(); //Return the state of the user trying to log in if (WSCommand.command == "ISLOGGEDIN") { //Store the session for later sSession = WSCommand.parameter; WSSend.command = "LOGGEDIN"; WSSend.aArray = new ArrayList(); WSSend.aArray.Add(m_Admin.IsSessionLoggedIn(sSession)); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); base.Send(jsonText); return; } //Return a ISLOGGEDIN if seesoin it not set if (sSession.Length == 0) { WSSend.command = "ISLOGGEDIN"; WSSend.aArray = new ArrayList(); WSSend.aArray.Add("You need to sens ISLOGGEDIN first"); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); base.Send(jsonText); return; } _logger.Information(typeof(MOTR_AdminWebsocket), "Session trying to admin: " + sSession); //Check password if (WSCommand.command == "LOGIN") { WSSend.command = "LOGIN"; WSSend.aArray = new ArrayList(); WSSend.aArray.Add(m_Admin.CheckAdminPassword(WSCommand.parameter, sSession)); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); base.Send(jsonText); return; } //========================================================================= //Everything below here is not available if not logged in if (!m_Admin.IsSessionLoggedIn(sSession)) { return; } //Return an array of users if (WSCommand.command == "ADDUSER") { //Add the user string[] aInfo = WSCommand.parameter.Split(','); string sUsername = aInfo[0]; string sPassword = aInfo[1]; bool bRet = m_Users.AddUserName(sUsername, sPassword); if (!bRet) { m_Admin.SetErrorString("Username exists or wrong parameters"); } //Send the userlist WSCommand.command = "USERLIST"; } if (WSCommand.command == "CHANGEUSER") { //Add the user string[] aInfo = WSCommand.parameter.Split(','); string sID = aInfo[0]; string sPassword = aInfo[1]; int nID = Convert.ToInt32(sID); WSSend.command = "CHANGEUSER"; WSSend.aArray = new ArrayList(); WSSend.aArray.Add(m_Users.ChangePassword(nID, sPassword)); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); } //Return an array of users if (WSCommand.command == "DELETEUSER") { //Delete the user int nID = Convert.ToInt32(WSCommand.parameter); m_Users.RemoveUser(nID); //Send the userlist back WSCommand.command = "USERLIST"; } //Sends the userlist, just names if (WSCommand.command == "USERLIST") { //Send new userlist WSSend.command = "USERLIST"; WSSend.aArray = m_Users.GetUserArray(); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); } //Adds a directory to the pathslist if (WSCommand.command == "ADMINADDIRECTORY") { string sDisplayName, sPath, sUncUser, sUncPass; string[] sTmp = WSCommand.parameter.Split(','); //Only add if the parameters are correct if (sTmp.Length > 2) { sDisplayName = sTmp[0]; sPath = sTmp[1]; sUncUser = sTmp[2]; sUncPass = sTmp[3]; //Now add the directory m_Dirs.AddDirectory(sDisplayName, sPath, sUncUser, sUncPass); } //Send directories available WSCommand.command = "DIRLIST"; } //Removes a directory and return new dirlist if (WSCommand.command == "ADMINREMOVEDIRECTORY") { //Delete the user int nID = Convert.ToInt32(WSCommand.parameter); m_Dirs.RemoveDirectory(nID); //Send the userlist back WSCommand.command = "DIRLIST"; } //Sends paths list if (WSCommand.command == "DIRLIST") { //Send new userlist WSSend.command = "DIRLIST"; WSSend.aArray = m_Dirs.GetDirsArray(); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); //Console.WriteLine("DIRLIST: " + jsonText); } //Sends drives and network list to the browser if (WSCommand.command == "ADMINDRIVES") { //Send new userlist WSSend.command = "ADMINDRIVES"; WSSend.aArray = m_Admin.GetDrivesAndNetwork(); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); //Console.WriteLine("ADMINDRIVES: " + jsonText); } //Set the drive we are going to browse if (WSCommand.command == "ADMINSETDRIVE") { m_Admin.SetBasePath(WSCommand.parameter); WSCommand.command = "ADMINFILELIST"; } //Set the drive we are going to browse if (WSCommand.command == "ADMINSETPATH") { m_Admin.SetCurrentPath(WSCommand.parameter); WSCommand.command = "ADMINFILELIST"; } //Return the filelist based on the current path if (WSCommand.command == "ADMINFILELIST") { //Send new userlist WSSend.command = "ADMINFILELIST"; WSSend.aArray = m_Admin.GetDirectoryList(); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); //Console.WriteLine("ADMINFILELIST: " + jsonText); } //Set the drive we are going to browse if (WSCommand.command == "ADMINCHECKFORTOOLUPDATE") { //Create return message WSSend.command = "ADMINCHECKFORTOOLUPDATE"; WSSend.aArray = new ArrayList(); //Check if the tool is updated string sTool = WSCommand.parameter; string sLocalVersion = MOTR_Settings.GetCurrentToolVersion(sTool); string sWebVersion = MOTR_Settings.GetWebsiteToolVersion(sTool); if (sLocalVersion != sWebVersion) { WSSend.aArray.Add("Updating " + sTool + " to v" + sWebVersion); bool bRet = MOTR_Settings.UpdateTool(sTool, sWebVersion); if (bRet) { WSSend.aArray.Add(sTool + " updated ok"); } else { WSSend.aArray.Add(sTool + " failed to update"); } } else { WSSend.aArray.Add("Newest version installed for " + sTool); } //Set the number of items added WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); } //Restarts the server with given ports if (WSCommand.command == "ADMINRESTARTSERVER") { //Get ports available string[] ports = WSCommand.parameter.Split(';'); int http = MOTR_Settings.GetNumber("http"); int https = MOTR_Settings.GetNumber("https"); bool bError = false; if (ports.Length > 1) { //Temp store ports to check if changed int httptemp = http; int httpstemp = https; http = Convert.ToInt32(ports[0]); https = Convert.ToInt32(ports[1]); //Check if the ports are available if (httptemp != http) { if (WindowsService.IsPortOpen(http)) { m_Admin.SetErrorString("http port is already taken, please choose another available port"); bError = true; } } if (httpstemp != https) { if (WindowsService.IsPortOpen(https)) { m_Admin.SetErrorString("https port is already taken, please choose another available port"); bError = true; } } } //No error, then we go fishing if (!bError) { //Store the new ports MOTR_Settings.SetNumber("http", http); MOTR_Settings.SetNumber("https", https); //Restart server OnRestartWebserver(this, EventArgs.Empty); } //Send response back to server WSSend.command = "ADMINRESTARTSERVER"; WSSend.aArray = new ArrayList(); WSSend.aArray.Add(bError); WSSend.aArray.Add(http); WSSend.aArray.Add(https); WSSend.count = WSSend.aArray.Count; jsonText = fastJSON.JSON.ToJSON(WSSend); } //Send if the jsonText is set if (jsonText != null) { base.Send(jsonText); } else { _logger.Information(typeof(MOTR_AdminWebsocket), "Unknown admin command from websocket: " + WSCommand.command); WSSend.command = "UNKNOWN"; WSSend.count = 2; WSSend.aArray = new ArrayList(); WSSend.aArray.Add(WSCommand.command); WSSend.aArray.Add(WSCommand.parameter); jsonText = fastJSON.JSON.ToJSON(WSSend); base.Send(jsonText); } //Check if the admin has errors, send it if nessesary if (m_Admin.HasError) { WSSend.command = "ADMINERRORMESSAGE"; WSSend.aArray = new ArrayList(); WSSend.aArray.Add(m_Admin.GetErrorString()); WSSend.count = WSSend.count; jsonText = fastJSON.JSON.ToJSON(WSSend); base.Send(jsonText); } }
//Send text public void Respond() { //Handle requests with a better error than exception ;) if (!File.Exists(sFilePath)) { _logger.Error(this.GetType(), "Binary file does not exist: " + sFilePath); return; } FileInfo fi = new FileInfo(sFilePath); string ext = fi.Extension.ToLower(); string contentType; if (!_mimeTypes.TryGetValue(ext, out contentType)) { contentType = "application/octet-stream"; } long _fileLength = fi.Length; string sFileName = fi.Name; //Checking if we are going todo partial bool bPartial = this.CheckRangeInHeader(sHTTPHeader); //bPartial = true; //Just a test //Set the end to filesize if not set if (bPartial) { if (lRangeStop <= lRangeStart) { lRangeStop = _fileLength; //-1 of filelength is standard of some kind? } } else { lRangeStop = _fileLength; } //Write the header RespondBinaryHeader(_fileLength, sFileName, sFilePath, contentType, bPartial, lRangeStart, lRangeStop, fi.LastWriteTimeUtc); //If we are requested with only head, return now if (bSendHeadOnly) { _logger.Debug(this.GetType(), "Sending only HEAD for the binary file"); return; } else { _logger.Debug(this.GetType(), "Sending binary header from: " + lRangeStart.ToString()); } byte[] SendingBuffer = null; FileStream Fs = new FileStream(sFilePath, FileMode.Open, FileAccess.Read); _logger.Debug(this.GetType(), "Sending binary file: " + sFilePath); //Try to get a BPS value long _start = Environment.TickCount; long _bytesread = 0; try { long lFileLength = Fs.Length; if (bPartial) { lFileLength = lRangeStop - lRangeStart; SeekOrigin seekOrigin; seekOrigin = new SeekOrigin(); if (Fs.CanSeek) { Fs.Seek(lRangeStart, seekOrigin); } } int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(lFileLength) / Convert.ToDouble(BufferSize))); _logger.Debug(this.GetType(), "Binary file packets: " + NoOfPackets.ToString() + " - ispartial: " + bPartial.ToString() + " - From: " + lRangeStart.ToString() + " - To: " + lRangeStop.ToString()); //progressBar1.Maximum = NoOfPackets; long TotalLength = lFileLength, CurrentPacketLength; for (int i = 0; i < NoOfPackets; i++) { if (TotalLength > BufferSize) { CurrentPacketLength = BufferSize; TotalLength = TotalLength - CurrentPacketLength; } else { CurrentPacketLength = TotalLength; } SendingBuffer = new byte[CurrentPacketLength]; Fs.Read(SendingBuffer, 0, Convert.ToInt32(CurrentPacketLength)); _stream.Write(SendingBuffer, 0, SendingBuffer.Length); //Get the Bytes Pr Second _bytesread += CurrentPacketLength; long elapsedMilliseconds = Environment.TickCount - _start; if (elapsedMilliseconds > 4) { // Calculate the current bps. long bps = _bytesread * 1000L / elapsedMilliseconds; _logger.Debug(this.GetType(), "Sending with speed " + PrintNiceBPS(bps) + " - percentage: " + ((double)_bytesread / lFileLength).ToString("0.00%")); } } //Here we are finished with the filereading Fs.Close(); _logger.Debug(this.GetType(), "Finished sending binary file: " + sFilePath); } catch (Exception ex) { _logger.Error(this.GetType(), "HTTPBinarySender: " + ex.Message); } finally { // //_stream.Close(); // //client.Close(); Fs.Close(); _logger.Debug(this.GetType(), "Binarysend: Finally close file"); } }