Esempio n. 1
0
        private void ServerThread_DoWork(Object args)
        {
            Object[]            arg         = (Object[])args;
            int                 port        = (int)arg[0];
            IPAddress           ifaceip     = (IPAddress)arg[1];
            //Boolean             natt        = (Boolean)arg[2];
            TcpListener         listener    = null;
            List<connection>    clients     = new List<connection>();
			int 				threadsleep = 100;

            listener 						= new TcpListener(ifaceip, port);

            listener.Start();
            while (true)
            {
				// Break loop if cancel pending
				if (_cancel)
				{
					_cancel = false;
					listener.Stop();
					foreach(connection c in clients)
					{
						c.Client.Client.Disconnect(false);
						c.Client.Close();
					}
					clients.Clear();
					return;
				}
				// Establishes new Client connections and adds them to the list to b
				// processed.
				while (listener.Pending())
				{
					TcpClient client = listener.AcceptTcpClient();
					//client.NoDelay = true;
					//client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
					connection tcc = new connection();
					tcc.Client = client;
					tcc.ConnectionEstablished = DateTime.Now;
					clients.Insert(0, tcc);
				}
				// Create a copy to work on instead of working directly on
				// the list.
				connection[] nowclients = clients.ToArray ();
#if DEBUG_CON
				if(nowclients.Length != lastclientc) {
					lastclientc = nowclients.Length;
					Console.Error.WriteLine("Client Connections: " + lastclientc);
				}
#endif

				// This thread has the potential to lock up the whole
				// pc if there are no connections to process. Here
				// we attempt to put in some sleep time if there are
				// no connections. This might require some tweaking.
				if(nowclients.Length > 0)
					threadsleep = 10;
				else
					threadsleep = 500;
                
                try
                {
                    #region Main Loop

                    for (int i = 0; i < nowclients.Length; i++)
                    {
                        // Skip Clients that are processing.
                        if (nowclients[i].processing)
                        {
                            continue;
                        }
						else if(nowclients[i].is_disposed) {
							nowclients[i].Tag = null;
							clients.Remove(nowclients[i]);
						}
                        // Remove clients that have disconnected.
                        else if (!nowclients[i].Client.Connected || nowclients[i].Client.Client.Poll(1, SelectMode.SelectError))
                        {
                            nowclients[i].Close();
                            nowclients[i].Tag = null;
							clients.Remove(nowclients[i]);
                            continue;
                        }
                        // This fires the main process
                        else if (!nowclients[i].processing && !nowclients[i].is_disposed && nowclients[i].data_available)
                        {
                            nowclients[i].processing = true;
                            nowclients[i].lifespans += 1;
                            nowclients[i].ActivityUpdate();
							HandleRequest(nowclients[i]);
                            continue;
						}
						// Disconnect clients that have been idle for too long.
						if(!nowclients[i].processing && (DateTime.Now - nowclients[i].LastActivity) > TimeSpan.FromSeconds(_idle_timeount)) {
							nowclients[i].Close();
							nowclients[i].Tag = null;
							clients.Remove(nowclients[i]);
						}
                    }
                    // Believe it or not this is extremely important.
                    // Without this line, this thread can lock the entire
                    // computer up.
                    Thread.Sleep(threadsleep);

                    #endregion
                }
                catch (Exception ex) 
				{
#if DEBUG
					Console.Error.WriteLine(ex.Message);
					Console.Error.WriteLine(ex.StackTrace);
#endif
					throw ex; 
				}
            }

        }    
Esempio n. 2
0
 public abstract void HandleRequest(connection cc);
Esempio n. 3
0
        public override void HandleRequest(connection cc)
        {
			ParameterizedThreadStart pts = new ParameterizedThreadStart(worker_DoWork);
			Thread t = new Thread(pts);
			t.IsBackground = false;
			t.Priority = ThreadPriority.Normal;
			t.Start(new Object[] { cc,_scripters });
        }
        public static proxied_http_response Create(http_request req, connection con)
        {
            if (req.Header.Values.ContainsKey("Proxy-Connection"))
            {
                String pcon = req.Header.GetValue("Proxy-Connection");

                req.Header.Values.Remove("Proxy-Connection");

                if (String.IsNullOrEmpty(pcon) == false)
                    req.Header.SetValue("Connection", pcon);
            }
            //ALL CUSTOM TAGS MUST BE REMOVED BEFORE SENDING HEADERS.
            //THIS IS FOR ONE TAG, NEEDS TO BE MORE ABSTACT. SUCH AS
            //REMOVE ALL "X-ANYTHING" TAGS. NEED TO FIND A WAY TO DO
            //THIS IN THE HEADER LOGIC POSSIBLY!
            if(req.Header.Values.ContainsKey("X-Profile"))
                req.Header.Values.Remove("X-Profile");
 
            // Formatting the proper header needs to happen before now
            // Correcting Target header.
            if(req.Header.Target.ToLower().StartsWith("http"))
            {
                if(req.Uri.OriginalString.Contains(String.Format("{0}:{1}",req.Uri.Host,req.Uri.Port)))
                {
                    req.Header.Target = req.Uri.OriginalString.Substring(
                    req.Uri.OriginalString.IndexOf(String.Format("{0}:{1}",req.Uri.Host,req.Uri.Port)) +
                    String.Format("{0}:{1}",req.Uri.Host,req.Uri.Port).Length);
                }
                else
                {
                    req.Header.Target = req.Uri.OriginalString.Substring(
                    req.Uri.OriginalString.IndexOf(req.Uri.Host) + req.Uri.Host.Length);
                }
            }
#if !OFFLINE_DEBUG
            if(con.data_available)
            {
#if DEBUG
				byte[] bytes = con.read();
				Console.Error.WriteLine(String.Format("{0}: {1}","EARLY SERVER DATA!",Encoding.Default.GetString(bytes)));
#endif
				proxied_retry_exception ex =
					new proxied_retry_exception(req,"We have not sent a request, yet the server has sent us something! This should not happen ever!",null,502);
				ex.secure = con.stream is SslStream;
				throw ex;
            }
            ///Send Request
            if (con.Client.Connected)
            {
                if (con.Client.Client.Poll(1, SelectMode.SelectWrite) && !con.Client.Client.Poll(1,SelectMode.SelectError))
                {
                    ///req.toByteArray() should be the entire request including POST!
                    byte[] requestbytes = req.ToByteArray();
					try {
	                    con.stream.Write(requestbytes, 0, requestbytes.Length);
	                    con.stream.Flush();
					} catch {
						proxied_retry_exception ex = new proxied_retry_exception(req,"Can not send request upstream!",null,502);
						ex.secure = con.stream is SslStream;
						throw ex;
					}
                }
                else { 
					proxied_retry_exception ex = new proxied_retry_exception(req,"Can not send request upstream!",null,502);
					ex.secure = con.stream is SslStream;
					throw ex;
				}
            }
			else { 
				proxied_retry_exception ex = new proxied_retry_exception(req,"Upstream server disconnected while send request!",null,502);
				ex.secure = con.stream is SslStream;
				throw ex;
			}
            //wait for data
            int count = 0;
            while (!con.is_disposed && !con.data_available && count < 3000 && con.Client.Client.Connected && req.Connection.Client.Connected &&
			       !con.Client.Client.Poll(1, SelectMode.SelectError) && !req.Connection.Client.Poll(1, SelectMode.SelectError)) 
            { 
                //if(server.Client.Poll(100, SelectMode.SelectRead))
                //    throw new Exception("Server connection failed!");
                if(count == 2999) {
					proxied_retry_exception ex = new proxied_retry_exception(req,"Server failed to respond in a timely manner after sending request!",null,502);
					ex.secure = con.stream is SslStream;
					throw ex;
				}
                System.Threading.Thread.Sleep(100); 
                count += 1;
            }
#endif
            proxied_http_response pres = new proxied_http_response();
            pres.Request = req;
            return pres;
            
        }
		public override void Initialize (connection con)
		{
			try {
				base.Initialize (con);
			} catch (Exception ex) {
#if DEBUG 

				if(_request != null)
					Console.Error.WriteLine("Error: " +_request.Uri.ToString());
				Console.Error.WriteLine(ex.Message);
				Console.Error.WriteLine(ex.StackTrace);
#endif
				proxied_retry_exception ex1 = new proxied_retry_exception(
					this.Request,"Response init problem",ex,502);
				ex1.secure = con.stream is SslStream;
				this.Errors.Add(ex1);
				throw ex1;
			}

			if(Header.Statuscode == "408") {
				proxied_retry_exception ex = new proxied_retry_exception(
					this.Request,"Server replied with 'bad request'",null,408);
				ex.secure = con.stream is SslStream;
				this.Errors.Add(ex);
				throw ex;
			}
		}
Esempio n. 6
0
		public virtual void           Initialize(connection con)
		{
			_connection                 = con.Client;
			_neworkStream               = con.stream;
			_neworkStream.WriteTimeout  = 10000;
			_neworkStream.ReadTimeout   = 10000;

			int         headersplit     = -1;
			Boolean     headerfound     = false;
			long        ContentLength   = -1;
			int         constpasses     = 0;
			byte[]      readbytes       = null;
			List<byte>  allbytes		= new List<byte>();

			while (con.Client.Connected && !con.Client.Client.Poll(1, SelectMode.SelectError))
			{
				if (_cancel)
					break;

				if (con.data_available)
				{
					//find the header first. Due to wacky initialization bytes are stored globally until header is found;
					readbytes = con.read();

					if (headerfound == false)
					{
						allbytes.AddRange(readbytes);

						//check for header!
						headersplit = http_function.FindHeaderBodySplit(allbytes.ToArray());
						if (headersplit > 0)
						{
							//Creates the header object and writes the intital
							//bytes to body if there are any
							HandleInitialBytes(allbytes.ToArray(),headersplit);
							CreateUri();
							headerfound = true;


							//Optimizations based on header
							// I can't measure how effective they are... yet.

							//Post data is not included in a head or get request.
							//So we know we are done regardless of the
							//Content-Length.
							if(_header.Verb == "GET" || _header.Verb == "CONNECT" || _header.Verb == "HEAD" )
								_cancel = true;

							//If we have a Content-Length then we have a definate
							//place to end the read.
							if (_header.Values.ContainsKey("Content-Length"))
							{
								ContentLength = Convert.ToInt64(_header.Values["Content-Length"]);
								if(ContentLength == 0)
									_cancel = true;
								//_timeOut = _timeOut * 2;
							}

							//Allow a little more time for the server to process post data
							//Might come in handy when uploading files.
							if (_header.Verb == "POST") {
								if(!_header.Values.ContainsKey("Content-Length"))
								{
									http_exception ex = new http_exception(this,"Content-Length is mandatory!",null,411);
									ex.add_header("Connection","close");
									throw ex;
								}
								//_timeOut = _timeOut * 2;
							}

							if(!string.IsNullOrEmpty(_header.Verb) && string.IsNullOrEmpty(this.Host)) {
								throw new Exception("request requires a host!");
							}

							//When there is a transfer-encoding there is usually no
							//Content-Length and the file size is unknown so
							//there is no exact point where we no we can end this read
							//For good measure we are giving a little more time.
							//if (_header.Values.ContainsKey("Transfer-Encoding"))
							//    if (_header.GetValue("Transfer-Encoding").ToLower() == "chunked")
							//        _timeOut = _timeOut * 2;
						}
					}

					else //headerfound == false
					{
						// Make sure that bytes is not empty very important.
						if (readbytes.Length > 0)
						{
							//Writing bytes to body file!
							AppendBytesToFile(readbytes);
							// Part of a hard timeout implemented as a death counter
							// in ProxyTransaction.
							if(Activity!=null){Activity(this,new EventArgs());}
							constpasses = 0;

						}
					}
				}
				else //client.Available <= 0
				{

					if (headerfound)
					{
						if (ContentLength == 0 )
						{
							_cancel = true;

						}
						//There is a Content-Length and it's greater than 0 but Body.Length is
						//less than Content-Length. Basically we are in mid-transfer
						else if (ContentLength > 0)
						{
							if (Body.Length < ContentLength)
							{
								Thread.Sleep(10);
								constpasses = constpasses + 1;
							} 
							else if(Body.Length == ContentLength) {
								_cancel = true;
							}
						}
						//There is no Content-Length so we are using the timeout.
						else if(ContentLength < 0)
						{
							if(_header.Httpversion == "HTTP/1.0")
								_cancel = true;
							Thread.Sleep(10);
							constpasses = constpasses + 1;
						}
					}
					else {
						Thread.Sleep(10);
						constpasses = constpasses +1;
					}
					//Checking for timeout situation.
					if (constpasses >= (_timeOut / 10))
					{
						Exception ex = new Exception("Read Timeout!");
						_errors.Add(ex);
						//if (ReadTimeOut != null) { ReadTimeOut(this, new EventArgs()); }
						//throw ex;
						_cancel = true;
					}
				}
			}
			if(! headerfound && _header.Connection.ToLower() != "close")
				if(!con.Client.Client.Connected || con.Client.Client.Poll(1, SelectMode.SelectError))
					throw new Exception("hr: Client Disconnected!");

			if(headerfound && _header != null && _header.Verb != "HEAD" && _header.Statuscode != " 206" && _header.Values.ContainsKey("Content-Length")) {
				if(Convert.ToInt32(_body.Length) != _header.ContentLength) {
#if DEBUG
					Console.Error.WriteLine(String.Format("Entity size mismatch {0}/{1}",_header.ContentLength,_body.Length));
#endif
					_header.ContentLength = Convert.ToInt32(_body.Length);
				}
			}

			if (headerfound == false || _header == null)
			{
				if(allbytes.Count == 0)
				{
					throw new Exception("Zero bytes have been recieved!");

				}
				else
				{
					throw new Exception("The request/response did not seem to have the http head/body dilimeter (CRLFCRLF)");
				}
			}
		}