+ if (fsm->state != S_CONNECTING) {
+ if (fsm->passive) {
+ VLOG(fsm->info, "%s: listening...", fsm->name);
+ } else {
+ VLOG(fsm->info, "%s: connecting...", fsm->name);
+ }
+ reconnect_transition__(fsm, now, S_CONNECTING);
+ }
+}
+
+/* Tell 'fsm' that the client is listening for connection attempts. This state
+ * last indefinitely until the client reports some change.
+ *
+ * The natural progression from this state is for the client to report that a
+ * connection has been accepted or is in progress of being accepted, by calling
+ * reconnect_connecting() or reconnect_connected().
+ *
+ * The client may also report that listening failed (e.g. accept() returned an
+ * unexpected error such as ENOMEM) by calling reconnect_listen_error(), in
+ * which case the FSM will back off and eventually return RECONNECT_CONNECT
+ * from reconnect_run() to tell the client to try listening again. */
+void
+reconnect_listening(struct reconnect *fsm, long long int now)
+{
+ if (fsm->state != S_LISTENING) {
+ VLOG(fsm->info, "%s: listening...", fsm->name);
+ reconnect_transition__(fsm, now, S_LISTENING);
+ }
+}
+
+/* Tell 'fsm' that the client's attempt to accept a connection failed
+ * (e.g. accept() returned an unexpected error such as ENOMEM).
+ *
+ * If the FSM is currently listening (reconnect_listening() was called), it
+ * will back off and eventually return RECONNECT_CONNECT from reconnect_run()
+ * to tell the client to try listening again. If there is an active
+ * connection, this will be delayed until that connection drops. */
+void
+reconnect_listen_error(struct reconnect *fsm, long long int now, int error)
+{
+ if (fsm->state == S_LISTENING) {
+ reconnect_disconnected(fsm, now, error);