X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Funixctl.c;h=20acc3c9cbb2ef7f0e3215b4a262eb4366f48ebb;hb=7efa3dccd1968535ae32caf59746aa11ce7532f2;hp=e59056ef2a5dc8a3b5066655674c345f75e25fbd;hpb=d1673b006d53fdea72c0744e835362ed1917f879;p=sliver-openvswitch.git diff --git a/lib/unixctl.c b/lib/unixctl.c index e59056ef2..20acc3c9c 100644 --- a/lib/unixctl.c +++ b/lib/unixctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * 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 @@ #include "poll-loop.h" #include "shash.h" #include "stream.h" +#include "stream-provider.h" #include "svec.h" #include "vlog.h" @@ -168,7 +169,7 @@ unixctl_command_reply(struct unixctl_conn *conn, const char *result) } /* Replies to the active unixctl connection 'conn'. 'error' is sent to the - * client indicating an error occured processing the command. Only one call to + * client indicating an error occurred processing the command. Only one call to * unixctl_command_reply() or unixctl_command_reply_error() may be made per * request. */ void @@ -177,19 +178,26 @@ unixctl_command_reply_error(struct unixctl_conn *conn, const char *error) unixctl_command_reply__(conn, false, error); } -/* Creates a unixctl server listening on 'path', which may be: +/* Creates a unixctl server listening on 'path', which for POSIX may be: * * - NULL, in which case /..ctl is used. * - * - "none", in which case the function will return successfully but - * no socket will actually be created. - * * - A name that does not start with '/', in which case it is put in * . * * - An absolute path (starting with '/') that gives the exact name of * the Unix domain socket to listen on. * + * For Windows, a kernel assigned TCP port is used and written in 'path' + * which may be: + * + * - NULL, in which case /.ctl is used. + * + * - An absolute path that gives the name of the file. + * + * For both POSIX and Windows, if the path is "none", the function will + * return successfully but no socket will actually be created. + * * A program that (optionally) daemonizes itself should call this function * *after* daemonization, so that the socket name contains the pid of the * daemon instead of the pid of the program that exited. (Otherwise, @@ -203,22 +211,28 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp) { struct unixctl_server *server; struct pstream *listener; - char *punix_path; + char *punix_path, *abs_path = NULL; int error; +#ifdef _WIN32 + FILE *file; +#endif *serverp = NULL; if (path && !strcmp(path, "none")) { return 0; } +#ifndef _WIN32 if (path) { - char *abs_path = abs_file_name(ovs_rundir(), path); + abs_path = abs_file_name(ovs_rundir(), path); punix_path = xasprintf("punix:%s", abs_path); - free(abs_path); } else { 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"); +#endif error = pstream_open(punix_path, &listener, 0); if (error) { @@ -226,6 +240,30 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp) 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); @@ -235,6 +273,9 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp) *serverp = server; exit: + if (abs_path) { + free(abs_path); + } free(punix_path); return error; } @@ -358,7 +399,7 @@ unixctl_server_run(struct unixctl_server *server) } else { VLOG_WARN_RL(&rl, "%s: accept failed: %s", pstream_get_name(server->listener), - strerror(error)); + ovs_strerror(error)); } } @@ -404,9 +445,12 @@ unixctl_server_destroy(struct unixctl_server *server) } } -/* Connects to a unixctl server socket. 'path' should be the name of a unixctl - * server socket. If it does not start with '/', it will be prefixed with the - * rundir (e.g. /usr/local/var/run/openvswitch). +/* On POSIX based systems, connects to a unixctl server socket. 'path' should + * be the name of a unixctl server socket. If it does not start with '/', it + * will be prefixed with the rundir (e.g. /usr/local/var/run/openvswitch). + * + * On Windows, connects to a localhost TCP port as written inside 'path'. + * 'path' should be an absolute path of the file. * * Returns 0 if successful, otherwise a positive errno value. If successful, * sets '*client' to the new jsonrpc, otherwise to NULL. */ @@ -416,11 +460,35 @@ unixctl_client_create(const char *path, struct jsonrpc **client) char *abs_path, *unix_path; struct stream *stream; int error; +#ifdef _WIN32 + FILE *file; + int port; + + 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; + } - *client = NULL; + 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 + + *client = NULL; + error = stream_open_block(stream_open(unix_path, &stream, DSCP_DEFAULT), &stream); free(unix_path); @@ -462,7 +530,7 @@ unixctl_client_transact(struct jsonrpc *client, const char *command, int argc, error = jsonrpc_transact_block(client, request, &reply); if (error) { VLOG_WARN("error communicating with %s: %s", jsonrpc_get_name(client), - strerror(error)); + ovs_retval_to_string(error)); return error; }