+/* 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)
+{
+ const struct pstream_class *class;
+ return pstream_lookup_class(name, &class);
+}
+
+/* Returns 1 if the stream or pstream specified by 'name' needs periodic probes
+ * to verify connectivity. For [p]streams which need probes, it can take a
+ * long time to notice the connection has been dropped. Returns 0 if the
+ * stream or pstream does not need probes, and -1 if 'name' is not valid. */
+int
+stream_or_pstream_needs_probes(const char *name)
+{
+ const struct pstream_class *pclass;
+ const struct stream_class *class;
+
+ if (!stream_lookup_class(name, &class)) {
+ return class->needs_probes;
+ } else if (!pstream_lookup_class(name, &pclass)) {
+ return pclass->needs_probes;
+ } else {
+ return -1;
+ }
+}
+
+/* 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, uint8_t dscp)
+{
+ const struct pstream_class *class;
+ struct pstream *pstream;
+ char *suffix_copy;
+ int error;
+
+ COVERAGE_INC(pstream_open);
+
+#ifdef _WIN32
+ winsock_start();
+#endif
+
+ /* 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, dscp);
+ free(suffix_copy);
+ if (error) {
+ goto error;
+ }
+
+ /* Success. */
+ *pstreamp = pstream;
+ return 0;
+
+error:
+ *pstreamp = NULL;
+ return error;
+}
+