From: Ben Pfaff Date: Tue, 23 Mar 2010 22:30:17 +0000 (-0700) Subject: stream: New functions stream_verify_name() and pstream_verify_name(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26ad129e69fc7c800630dbd541dc2dcc8150c3a4;p=openvswitch 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(). --- 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 * diff --git a/lib/stream.h b/lib/stream.h index e7eef365..d21de2f7 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -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 *);