aboutsummaryrefslogtreecommitdiff
path: root/lib/stream.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2010-03-23 15:30:17 -0700
committerBen Pfaff <blp@nicira.com>2010-04-12 11:03:32 -0700
commit26ad129e69fc7c800630dbd541dc2dcc8150c3a4 (patch)
tree4abd73e263bcf43bc2ea8cb75d07d03c8e001726 /lib/stream.c
parent218a6f5959af42f0fb089bc7d20f418d193832dc (diff)
stream: New functions stream_verify_name() and pstream_verify_name().
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().
Diffstat (limited to 'lib/stream.c')
-rw-r--r--lib/stream.c158
1 files changed, 118 insertions, 40 deletions
diff --git a/lib/stream.c b/lib/stream.c
index db6ec61b..ed497d69 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -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 *