private void socket_event_Socket_Data_Closed_by_Remote_Side(easy_socket.tcp.Socket_Data sender, EventArgs e)
 {
     this.ConnectionState = PROXY_CONNECTION_STATE.CLOSED;
     this.hevt_remotely_closed.Set();
     if (this.event_ClassProxy_Closed_by_Remote_Side != null)
     {
         this.event_ClassProxy_Closed_by_Remote_Side(this, e);
     }
 }
 private void socket_event_Socket_Data_Connected_To_Remote_Host(easy_socket.tcp.Socket_Data sender, EventArgs e)
 {
     this.ConnectionState = PROXY_CONNECTION_STATE.CONNECTED;
     this.hevt_connected.Set();
     if (this.event_ClassProxy_Connected_To_Remote_Host != null)
     {
         this.event_ClassProxy_Connected_To_Remote_Host(this, e);
     }
 }
 private void socket_event_Socket_Data_Error(easy_socket.tcp.Socket_Data sender, easy_socket.tcp.EventArgs_Exception e)
 {
     this.ConnectionState = PROXY_CONNECTION_STATE.CLOSED;
     this.hevt_error.Set();
     if (this.event_ClassProxy_Error != null)
     {
         this.event_ClassProxy_Error(this, e);
     }
 }
        public long proxy_time_out = 20;// timeout in sec

        #endregion

        #region constructors

        public ClassProxy()
        {
            this.hevt_connected                 = new System.Threading.AutoResetEvent(false);
            this.hevt_data_arrival              = new System.Threading.AutoResetEvent(false);
            this.hevt_remotely_closed           = new System.Threading.AutoResetEvent(false);
            this.hevt_error                     = new System.Threading.AutoResetEvent(false);
            this.hevt_connection_state_unlocked = new System.Threading.AutoResetEvent(true);

            this.connection_state = PROXY_CONNECTION_STATE.CLOSED;
            this.socket           = new easy_socket.tcp.Socket_Data();
            this.socket.event_Socket_Data_Error       += new easy_socket.tcp.Socket_Data_Error_EventHandler(socket_event_Socket_Data_Error);
            this.socket.event_Socket_Data_DataArrival += new easy_socket.tcp.Socket_Data_DataArrival_EventHandler(socket_event_Socket_Data_DataArrival);
            this.socket.event_Socket_Data_Connected_To_Remote_Host += new easy_socket.tcp.Socket_Data_Connected_To_Remote_Host_EventHandler(socket_event_Socket_Data_Connected_To_Remote_Host);
            this.socket.event_Socket_Data_Closed_by_Remote_Side    += new easy_socket.tcp.Socket_Data_Closed_by_Remote_Side_EventHandler(socket_event_Socket_Data_Closed_by_Remote_Side);
            this.socket.event_Socket_Data_Send_Completed           += new easy_socket.tcp.Socket_Data_Send_Completed_EventHandler(socket_event_Socket_Data_Send_Completed);
            this.socket.event_Socket_Data_Send_Progress            += new easy_socket.tcp.Socket_Data_Send_Progress_EventHandler(socket_event_Socket_Data_Send_Progress);
        }
 /// <summary>
 /// usefull if http keep alive, or not http connection (proxy socks or direct connection)
 /// </summary>
 public void close()
 {
     this.socket.close();
     this.ConnectionState = PROXY_CONNECTION_STATE.CLOSED;
 }
        public bool send(string query)
        {
            long   time_ticks;
            int    data_size;
            int    iret_waitany      = -1;
            int    pos_end_of_header = -1;
            string str = "";

            byte[] data;
            byte[] tmp_data;
            System.Net.IPAddress   ipaddr;
            System.Net.IPHostEntry iphe;
            this.hevt_connected.Reset();
            this.hevt_data_arrival.Reset();
            this.hevt_remotely_closed.Reset();
            this.hevt_error.Reset();
            System.Threading.WaitHandle[] waithandles = { this.hevt_connected, this.hevt_data_arrival, this.hevt_remotely_closed, this.hevt_error };
            switch (this.type)
            {
            case PROXY_TYPE.NONE:
                if (this.ConnectionState != PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA)
                {
                    this.socket.connect(this.target_ip, this.target_port);
                    iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                    if (iret_waitany != 0)  // connected
                    {
                        return(false);
                    }
                    this.ConnectionState = PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA;
                }
                this.socket.send(query);
                break;

            case PROXY_TYPE.HTTP_GET:
                if (this.ConnectionState != PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA)
                {
                    this.socket.connect(this.proxy_ip, this.proxy_port);
                    iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                    if (iret_waitany != 0)  // connected
                    {
                        return(false);
                    }
                    this.ConnectionState = PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA;
                }
                this.socket.send(this.modify_query(query));
                break;

            case PROXY_TYPE.HTTP_CONNECT:
                if (this.ConnectionState != PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA)
                {
                    this.socket.connect(this.proxy_ip, this.proxy_port);
                    iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                    if (iret_waitany != 0)  // connected
                    {
                        return(false);
                    }
                    this.ConnectionState = PROXY_CONNECTION_STATE.PROXY_NEGOCIATION;
                    this.socket.send("CONNECT " + this.target_ip + ":" + this.target_port + " HTTP/1.1\r\n" + "HOST:" + this.target_ip + ":" + this.target_port + "\r\n\r\n");
                    data       = null;
                    time_ticks = System.Environment.TickCount;
                    // loop until full header is received or error occurs
                    while (pos_end_of_header < 0)
                    {
                        iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                        if (iret_waitany != 1)  // data arrival
                        {
                            return(false);
                        }
                        if (data == null)
                        {
                            data = this.last_data;
                        }
                        else
                        {
                            tmp_data = data;
                            data     = new byte[tmp_data.Length + this.last_data.Length];
                            System.Array.Copy(tmp_data, 0, data, 0, tmp_data.Length);
                            System.Array.Copy(this.last_data, 0, data, tmp_data.Length, this.last_data.Length);
                        }
                        str = System.Text.Encoding.ASCII.GetString(data, 0, data.Length).ToUpper();
                        pos_end_of_header = str.IndexOf("\r\n\r\n");
                        if ((System.Environment.TickCount - time_ticks) > (proxy_time_out * 1000))
                        {
                            if (this.event_ClassProxy_Error != null)
                            {
                                this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Proxy Time Out")));
                            }
                            return(false);
                        }
                    }
                    string str_header = str.Substring(0, pos_end_of_header);

                    if (!System.Text.RegularExpressions.Regex.IsMatch(str_header, "HTTP/[0-9]+.[0-9]+ 2[0-9]{2}", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
                    {
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Bad proxy reply: " + str)));
                        }
                        return(false);
                    }
                    this.ConnectionState = PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA;
                }
                this.socket.send(query);
                break;

            case PROXY_TYPE.SOCKS4:
                if (this.ConnectionState != PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA)
                {
                    this.socket.connect(this.proxy_ip, this.proxy_port);
                    iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                    if (iret_waitany != 0)  // connected
                    {
                        return(false);
                    }
                    this.ConnectionState = PROXY_CONNECTION_STATE.PROXY_NEGOCIATION;
                    data = new byte[9];
                    // version number 4
                    data[0] = 4;
                    // command code 1 (connect)
                    data[1] = 1;
                    // dest port
                    System.Array.Copy(System.BitConverter.GetBytes(easy_socket.network_convert.switch_ushort(this.target_port)), 0, data, 2, 2);
                    // dest ip
                    try
                    {
                        // don't resolve if ip is like xxx.yyy.uuu.vvv
                        ipaddr = System.Net.IPAddress.Parse(this.target_ip);
                    }
                    catch
                    {
                        // else resolve
                        try
                        {
                            iphe = System.Net.Dns.Resolve(this.target_ip);
                        }
                        catch (Exception e)
                        {
                            if (this.event_ClassProxy_Error != null)
                            {
                                this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(e));
                            }
                            return(false);
                        }
                        ipaddr = iphe.AddressList[0];
                    }
                    System.Array.Copy(ipaddr.GetAddressBytes(), 0, data, 4, 4);
                    // user id (none)
                    // null char
                    data[8] = 0;
                    this.socket.send(data);
                    data_size = 0;

                    time_ticks = System.Environment.TickCount;
                    data       = null;
                    // loop until full header is received or error occurs
                    while (data_size < 8)
                    {
                        iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                        if (iret_waitany != 1)  // data arrival
                        {
                            return(false);
                        }
                        if (data == null)
                        {
                            data = this.last_data;
                        }
                        else
                        {
                            tmp_data = data;
                            data     = new byte[tmp_data.Length + this.last_data.Length];
                            System.Array.Copy(tmp_data, 0, data, 0, tmp_data.Length);
                            System.Array.Copy(this.last_data, 0, data, tmp_data.Length, this.last_data.Length);
                        }
                        data_size = data.Length;
                        if ((System.Environment.TickCount - time_ticks) > (proxy_time_out * 1000))
                        {
                            if (this.event_ClassProxy_Error != null)
                            {
                                this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Proxy Time Out")));
                            }
                            return(false);
                        }
                    }
                    // vn should = 0
                    if (data[0] != 0)
                    {
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Bad proxy handshake")));
                        }
                        return(false);
                    }

                    // code should be 90
                    if (data[1] != 90)
                    {
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Proxy error code :" + data[1] + ". ")));
                        }
                        return(false);
                    }
                    // dst port
                    // dst ip
                    this.ConnectionState = PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA;
                }
                this.socket.send(query);

                break;

            case PROXY_TYPE.SOCKS5:
                if (this.ConnectionState != PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA)
                {
                    this.socket.connect(this.proxy_ip, this.proxy_port);
                    iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                    if (iret_waitany != 0)  // connected
                    {
                        return(false);
                    }
                    this.ConnectionState = PROXY_CONNECTION_STATE.PROXY_NEGOCIATION;
                    data = new byte[3];
                    // version number 5
                    data[0] = 5;
                    data[1] = 1;  // number of methods
                    data[2] = 0;  // ask for NO AUTHENTICATION REQUIRED
                    this.socket.send(data);

                    data_size  = 0;
                    time_ticks = System.Environment.TickCount;
                    data       = null;
                    // loop until full header is received or error occurs
                    while (data_size < 2)
                    {
                        iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                        if (iret_waitany != 1)  // data arrival
                        {
                            return(false);
                        }
                        if (data == null)
                        {
                            data = this.last_data;
                        }
                        else
                        {
                            tmp_data = data;
                            data     = new byte[tmp_data.Length + this.last_data.Length];
                            System.Array.Copy(tmp_data, 0, data, 0, tmp_data.Length);
                            System.Array.Copy(this.last_data, 0, data, tmp_data.Length, this.last_data.Length);
                        }
                        data_size = data.Length;
                        if ((System.Environment.TickCount - time_ticks) > (proxy_time_out * 1000))
                        {
                            if (this.event_ClassProxy_Error != null)
                            {
                                this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Proxy Time Out")));
                            }
                            return(false);
                        }
                    }

                    // vn should = 5
                    if (data[0] != 5)
                    {
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Bad proxy handshake")));
                        }
                        return(false);
                    }
                    //X'00' NO AUTHENTICATION REQUIRED
                    //X'01' GSSAPI
                    //X'02' USERNAME/PASSWORD
                    //X'03' to X'7F' IANA ASSIGNED
                    //X'80' to X'FE' RESERVED FOR PRIVATE METHODS
                    //X'FF' NO ACCEPTABLE METHODS
                    if (data[1] != 0)
                    {
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("No authentication not allowed")));
                        }
                        return(false);
                    }
                    // No Authentication accepted
                    data    = new byte[10];
                    data[0] = 5;  // version
                    data[1] = 1;  // connect cmd
                    data[2] = 0;  // reserved
                    data[3] = 1;  // adress type=ipv4
                    try
                    {
                        // don't resolve if ip is like xxx.yyy.uuu.vvv
                        ipaddr = System.Net.IPAddress.Parse(this.target_ip);
                    }
                    catch
                    {
                        // else resolve
                        try
                        {
                            iphe = System.Net.Dns.Resolve(this.target_ip);
                        }
                        catch (Exception e)
                        {
                            if (this.event_ClassProxy_Error != null)
                            {
                                this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(e));
                            }
                            return(false);
                        }
                        ipaddr = iphe.AddressList[0];
                    }
                    // dest ip
                    System.Array.Copy(ipaddr.GetAddressBytes(), 0, data, 4, 4);
                    // dest port
                    System.Array.Copy(System.BitConverter.GetBytes(easy_socket.network_convert.switch_ushort(this.target_port)), 0, data, 8, 2);// warning 8 only because ipv4
                    this.socket.send(data);

                    data_size  = 0;
                    time_ticks = System.Environment.TickCount;
                    data       = null;
                    // loop until full header is received or error occurs
                    while (data_size < 10)
                    {
                        iret_waitany = System.Threading.WaitHandle.WaitAny(waithandles);
                        if (iret_waitany != 1)  // data arrival
                        {
                            return(false);
                        }
                        if (data == null)
                        {
                            data = this.last_data;
                        }
                        else
                        {
                            tmp_data = data;
                            data     = new byte[tmp_data.Length + this.last_data.Length];
                            System.Array.Copy(tmp_data, 0, data, 0, tmp_data.Length);
                            System.Array.Copy(this.last_data, 0, data, tmp_data.Length, this.last_data.Length);
                        }
                        data_size = data.Length;
                        if ((System.Environment.TickCount - time_ticks) > (proxy_time_out * 1000))
                        {
                            if (this.event_ClassProxy_Error != null)
                            {
                                this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Proxy Time Out")));
                            }
                            return(false);
                        }
                    }
                    // vn should = 5
                    if (data[0] != 5)
                    {
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Bad proxy handshake")));
                        }
                        return(false);
                    }

                    switch (data[1])
                    {
                    case 0:        //successfull
                        //"Successfully Connected to remote host"
                        this.ConnectionState = PROXY_CONNECTION_STATE.READY_TO_SEND_USER_DATA;
                        break;

                    case 1:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("General SOCKS server failure.")));
                        }
                        return(false);

                    case 2:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Connection not allowed by ruleset.")));
                        }
                        return(false);

                    case 3:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Network unreachable.")));
                        }
                        return(false);

                    case 4:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Host unreachable.")));
                        }
                        return(false);

                    case 5:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Connection refused.")));
                        }
                        return(false);

                    case 6:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("TTL expired.")));
                        }
                        return(false);

                    case 7:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Command not supported.")));
                        }
                        return(false);

                    case 8:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Address type not supported.")));
                        }
                        return(false);

                    default:
                        if (this.event_ClassProxy_Error != null)
                        {
                            this.event_ClassProxy_Error(this, new easy_socket.tcp.EventArgs_Exception(new Exception("Unknown error code.")));
                        }
                        return(false);
                    }
                }
                this.socket.send(query);
                break;
            }
            return(true);
        }