bridge: Optimize port_lookup() using a hash.
[openvswitch] / lib / stream.c
index ed497d693300c9bfba3511700ee78552ee2231a5..43b73af0adf9f7f542019a031e57b3515a799298 100644 (file)
@@ -25,6 +25,7 @@
 #include <string.h>
 #include "coverage.h"
 #include "dynamic-string.h"
+#include "fatal-signal.h"
 #include "flow.h"
 #include "ofp-print.h"
 #include "ofpbuf.h"
@@ -222,13 +223,23 @@ error:
     return error;
 }
 
+/* Blocks until a previously started stream connection attempt succeeds or
+ * fails.  'error' should be the value returned by stream_open() and 'streamp'
+ * should point to the stream pointer set by stream_open().  Returns 0 if
+ * successful, otherwise a positive errno value other than EAGAIN or
+ * EINPROGRESS.  If successful, leaves '*streamp' untouched; on error, closes
+ * '*streamp' and sets '*streamp' to null.
+ *
+ * Typical usage:
+ *   error = stream_open_block(stream_open("tcp:1.2.3.4:5", &stream), &stream);
+ */
 int
-stream_open_block(const char *name, struct stream **streamp)
+stream_open_block(int error, struct stream **streamp)
 {
-    struct stream *stream;
-    int error;
+    struct stream *stream = *streamp;
+
+    fatal_signal_run();
 
-    error = stream_open(name, &stream);
     while (error == EAGAIN) {
         stream_run(stream);
         stream_run_wait(stream);
@@ -562,6 +573,7 @@ pstream_accept_block(struct pstream *pstream, struct stream **new_stream)
 {
     int error;
 
+    fatal_signal_run();
     while ((error = pstream_accept(pstream, new_stream)) == EAGAIN) {
         pstream_wait(pstream);
         poll_block();
@@ -639,3 +651,72 @@ pstream_init(struct pstream *pstream, struct pstream_class *class,
     pstream->class = class;
     pstream->name = xstrdup(name);
 }
+\f
+static int
+count_fields(const char *s_)
+{
+    char *s, *field, *save_ptr;
+    int n = 0;
+
+    save_ptr = NULL;
+    s = xstrdup(s_);
+    for (field = strtok_r(s, ":", &save_ptr); field != NULL;
+         field = strtok_r(NULL, ":", &save_ptr)) {
+        n++;
+    }
+    free(s);
+
+    return n;
+}
+
+/* Like stream_open(), but for tcp streams the port defaults to
+ * 'default_tcp_port' if no port number is given and for SSL streams the port
+ * defaults to 'default_ssl_port' if no port number is given. */
+int
+stream_open_with_default_ports(const char *name_,
+                               uint16_t default_tcp_port,
+                               uint16_t default_ssl_port,
+                               struct stream **streamp)
+{
+    char *name;
+    int error;
+
+    if (!strncmp(name_, "tcp:", 4) && count_fields(name_) < 3) {
+        name = xasprintf("%s:%d", name_, default_tcp_port);
+    } else if (!strncmp(name_, "ssl:", 4) && count_fields(name_) < 3) {
+        name = xasprintf("%s:%d", name_, default_ssl_port);
+    } else {
+        name = xstrdup(name_);
+    }
+    error = stream_open(name, streamp);
+    free(name);
+
+    return error;
+}
+
+/* Like pstream_open(), but for ptcp streams the port defaults to
+ * 'default_ptcp_port' if no port number is given and for passive SSL streams
+ * the port defaults to 'default_pssl_port' if no port number is given. */
+int
+pstream_open_with_default_ports(const char *name_,
+                                uint16_t default_ptcp_port,
+                                uint16_t default_pssl_port,
+                                struct pstream **pstreamp)
+{
+    char *name;
+    int error;
+
+    if (!strncmp(name_, "ptcp:", 5) && count_fields(name_) < 2) {
+        name = xasprintf("%s%d", name_, default_ptcp_port);
+    } else if (!strncmp(name_, "pssl:", 5) && count_fields(name_) < 2) {
+        name = xasprintf("%s%d", name_, default_pssl_port);
+    } else {
+        name = xstrdup(name_);
+    }
+    error = pstream_open(name, pstreamp);
+    free(name);
+
+    return error;
+}
+
+