stream: New functions stream_verify_name() and pstream_verify_name().
authorBen Pfaff <blp@nicira.com>
Tue, 23 Mar 2010 22:30:17 +0000 (15:30 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 12 Apr 2010 18:03:32 +0000 (11:03 -0700)
These functions can be useful for checking whether a given name is an
active or passive connection method.

The implementation is cut-and-paste from vconn_verify_name() and
pvconn_verify_name().

lib/stream.c
lib/stream.h

index db6ec61..ed497d6 100644 (file)
@@ -145,46 +145,83 @@ stream_usage(const char *name, bool active, bool passive,
 #endif
 }
 
-/* Attempts to connect a stream to a remote peer.  'name' is a connection name
- * in the form "TYPE:ARGS", where TYPE is an active stream class's name and
- * ARGS are stream class-specific.
- *
- * Returns 0 if successful, otherwise a positive errno value.  If successful,
- * stores a pointer to the new connection in '*streamp', otherwise a null
- * pointer.  */
-int
-stream_open(const char *name, struct stream **streamp)
+/* Given 'name', a stream name in the form "TYPE:ARGS", stores the class
+ * named "TYPE" into '*classp' and returns 0.  Returns EAFNOSUPPORT and stores
+ * a null pointer into '*classp' if 'name' is in the wrong form or if no such
+ * class exists. */
+static int
+stream_lookup_class(const char *name, struct stream_class **classp)
 {
     size_t prefix_len;
     size_t i;
 
-    COVERAGE_INC(stream_open);
     check_stream_classes();
 
-    *streamp = NULL;
+    *classp = NULL;
     prefix_len = strcspn(name, ":");
-    if (prefix_len == strlen(name)) {
+    if (name[prefix_len] == '\0') {
         return EAFNOSUPPORT;
     }
     for (i = 0; i < ARRAY_SIZE(stream_classes); i++) {
         struct stream_class *class = stream_classes[i];
         if (strlen(class->name) == prefix_len
             && !memcmp(class->name, name, prefix_len)) {
-            struct stream *stream;
-            char *suffix_copy = xstrdup(name + prefix_len + 1);
-            int retval = class->open(name, suffix_copy, &stream);
-            free(suffix_copy);
-            if (!retval) {
-                assert(stream->state != SCS_CONNECTING
-                       || stream->class->connect);
-                *streamp = stream;
-            }
-            return retval;
+            *classp = class;
+            return 0;
         }
     }
     return EAFNOSUPPORT;
 }
 
+/* Returns 0 if 'name' is a stream name in the form "TYPE:ARGS" and TYPE is
+ * a supported stream type, otherwise EAFNOSUPPORT.  */
+int
+stream_verify_name(const char *name)
+{
+    struct stream_class *class;
+    return stream_lookup_class(name, &class);
+}
+
+/* Attempts to connect a stream to a remote peer.  'name' is a connection name
+ * in the form "TYPE:ARGS", where TYPE is an active stream class's name and
+ * ARGS are stream class-specific.
+ *
+ * Returns 0 if successful, otherwise a positive errno value.  If successful,
+ * stores a pointer to the new connection in '*streamp', otherwise a null
+ * pointer.  */
+int
+stream_open(const char *name, struct stream **streamp)
+{
+    struct stream_class *class;
+    struct stream *stream;
+    char *suffix_copy;
+    int error;
+
+    COVERAGE_INC(stream_open);
+
+    /* Look up the class. */
+    error = stream_lookup_class(name, &class);
+    if (!class) {
+        goto error;
+    }
+
+    /* Call class's "open" function. */
+    suffix_copy = xstrdup(strchr(name, ':') + 1);
+    error = class->open(name, suffix_copy, &stream);
+    free(suffix_copy);
+    if (error) {
+        goto error;
+    }
+
+    /* Success. */
+    *streamp = stream;
+    return 0;
+
+error:
+    *streamp = NULL;
+    return error;
+}
+
 int
 stream_open_block(const char *name, struct stream **streamp)
 {
@@ -399,42 +436,83 @@ stream_send_wait(struct stream *stream)
     stream_wait(stream, STREAM_SEND);
 }
 
-/* Attempts to start listening for remote stream connections.  'name' is a
- * connection name in the form "TYPE:ARGS", where TYPE is an passive stream
- * class's name and ARGS are stream class-specific.
- *
- * Returns 0 if successful, otherwise a positive errno value.  If successful,
- * stores a pointer to the new connection in '*pstreamp', otherwise a null
- * pointer.  */
-int
-pstream_open(const char *name, struct pstream **pstreamp)
+/* Given 'name', a pstream name in the form "TYPE:ARGS", stores the class
+ * named "TYPE" into '*classp' and returns 0.  Returns EAFNOSUPPORT and stores
+ * a null pointer into '*classp' if 'name' is in the wrong form or if no such
+ * class exists. */
+static int
+pstream_lookup_class(const char *name, struct pstream_class **classp)
 {
     size_t prefix_len;
     size_t i;
 
     check_stream_classes();
 
-    *pstreamp = NULL;
+    *classp = NULL;
     prefix_len = strcspn(name, ":");
-    if (prefix_len == strlen(name)) {
+    if (name[prefix_len] == '\0') {
         return EAFNOSUPPORT;
     }
     for (i = 0; i < ARRAY_SIZE(pstream_classes); i++) {
         struct pstream_class *class = pstream_classes[i];
         if (strlen(class->name) == prefix_len
             && !memcmp(class->name, name, prefix_len)) {
-            char *suffix_copy = xstrdup(name + prefix_len + 1);
-            int retval = class->listen(name, suffix_copy, pstreamp);
-            free(suffix_copy);
-            if (retval) {
-                *pstreamp = NULL;
-            }
-            return retval;
+            *classp = class;
+            return 0;
         }
     }
     return EAFNOSUPPORT;
 }
 
+/* Returns 0 if 'name' is a pstream name in the form "TYPE:ARGS" and TYPE is
+ * a supported pstream type, otherwise EAFNOSUPPORT.  */
+int
+pstream_verify_name(const char *name)
+{
+    struct pstream_class *class;
+    return pstream_lookup_class(name, &class);
+}
+
+/* Attempts to start listening for remote stream connections.  'name' is a
+ * connection name in the form "TYPE:ARGS", where TYPE is an passive stream
+ * class's name and ARGS are stream class-specific.
+ *
+ * Returns 0 if successful, otherwise a positive errno value.  If successful,
+ * stores a pointer to the new connection in '*pstreamp', otherwise a null
+ * pointer.  */
+int
+pstream_open(const char *name, struct pstream **pstreamp)
+{
+    struct pstream_class *class;
+    struct pstream *pstream;
+    char *suffix_copy;
+    int error;
+
+    COVERAGE_INC(pstream_open);
+
+    /* Look up the class. */
+    error = pstream_lookup_class(name, &class);
+    if (!class) {
+        goto error;
+    }
+
+    /* Call class's "open" function. */
+    suffix_copy = xstrdup(strchr(name, ':') + 1);
+    error = class->listen(name, suffix_copy, &pstream);
+    free(suffix_copy);
+    if (error) {
+        goto error;
+    }
+
+    /* Success. */
+    *pstreamp = pstream;
+    return 0;
+
+error:
+    *pstreamp = NULL;
+    return error;
+}
+
 /* Returns the name that was used to open 'pstream'.  The caller must not
  * modify or free the name. */
 const char *
index e7eef36..d21de2f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ struct stream;
 void stream_usage(const char *name, bool active, bool passive, bool bootstrap);
 
 /* Bidirectional byte streams. */
+int stream_verify_name(const char *name);
 int stream_open(const char *name, struct stream **);
 int stream_open_block(const char *name, struct stream **);
 void stream_close(struct stream *);
@@ -53,6 +54,7 @@ void stream_recv_wait(struct stream *);
 void stream_send_wait(struct stream *);
 
 /* Passive streams: listeners for incoming stream connections. */
+int pstream_verify_name(const char *name);
 int pstream_open(const char *name, struct pstream **);
 const char *pstream_get_name(const struct pstream *);
 void pstream_close(struct pstream *);