# Npgsql: Communication State Machine

← Suggested Readings | Up | Next Topic →

Last update: 2002-06-12 00:35:00 by usp

Category: Internal documentation

Intended Audience: Npgsql Developers

This document describes the behaviour of the connection object. This is done in form of a state/event/transition table: For each specific state of a connection object all possible events are listed, together with a short description of the reactions, and a state the connection will be in after performing the actions.

The first column type identifies the kind of event. We distinguish between 3 types:

- Messages from the backend,
- Function calls done by the application, and
- asynchronous Events like timeouts.

The second column denotes the event. I have chosen the names similar to their corresponding message names, as defined in the PostgreSQL 7.2.1 Documentation, Chapter 4.4, Message Formats. However, with respect to the somewhat limited space, I have shortened them where possible in an unambiguous way. Additionally the full length message names are mentioned in the description parts, in most cases hyperlinked to their definitons.

The third column contains the state the connection will receive after carrying out the actions, described in the fourth column. The state names may be abbreviated, too.

The fourth column contains a general description of the situation an the actions to be taken, often in conjunction with hyperlinks to the corresponding message definitions.

And here comes the description:

Communication State Table
Type | Event/Action | Next State | Description
Ground Zero
This state is active right after instantiation of a new connection object. There is no open connection.
F | OpenConn() | Connected | This method is called to open a communication channel to the backend. The connection parameters are retrieved from the connection string. A successul OpenConn() causes a state transition to Connected, otherwise an errormessage should be displayed.
Connected
In this state the communication with the backend is initiated. A communication channel has already been successfully opened. The frontend may choose an SSL connection by calling SSLReq() instead of Startup() or CancelReq().
F | Startup() | Startup | This method call occurs in order to establish a regular unsecure connection to the backend. The frontend send a Startup Packet to the backend.
F | CancelReq() | Ground Zero | The Cancel Request Message is sent asynchronously through an unsecure connection. It contains the PID and Secret Key previously obtained in the authentication state of another startup sequence. After processing this message the backend immediately closes the connection. The frontend also closes the connection an makes a transition to Ground Zero.
F | SSLRequest() | SSLStartup | To initiate an SSL-encrypted connection, the frontend initially sends an SSLRequest message rather than a StartupPacket or Cancel Request Message. The state will transit to SSLRequest.
SSL Startup
In this state the frontend awaits the SSL Request response from the server. This is a single byte containing 'Y' or 'N', indicating that it is willing or unwilling to perform SSL, respectively. While the protocol itself does not provide a way for the server to force SSL encryption, the administrator may configure the server to reject unencrypted sessions as a byproduct of authentication checking.
M | Y-Response | SSLHandshake | The server indicates that it is willing to accept a SSL connection by transmitting a single byte 'Y'. The frontend will perform an SSL Startup Handshake with the Server. If successful, the Startup Package is sent to the Server, and
M | N-Response | Ground Zero | The Server is not willing to accept a SSL connection. Close the connection and return to Ground Zero.
M | Error | Ground Zero | This should really not happen in this state. Close the connection and return to Ground Zero.
E | Timeout | Ground Zero | In case of a backend response timeout the frontend closes the connection and goes back to Ground Zero.
SSL Handshake
In this state the frontend and backend perform the SSL startup handshake (not described here, part of the SSL specification). If this is successful, the frontend sends the usual StartupPacket to the backend. In this case the StartupPacket and all subsequent data will be SSL-encrypted. An initial SSLRequest may also be used in a connection that is being opened to send a CancelRequest message. While the protocol itself does not provide a way for the server to force SSL encryption, the administrator may configure the server to reject unencrypted sessions as a byproduct of authentication checking.
M | SSLSuccess | SSLConnected | Send the regular Startup Package to the backend and switch to the SSL Connected State.
M | SSLFailed | Ground Zero | Close the current connection and return to Ground Zero. The caller might then choose to open a connection without SSL encryption.
M | Error | Ground Zero | This would only occur if the server predates the addition of SSL support to PostgreSQL. The current connection is closed and state is returned to Ground Zero. The caller might then choose to open a connection without SSL encryption.
SSL Connected
This state is entered after successfully establishing a Secure Socket Layer Connection. Communications at this point are already encrypted. This states corresponds to the unsecured Connected state: The Caller may now choose to issue a Startup Package or a Cancel Reques Message.
F | Startup() | Startup | The frontend sends a regular Startup Package. This will install a regular secured connection to the backend.
F | CancelReq() | Ground Zero | The frontend sends a Cancel Request Message. It contains the PID and Secret Key which have been previously received in a different startup sequence. After processing this message the backend will close the connection immediately. So should the frontend do, an then return to Ground Zero.
M | Error | Ground Zero | This message should not occur in this state, as the backend is awaiting a message from the frontend. The frontend issues a Terminate Message, Closes the Connection and returns to Ground Zero.
Startup
In this phase the authentication takes place. The course of the previous startup sequence determines if the connection is secured or not. The backend decides the authentication method by the information sent in the Startup Package and the contents of its pg_hba.conf file. If the frontend does not support the requested authentication method, then it should immediately close the connection and return to Ground Zero.
M | AuthKer4 | Startup | The backend demands a Kerberos V4 authentication dialog (not described here, part of the Kerberos specification). Not shure what to be done here. Currently not supported.
M | AuthKer5 | Startup | The backend demands a Kerberos V5 authentication dialog (not described here, part of the Kerberos specification). Not shure what to be done here. Currently not supported.
M | AuthClearTxt | Startup | The frontend must then send a PasswordPacket containing the password in clear-text form.
M | AuthCrypt | Startup | The frontend must then send a PasswordPacket containing the password encrypted via crypt(3), using the 2-character salt specified in the AuthenticationCryptPassword packet. Currently not supported.
M | AuthMD5 | Startup | The frontend must then send a PasswordPacket containing the password encrypted via MD5, using the 4-character salt specified in the AuthenticationMD5Password packet. Currently not supported.
M | AuthCred | Startup | This method is only possible for local Unix-domain connections on platforms that support SCM credential messages. The frontend must issue an SCM credential message and then send a single data byte. (The contents of the data byte are uninteresting; it's only used to ensure that the server waits long enough to receive the credential message.) Currently not supported.
M | AuthOK | Authenticated | The authentication exchange is successfully completed. The "Authenticated" state is entered then.
M | Error | Ground Zero | The authentication exchange failed. After sending this message the server immediately closes the connection. The frontend also closes the connection and returns to Ground Zero.
Authenticated
After having received the AuthenticationOk, the server should send the BackendKeyData Message and then a ReadyForQuery Message. This will conclude the startup/authentication sequence and the connetion will enter its normal operational mode.
M | BackendKey | ? I(fxjr) think it should be in the same state Authenticated. | The BackendKeyData Message provides the PID and the secret-key data that the frontend must save if it wants to be able to issue cancel requests later. The frontend should not respond to this message, but should continue listening for a ReadyForQuery message.
M | ReadyForQuery | Ready | The ReadyForQuery message concludes the startup sequence. The frontend enters the ReadyForQuery State and may then issue query or function call messages.
M | Error | ? | Start-up failed for some reason. The frontend closes the socket connection and returns to Ground Zero.
M | Notice | Startup I(fxjr) think it should be in the same state Authenticated. Of course it can change also depending on what this Notice message is saying. :) | A warning message is sent to the frontend in a NoticeResponse Message. The frontend should display the message but continue listening for ReadyForQuery or Error.
Ready for Query (Ready)
This state indicates the backend is ready to accept Query or Function Call Messages.
A | Query() | Query | A Query Cycle is initiated by the frontend sending a Query Message to the backend. A state transition to Query is done.
A | FunctionCall() | ? State Function Call as defined below?? :) | This method generates a Function Call Message. A state transition to FunctionCall is done.
A | Listen() | Ready | After sending a Listen Command the frontend is enabled to receive notification messages. If a Notify Command is executed for the same notification name. State is not affected.
M | Notice | Ready | A warning message has been issued. The warning should be displayed. Not to be confused with Notification Messages.
M | Notification | Ready | A Notify command has been executed for a name for which a previous Listen command was executed. Notification Response Messages may be sent at any time. State is not affected.
Query Processing (Query)
A Query cycle is initiated by the frontend sending a Query message to the backend. The backend then sends one or more response messages depending on the contents of the query command string, and finally a ReadyForQuery response message. Since a query string could contain several queries (separated by semicolons), there might be several such response sequences before the backend finishes processing the query string. ReadyForQuery is issued when the entire string has been processed and the backend is ready to accept a new query string. In the event of an error, an Error Message is issued followed by ReadyForQuery. All further processing of the query string is aborted by Error Response (even if more queries remained in it). Note that this may occur partway through the sequence of messages generated by an individual query.
M | Completed | Query | The Completed Response Message Informs the FE that an SQL command completed normally. This message is sent for each separate statement in the query string.
M | CopyIn | Query | The Copy In Response Message tells the backend is ready to copy data from the frontend to a table. The frontend should then send a CopyDataRows message. The backend will then respond with a CompletedResponse message with a tag of COPY.
M | CopyOut | Query | The backend is ready to copy data from a table to the frontend. This is signaled by the Copy Out Response Message. It then sends a CopyDataRows message, and then a CompletedResponse message with a tag of COPY.
M | CopyDataRows | Query | The backend sends data in a CopyDataRows Message to the frontend. This is a stream of rows where each row is terminated by a Byte1('\n'). This is then followed by the sequence Byte1('\\'), Byte1('.'), Byte1('\n').
F | CopyDataRows() | Query | The frontend sends data in a CopyDataRows Message to the backend.
M | Cursor | Query | The Cursor Response Message indicates the beginning of the response to a SELECT, FETCH, INSERT, UPDATE, or DELETE query. In the FETCH case the name of the cursor being fetched from is included in the message. Otherwise the message always mentions the "blank" cursor.
M | RowDescription | Query | The Row Description message indicates that rows are about to be returned in response to a SELECT or FETCH query. The message contents describe the layout of the rows. This will be followed by an AsciiRow or BinaryRow message (depending on whether a binary cursor was specified) for each row being returned to the frontend.
M | AsciiRow | Query | Identifies the message as an ASCII data row. A prior RowDescription message defines the number of fields in the row and their data types.
M | BinaryRow | Query | Identifies the message as an binary data row. A prior RowDescription message defines the number of fields in the row and their data types.
M | EmptyQuery | Query | The Empty Query Response Message indicates an empty query string was recognized.
M | Error | Query | An error has occured. This will normally be followed by a ReadyForQuery Message.
M | ReadyForQuery | Ready | Processing of the query string is complete. ReadyForQuery will always be sent, whether processing terminates successfully or with an error. A transition is done to the Ready for Query state.
M | Notice | Query | A warning message has been issued in relation to the query. Notices are in addition to other responses, i.e., the backend will continue processing the command.
M | Notification | Query | A Notify Command has been executed for a name for which a previous Listen Command has been executed. Notifications may be sent at any time, but not within a message.
Function Call (Function)
A transition to the Funcktion Call State is initiated by the frontend by sending a Function Call Message to the backend. The backend then sends one or more response messages depending on the results of the function call, and finally a ReadyForQuery Response Message, which results in a transition to the Ready For Query state.
M | Error | Function | An Error has occured. The frontend should display a message.
M | FunctionResult | Function | The Function Result Response Messages indicates a successful function call processing and returns a result to the frontend.
M | FunctionVoid | Function | The Function Void Response Messages indicates a successful function call processing, it does not return a result to the frontend.
M | ReadyForQuery | Ready | Processing of the function call is complete. Results in a transition to the Ready For Query state. ReadyForQuery will always be sent, whether processing terminates successfully or with an error.
M | Notice | Function | A warning message has been issued in relation to the function call. Notices are in addition to other responses, i.e., the backend will continue processing the command.
M | Notification | Function | A Notify Command has been executed for a name for which a previous Listen Command was executed. Notifications may be sent at any time.

## State Diagram

NpgsqlConnection StateMachine

## Methods

### Terminate()

The frontend sends a Terminate message and immedialtely closes the connection. The connection state will transit to Ground Zero.

This method is available in all states except Ground Zero.

### Listen()

The Listen Command enables the client to receive notification messages regarding a specific topic.

The Listen() Method is not available in the following states:

- Ground Zero
- Connected
- SSLStartup
- SSLHandshake
- SSLConnected
- Startup

### Notify()

A Notification Command Message is sent to the backend. The backend will respond by sending notification messages to all frontends which previously have subscribed with a Listen Command Message to the same topic.

## Message Definitions

Message Definitions are specified in the PostgreSQL Frontend/Backend Protocol