+/* Like pstream_open(), but port defaults to 'default_port' if no port
+ * number is given. */
+int
+pstream_open_with_default_port(const char *name_,
+ uint16_t default_port,
+ struct pstream **pstreamp,
+ uint8_t dscp)
+{
+ char *name;
+ int error;
+
+ if ((!strncmp(name_, "ptcp:", 5) || !strncmp(name_, "pssl:", 5))
+ && count_fields(name_) < 2) {
+ name = xasprintf("%s%d", name_, default_port);
+ } else {
+ name = xstrdup(name_);
+ }
+ error = pstream_open(name, pstreamp, dscp);
+ free(name);
+
+ return error;
+}
+
+/*
+ * This function extracts IP address and port from the target string.
+ *
+ * - On success, function returns true and fills *ss structure with port
+ * and IP address. If port was absent in target string then it will use
+ * corresponding default port value.
+ * - On error, function returns false and *ss contains garbage.
+ */
+bool
+stream_parse_target_with_default_port(const char *target,
+ uint16_t default_port,
+ struct sockaddr_storage *ss)
+{
+ return ((!strncmp(target, "tcp:", 4) || !strncmp(target, "ssl:", 4))
+ && inet_parse_active(target + 4, default_port, ss));
+}
+
+/* Attempts to guess the content type of a stream whose first few bytes were
+ * the 'size' bytes of 'data'. */
+static enum stream_content_type
+stream_guess_content(const uint8_t *data, ssize_t size)
+{
+ if (size >= 2) {
+#define PAIR(A, B) (((A) << 8) | (B))
+ switch (PAIR(data[0], data[1])) {
+ case PAIR(0x16, 0x03): /* Handshake, version 3. */
+ return STREAM_SSL;
+ case PAIR('{', '"'):
+ return STREAM_JSONRPC;
+ case PAIR(OFP10_VERSION, 0 /* OFPT_HELLO */):
+ return STREAM_OPENFLOW;
+ }
+ }
+
+ return STREAM_UNKNOWN;
+}
+
+/* Returns a string represenation of 'type'. */
+static const char *
+stream_content_type_to_string(enum stream_content_type type)