Example #1
0
        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));
            }
        }