private void SendHandshakeCallback(IAsyncResult asyncResult) { AsyncHandshakeResult asyncHandshakeResult = (AsyncHandshakeResult)asyncResult.AsyncState; try { _recordStream.EndSend(asyncResult); lock (_handshakeLock) { if (_isAuthenticated && !_isHandshaking) { // Mark send result as complete asyncHandshakeResult.SetComplete(); return; } } // Handshake not finished yet, continue performing ProcessSendHandshakePacket(asyncHandshakeResult); } catch (AlertException ae) { ProcessSendFatalAlert(new Alert(ae.AlertDescription, _handshakeSession.NegotiatedVersion)); asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local alert", ae)); } catch (IOException) { asyncHandshakeResult.SetComplete(new EndOfStreamException("Connection closed unexpectedly")); } catch (Exception e) { ProcessSendFatalAlert(new Alert(AlertDescription.InternalError, _handshakeSession.NegotiatedVersion)); asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local error", e)); } }
private void ProcessSendHandshakePacket(AsyncHandshakeResult asyncHandshakeResult) { HandshakeMessage[] messages = _handshakeSession.GetOutputMessages(); Record[] records = _handshakePacketizer.ProcessHandshakeMessages(_handshakeSession.NegotiatedVersion, messages, _recordStream.MaximumFragmentLength); if (records.Length > 0) { // Encrypt the handshake records for (int i = 0; i < records.Length; i++) { _recordHandler.ProcessOutputRecord(records[i]); } _recordStream.BeginSend(records, new AsyncCallback(SendHandshakeCallback), asyncHandshakeResult); } else { if (_handshakeSession.State == HandshakeState.Finished) { // Handshake finished, mark result as complete asyncHandshakeResult.SetComplete(); } else if (_handshakeSession.State == HandshakeState.SendChangeCipherSpec) { ProcessSendChangeCipherSpec(asyncHandshakeResult); } else { // Handshake not finished, receive the next handshake packet _recordStream.BeginReceive(new AsyncCallback(ReceiveHandshakeCallback), asyncHandshakeResult); } } }
private void ProcessSendHandshakePacket(AsyncHandshakeResult asyncHandshakeResult) { HandshakeMessage[] messages = _handshakeSession.GetOutputMessages(); Record[] records = _handshakePacketizer.ProcessHandshakeMessages(_handshakeSession.NegotiatedVersion, messages, _recordStream.MaximumFragmentLength); if (records.Length > 0) { // Encrypt the handshake records for (int i=0; i<records.Length; i++) { _recordHandler.ProcessOutputRecord(records[i]); } _recordStream.BeginSend(records, new AsyncCallback(SendHandshakeCallback), asyncHandshakeResult); } else { if (_handshakeSession.State == HandshakeState.Finished) { // Handshake finished, mark result as complete asyncHandshakeResult.SetComplete(); } else if (_handshakeSession.State == HandshakeState.SendChangeCipherSpec) { ProcessSendChangeCipherSpec(asyncHandshakeResult); } else { // Handshake not finished, receive the next handshake packet _recordStream.BeginReceive(new AsyncCallback(ReceiveHandshakeCallback), asyncHandshakeResult); } } }
private void ReceiveHandshakeCallback(IAsyncResult asyncResult) { AsyncHandshakeResult asyncHandshakeResult = (AsyncHandshakeResult)asyncResult.AsyncState; try { Record[] records = _recordStream.EndReceive(asyncResult); for (int i = 0; i < records.Length; i++) { Record record = records[i]; if (!_recordHandler.ProcessInputRecord(record)) { // Ignore records from invalid epoch continue; } lock (_handshakeLock) { if (!_isAuthenticated && record.Type == RecordType.Data) { // Refuse data packets before authentication throw new AlertException(AlertDescription.UnexpectedMessage, "Data packet received before handshake"); } if (!_isHandshaking && (record.Type == RecordType.ChangeCipherSpec || record.Type == RecordType.Handshake)) { // Refuse ChangeCipherSpec and Handshake packets if not handshaking // TODO: Should handle HelloRequest if renegotiation is supported throw new AlertException(AlertDescription.UnexpectedMessage, "Handshake packet received outside handshake"); } if (_isHandshaking && record.Type == RecordType.Data) { // Queue data packets during new handshake to avoid sync problems // TODO: Should handle the data correctly if renegotiation is supported throw new AlertException(AlertDescription.UnexpectedMessage, "Received a data packet during handshake"); } } switch (record.Type) { case RecordType.ChangeCipherSpec: ProcessChangeCipherSpecRecord(record, asyncHandshakeResult); break; case RecordType.Alert: ProcessAlertRecord(record, asyncHandshakeResult); break; case RecordType.Handshake: ProcessHandshakeRecord(record, asyncHandshakeResult); break; case RecordType.Data: // TODO: Implement this properly if renegotiation is supported break; default: ProcessUnknownRecord(record, asyncHandshakeResult); break; } } } catch (AlertException ae) { ProcessSendFatalAlert(new Alert(ae.AlertDescription, _handshakeSession.NegotiatedVersion)); asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local alert", ae)); } catch (IOException) { asyncHandshakeResult.SetComplete(new EndOfStreamException("Connection closed unexpectedly")); } catch (Exception e) { ProcessSendFatalAlert(new Alert(AlertDescription.InternalError, _handshakeSession.NegotiatedVersion)); asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local error", e)); } }