Add the ability to connect to a vconn asynchronously.
[sliver-openvswitch.git] / include / vconn.h
index 064947c..a305523 100644 (file)
@@ -34,24 +34,31 @@ struct pollfd;
 /* Virtual connection to an OpenFlow device. */
 struct vconn {
     struct vconn_class *class;
-};
-
-/* What kind of operation do we want to perform? */
-enum {
-    WANT_ACCEPT = 1 << 0,          /* Want to accept a new connection. */
-    WANT_RECV = 1 << 1,            /* Want to receive a message. */
-    WANT_SEND = 1 << 2             /* Want to send a message. */
+    int connect_status;
 };
 
 int vconn_open(const char *name, struct vconn **);
 void vconn_close(struct vconn *);
 bool vconn_is_passive(const struct vconn *);
-bool vconn_prepoll(struct vconn *, int want, struct pollfd *);
-void vconn_postpoll(struct vconn *, short int *revents);
+int vconn_connect(struct vconn *);
 int vconn_accept(struct vconn *, struct vconn **);
 int vconn_recv(struct vconn *, struct buffer **);
 int vconn_send(struct vconn *, struct buffer *);
-int vconn_send_wait(struct vconn *, struct buffer *);
+
+int vconn_open_block(const char *name, struct vconn **);
+int vconn_send_block(struct vconn *, struct buffer *);
+
+enum vconn_wait_type {
+    WAIT_CONNECT,
+    WAIT_ACCEPT,
+    WAIT_RECV,
+    WAIT_SEND
+};
+void vconn_wait(struct vconn *, enum vconn_wait_type);
+void vconn_connect_wait(struct vconn *);
+void vconn_accept_wait(struct vconn *);
+void vconn_recv_wait(struct vconn *);
+void vconn_send_wait(struct vconn *);
 
 struct buffer *make_add_simple_flow(const struct flow *,
                                     uint32_t buffer_id, uint16_t out_port);
@@ -69,43 +76,29 @@ struct vconn_class {
     /* Attempts to connect to an OpenFlow device.  'name' is the full
      * connection name provided by the user, e.g. "nl:0", "tcp:1.2.3.4".  This
      * name is useful for error messages but must not be modified.
-     * 
+     *
      * 'suffix' is a copy of 'name' following the colon and may be modified.
      *
      * Returns 0 if successful, otherwise a positive errno value.  If
-     * successful, stores a pointer to the new connection in '*vconnp'. */
+     * successful, stores a pointer to the new connection in '*vconnp'.
+     *
+     * The open function must not block waiting for a connection to complete.
+     * If the connection cannot be completed immediately, it should return
+     * EAGAIN (not EINPROGRESS, as returned by the connect system call) and
+     * continue the connection in the background. */
     int (*open)(const char *name, char *suffix, struct vconn **vconnp);
 
     /* Closes 'vconn' and frees associated memory. */
     void (*close)(struct vconn *vconn);
 
-    /* Called by the main loop before calling poll(), this function must
-     * initialize 'pfd->fd' and 'pfd->events' appropriately so that poll() will
-     * wake up when the connection becomes available for the operations
-     * specified in 'want'.  The prepoll function may also set bits in 'pfd' to
-     * allow for internal processing.
-     *
-     * Should return false normally.  May return true to indicate that no
-     * blocking should happen in poll() because the connection is available for
-     * some operation specified in 'want' but that status cannot be detected
-     * via poll() and thus poll() could block forever otherwise. */
-    bool (*prepoll)(struct vconn *, int want, struct pollfd *pfd);
-
-    /* Called by the main loop after calling poll(), this function may perform
-     * any internal processing needed by the connection.  It is provided with
-     * the vconn file descriptor's status in '*revents', as reported by poll().
+    /* Tries to complete the connection on 'vconn', which must be an active
+     * vconn.  If 'vconn''s connection is complete, returns 0 if the connection
+     * was successful or a positive errno value if it failed.  If the
+     * connection is still in progress, returns EAGAIN.
      *
-     * The postpoll function should adjust '*revents' to reflect the status of
-     * the connection from the caller's point of view: that is, upon return
-     * '*revents & POLLIN' should indicate that a packet is (potentially) ready
-     * to be read (for an active vconn) or a new connection is ready to be
-     * accepted (for a passive vconn) and '*revents & POLLOUT' should indicate
-     * that a packet is (potentially) ready to be written.
-     *
-     * This function may be a null pointer in a vconn class that has no use for
-     * it, that is, if the vconn does not need to do any internal processing
-     * and poll's revents out properly reflects the vconn's status.  */
-    void (*postpoll)(struct vconn *, short int *revents);
+     * The connect function must not block waiting for the connection to
+     * complete; instead, it should return EAGAIN immediately. */
+    int (*connect)(struct vconn *vconn);
 
     /* Tries to accept a new connection on 'vconn', which must be a passive
      * vconn.  If successful, stores the new connection in '*new_vconnp' and
@@ -114,7 +107,7 @@ struct vconn_class {
      * The accept function must not block waiting for a connection.  If no
      * connection is ready to be accepted, it should return EAGAIN.
      *
-     * Nonnull iff this is a passive vconn (one that accepts connection and
+     * Nonnull iff this is a passive vconn (one that accepts connections and
      * does not transfer data). */
     int (*accept)(struct vconn *vconn, struct vconn **new_vconnp);
 
@@ -148,6 +141,8 @@ struct vconn_class {
      * Nonnull iff this is an active vconn (one that transfers data and does
      * not accept connections). */
     int (*send)(struct vconn *vconn, struct buffer *msg);
+
+    void (*wait)(struct vconn *vconn, enum vconn_wait_type);
 };
 
 extern struct vconn_class tcp_vconn_class;