public override void Start()
        {
            if (FileTransfer.FileTransferDirection == FileTransferDirection.Send)
            {
                /// Tell the other end we want to send a file..  give them a list of SOCKS5 servers they can connect to (hopefully our open fire server supports it)
                ///

                IQStart = new ByteStreamQueryIQ();
                //IQStart.SID = this.FileTransfer.sid;
                IQStart.ByteStreamQuery = new ByteStreamQuery();
                IQStart.ByteStreamQuery.SID = this.FileTransfer.sid;
                IQStart.ByteStreamQuery.Mode = StreamMode.tcp.ToString();
                IQStart.From = XMPPClient.JID;
                IQStart.To = FileTransfer.RemoteJID;
                IQStart.Type = IQType.set.ToString();

                /// Build our stream objects
                ///
                /// For windows we can start a local listener and a proxy listener
                /// For windows phone we can only use the proxy (if our jabber server supports it) because we can't listen for connections
                ///

                string strJID = string.Format("proxy.{0}", XMPPClient.Domain);
                string strHost = XMPPClient.Server;
                string strPort = "7777";

                if ((FileTransferManager.SOCKS5Proxy != null) && (FileTransferManager.SOCKS5Proxy.Length > 0))
                {
                    /// User supplied socks5 proxy...TODO, add port configuration
                    strJID = FileTransferManager.SOCKS5Proxy;
                    strHost = FileTransferManager.SOCKS5Proxy;
                    strPort = "7777";
                }
                else
                {
                    /// Query our xmpp server for a proxy, then for the details
                    ///

                    item filetransfer = FindProxyItem();
                    if (filetransfer != null)
                    {
                        strJID = filetransfer.JID;
                        /// Query the server for the actual stream host of thi sitem

                        ByteStreamQueryIQ iqqueryproxy = new ByteStreamQueryIQ();
                        iqqueryproxy.From = XMPPClient.JID;
                        iqqueryproxy.To = strJID;
                        iqqueryproxy.Type = IQType.get.ToString();
                        iqqueryproxy.ByteStreamQuery = new ByteStreamQuery();

                        IQ iqret = XMPPClient.SendRecieveIQ(iqqueryproxy, 15000, SerializationMethod.XMLSerializeObject);
                        if ((iqret != null) && (iqret is ByteStreamQueryIQ))
                        {
                            ByteStreamQueryIQ response = iqret as ByteStreamQueryIQ;
                            if ((response.ByteStreamQuery != null) && (response.ByteStreamQuery.Hosts != null) && (response.ByteStreamQuery.Hosts.Length > 0))
                            {
                                strHost = response.ByteStreamQuery.Hosts[0].Host;
                                strPort = response.ByteStreamQuery.Hosts[0].Port;
                                strJID = response.ByteStreamQuery.Hosts[0].Jid;
                            }
                        }

                    }
                }

                StreamHost host = new StreamHost() { Host = strHost, Port = strPort, Jid = strJID };
                //StreamHost host = new StreamHost() { Host = "192.168.1.124", Port = "7777", Jid = string.Format("proxy.{0}", XMPPClient.Domain) };
                IQStart.ByteStreamQuery.Hosts = new StreamHost[] { host };
                IQStart.ByteStreamQuery.Mode = StreamMode.tcp.ToString();

                XMPPClient.SendObject(IQStart);

            }
            else
            {
            }

            base.Start();
        }
        public void SendFileThread(object obj)
        {
            ByteStreamQueryIQ bsiq = obj as ByteStreamQueryIQ;

            /// Attempt to open our hosts
            ///
            StreamHost host = bsiq.ByteStreamQuery.StreamHostUsed;

            SocketServer.SocketClient client = new SocketClient();

            client.SetSOCKSProxy(5, XMPPClient.Server, 7777, "xmppclient");
            client.OnAsyncConnectFinished += new DelegateConnectFinish(client_OnAsyncConnectFinished);
            EventConnected.Reset();
            ConnectSuccesful = false;

            string strHost = string.Format("{0}{1}{2}", this.FileTransfer.sid, XMPPClient.JID, bsiq.From);
            System.Security.Cryptography.SHA1Managed sha = new System.Security.Cryptography.SHA1Managed();
            byte [] bBytes = sha.ComputeHash(System.Text.UTF8Encoding.UTF8.GetBytes(strHost));
            strHost = SocketServer.TLS.ByteHelper.HexStringFromByte(bBytes, false, int.MaxValue).ToLower();

            /// Connect parametrs are the sha1 hash and 0, the socks proxy will connect us to the correct place
            client.ConnectAsync(strHost, 0);

            EventConnected.WaitOne();
            if (ConnectSuccesful == true)
            {

                /// Now we must activate the proxy so we can send
                ///
                EventActivate.Reset();
                IQActivate = new ByteStreamQueryIQ();
                IQActivate.ByteStreamQuery = new ByteStreamQuery();
                IQActivate.ByteStreamQuery.SID = this.FileTransfer.sid;
                IQActivate.From = XMPPClient.JID;
                IQActivate.To = host.Jid;
                IQActivate.Type = IQType.set.ToString();
                IQActivate.ByteStreamQuery.Activate = FileTransfer.RemoteJID;
                XMPPClient.SendObject(IQActivate);
                EventActivate.WaitOne();

                if (IsCompleted == true)
                {
                    /// Error, exit this thread
                    FileTransfer.FileTransferState = FileTransferState.Error;
                    XMPPClient.FileTransferManager.FinishActiveFileTransfer(FileTransfer);
                    return;
                }

                FileTransfer.BytesRemaining = FileTransfer.Bytes.Length;
                FileTransfer.FileTransferState = FileTransferState.Transferring;

                /// Now send all our data
                ///
                ByteBuffer buffer = new ByteBuffer();
                buffer.AppendData(FileTransfer.Bytes);

                while (buffer.Size > 0)
                {
                    int nSize = (buffer.Size > 16384) ? 16384 : buffer.Size;
                    Sockets.SocketAsyncEventArgs asyncsend = new Sockets.SocketAsyncEventArgs();
                    asyncsend.SetBuffer(buffer.GetNSamples(nSize), 0, nSize);
                    asyncsend.Completed += new EventHandler<Sockets.SocketAsyncEventArgs>(asyncsend_Completed);

                    SendCompletedEvent.Reset();
                    bSendSuccess = false;
                    bool bSent = false;
                    try
                    {
                        client.socket.SendAsync(asyncsend);
                    }
                    catch (Exception ex)
                    {
                        IsCompleted = true;
                        FileTransfer.Error = ex.Message;
                        FileTransfer.FileTransferState = FileTransferState.Error;
                        return;
                    }
                    SendCompletedEvent.WaitOne();
                    if (IsCompleted == true)
                        break;

                    if ((bSendSuccess == false) && (bSent == false) ) /// was sent async because bSent is false, so we can examine bSendSuccess to make sure we sent the right number of bytes
                    {
                        break;
                    }
                    FileTransfer.BytesRemaining -= nSize;
                }

                client.Disconnect();

                FileTransfer.FileTransferState = FileTransferState.Done;
                IsCompleted = true;
                XMPPClient.FileTransferManager.FinishActiveFileTransfer(FileTransfer);
                return;
            }

            FileTransfer.Error = "Failed to send data";
            FileTransfer.FileTransferState = FileTransferState.Error;
            IsCompleted = true;
        }
        public void DownloadThread(object obj)
        {
            ByteStreamQueryIQ bsiq = obj as ByteStreamQueryIQ;

            /// Attempt to open our hosts
            ///
            foreach (StreamHost host in bsiq.ByteStreamQuery.Hosts)
            {
                if (IsCompleted == true)
                    break;

                SocketServer.SocketClient client = new SocketClient();

                client.SetSOCKSProxy(5, host.Host, Convert.ToInt32(host.Port), "xmppclient");
                client.OnAsyncConnectFinished += new DelegateConnectFinish(client_OnAsyncConnectFinished);
                EventConnected.Reset();
                ConnectSuccesful = false;

                string strHost = string.Format("{0}{1}{2}", this.FileTransfer.sid, bsiq.From, bsiq.To);
                System.Security.Cryptography.SHA1Managed sha = new System.Security.Cryptography.SHA1Managed();
                byte [] bBytes = sha.ComputeHash(System.Text.UTF8Encoding.UTF8.GetBytes(strHost));
                strHost = SocketServer.TLS.ByteHelper.HexStringFromByte(bBytes, false, int.MaxValue).ToLower();

                /// Connect parametrs are the sha1 hash and 0, the socks proxy will connect us to the correct place
                client.StartReadOnConnect = true;
                client.ConnectAsync(strHost, 0);

                EventConnected.WaitOne();

                if (ConnectSuccesful == true)
                {
                    FileTransfer.FileTransferState = FileTransferState.Transferring;
                    client.OnReceiveMessage += new SocketClient.SocketReceiveHandler(client_OnReceiveMessage);
                    DownloadFileBuffer.GetAllSamples();

                    /// connected and negotiated socks5, tell the far end to start sending data
                    ///
                    ByteStreamQueryIQ iqresponse = new ByteStreamQueryIQ();
                    iqresponse.SID = this.FileTransfer.sid;
                    iqresponse.ByteStreamQuery = new ByteStreamQuery();
                    iqresponse.ByteStreamQuery.StreamHostUsed = new StreamHost();
                    iqresponse.ByteStreamQuery.StreamHostUsed.Jid = host.Jid;
                    iqresponse.From = XMPPClient.JID;
                    iqresponse.ID = bsiq.ID;
                    iqresponse.To = bsiq.From;
                    iqresponse.Type = IQType.result.ToString();
                    XMPPClient.SendObject(iqresponse);

                    /// Now read data until we get our desired amount
                    ///
                    EventGotAllData.WaitOne();

                    client.Disconnect();
                    return;
                }
            }

            /// Couldn't transfer file, send error
            ///
            ByteStreamQueryIQ response = new ByteStreamQueryIQ();
            response.ByteStreamQuery = bsiq.ByteStreamQuery;
            response.From = XMPPClient.JID;
            response.To = bsiq.From;
            response.ID = bsiq.ID;
            response.Type = IQType.error.ToString();
            response.Error = new Error(ErrorType.remoteservertimeout);
            XMPPClient.SendXMPP(response);
            FileTransfer.Error = "Could not connect to proxy";
            FileTransfer.FileTransferState = FileTransferState.Error;
            XMPPClient.FileTransferManager.FinishActiveFileTransfer(FileTransfer);
        }
        public override bool NewIQ(IQ iq)
        {
            if (this.IsCompleted == true)  // We've been cancelled
                return false;

            if (FileTransfer.FileTransferDirection == FileTransferDirection.Send)
            {
                if  ( (IQStart != null) && (iq.ID == IQStart.ID) )
                {
                    if (iq.Type == IQType.error.ToString())
                    {
                        IsCompleted = true;
                        if (iq.Error != null)
                            FileTransfer.Error = iq.Error.ErrorDescription;
                        FileTransfer.FileTransferState = FileTransferState.Error;
                        XMPPClient.FileTransferManager.FinishActiveFileTransfer(FileTransfer);
                    }
                    else if (iq is ByteStreamQueryIQ)
                    {
                        ByteStreamQueryIQ bsiq = iq as ByteStreamQueryIQ;
                        if (bsiq.Type == IQType.result.ToString())
                        {
                            System.Threading.ThreadPool.QueueUserWorkItem(new Threading.WaitCallback(SendFileThread), bsiq);
                        }
                        else if (bsiq.Type == IQType.error.ToString())
                        {
                            IsCompleted = true;
                            if (iq.Error != null)
                                FileTransfer.Error = bsiq.Error.ErrorDescription;
                            FileTransfer.FileTransferState = FileTransferState.Error;

                        }
                    }

                    return true;
                }
                if ((IQActivate != null)  && (iq.ID == IQActivate.ID))
                {
                    EventActivate.Set();
                    return true;
                }

            }
            else
            {
                if (iq is ByteStreamQueryIQ)
                {
                    ByteStreamQueryIQ bsiq = iq as ByteStreamQueryIQ;

                    if ( (bsiq.ByteStreamQuery != null) && (bsiq.ByteStreamQuery.Hosts != null) && (bsiq.ByteStreamQuery.Hosts.Length > 0) )
                    {
                        System.Threading.ThreadPool.QueueUserWorkItem(new Threading.WaitCallback(DownloadThread), bsiq);
                    }
                    else
                    {
                        ByteStreamQueryIQ response = new ByteStreamQueryIQ();
                        response.ByteStreamQuery = bsiq.ByteStreamQuery;
                        response.From = XMPPClient.JID;
                        response.To = bsiq.From;
                        response.ID = bsiq.ID;
                        response.Type = IQType.error.ToString();
                        response.Error = new Error(ErrorType.notacceptable);
                        XMPPClient.SendXMPP(response);
                    }
                    /// See qh
                    ///
                    return true;
                }

            }

            return false;
        }
        public override void Start()
        {
            if (FileTransfer.FileTransferDirection == FileTransferDirection.Send)
            {
                /// Tell the other end we want to send a file..  give them a list of SOCKS5 servers they can connect to (hopefully our open fire server supports it)
                ///

                IQStart = new ByteStreamQueryIQ();
                //IQStart.SID = this.FileTransfer.sid;
                IQStart.ByteStreamQuery = new ByteStreamQuery();
                IQStart.ByteStreamQuery.SID = this.FileTransfer.sid;
                IQStart.ByteStreamQuery.Mode = StreamMode.tcp.ToString();
                IQStart.From = XMPPClient.JID;
                IQStart.To = FileTransfer.RemoteJID;
                IQStart.Type = IQType.set.ToString();

                /// Build our stream objects
                ///
                /// For windows we can start a local listener and a proxy listener
                /// For windows phone we can only use the proxy (if our jabber server supports it) because we can't listen for connections
                ///

                string strJID = string.Format("proxy.{0}", XMPPClient.Domain);
                string strHost = XMPPClient.Server;
                string strPort = "7777";

                if ((FileTransferManager.SOCKS5Proxy != null) && (FileTransferManager.SOCKS5Proxy.Length > 0))
                {
                    /// User supplied socks5 proxy...TODO, add port configuration
                    strJID = FileTransferManager.SOCKS5Proxy;
                    strHost = FileTransferManager.SOCKS5Proxy;
                    strPort = "7777";
                }
                else
                {
                    /// Query our xmpp server for a proxy, then for the details
                    ///

                    item filetransfer = FindProxyItem();
                    if (filetransfer != null)
                    {
                        strJID = filetransfer.JID;
                        /// Query the server for the actual stream host of thi sitem

                        ByteStreamQueryIQ iqqueryproxy = new ByteStreamQueryIQ();
                        iqqueryproxy.From = XMPPClient.JID;
                        iqqueryproxy.To = strJID;
                        iqqueryproxy.Type = IQType.get.ToString();
                        iqqueryproxy.ByteStreamQuery = new ByteStreamQuery();

                        IQ iqret = XMPPClient.SendRecieveIQ(iqqueryproxy, 15000, SerializationMethod.XMLSerializeObject);
                        if ((iqret != null) && (iqret is ByteStreamQueryIQ))
                        {
                            ByteStreamQueryIQ response = iqret as ByteStreamQueryIQ;
                            if ((response.ByteStreamQuery != null) && (response.ByteStreamQuery.Hosts != null) && (response.ByteStreamQuery.Hosts.Length > 0))
                            {
                                strHost = response.ByteStreamQuery.Hosts[0].Host;
                                strPort = response.ByteStreamQuery.Hosts[0].Port;
                                strJID = response.ByteStreamQuery.Hosts[0].Jid;
                            }
                        }

                    }
                }

                List<StreamHost> hosts = new List<StreamHost>();

                /// See if we have a public IP for our local stream.  If so, send it, and setup a local socks5 proxy
                //StreamHost hostloco = new StreamHost() { Host = strHost, Port = strPort, Jid = XMPPClient.JID };
            #if !WINDOWS_PHONE

                if (FileTransferManager.UseLocalSOCKS5Server == true)
                {
                    if ((FileTransferManager.SOCKS5ByteServerPublicIP != null) && (FileTransferManager.SOCKS5ByteServerPublicIP.Length > 0))
                    {
                        FileTransferManager.StartSocks5ByteServer();
                        hosts.Add(new StreamHost() { Host = FileTransferManager.SOCKS5ByteServerPublicIP, Port = FileTransferManager.SOCKS5ByteServerPort.ToString(), Jid = XMPPClient.JID });
                    }
                    else
                    {
                        IPAddress[] addresses = SocketServer.ConnectMgr.FindAddresses();
                        /// Find out which addresses are public, and if they are advertise them.  (If they're private we can stun and use them in Jingle streams sessions, but not here)
                        /// the one exception is if we let the user specify an address because they opened the port
                        ///

                        foreach (IPAddress address in addresses)
                        {
                            if (SocketServer.ConnectMgr.IsInPrivateRange(address) == false)
                            {
                                FileTransferManager.StartSocks5ByteServer();

                                /// Need a port to listen on for this address... needs socks5 server listening
                                hosts.Add(new StreamHost() { Host = address.ToString(), Port = FileTransferManager.SOCKS5ByteServerPort.ToString(), Jid = XMPPClient.JID });
                            }
                        }
                    }
                }

            #endif

                hosts.Add(new StreamHost() { Host = strHost, Port = strPort, Jid = strJID });
                //StreamHost host = new StreamHost() { Host = "192.168.1.124", Port = "7777", Jid = string.Format("proxy.{0}", XMPPClient.Domain) };
                IQStart.ByteStreamQuery.Hosts = hosts.ToArray();
                IQStart.ByteStreamQuery.Mode = StreamMode.tcp.ToString();

                XMPPClient.SendObject(IQStart);

            }
            else
            {
            }

            base.Start();
        }