示例#1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sock"></param>
        public virtual void OnConnect(BaseSocket sock)
        {
            if (m_ssl)
            {
#if !NO_SSL
                m_sock.StartTLS();
#else
                throw new NotImplementedException("SSL not compiled in");
#endif
            }
            m_listener.OnConnect(sock);
        }
示例#2
0
        void ISocketEventListener.OnError(BaseSocket sock, Exception ex)
        {
            if (Interlocked.Increment(ref m_errorCount) > m_maxErrors)
            {
                m_keepRunning = false;
                m_listener.OnError(null, ex);
            }

            lock (m_lock)
            {
                Monitor.Pulse(m_lock);
            }
        }
示例#3
0
        void ISocketEventListener.OnConnect(BaseSocket sock)
        {
            lock (m_queue)
            {
                if (!m_running &&
                    m_sockA != null && m_sockA.Connected &&
                    m_sockB != null && m_sockB.Connected)
                {
                    m_running  = true;
                    m_lastSock = m_sockB;

                    m_thread = new Thread(ProcessThread);
                    m_thread.IsBackground = true;
                    m_thread.Name         = "XEP 124 processing thread";
                    m_thread.Start();

                    m_listener.OnConnect(this);
                }
            }
        }
示例#4
0
            public bool OnRead(BaseSocket sock, byte[] buf, int offset, int length)
            {
                string str = ENC.GetString(buf, offset, length);
                Console.WriteLine("SR: " + str);
                if (str.Contains("11111"))
                {
                    sock.Write(ENC.GetBytes(@"HTTP/1.1 200 OK
Content-Length: 10
Content-Type: text/plain

1234567890"));
                }
                else if (str.Contains("22222"))
                {
                    sock.Write(ENC.GetBytes(@"HTTP/1.1 200 OK
Content-Length: 10
Content-Type: text/plain

12345"));
                    sock.Write(ENC.GetBytes("67890"));
                }
                else if (str.Contains("33333"))
                {
                    sock.Write(ENC.GetBytes(@"HTTP/1.1 200 OK
Content-Length: 20
Content-Type: text/plain

12345"));
                    // Turning off Nagle didn't fix this.  Mrmph.
                    Thread.Sleep(300);
                    sock.Write(ENC.GetBytes("67890"));
                    Thread.Sleep(300);
                    sock.Write(ENC.GetBytes("12345"));
                    Thread.Sleep(300);
                    sock.Write(ENC.GetBytes("67890"));
                }
                return true;
            }
示例#5
0
 bool ISocketEventListener.OnAccept(BaseSocket newsocket)
 {
     throw new Exception("The method or operation is not implemented.");
 }
示例#6
0
 void ISocketEventListener.OnClose(BaseSocket sock)
 {
     throw new Exception("The method or operation is not implemented.");
 }
示例#7
0
 public void OnConnect(BaseSocket sock)
 {
     throw new NotImplementedException("The method or operation is not implemented.");
 }
示例#8
0
 bool ISocketEventListener.OnAccept(BaseSocket newsocket)
 {
     throw new Exception("The method or operation is not implemented.");
 }
示例#9
0
        bool IStanzaEventListener.OnInvalidCertificate(BaseSocket sock, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (OnInvalidCertificate != null)
            {
                if ((m_invoker == null) || (!m_invoker.InvokeRequired))
                    return OnInvalidCertificate(sock, certificate, chain, sslPolicyErrors);

                try
                {
                    // Note: can't use CheckedInvoke here, since we need the return value.  We'll wait for the response.
                    return (bool)m_invoker.Invoke(OnInvalidCertificate, new object[] { sock, certificate, chain, sslPolicyErrors });
                }
                catch (Exception e)
                {
                    Debug.WriteLine("Exception passed along by XmppStream: " + e.ToString());
                    return false;
                }
            }
            if ((m_invoker == null) || (!m_invoker.InvokeRequired))
                return ShowCertificatePrompt(sock, certificate, chain, sslPolicyErrors);

            return (bool)m_invoker.Invoke(new RemoteCertificateValidationCallback(ShowCertificatePrompt), new object[]{ sock, certificate, chain, sslPolicyErrors });
        }
示例#10
0
 public bool OnRead(BaseSocket sock, byte[] buf, int offset, int length)
 {
     Last = ENC.GetString(buf, offset, length);
     Console.WriteLine("RR: " + Last);
     Event.Set();
     return true;
 }
示例#11
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="newSock"></param>
 public virtual void OnInit(BaseSocket newSock)
 {
     m_listener.OnInit(newSock);
 }
示例#12
0
 public bool OnRead(BaseSocket sock, byte[] buf, int offset, int length)
 {
     success = ENC.GetString(buf, offset, length);
     lock (done)
     {
         Monitor.Pulse(done);
     }
     return false;
 }
示例#13
0
 void ISocketEventListener.OnWrite(BaseSocket sock, byte[] buf, int offset, int length)
 {
     m_listener.OnWrite(this, buf, offset, length);
 }
示例#14
0
 bool ISocketEventListener.OnInvalidCertificate(BaseSocket sock, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
 {
     return(m_listener.OnInvalidCertificate(this, certificate, chain, sslPolicyErrors));
 }
示例#15
0
        bool ISocketEventListener.OnRead(BaseSocket sock, byte[] buf, int offset, int length)
        {
            if (!m_running)
            {
                Debug.WriteLine("shutting down.  extra bytes received.");
                return(false);
            }

            Debug.WriteLine("OnRead: " + ((HttpSocket)sock).Name);

            // Parse out the first start tag or empty element, which will be
            // <body/>.
            XpNet.UTF8Encoding e   = new XpNet.UTF8Encoding();
            XpNet.ContentToken ct  = new XpNet.ContentToken();
            XpNet.TOK          tok = e.tokenizeContent(buf, offset, offset + length, ct);

            if ((tok != XpNet.TOK.START_TAG_WITH_ATTS) &&
                (tok != XpNet.TOK.EMPTY_ELEMENT_WITH_ATTS))
            {
                m_listener.OnError(this, new ProtocolViolationException("Invalid HTTP binding XML.  Token type: " + tok.ToString()));
                return(false);
            }

            string name = ENC.GetString(buf,
                                        offset + e.MinBytesPerChar,
                                        ct.NameEnd - offset - e.MinBytesPerChar);

            Debug.Assert(name == "body");
            Body   b = new Body(m_doc);
            string val;
            int    start;
            int    end;

            for (int i = 0; i < ct.getAttributeSpecifiedCount(); i++)
            {
                start = ct.getAttributeNameStart(i);
                end   = ct.getAttributeNameEnd(i);
                name  = ENC.GetString(buf, start, end - start);

                start = ct.getAttributeValueStart(i);
                end   = ct.getAttributeValueEnd(i);
                val   = ENC.GetString(buf, start, end - start);

                if (!name.StartsWith("xmlns"))
                {
                    b.SetAttribute(name, val);
                }
            }

            if (b.SID != null)
            {
                m_sid = b.SID;
            }

            if (m_sid == null)
            {
                m_listener.OnError(this, new ProtocolViolationException("Invalid HTTP binding.  No SID."));
                return(false);
            }

            if (b.Wait != -1)
            {
                m_wait = b.Wait;
            }

            if (StartStream)
            {
                StartStream = false;
                m_authID    = b.AuthID;
                if (!FakeReceivedStream())
                {
                    return(false);
                }
            }

            lock (m_queue)
            {
                if (!m_running)
                {
                    return(false);
                }

                if (b.Type == BodyType.terminate)
                {
                    m_running = false;
                    Error err = new Error(m_doc);
                    err.AppendChild(m_doc.CreateElement(b.Condition.ToString(), URI.STREAM_ERROR));
                    byte[] sbuf = ENC.GetBytes(err.OuterXml);
                    m_listener.OnRead(this, sbuf, 0, sbuf.Length);
                    sbuf = ENC.GetBytes("</stream:stream>");
                    m_listener.OnRead(this, sbuf, 0, sbuf.Length);
                    Close();
                    return(false);
                }
            }


            if (tok == XpNet.TOK.START_TAG_WITH_ATTS)
            {
                // len(</body>) = 7
                start = ct.TokenEnd;
                if (m_listener.OnRead(this, buf, start, offset + length - start - 7))
                {
                    RequestRead();
                }
            }
            else
            {
                RequestRead();
            }

            lock (m_queue)
            {
                Monitor.Pulse(m_queue);
            }
            return(true);
        }
示例#16
0
 void ISocketEventListener.OnClose(BaseSocket sock)
 {
     throw new Exception("The method or operation is not implemented.");
 }
示例#17
0
 void ISocketEventListener.OnInit(BaseSocket newSock)
 {
     m_listener.OnInit(newSock);
 }
示例#18
0
        bool ISocketEventListener.OnRead(BaseSocket sock, byte[] buf, int offset, int length)
        {
            if (!m_running)
            {
                Debug.WriteLine("shutting down.  extra bytes received.");
                return false;
            }

            Debug.WriteLine("OnRead: " + ((HttpSocket)sock).Name);

            // Parse out the first start tag or empty element, which will be
            // <body/>.
            XpNet.UTF8Encoding e = new XpNet.UTF8Encoding();
            XpNet.ContentToken ct = new XpNet.ContentToken();
            XpNet.TOK tok = e.tokenizeContent(buf, offset, offset + length, ct);

            if ((tok != XpNet.TOK.START_TAG_WITH_ATTS) &&
                (tok != XpNet.TOK.EMPTY_ELEMENT_WITH_ATTS))
            {
                m_listener.OnError(this, new ProtocolViolationException("Invalid HTTP binding XML.  Token type: " + tok.ToString()));
                return false;
            }

            string name = ENC.GetString(buf,
                                        offset + e.MinBytesPerChar,
                                        ct.NameEnd - offset - e.MinBytesPerChar);

            Debug.Assert(name == "body");
            Body b = new Body(m_doc);
            string val;
            int start;
            int end;
            for (int i = 0; i < ct.getAttributeSpecifiedCount(); i++)
            {
                start = ct.getAttributeNameStart(i);
                end = ct.getAttributeNameEnd(i);
                name = ENC.GetString(buf, start, end - start);

                start = ct.getAttributeValueStart(i);
                end = ct.getAttributeValueEnd(i);
                val = ENC.GetString(buf, start, end - start);

                if (!name.StartsWith("xmlns"))
                    b.SetAttribute(name, val);
            }

            if (b.SID != null)
                m_sid = b.SID;

            if (m_sid == null)
            {
                m_listener.OnError(this, new ProtocolViolationException("Invalid HTTP binding.  No SID."));
                return false;
            }

            if (b.Wait != -1)
                m_wait = b.Wait;

            if (StartStream)
            {
                StartStream = false;
                m_authID = b.AuthID;
                if (!FakeReceivedStream())
                    return false;
            }

            lock (m_queue)
            {
                if (!m_running)
                    return false;

                if (b.Type == BodyType.terminate)
                {
                    m_running = false;
                    Error err = new Error(m_doc);
                    err.AppendChild(m_doc.CreateElement(b.Condition.ToString(), URI.STREAM_ERROR));
                    byte[] sbuf = ENC.GetBytes(err.OuterXml);
                    m_listener.OnRead(this, sbuf, 0, sbuf.Length);
                    sbuf = ENC.GetBytes("</stream:stream>");
                    m_listener.OnRead(this, sbuf, 0, sbuf.Length);
                    Close();
                    return false;
                }
            }


            if (tok == XpNet.TOK.START_TAG_WITH_ATTS)
            {
                // len(</body>) = 7
                start = ct.TokenEnd;
                if (m_listener.OnRead(this, buf, start, offset + length - start - 7))
                    RequestRead();
            }
            else
                RequestRead();

            lock (m_queue)
            {
                Monitor.Pulse(m_queue);
            }
            return true;
        }
示例#19
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="newSock"></param>
 /// <returns></returns>
 public virtual ISocketEventListener GetListener(BaseSocket newSock)
 {
     return(m_listener.GetListener(newSock));
 }
示例#20
0
 bool ISocketEventListener.OnInvalidCertificate(BaseSocket sock, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
 {
     return m_listener.OnInvalidCertificate(this, certificate, chain, sslPolicyErrors);
 }
示例#21
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="newsocket"></param>
 /// <returns></returns>
 public virtual bool OnAccept(BaseSocket newsocket)
 {
     return(m_listener.OnAccept(newsocket));
 }
示例#22
0
 public void OnConnect(BaseSocket sock)
 {
     sock.Write(sbuf, 5, 10);
 }
示例#23
0
 bool ISocketEventListener.OnInvalidCertificate(BaseSocket sock, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
 {
     // TODO: pass up the chain
     return(m_listener.OnInvalidCertificate(null, certificate, chain, sslPolicyErrors));
 }
示例#24
0
 public bool OnAccept(BaseSocket newsocket)
 {
     throw new NotImplementedException("The method or operation is not implemented.");
 }
示例#25
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="sock"></param>
 public virtual void OnClose(BaseSocket sock)
 {
     m_listener.OnClose(sock);
 }
示例#26
0
 public ISocketEventListener GetListener(BaseSocket newSock)
 {
     return this;
 }
示例#27
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="sock"></param>
 /// <param name="ex"></param>
 public virtual void OnError(BaseSocket sock, System.Exception ex)
 {
     m_listener.OnError(sock, ex);
 }
示例#28
0
 public void OnError(BaseSocket sock, Exception ex)
 {
     throw ex;
 }
示例#29
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="sock"></param>
 /// <param name="buf"></param>
 /// <param name="offset"></param>
 /// <param name="length"></param>
 /// <returns></returns>
 public virtual bool OnRead(BaseSocket sock, byte[] buf, int offset, int length)
 {
     return(m_listener.OnRead(sock, buf, offset, length));
 }
示例#30
0
 ISocketEventListener ISocketEventListener.GetListener(BaseSocket newSock)
 {
     throw new Exception("The method or operation is not implemented.");
 }
示例#31
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="sock"></param>
 /// <param name="buf"></param>
 /// <param name="offset"></param>
 /// <param name="length"></param>
 public virtual void OnWrite(BaseSocket sock, byte[] buf, int offset, int length)
 {
     m_listener.OnWrite(sock, buf, offset, length);
 }
示例#32
0
        void ISocketEventListener.OnConnect(BaseSocket sock)
        {
            lock (m_queue)
            {
                if (!m_running &&
                    m_sockA != null && m_sockA.Connected &&
                    m_sockB != null && m_sockB.Connected)
                {
                    m_running = true;
                    m_lastSock = m_sockB;

                    m_thread = new Thread(ProcessThread);
                    m_thread.IsBackground = true;
                    m_thread.Name = "XEP 124 processing thread";
                    m_thread.Start();

                    m_listener.OnConnect(this);
                }
            }            
        }
 /// <summary>
 /// An accept socket is about to be bound, or a connect socket is about to connect,
 /// or an incoming socket just came in.  Use this as an opportunity to
 /// </summary>
 /// <param name="newSock">The new socket that is about to be connected.</param>
 public virtual void OnInit(BaseSocket newSock)
 {
 }
示例#34
0
        void ISocketEventListener.OnError(BaseSocket sock, Exception ex)
        {
            // shutdown race.
            if (!m_running)
                return;

            m_listener.OnError(this, ex);
        }
 /// <summary>
 /// We accepted a socket, and need to get a listener.
 /// If the return value is null, then the socket will be closed,
 /// and RequestAccept will ALWAYS be called.
 /// </summary>
 /// <param name="newSock">The new socket.</param>
 /// <returns>The listener for the *new* socket, as compared to
 /// the listener for the *listen* socket</returns>
 public virtual ISocketEventListener GetListener(BaseSocket newSock)
 {
     return(this);
 }
示例#36
0
 void ISocketEventListener.OnWrite(BaseSocket sock, byte[] buf, int offset, int length)
 {
     m_listener.OnWrite(this, buf, offset, length);
 }
 /// <summary>
 /// A new incoming connection was accepted.
 /// </summary>
 /// <param name="newsocket">Socket for new connection.</param>
 /// <returns>true if RequestAccept() should be called automatically again</returns>
 public virtual bool OnAccept(BaseSocket newsocket)
 {
     return(true);
 }
示例#38
0
 public bool OnAccept(BaseSocket newsocket)
 {
     Assert.IsTrue(((AsyncSocket)newsocket).IsMutuallyAuthenticated);
     newsocket.RequestRead();
     return false;
 }
 /// <summary>
 /// Outbound connection was connected.
 /// </summary>
 /// <param name="sock">Connected socket.</param>
 public virtual void OnConnect(BaseSocket sock)
 {
 }
示例#40
0
 public void OnWrite(BaseSocket sock, byte[] buf, int offset, int length)
 {
     System.Diagnostics.Debug.WriteLine(ENC.GetString(buf, offset, length));
     sock.Close();
 }
 /// <summary>
 /// Connection was closed.
 /// </summary>
 /// <param name="sock">Closed socket.  Already closed!</param>
 public virtual void OnClose(BaseSocket sock)
 {
 }
示例#42
0
 public bool OnInvalidCertificate(BaseSocket sock,
     System.Security.Cryptography.X509Certificates.X509Certificate certificate,
     System.Security.Cryptography.X509Certificates.X509Chain chain,
     System.Net.Security.SslPolicyErrors sslPolicyErrors)
 {
     return true;
 }
 /// <summary>
 /// An error happened in processing.  The socket is no longer open.
 /// </summary>
 /// <param name="sock">Socket in error</param>
 /// <param name="ec">Exception that caused the error</param>
 public virtual void OnError(BaseSocket sock, System.Exception ec)
 {
 }
示例#44
0
 public ISocketEventListener GetListener(BaseSocket newSock)
 {
     throw new NotImplementedException("The method or operation is not implemented.");
 }
 /// <summary>
 /// Bytes were read from the socket.
 /// </summary>
 /// <param name="sock">The socket that was read from.</param>
 /// <param name="buf">The bytes that were read.</param>
 /// <returns>true if RequestRead() should be called automatically again</returns>
 /// <param name="offset">Offset into the buffer to start at</param>
 /// <param name="length">Number of bytes to use out of the buffer</param>
 public virtual bool OnRead(BaseSocket sock, byte[] buf, int offset, int length)
 {
     return(true);
 }
示例#46
0
 public void OnConnect(BaseSocket sock)
 {
 }
 /// <summary>
 /// Bytes were written to the socket.
 /// </summary>
 /// <param name="sock">The socket that was written to.</param>
 /// <param name="buf">The bytes that were written.</param>
 /// <param name="offset">Offset into the buffer to start at</param>
 /// <param name="length">Number of bytes to use out of the buffer</param>
 public virtual void OnWrite(BaseSocket sock, byte[] buf, int offset, int length)
 {
 }
示例#48
0
 public void OnInit(BaseSocket newSock)
 {
 }
示例#49
0
 public void OnWrite(BaseSocket sock, byte[] buf, int offset, int length)
 {
     Console.WriteLine("SW: " + ENC.GetString(buf, offset, length));
 }
示例#50
0
 public bool OnAccept(BaseSocket newsocket)
 {
     AsyncSocket s = (AsyncSocket)newsocket;
     newsocket.RequestRead();
     return true;
 }
示例#51
0
        bool ISocketEventListener.OnRead(BaseSocket sock, byte[] buf, int offset, int length)
        {
            Debug.WriteLine("IN HTTP(" + m_name + "): " + ENC.GetString(buf, offset, length));
            int    i      = offset;
            string header = null;
            int    last   = offset + length;

            while (i < last)
            {
                // HTTP/1.1 200 OK
                // Header: value
                // Header: value
                //
                // Content
                switch (m_state)
                {
                case ParseState.START:
                    if (!ParseAt(buf, ref i, last, HTTP11_SP, 0))
                    {
                        goto ERROR;
                    }
                    m_state = ParseState.RESPONSE;
                    break;

                case ParseState.RESPONSE:
                    string code = ParseTo(buf, ref i, last, SPACE);
                    if (code == null)
                    {
                        goto ERROR;
                    }

                    if (code != "200")
                    {
                        Debug.WriteLine("Non-OK response from server (" + code + ").  STOP!");
                        goto ERROR;
                    }

                    try
                    {
                        // I know this can never fail.  it's here for when we
                        // implement redirects and the like.
                        m_current.Code = int.Parse(code);
                    }
                    catch (Exception)
                    {
                        Debug.WriteLine("invalid response code");
                        goto ERROR;
                    }

                    m_state = ParseState.RESPONSE_TEXT;
                    break;

                case ParseState.RESPONSE_TEXT:
                    m_current.ResponseText = ParseTo(buf, ref i, last, CRLF);
                    if (m_current.ResponseText == null)
                    {
                        goto ERROR;
                    }
                    m_state = ParseState.HEADER_NAME;
                    break;

                case ParseState.HEADER_NAME:
                    if (ParseAt(buf, ref i, last, CRLF, 0))
                    {
                        m_state = ParseState.BODY_START;
                        break;
                    }
                    header = ParseTo(buf, ref i, last, COL_SP);
                    if (header == null)
                    {
                        goto ERROR;
                    }
                    m_state = ParseState.HEADER_VALUE;
                    break;

                case ParseState.HEADER_VALUE:
                    string val = ParseTo(buf, ref i, last, CRLF);
                    if (val == null)
                    {
                        goto ERROR;
                    }
                    m_current.Headers.Add(header, val);
                    m_state = ParseState.HEADER_NAME;
                    break;

                case ParseState.BODY_START:
                    // if we have the whole response, which is typical in XEP-124, then return it all at
                    // once, without creating a MemoryStream.
                    int len = m_current.ContentLength;
                    if (len == -1)
                    {
                        goto ERROR;
                    }
                    if (i + len <= last)
                    {
                        Done();
                        if (!m_listener.OnRead(this, buf, i, len) || !m_keepRunning)
                        {
                            Close();
                            return(false);
                        }
                        return(false);
                    }

                    // We got a partial response.  We're going to have to wait until OnRead is called
                    // again before we can pass a full response upstream.  Hold on to the pieces in a
                    // MemoryStream.
                    m_current.Response = new MemoryStream(len);
                    m_current.Response.Write(buf, i, last - i);
                    m_state = ParseState.BODY_CONTINUE;
                    return(true);

                case ParseState.BODY_CONTINUE:
                    m_current.Response.Write(buf, i, last - i);
                    if (m_current.Response.Length == m_current.Response.Capacity)
                    {
                        PendingRequest req = m_current;
                        Done();

                        byte[] resp = req.Response.ToArray();
                        if (!m_listener.OnRead(this, resp, 0, resp.Length) || !m_keepRunning)
                        {
                            Close();
                            return(false);
                        }

                        return(false);
                    }
                    return(true);

                default:
                    break;
                }
            }
            return(true);

ERROR:
            m_listener.OnError(null, new ProtocolViolationException("Error parsing HTTP response"));
            Close();
            return(false);
        }
示例#52
0
            public void OnClose(BaseSocket sock)
            {

            }
示例#53
0
 void ISocketEventListener.OnInit(BaseSocket newSock)
 {
     m_listener.OnInit(newSock);
 }
示例#54
0
 // #pragma warning restore
 #region Implementation of ISocketEventListener
 public bool OnAccept(BaseSocket newsocket)
 {
     newsocket.RequestRead();
     return false;
 }
示例#55
0
 ISocketEventListener ISocketEventListener.GetListener(BaseSocket newSock)
 {
     throw new Exception("The method or operation is not implemented.");
 }
示例#56
0
 public bool OnInvalidCertificate(BaseSocket sock, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
 {
     throw new NotImplementedException("The method or operation is not implemented.");
 }
示例#57
0
 public void OnError(BaseSocket sock, Exception ex)
 {
     lock (done)
     {
         succeeded = false;
         errorMessage = ex.Message;
         Monitor.Pulse(done);
     }
 }