예제 #1
0
        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;
            }
        }
예제 #2
0
 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);
     }
 }
예제 #3
0
        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);
            }
        }
예제 #4
0
파일: HttpService.cs 프로젝트: large/MOTRd
        //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");
            }
        }
예제 #5
0
/*
 *      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));
        }