protected override void PerformHandshake(Stream stream) { string header = _header; try { Regex webSocketKeyRegex = new Regex("Sec-WebSocket-Key: (.*)"); Regex webSocketVersionRegex = new Regex("Sec-WebSocket-Version: (.*)"); // check the version. Support version 13 and above const int WebSocketVersion = 13; int secWebSocketVersion = Convert.ToInt32(webSocketVersionRegex.Match(header).Groups[1].Value.Trim()); if (secWebSocketVersion < WebSocketVersion) { throw new WebSocketVersionNotSupportedException(string.Format("WebSocket Version {0} not suported. Must be {1} or above", secWebSocketVersion, WebSocketVersion)); } string secWebSocketKey = webSocketKeyRegex.Match(header).Groups[1].Value.Trim(); string setWebSocketAccept = base.ComputeSocketAcceptString(secWebSocketKey); string response = ("HTTP/1.1 101 Switching Protocols" + Environment.NewLine + "Connection: Upgrade" + Environment.NewLine + "Upgrade: websocket" + Environment.NewLine + "Sec-WebSocket-Accept: " + setWebSocketAccept); HttpHelper.WriteHttpHeader(response, stream); _logger.Debug(this.GetType(), "Web Socket handshake sent"); } catch (WebSocketVersionNotSupportedException ex) { string response = "HTTP/1.1 426 Upgrade Required" + Environment.NewLine + "Sec-WebSocket-Version: 13"; HttpHelper.WriteHttpHeader(response, stream); throw; } catch (Exception ex) { HttpHelper.WriteHttpHeader("HTTP/1.1 400 Bad Request høtt", stream); throw; } }
public void Listen(int port, X509Certificate2 sslCertificate) { try { _sslCertificate = sslCertificate; IPAddress localAddress = IPAddress.Any; _listener = new TcpListener(localAddress, port); _listener.Start(); if (sslCertificate == null) { _logger.Debug(this.GetType(), string.Format("Server started listening on port {0} for http", port)); } else { _logger.Debug(this.GetType(), string.Format("Secure server started listening on port {0} using cert for https", port)); } StartAccept("void Webserver:Listen with cert param"); } catch (SocketException ex) { string message = string.Format("Error listening on port {0}. Make sure IIS or another application is not running and blocking your portselection.", port); throw new ServerListenerSocketException(message, ex); } }
public MOTR_WebserverFactory(string webRoot, MOTR_Sessions sessions, MOTR_Users users, MOTR_Dirs dirs, MOTR_Queue queue, MOTR_Admin _admin, MOTR_Downloads _downloads, IWebSocketLogger logger, MOTR_Webserver _webserver) { _logger = logger; _webRoot = string.IsNullOrWhiteSpace(webRoot) ? GetWebRoot() : webRoot; m_Sessions = sessions; m_Users = users; m_Dirs = dirs; m_Queue = queue; m_WebServer = _webserver; m_Admin = _admin; m_Downloads = _downloads; if (!Directory.Exists(_webRoot)) { _logger.Warning(this.GetType(), "Web root not found: {0}", _webRoot); } else { _logger.Debug(this.GetType(), "Web root: " + _webRoot); } }
//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"); } }
/* * private LoginReturn LoginValid(string sHeader) * { * //Hent ut info fra svaret * int iLength = GetContentLength(sHeader); * int nEndPos = sHeader.IndexOf("\r\n\r\n"); * if (nEndPos+4 > (sHeader.Length - iLength)) * { * Console.WriteLine("No userdata ffs: " + sHeader); * return LoginReturn.NO_CONTENT; * } * string sPostData = sHeader.Substring(sHeader.Length - iLength); * _logger.Information(typeof(MOTR_WebserverFactory), "Header in POST: " + sHeader); * _logger.Information(typeof(MOTR_WebserverFactory), "PostData: " + sPostData); * * //Data needs to be at least u=x&p=x * if (sPostData.Length < 7) * return LoginReturn.NOT_LOGGED_IN; * * //Split the chars * char[] delimiterChars = { '=', '&'}; * string[] verbs= sPostData.Split(delimiterChars); * * //Fill username and password * string sUsername=""; * string sPassword=""; * for(int i=0;i<verbs.Count();i++) * { * //Find username * if (verbs[i].ToUpper() == "U") * if(verbs.Count() > i+1) * sUsername = verbs[i + 1]; * if (verbs[i].ToUpper() == "P") * if (verbs.Count() > i + 1) * sPassword = verbs[i + 1]; * } * * //Console.WriteLine("Username: "******"Password: "******"/directory") { MOTR_DirectoryWebsocket pWS = new MOTR_DirectoryWebsocket(connectionDetails.Stream, connectionDetails.TcpClient, connectionDetails.Header, _logger, m_Sessions, m_Dirs, m_Queue, m_Users, m_Downloads); pWS.OnQueueUpdate += m_WebServer.HandleEvent; return(pWS); } if (connectionDetails.Path == "/admin") { MOTR_AdminWebsocket pWS = new MOTR_AdminWebsocket(connectionDetails.Stream, connectionDetails.TcpClient, connectionDetails.Header, _logger, m_Sessions, m_Dirs, m_Users, m_Admin); pWS.OnRestartWebserver += this.OnRestartWebserver; return(pWS); } break; case ConnectionType.Http: // this path actually refers to the reletive location of some html file or image string extension = connectionDetails.Path; //_logger.Information(this.GetType(), "Header: {0}", connectionDetails.Header); //_logger.Information(this.GetType(), "Path: {0}", connectionDetails.Path); if (extension.Length > 4) { extension = extension.Substring(extension.Length - 4); extension = extension.ToUpper(); string sIP = connectionDetails.TcpClient.Client.RemoteEndPoint.ToString(); //_logger.Information(this.GetType(), "IP adress: {0}", sIP); } //Special extension for our file if (extension == "MOTR" || extension == "LOAD") { //_logger.Information(this.GetType(), "Handling MOTR or LOAD: " + extension); //Sjekk at brukeren er logget inn (SessionID = gullgutten), TempID er for å sette gullgutten ;) string sSessionID = GetCookie(connectionDetails.Header, "SessionID"); if (sSessionID.Length > 0) { if (!m_Sessions.SessionLoggedIn(sSessionID, "[WEBBASEDAUTH, NOT USER]")) { return(new HttpRedirectService(connectionDetails.Stream, "/", connectionDetails.Path, "[DELETE]", _logger)); } else if (GetCookie(connectionDetails.Header, "TempID").Length > 0) { return(new HttpRedirectService(connectionDetails.Stream, connectionDetails.Path, connectionDetails.Path, sSessionID, _logger)); } } else //Just forward when we don't have any session { string sTempID = GetCookie(connectionDetails.Header, "TempID"); if (sTempID.Length == 0) { return(new HttpRedirectService(connectionDetails.Stream, "/", connectionDetails.Path, "", _logger)); } else { //Get the session, if it is real, set the session to login sSessionID = m_Sessions.GetSessionByTempID(sTempID); if (sSessionID.Length == 0) { return(new HttpRedirectService(connectionDetails.Stream, "/", connectionDetails.Path, "", _logger)); } else { return(new HttpRedirectService(connectionDetails.Stream, connectionDetails.Path, connectionDetails.Path, sSessionID, _logger)); } } } //Sjekk om det er utlogging som skal foregå bool bRemoveCookies = false; if (connectionDetails.Path.ToUpper().Contains("LOGOFF.MOTR")) { //Slett sesjonen fra listen, la parseren håndtere resten m_Sessions.RemoveSession(sSessionID); bRemoveCookies = true; } //Her skal vi parse fila før vi sender avgårde html'n... if (extension == "MOTR") //Ignore if we are going to remove cookies, normally logging out { MOTR_Parser m_Parser = new MOTR_Parser(_logger, sSessionID, m_Sessions); return(new HttpTextService(connectionDetails.Stream, m_Parser.ParseFile(_webRoot + connectionDetails.Path), _logger, bRemoveCookies)); } else //Handling "DOWN.LOAD" { string[] aTemp = connectionDetails.Path.Split('/'); if (aTemp.Count() > 0) { string nID = aTemp[1]; string sPath = m_Sessions.GetTemporaryVariable(sSessionID, "DrivePosition"); string sFile = m_Sessions.GetPathByID(sSessionID, Convert.ToInt32(nID)); string sOneHour = DateTime.Now.AddHours(1).ToString(); string sDownloadID = m_Downloads.AddDownload(sSessionID, sPath + sFile, false, sOneHour); return(new HttpRedirectService(connectionDetails.Stream, "/MOTR-download/" + sDownloadID + "/" + sFile, "", "", _logger)); } else { return(new HttpTextService(connectionDetails.Stream, "Did not provide correct nID for file", _logger)); } } } //Here we handle the tag "/motr-download/" to ensure we download the file binary if (connectionDetails.Path.Contains("/MOTR-download/")) { //Check if we have a session (This blocks several clients, temp disabled) //string sSessionID = GetCookie(connectionDetails.Header, "SessionID"); //if(sSessionID.Length == 0) // return new HttpTextService(connectionDetails.Stream, "Session is no longer valid, unable to download", _logger); string[] aDownloads = connectionDetails.Path.Split('/'); string sDownloadID = ""; if (aDownloads.Count() > 2) { sDownloadID = aDownloads[2]; } if (sDownloadID.Length > 0) { //Get the filename //string sFileName = connectionDetails.Path.Substring(connectionDetails.Path.LastIndexOf('/') + 1); string sFileName = m_Downloads.GetDownload(sDownloadID); //No filename, no love... if (sFileName.Length == 0) { _logger.Warning(typeof(MOTR_WebserverFactory), "Download is no longer valid..."); return(new BadRequestService(connectionDetails.Stream, connectionDetails.Header, _logger)); } sFileName = Uri.UnescapeDataString(sFileName); if (connectionDetails != null) { if (connectionDetails.Header != null) { _logger.Debug(typeof(MOTR_WebserverFactory), "MOTR-download: " + WebUtility.HtmlDecode(connectionDetails.Header)); } } //This is where the file actually is //string sBasePath = m_Sessions.GetTemporaryVariable(sSessionID, "DrivePosition"); //return new HttpBinaryService(connectionDetails.Stream, sBasePath + sFileName, _logger); return(new HttpBinaryService(connectionDetails.Stream, sFileName, _webRoot, connectionDetails.Header, _logger)); } } //END: /MOTR-download else if (connectionDetails.Path.Contains("/kodi/")) //Kodi directory is special { extension = extension.ToUpper(); if (extension == ".ZIP") { return(new HttpBinaryService(connectionDetails.Stream, _webRoot + connectionDetails.Path, _webRoot, connectionDetails.Header, _logger)); } } else if (connectionDetails.Path.Contains("/MovieInfo/")) //Kodi directory is special { int nSlashPos = connectionDetails.Path.LastIndexOf('/'); string sImageName = connectionDetails.Path.Substring(nSlashPos, connectionDetails.Path.Length - (nSlashPos)); sImageName = sImageName.Substring(1, sImageName.Length - 1); sImageName = sImageName.Replace("..", ""); sImageName = sImageName.Replace("%", ""); string movieInfoPath = MOTR_Settings.GetGlobalApplicationPath("MovieImages"); return(new HttpBinaryService(connectionDetails.Stream, movieInfoPath + sImageName, _webRoot, connectionDetails.Header, _logger)); } //Redirect to front page on initalsetup if (connectionDetails.Path.Contains("/initalsetup/")) { return(new HttpRedirectService(connectionDetails.Stream, "/", connectionDetails.Path, "", _logger)); } //Everything else is served here (but limited to the mimelist...) return(new HttpService(connectionDetails.Stream, connectionDetails.Path, _webRoot, _logger)); case ConnectionType.Head: //Only handle MOTR-download on head requests //_logger.Information(typeof(MOTR_WebserverFactory), "HEAD: " + connectionDetails.Header); if (connectionDetails.Path.Contains("/MOTR-download/")) { string[] aDownloads = connectionDetails.Path.Split('/'); string sDownloadID = ""; if (aDownloads.Count() > 2) { sDownloadID = aDownloads[2]; } if (sDownloadID.Length > 0) { string sFileName = m_Downloads.GetDownload(sDownloadID, true); return(new HttpBinaryService(connectionDetails.Stream, sFileName, _webRoot, connectionDetails.Header, _logger, true)); //True is head only! } } else if (connectionDetails.Path.Contains("/kodi/")) //Kodi directory is special { return(new HttpBinaryService(connectionDetails.Stream, _webRoot + connectionDetails.Path, _webRoot, connectionDetails.Header, _logger, true)); //True is head only! } else if (connectionDetails.Path.Contains("/MovieInfo/")) //Kodi directory is special { int nSlashPos = connectionDetails.Path.LastIndexOf('/'); string sImageName = connectionDetails.Path.Substring(nSlashPos, connectionDetails.Path.Length - (nSlashPos)); sImageName = sImageName.Substring(1, sImageName.Length - 1); sImageName = sImageName.Replace("..", ""); sImageName = sImageName.Replace("%", ""); string movieInfoPath = MOTR_Settings.GetGlobalApplicationPath("MovieImages"); return(new HttpBinaryService(connectionDetails.Stream, movieInfoPath + sImageName, _webRoot, connectionDetails.Header, _logger, true)); //True is head only! } //Redirect to front page on initalsetup _logger.Warning(typeof(MOTR_WebserverFactory), "Head requested, not supported for all paths: " + connectionDetails.Header); return(new BadRequestService(connectionDetails.Stream, connectionDetails.Header, _logger)); //return new HttpTextService(connectionDetails.Stream, "HEAD is not supported", _logger); } return(new BadRequestService(connectionDetails.Stream, connectionDetails.Header, _logger)); }