Beispiel #1
0
 public virtual HandlerThread GetHandlerThread(ClientInfo info)
 {
     return new HandlerThread (info);
 }
Beispiel #2
0
 internal void ClientClosed(ClientInfo ci)
 {
     clients.Remove (ci);
 }
Beispiel #3
0
 void DoProcess(ClientInfo ci)
 {
     ClientData data = (ClientData)ci.Data;
     string sessid = (string)data.req.Cookies ["_sessid"];
     if (sessid != null)
         data.req.Session = (Session)sessions [sessid];
     bool closed = Process (ci, data.req);
     data.state = closed ? ClientState.Closed : ClientState.Header;
     data.read = 0;
     HttpRequest oldreq = data.req;
     data.req = new HttpRequest ();
     // Once processed, the connection will be used for a new request
     data.req.Session = oldreq.Session;
     // ... but session is persisted
     data.req.From = ((IPEndPoint)ci.Socket.RemoteEndPoint).Address;
 }
Beispiel #4
0
        void SendResponse(ClientInfo ci, HttpRequest req, HttpResponse resp, bool close)
        {
            StringBuilder builder = new StringBuilder ();
            // Create Headers
            builder.Append ("HTTP/1.0 ");
            builder.Append (resp.ReturnCode);
            builder.Append (Responses [resp.ReturnCode]);
            builder.Append ("\r\nDate: ");
            builder.Append (DateTime.Now.ToString ("R"));
            builder.Append ("\r\nServer: UnityEmbedded/1.0 (iOS)");
            //builder.Append ("\r\nConnection: ");
            //builder.Append ((close ? "close" : "Keep-Alive"));

            if (resp.RawContent == null) {
                builder.Append ("\r\nContent-Length: ");
                builder.Append (resp.Content.Length);
            } else {
                builder.Append ("\r\nContent-Length: ");
                builder.Append (resp.RawContent.Length);
            }

            builder.Append ("\r\nContent-Encoding: utf-8");
            builder.Append ("\r\nContent-Type: ");

            builder.Append (resp.ContentType);

            // ADDING CUSTOM HEADERS(new feature)
            if (!CUSTOM_RESPONSE_HEADERS.StartsWith ("$"))
                builder.Append (CUSTOM_RESPONSE_HEADERS);

            if (req.Session != null) {
                builder.Append ("\r\nSet-Cookie: _sessid=");
                builder.Append (req.Session.ID);
                builder.Append ("; path=/");
            }

            foreach (DictionaryEntry de in resp.Header) {
                builder.Append ("\r\n");
                builder.Append (de.Key);
                builder.Append (": ");
                builder.Append (de.Value);
            }
            builder.Append ("\r\n\r\n");

            // Send Header
            ci.Send (builder.ToString ());

            // Send Body
            if (resp.RawContent != null) {
                ci.Send (resp.RawContent);
            } else {
                ci.Send (resp.Content);
            }

            // Close if not persistent connection
            if (close) {
                ci.Close ();
            }
        }
Beispiel #5
0
        void ClientRead(ClientInfo ci, string text)
        {
            // Read header, if in right state
            ClientData data = (ClientData)ci.Data;
            if (data.state != ClientState.Header)
                return;
            // already done; must be some text in content, which will be handled elsewhere
            text = text.Substring (data.headerskip);

            data.headerskip = 0;
            string[] lines = text.Replace ("\r\n", "\n").Split ('\n');
            data.req.HeaderText = text;
            // First line: METHOD /path/url HTTP/version
            string[] firstline = lines [0].Split (' ');
            if (firstline.Length != 3) {
                SendResponse (ci, data.req, new HttpResponse (400, "Incorrect first header line " + lines [0]), true);
                return;
            }
            if (firstline [2].Substring (0, 4) != "HTTP") {
                SendResponse (ci, data.req, new HttpResponse (400, "Unknown protocol " + firstline [2]), true);
                return;
            }
            data.req.Method = firstline [0];
            data.req.Url = firstline [1];
            data.req.HttpVersion = firstline [2].Substring (5);
            int p;
            for (int i = 1; i < lines.Length; i++) {
                p = lines [i].IndexOf (':');
                if (p > 0)
                    data.req.Header [lines [i].Substring (0, p)] = lines [i].Substring (p + 2);
            }
            // If ? in URL, split out query information
            p = firstline [1].IndexOf ('?');
            if (p > 0) {
                data.req.Page = data.req.Url.Substring (0, p);
                data.req.QueryString = data.req.Url.Substring (p + 1);
            } else {
                data.req.Page = data.req.Url;
                data.req.QueryString = "";
            }

            if (data.req.Page.IndexOf ("..") >= 0) {
                SendResponse (ci, data.req, new HttpResponse (400, "Invalid path"), true);
                return;
            }

            data.req.Host = (string)data.req.Header ["Host"];
            if (null == data.req.Host) {
                SendResponse (ci, data.req, new HttpResponse (400, "No Host specified"), true);
                return;
            }

            if (null != data.req.Header ["Cookie"]) {
                string[] cookies = ((string)data.req.Header ["Cookie"]).Split (';');
                foreach (string cookie in cookies) {
                    p = cookie.IndexOf ('=');
                    if (p > 0) {
                        data.req.Cookies [cookie.Substring (0, p).Trim ()] = cookie.Substring (p + 1);
                    } else {
                        data.req.Cookies [cookie.Trim ()] = "";
                    }
                }
            }

            if (null == data.req.Header ["Content-Length"])
                data.req.ContentLength = 0;
            else
                data.req.ContentLength = Int32.Parse ((string)data.req.Header ["Content-Length"]);

            //if(data.req.ContentLength > 0){
            data.state = ClientState.PreContent;
            data.skip = text.Length + 4;
            //} else DoProcess(ci);

            //ClientReadBytes(ci, new byte[0], 0); // For content length 0 body
        }
Beispiel #6
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ci"></param>
        /// <param name="bytes"></param>
        /// <param name="len"></param>
        void ClientReadBytes(ClientInfo ci, byte[] bytes, int len)
        {
            //CleanUpSessions ();
            int ofs = 0;
            ClientData data = (ClientData)ci.Data;
            switch (data.state) {
            case ClientState.Content:
                break;
            case ClientState.PreContent:
                data.state = ClientState.Content;
                if ((data.skip - data.read) > len) {
                    data.skip -= len;
                    return;
                }
                ofs = data.skip - data.read;
                data.skip = 0;
                break;
            default:
                //case ClientState.Header: data.read += len - data.headerskip; return;
                data.read += len;
                return;
            }
            //data.req.Content += Encoding.Default.GetString (bytes, ofs, len - ofs);
            data.req.Content += Encoding.UTF8.GetString (bytes, ofs, len - ofs);
            data.req.BytesRead += len - ofs;
            data.headerskip += len - ofs;

            if (data.req.BytesRead >= data.req.ContentLength) {
                if (data.req.Method == "POST") {
                    if (data.req.QueryString == "")
                        data.req.QueryString = data.req.Content;
                    else
                        data.req.QueryString += "&" + data.req.Content;
                }
                ParseQuery (data.req);
                DoProcess (ci);
            }
        }
Beispiel #7
0
 //static long tTotal;
 protected virtual bool Process(ClientInfo ci, HttpRequest req)
 {
     //long tIn = DateTime.Now.Ticks;
     HttpResponse resp = new HttpResponse ();
     resp.Url = req.Url;
     for (int i = handlers.Count - 1; i >= 0; i--) {
         IHttpHandler handler = (IHttpHandler)handlers [i];
         if (handler.Process (this, req, resp)) {
             SendResponse (ci, req, resp, resp.ReturnCode != 200);
             //tTotal += DateTime.Now.Ticks - tIn;
             //Console.WriteLine ("Total: " + tTotal + " ticks");
             return resp.ReturnCode != 200;
         }
     }
     return true;
 }
 public override HandlerThread GetHandlerThread(ClientInfo info)
 {
     return new IPhoneHandlerThread(info);
 }
Beispiel #9
0
        void SendResponse(ClientInfo ci, HttpRequest req, HttpResponse resp, bool close)
        {
            StringBuilder builder = new StringBuilder();

            // Create Headers
            builder.Append("HTTP/1.0 ");
            builder.Append(resp.ReturnCode);
            builder.Append(Responses [resp.ReturnCode]);
            builder.Append("\r\nDate: ");
            builder.Append(DateTime.Now.ToString("R"));
            builder.Append("\r\nServer: UnityEmbedded/1.0 (iOS)");
            //builder.Append ("\r\nConnection: ");
            //builder.Append ((close ? "close" : "Keep-Alive"));

            if (resp.RawContent == null)
            {
                builder.Append("\r\nContent-Length: ");
                builder.Append(resp.Content.Length);
            }
            else
            {
                builder.Append("\r\nContent-Length: ");
                builder.Append(resp.RawContent.Length);
            }

            builder.Append("\r\nContent-Encoding: utf-8");
            builder.Append("\r\nContent-Type: ");

            builder.Append(resp.ContentType);

            // ADDING CUSTOM HEADERS(new feature)
            if (!CUSTOM_RESPONSE_HEADERS.StartsWith("$"))
            {
                builder.Append(CUSTOM_RESPONSE_HEADERS);
            }

            if (req.Session != null)
            {
                builder.Append("\r\nSet-Cookie: _sessid=");
                builder.Append(req.Session.ID);
                builder.Append("; path=/");
            }

            foreach (DictionaryEntry de in resp.Header)
            {
                builder.Append("\r\n");
                builder.Append(de.Key);
                builder.Append(": ");
                builder.Append(de.Value);
            }
            builder.Append("\r\n\r\n");

            // Send Header
            ci.Send(builder.ToString());

            // Send Body
            if (resp.RawContent != null)
            {
                ci.Send(resp.RawContent);
            }
            else
            {
                ci.Send(resp.Content);
            }

            // Close if not persistent connection
            if (close)
            {
                ci.Close();
            }
        }
Beispiel #10
0
 internal ClientData(ClientInfo ci)
 {
     req.From = ((IPEndPoint)ci.Socket.RemoteEndPoint).Address;
 }
Beispiel #11
0
        void ClientRead(ClientInfo ci, string text)
        {
            // Read header, if in right state
            ClientData data = (ClientData)ci.Data;

            if (data.state != ClientState.Header)
            {
                return;
            }
            // already done; must be some text in content, which will be handled elsewhere
            text = text.Substring(data.headerskip);

            data.headerskip = 0;
            string[] lines = text.Replace("\r\n", "\n").Split('\n');
            data.req.HeaderText = text;
            // First line: METHOD /path/url HTTP/version
            string[] firstline = lines [0].Split(' ');
            if (firstline.Length != 3)
            {
                SendResponse(ci, data.req, new HttpResponse(400, "Incorrect first header line " + lines [0]), true);
                return;
            }
            if (firstline [2].Substring(0, 4) != "HTTP")
            {
                SendResponse(ci, data.req, new HttpResponse(400, "Unknown protocol " + firstline [2]), true);
                return;
            }
            data.req.Method      = firstline [0];
            data.req.Url         = firstline [1];
            data.req.HttpVersion = firstline [2].Substring(5);
            int p;

            for (int i = 1; i < lines.Length; i++)
            {
                p = lines [i].IndexOf(':');
                if (p > 0)
                {
                    data.req.Header [lines [i].Substring(0, p)] = lines [i].Substring(p + 2);
                }
            }
            // If ? in URL, split out query information
            p = firstline [1].IndexOf('?');
            if (p > 0)
            {
                data.req.Page        = data.req.Url.Substring(0, p);
                data.req.QueryString = data.req.Url.Substring(p + 1);
            }
            else
            {
                data.req.Page        = data.req.Url;
                data.req.QueryString = "";
            }

            if (data.req.Page.IndexOf("..") >= 0)
            {
                SendResponse(ci, data.req, new HttpResponse(400, "Invalid path"), true);
                return;
            }

            data.req.Host = (string)data.req.Header ["Host"];
            if (null == data.req.Host)
            {
                SendResponse(ci, data.req, new HttpResponse(400, "No Host specified"), true);
                return;
            }

            if (null != data.req.Header ["Cookie"])
            {
                string[] cookies = ((string)data.req.Header ["Cookie"]).Split(';');
                foreach (string cookie in cookies)
                {
                    p = cookie.IndexOf('=');
                    if (p > 0)
                    {
                        data.req.Cookies [cookie.Substring(0, p).Trim()] = cookie.Substring(p + 1);
                    }
                    else
                    {
                        data.req.Cookies [cookie.Trim()] = "";
                    }
                }
            }

            if (null == data.req.Header ["Content-Length"])
            {
                data.req.ContentLength = 0;
            }
            else
            {
                data.req.ContentLength = Int32.Parse((string)data.req.Header ["Content-Length"]);
            }

            //if(data.req.ContentLength > 0){
            data.state = ClientState.PreContent;
            data.skip  = text.Length + 4;
            //} else DoProcess(ci);

            //ClientReadBytes(ci, new byte[0], 0); // For content length 0 body
        }
Beispiel #12
0
 internal ClientData(ClientInfo ci)
 {
     req.From = ((IPEndPoint)ci.Socket.RemoteEndPoint).Address;
 }
 public HandlerThread(ClientInfo ci)
 {
     this.clientInfo = ci;
 }
Beispiel #14
0
 internal void KeyExchangeComplete(ClientInfo ci)
 {
     // Key exchange is complete on this client. Client ready
     // handlers may still force a close of the connection
     if (ClientReady != null)
     if (!ClientReady (this, ci))
         ci.Close ();
 }
Beispiel #15
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        /*
        public Session RequestSession (HttpRequest req)
        {
            if (req.Session != null) {
                if (sessions[req.Session.ID] == req.Session)
                    return req.Session;
            }
            req.Session = new Session (req.From);
            sessions[req.Session.ID] = req.Session;
            return req.Session;
        }
        */
        /// <summary>
        /// 
        /// </summary>
        /*
        void CleanUpSessions (bool unconditionally)
        {
            ICollection keys = sessions.Keys;
            ArrayList toRemove = new ArrayList ();
            foreach (string k in keys) {
                Session s = (Session)sessions[k];
                int time = (int)((DateTime.Now - s.LastTouched).TotalSeconds);
                if ((time > sessionTimeout) || unconditionally) {
                    toRemove.Add (k);
                }
            }
            foreach (object k in toRemove)
                sessions.Remove (k);
        }

        void CleanUpSessions ()
        {
            CleanUpSessions (false);
        }
        */
        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        /// <param name="ci"></param>
        /// <returns></returns>
        bool ClientConnect(Server s, ClientInfo ci)
        {
            ci.Delimiter = "\r\n\r\n";
            ci.Data = new ClientData (ci);
            ci.OnRead += new ConnectionRead (ClientRead);
            ci.OnReadBytes += new ConnectionReadBytes (ClientReadBytes);
            return true;
        }
Beispiel #16
0
        // ASYNC CALLBACK CODE
        void AcceptCallback(IAsyncResult ar)
        {
            try {
                Socket server = (Socket)ar.AsyncState;
                Socket cs = server.EndAccept (ar);

                // Start the thing listening again
                server.BeginAccept (new AsyncCallback (AcceptCallback), server);

                ClientInfo c = new ClientInfo (cs, null, null, ClientDirection.Both, false);
                c.server = this;
                // Allow the new client to be rejected by the application
                if (Connect != null) {
                    if (!Connect (this, c)) {
                        // Rejected
                        cs.Close ();
                        return;
                    }
                }
                // Initiate key exchange
                c.EncryptionType = encType;
                switch (encType) {
                case EncryptionType.None:
                    KeyExchangeComplete (c);
                    break;
                /*
                case EncryptionType.ServerKey:
                    c.encKey = GetSymmetricKey ();
                    byte[] key = ClientInfo.GetLengthEncodedVector (c.encKey);
                    cs.Send (key);
                    c.MakeEncoders ();
                    KeyExchangeComplete (c);
                    break;
                case EncryptionType.ServerRSAClientKey:
                    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider ();
                    RSAParameters p = rsa.ExportParameters (true);
                    cs.Send (ClientInfo.GetLengthEncodedVector (p.Modulus));
                    cs.Send (ClientInfo.GetLengthEncodedVector (p.Exponent));
                    c.encParams = p;
                    break;
                */
                default:
                    throw new ArgumentException ("Unknown or unsupported encryption type " + encType);
                }
                clients.Add (c);

            #if MONOTOUCH
                GetHandlerThread(c).Start();
            #else
                c.BeginReceive ();
            #endif

            } catch (ObjectDisposedException) {
            } catch (SocketException) {
            } catch (Exception e) {
                SystemLogger.Log (SystemLogger.Module .CORE, null, e);
            }
        }
 public IPhoneHandlerThread(ClientInfo ci)
     : base(ci)
 {
 }