On Linux, we heavily use --remote=punix:* to listen for
connections through unix domain sockets. We also use, unix:*
to connect to a daemon that is listening on unix domain sockets.
Many times, we create default unix domain sockets for listening
and many utilities connect to these sockets by default.
Windows does not have unix domain sockets. So far, we could just use
ptcp:* and tcp:* for listening and initiating connections respectively.
The drawback here is that one has to provide a specific TCP port.
For unit tests, it looks useful to let kernel choose that port.
As such, we can let that chosen kernel port be stored in the
file specified with punix:* and unix:*. For this purpose, introduce
a new [p]windows_[p]stream_class. Since it is just a wrapper around
[p]tcp_[p]stream_class, add it to stream-tcp.c.
commit
cb54a8c (unixctl: Add support for Windows.) used the above concept
for only control channel connections (i.e., --unixctl for daemons and its
interaction with ovs-appctl). This commit adds the same support for
all unix domain sockets. Now that we have a separate class
[p]stream_class for hiding kernel assigned TCP port inside a file meant for
unix domain sockets in windows, make unixctl use it.
Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
/* Active and passive stream classes. */
extern const struct stream_class tcp_stream_class;
extern const struct pstream_class ptcp_pstream_class;
+#ifndef _WIN32
extern const struct stream_class unix_stream_class;
extern const struct pstream_class punix_pstream_class;
+#else
+extern const struct stream_class windows_stream_class;
+extern const struct pstream_class pwindows_pstream_class;
+#endif
#ifdef HAVE_OPENSSL
extern const struct stream_class ssl_stream_class;
extern const struct pstream_class pssl_pstream_class;
NULL, /* run_wait */
NULL, /* wait */
};
+
+#ifdef _WIN32
+static int
+windows_open(const char *name, char *suffix, struct stream **streamp,
+ uint8_t dscp)
+{
+ int error, port;
+ FILE *file;
+ char *suffix_new, *path;
+
+ /* If the path does not contain a ':', assume it is relative to
+ * OVS_RUNDIR. */
+ if (!strchr(suffix, ':')) {
+ path = xasprintf("%s/%s", ovs_rundir(), suffix);
+ } else {
+ path = strdup(suffix);
+ }
+
+ file = fopen(path, "r");
+ if (!file) {
+ error = errno;
+ VLOG_DBG("%s: could not open %s (%s)", name, suffix,
+ ovs_strerror(error));
+ return error;
+ }
+
+ error = fscanf(file, "%d", &port);
+ if (error != 1) {
+ VLOG_ERR("failed to read port from %s", suffix);
+ fclose(file);
+ return EINVAL;
+ }
+ fclose(file);
+
+ suffix_new = xasprintf("127.0.0.1:%d", port);
+
+ error = tcp_open(name, suffix_new, streamp, dscp);
+
+ free(suffix_new);
+ free(path);
+ return error;
+}
+
+const struct stream_class windows_stream_class = {
+ "unix", /* name */
+ false, /* needs_probes */
+ windows_open, /* open */
+ NULL, /* close */
+ NULL, /* connect */
+ NULL, /* recv */
+ NULL, /* send */
+ NULL, /* run */
+ NULL, /* run_wait */
+ NULL, /* wait */
+};
+#endif
\f
/* Passive TCP. */
NULL,
};
+#ifdef _WIN32
+static int
+pwindows_open(const char *name OVS_UNUSED, char *suffix,
+ struct pstream **pstreamp, uint8_t dscp)
+{
+ int error;
+ char *suffix_new, *path;
+ FILE *file;
+ struct pstream *listener;
+
+ suffix_new = xstrdup("0:127.0.0.1");
+ error = ptcp_open(name, suffix_new, pstreamp, dscp);
+ if (error) {
+ goto exit;
+ }
+ listener = *pstreamp;
+
+ /* If the path does not contain a ':', assume it is relative to
+ * OVS_RUNDIR. */
+ if (!strchr(suffix, ':')) {
+ path = xasprintf("%s/%s", ovs_rundir(), suffix);
+ } else {
+ path = strdup(suffix);
+ }
+
+ file = fopen(path, "w");
+ if (!file) {
+ error = errno;
+ VLOG_DBG("could not open %s (%s)", path, ovs_strerror(error));
+ goto exit;
+ }
+
+ fprintf(file, "%d\n", ntohs(listener->bound_port));
+ if (fflush(file) == EOF) {
+ error = EIO;
+ VLOG_ERR("write failed for %s", path);
+ fclose(file);
+ goto exit;
+ }
+ fclose(file);
+ free(path);
+
+exit:
+ free(suffix_new);
+ return error;
+}
+
+const struct pstream_class pwindows_pstream_class = {
+ "punix",
+ false,
+ pwindows_open,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+#endif
&tcp_stream_class,
#ifndef _WIN32
&unix_stream_class,
+#else
+ &windows_stream_class,
#endif
#ifdef HAVE_OPENSSL
&ssl_stream_class,
&ptcp_pstream_class,
#ifndef _WIN32
&punix_pstream_class,
+#else
+ &pwindows_pstream_class,
#endif
#ifdef HAVE_OPENSSL
&pssl_pstream_class,
{
struct unixctl_server *server;
struct pstream *listener;
- char *punix_path, *abs_path = NULL;
+ char *punix_path;
int error;
-#ifdef _WIN32
- FILE *file;
-#endif
*serverp = NULL;
if (path && !strcmp(path, "none")) {
return 0;
}
-#ifndef _WIN32
if (path) {
+ char *abs_path;
+#ifndef _WIN32
abs_path = abs_file_name(ovs_rundir(), path);
+#else
+ abs_path = strdup(path);
+#endif
punix_path = xasprintf("punix:%s", abs_path);
+ free(abs_path);
} else {
+#ifndef _WIN32
punix_path = xasprintf("punix:%s/%s.%ld.ctl", ovs_rundir(),
program_name, (long int) getpid());
- }
#else
- punix_path = xstrdup("ptcp:0:127.0.0.1");
+ punix_path = xasprintf("punix:%s/%s.ctl", ovs_rundir(), program_name);
#endif
+ }
error = pstream_open(punix_path, &listener, 0);
if (error) {
goto exit;
}
-#ifdef _WIN32
- if (path) {
- abs_path = xstrdup(path);
- } else {
- abs_path = xasprintf("%s/%s.ctl", ovs_rundir(), program_name);
- }
-
- file = fopen(abs_path, "w");
- if (!file) {
- error = errno;
- ovs_error(error, "could not open %s", abs_path);
- goto exit;
- }
-
- fprintf(file, "%d\n", ntohs(listener->bound_port));
- if (fflush(file) == EOF) {
- error = EIO;
- ovs_error(error, "write failed for %s", abs_path);
- fclose(file);
- goto exit;
- }
- fclose(file);
-#endif
-
unixctl_command_register("help", "", 0, 0, unixctl_help, NULL);
unixctl_command_register("version", "", 0, 0, unixctl_version, NULL);
*serverp = server;
exit:
- if (abs_path) {
- free(abs_path);
- }
free(punix_path);
return error;
}
char *abs_path, *unix_path;
struct stream *stream;
int error;
-#ifdef _WIN32
- FILE *file;
- int port;
+#ifdef _WIN32
abs_path = strdup(path);
- file = fopen(abs_path, "r");
- if (!file) {
- int error = errno;
- ovs_error(error, "could not open %s", abs_path);
- free(abs_path);
- return error;
- }
-
- error = fscanf(file, "%d", &port);
- if (error != 1) {
- ovs_error(errno, "failed to read port from %s", abs_path);
- free(abs_path);
- return EINVAL;
- }
- fclose(file);
-
- unix_path = xasprintf("tcp:127.0.0.1:%d", port);
#else
abs_path = abs_file_name(ovs_rundir(), path);
- unix_path = xasprintf("unix:%s", abs_path);
#endif
+ unix_path = xasprintf("unix:%s", abs_path);
*client = NULL;
value.
.TP
\fBunix:\fIfile\fR
-The Unix domain server socket named \fIfile\fR.
+On POSIX, a Unix domain server socket named \fIfile\fR.
+.IP
+On Windows, a localhost TCP port written in \fIfile\fR.
square brackets, e.g.: \fBtcp:[::1]:6632\fR.
.
.IP "\fBunix:\fIfile\fR"
-Connect to the Unix domain server socket named \fIfile\fR.
+On POSIX, connect to the Unix domain server socket named \fIfile\fR.
+.IP
+On Windows, connect to a localhost TCP port whose value is written in
+\fIfile\fR.
\fBptcp:6632:[::1]\fR.
.
.IP "\fBpunix:\fIfile\fR"
-Listen on the Unix domain server socket named \fIfile\fR for a
+On POSIX, listen on the Unix domain server socket named \fIfile\fR for a
connection.
+.IP
+On Windows, listen on a kernel chosen TCP port on the localhost. The kernel
+chosen TCP port value is written in \fIfile\fR.