BackendMessage ParseServerMessage(NpgsqlBuffer buf, BackendMessageCode code, int len, DataRowLoadingMode dataRowLoadingMode) { switch (code) { case BackendMessageCode.RowDescription: // TODO: Recycle var rowDescriptionMessage = new RowDescriptionMessage(); return rowDescriptionMessage.Load(buf, TypeHandlerRegistry); case BackendMessageCode.DataRow: Contract.Assert(dataRowLoadingMode == DataRowLoadingMode.NonSequential || dataRowLoadingMode == DataRowLoadingMode.Sequential); return dataRowLoadingMode == DataRowLoadingMode.Sequential ? _dataRowSequentialMessage.Load(buf) : _dataRowNonSequentialMessage.Load(buf); case BackendMessageCode.CompletedResponse: return _commandCompleteMessage.Load(buf, len); case BackendMessageCode.ReadyForQuery: var rfq = _readyForQueryMessage.Load(buf); TransactionStatus = rfq.TransactionStatusIndicator; return rfq; case BackendMessageCode.EmptyQueryResponse: return EmptyQueryMessage.Instance; case BackendMessageCode.ParseComplete: return ParseCompleteMessage.Instance; case BackendMessageCode.ParameterDescription: return _parameterDescriptionMessage.Load(buf); case BackendMessageCode.BindComplete: return BindCompleteMessage.Instance; case BackendMessageCode.NoData: return NoDataMessage.Instance; case BackendMessageCode.CloseComplete: return CloseCompletedMessage.Instance; case BackendMessageCode.ParameterStatus: HandleParameterStatus(buf.ReadNullTerminatedString(), buf.ReadNullTerminatedString()); return null; case BackendMessageCode.NoticeResponse: // TODO: Recycle FireNotice(new NpgsqlError(buf)); return null; case BackendMessageCode.NotificationResponse: FireNotification(new NpgsqlNotificationEventArgs(buf)); return null; case BackendMessageCode.AuthenticationRequest: var authType = (AuthenticationRequestType)buf.ReadInt32(); _log.Trace("Received AuthenticationRequest of type " + authType); switch (authType) { case AuthenticationRequestType.AuthenticationOk: return AuthenticationOkMessage.Instance; case AuthenticationRequestType.AuthenticationCleartextPassword: return AuthenticationCleartextPasswordMessage.Instance; case AuthenticationRequestType.AuthenticationMD5Password: return AuthenticationMD5PasswordMessage.Load(buf); case AuthenticationRequestType.AuthenticationGSS: return AuthenticationGSSMessage.Instance; case AuthenticationRequestType.AuthenticationSSPI: return AuthenticationSSPIMessage.Instance; case AuthenticationRequestType.AuthenticationGSSContinue: return AuthenticationGSSContinueMessage.Load(buf, len); default: throw new NotSupportedException(String.Format(L10N.AuthenticationMethodNotSupported, authType)); } case BackendMessageCode.BackendKeyData: BackendProcessId = buf.ReadInt32(); BackendSecretKey = buf.ReadInt32(); return null; case BackendMessageCode.CopyData: case BackendMessageCode.CopyDone: case BackendMessageCode.CancelRequest: case BackendMessageCode.CopyDataRows: case BackendMessageCode.CopyInResponse: case BackendMessageCode.CopyOutResponse: throw new NotImplementedException(); case BackendMessageCode.PortalSuspended: case BackendMessageCode.IO_ERROR: Debug.Fail("Unimplemented message: " + code); throw new NotImplementedException("Unimplemented message: " + code); case BackendMessageCode.ErrorResponse: return null; case BackendMessageCode.FunctionCallResponse: // We don't use the obsolete function call protocol throw new Exception("Unexpected backend message: " + code); default: throw PGUtil.ThrowIfReached("Unknown backend message code: " + code); } }
internal BackendMessage ReadSingleMessage(DataRowLoadingMode dataRowLoadingMode = DataRowLoadingMode.NonSequential, bool ignoreNotifications = true) { try { return DoReadSingleMessage(dataRowLoadingMode, ignoreNotifications); } catch (NpgsqlException) { throw; } catch { State = ConnectorState.Broken; throw; } }
BackendMessage DoReadSingleMessage(DataRowLoadingMode dataRowLoadingMode = DataRowLoadingMode.NonSequential, bool ignoreNotifications = true) { NpgsqlError error = null; while (true) { var buf = Buffer; Buffer.Ensure(5); var messageCode = (BackendMessageCode) Buffer.ReadByte(); Contract.Assume(Enum.IsDefined(typeof(BackendMessageCode), messageCode), "Unknown message code: " + messageCode); var len = Buffer.ReadInt32() - 4; // Transmitted length includes itself if (messageCode == BackendMessageCode.DataRow && dataRowLoadingMode != DataRowLoadingMode.NonSequential) { if (dataRowLoadingMode == DataRowLoadingMode.Skip) { Buffer.Skip(len); continue; } } else if (len > Buffer.ReadBytesLeft) { buf = buf.EnsureOrAllocateTemp(len); } var msg = ParseServerMessage(buf, messageCode, len, dataRowLoadingMode); if (msg != null || !ignoreNotifications && (messageCode == BackendMessageCode.NoticeResponse || messageCode == BackendMessageCode.NotificationResponse)) { if (error != null) { Contract.Assert(messageCode == BackendMessageCode.ReadyForQuery, "Expected ReadyForQuery after ErrorResponse"); throw new NpgsqlException(error); } return msg; } else if (messageCode == BackendMessageCode.ErrorResponse) { // An ErrorResponse is (almost) always followed by a ReadyForQuery. Save the error // and throw it as an exception when the ReadyForQuery is received (next) // The exception is during the startup/authentication phase, where the server closes // the connection after an ErrorResponse error = new NpgsqlError(buf); if (State == ConnectorState.Connecting) { throw new NpgsqlException(error); } } } }
BackendMessage DoReadSingleMessage(DataRowLoadingMode dataRowLoadingMode = DataRowLoadingMode.NonSequential, bool ignoreNotifications = true) { NpgsqlError error = null; while (true) { var buf = Buffer; Buffer.Ensure(5); var messageCode = (BackendMessageCode) Buffer.ReadByte(); Contract.Assume(Enum.IsDefined(typeof(BackendMessageCode), messageCode), "Unknown message code: " + messageCode); var len = Buffer.ReadInt32() - 4; // Transmitted length includes itself if (messageCode == BackendMessageCode.DataRow && dataRowLoadingMode != DataRowLoadingMode.NonSequential) { if (dataRowLoadingMode == DataRowLoadingMode.Skip) { Buffer.Skip(len); continue; } } else if (len > Buffer.ReadBytesLeft) { buf = buf.EnsureOrAllocateTemp(len); } var msg = ParseServerMessage(buf, messageCode, len, dataRowLoadingMode); if (msg != null || !ignoreNotifications && (messageCode == BackendMessageCode.NoticeResponse || messageCode == BackendMessageCode.NotificationResponse)) { if (error != null) { Contract.Assert(messageCode == BackendMessageCode.ReadyForQuery, "Expected ReadyForQuery after ErrorResponse"); throw new NpgsqlException(error); } return msg; } else if (messageCode == BackendMessageCode.ErrorResponse) { error = new NpgsqlError(buf); } } }