2011-10-01 76 views
1

我得到一個奇怪的錯誤:爲什麼此TLS代碼只能在調試模式下運行?

The handshake failed due to an unexpected packet format

,如果我的情況下直接調試運行我的代碼。

而且,如果我設置了一個斷點,然後逐行調試代碼,它的工作正常。

下面是詳細的異常

The handshake failed due to an unexpected packet format. 

    at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) 
    at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation) 
    at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost) 
    at Searock_IM.Facebook.LoginForm.StartTls() in D:\Projects\Searock IM\Facebook\LoginForm.cs:line 456 
    at Searock_IM.Facebook.LoginForm.button2_Click(Object sender, EventArgs e) in D:\Projects\Searock IM\Facebook\LoginForm.cs:line 137 
    at System.Windows.Forms.Control.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
    at System.Windows.Forms.Button.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.Run(Form mainForm) 
    at Searock_IM.Program.Main() in D:\Projects\Searock IM\Program.cs:line 18 
    at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 

這裏是代碼:

class Connection : IDisposable 
{ 
    private readonly Socket _socket; 
    private NetworkStream _networkStream; 
    private SslStream _sslStream; 

    private int _bufferStartIndex; 
    private readonly byte[] _buffer = new byte[0x8000]; 
    private StringBuilder _recievedText = new StringBuilder(); 

     public StringBuilder Debug { get; private set; } 

    public bool UseSecure { get; set; } 

    public void StartTls() 
    { 
     UseSecure = true; 

     if (_networkStream == null) 
      _networkStream = new NetworkStream(_socket); 

     if (_sslStream != null) 
      return; 

     _sslStream = new SslStream(_networkStream); 
     _sslStream.AuthenticateAsClient("chat.facebook.com"); 

     lock (Debug) 
      Debug.AppendFormat("** Started TLS **<br/>"); 
    } 

    public Connection() 
    { 
     Debug = new StringBuilder(); 

     _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     _socket.Connect("chat.facebook.com", 5222); 
    } 

    public void Dispose() 
    { 
     if (_sslStream != null) 
      _sslStream.Dispose(); 

     if (_networkStream != null) 
      _networkStream.Dispose(); 
    } 

    public void Send(string text) 
    { 
     if (String.IsNullOrEmpty(text)) 
      return; 

     lock (Debug) 
      Debug.AppendFormat("Out: {0} <br/>", HttpUtility.HtmlEncode(text)); 

     byte[] outp = Encoding.UTF8.GetBytes(text); 

     if (UseSecure) 
      _sslStream.Write(outp); 
     else 
      _socket.Send(outp); 
    } 

    public string Recieve() 
    { 
     if (_socket.Available == 0) 
      return null; 

     int bytesRead = 0; 
     if (UseSecure) 
      bytesRead = _sslStream.Read(_buffer, _bufferStartIndex, _buffer.Length - _bufferStartIndex); 
     else 
      bytesRead = _socket.Receive(_buffer, _bufferStartIndex, _buffer.Length - _bufferStartIndex, SocketFlags.None); 

     ReadBytes(bytesRead); 

     var incomming = ClearStringBuffer(); 

     lock (Debug) 
      Debug.AppendFormat("In: {0}<br/> ", HttpUtility.HtmlEncode(incomming)); 

     return incomming; 
    } 

    private void ReadBytes(int bytesRead) 
    { 
     // http://en.wikipedia.org/wiki/UTF-8#Design 
     // Top 2 bits are either; 
     // 00xx xxxx => 6 bit ASCII mapped character 
     // 11xx xxxx => multi byte chatacter Start 
     // 10xx xxxx => multi byte chatacter Middle of definition 
     // So while last character in buffer is 'middle of definition' rewind end buffer pointer 
     int endOfBuffer = bytesRead + _bufferStartIndex; 
     if (endOfBuffer == 0) 
      return; 

     int end = endOfBuffer; 
     while ((_buffer[end - 1] & 0xC0) == 0x80) --end; 

     string part = Encoding.UTF8.GetString(_buffer, 0, end).TrimEnd('\0'); 

     if (end != endOfBuffer) 
     { 
      _bufferStartIndex = endOfBuffer - end; 
      for (int i = 0; i < _bufferStartIndex; i++) 
       _buffer[i] = _buffer[i + end]; 
     } 

     lock (_recievedText) 
      _recievedText.Append(part); 
    } 


    private string ClearStringBuffer() 
    { 
     string result; 

     lock (_recievedText) 
     { 
      result = _recievedText.ToString(); 
      _recievedText = new StringBuilder(); 
     } 

     return result; 
    } 
} 

我得到錯誤的握手在行失敗,因爲一個意外的數據包格式:

_sslStream.AuthenticateAsClient("chat.facebook.com"); 

我從窗體窗體調用這個類,我沒有使用這種形式的任何線程。

有人可以指出我正確的方向嗎?謝謝。

+0

? [請幫幫忙](http://code.google.com/p/jabber-net/)。 –

+0

否則,不要相信來自Facebook的文檔;它可能都是關閉的。瞭解如何實現它(來自真實來源)(http://xmpp.org/xmpp-protocols/rfcs/),但它確實不是微不足道的 - 您可以花費3個月時間實現完整的堆棧,真的,只需要用jabber-net。 –

+0

@Jonathan Dickinson出於學習目的。它不像我的代碼根本不工作,但只是一個奇怪的錯誤。 – Searock

回答

2

http://chat.facebook.com:5222可能不需要安全連接嗎?見this Facebook help article。如果您遠程登錄到該地址併發送一些虛擬數據爲什麼你要從頭開始編寫的XMPP客戶端,你會得到一個XML響應,

<?xml version="1.0"?> 
<stream:stream id="none" from="chat.facebook.com" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams"> 
<stream:error> 
    <xml-not-well-formed xmlns="urn:ietf:params:xml:ns:xmpp-streams"/> 
</stream:error> 

+0

在他們最近的文檔(http://developers.facebook.com/docs/chat/)中,他們表示通信應該在TLS之上。奇怪的是,如果我進入代碼,它的工作正常,但如果我正常運行它失敗。 – Searock

相關問題