Browse Source

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2009 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 15 years ago
parent
commit
51803e4064

+ 12 - 1
configure.ac

@@ -141,13 +141,15 @@ AC_SEARCH_LIBS(recvfrom, [socket])
 AC_HEADER_STDBOOL
 AC_TYPE_SIZE_T
 
+
+
 AC_MSG_CHECKING(for sa_len in struct sockaddr)
 AC_TRY_COMPILE([
 #include <sys/types.h>
 #include <sys/socket.h>],
 [struct sockaddr sa; sa.sa_len = 0; return (0);],
         [AC_MSG_RESULT(yes)
-        AC_DEFINE(HAVE_SIN_LEN, 1, Define to 1 if sockaddr_in has a sin_len member)],
+        AC_DEFINE(HAVE_SA_LEN, 1, [Define to 1 if sockaddr has a sa_len member, and corresponding sin_len and sun_len])],
         AC_MSG_RESULT(no))
 
 AC_ARG_WITH(lcov,
@@ -310,6 +312,13 @@ AC_SUBST(GTEST_LDADD)
 
 PKG_CHECK_MODULES(SQLITE, sqlite3 >= 3.3.9, enable_features="$enable_features SQLite3")
 
+# I can't get some of the #include <asio.hpp> right without this
+# TODO: find the real cause of asio/boost wanting pthreads
+# (this currently only occurs for src/lib/cc/session_unittests)
+PTHREAD_LDFLAGS=
+AC_CHECK_LIB(pthread, pthread_create,[ PTHREAD_LDFLAGS=-lpthread ], [])
+AC_SUBST(PTHREAD_LDFLAGS)
+
 #
 # ASIO: we extensively use it as the C++ event management module.
 #
@@ -450,7 +459,9 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            src/lib/python/isc/config/tests/config_test
            src/lib/python/isc/cc/tests/cc_test
            src/lib/dns/gen-rdatacode.py
+           src/lib/python/isc/cc/session.py
            src/lib/dns/tests/testdata/gen-wiredata.py
+           src/lib/cc/session_config.h.pre
           ], [
            chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
            chmod +x src/bin/xfrin/run_b10-xfrin.sh

+ 23 - 22
src/bin/bind10/bind10.py.in

@@ -158,24 +158,23 @@ class ProcessInfo:
 
 class BoB:
     """Boss of BIND class."""
-    def __init__(self, c_channel_port=9912, auth_port=5300, verbose=False):
+    
+    def __init__(self, msgq_socket_file=None, auth_port=5300, verbose=False):
         """Initialize the Boss of BIND. This is a singleton (only one
         can run).
         
-        The c_channel_port specifies the TCP/IP port that the msgq
-        process listens on. If verbose is True, then the boss reports
-        what it is doing.
+        The msgq_socket_file specifies the UNIX domain socket file
+        that the msgq process listens on.
+        If verbose is True, then the boss reports what it is doing.
         """
         self.verbose = verbose
-        self.c_channel_port = c_channel_port
+        self.msgq_socket_file = msgq_socket_file
         self.auth_port = auth_port
         self.cc_session = None
         self.ccs = None
         self.processes = {}
         self.dead_processes = {}
         self.runnable = False
-        
-        os.environ['ISC_MSGQ_PORT'] = str(self.c_channel_port)
 
     def config_handler(self, new_config):
         if self.verbose:
@@ -220,20 +219,22 @@ class BoB:
         """
         # try to connect to the c-channel daemon, 
         # to see if it is already running
-        c_channel_env = { "ISC_MSGQ_PORT": str(self.c_channel_port), }
+        c_channel_env = {}
+        if self.msgq_socket_file is not None:
+             c_channel_env["BIND10_MSGQ_SOCKET_FILE"] = self.msgq_socket_file 
         if self.verbose:
             sys.stdout.write("Checking for already running b10-msgq\n")
         # try to connect, and if we can't wait a short while
         try:
-            self.cc_session = isc.cc.Session(self.c_channel_port)
-            return "b10-msgq already running, cannot start"
+            self.cc_session = isc.cc.Session(self.msgq_socket_file)
+            return "b10-msgq already running, or socket file not cleaned , cannot start"
         except isc.cc.session.SessionError:
             pass
 
         # start the c-channel daemon
         if self.verbose:
-            sys.stdout.write("Starting b10-msgq using port %d\n" % 
-                             self.c_channel_port)
+            if self.msgq_socket_file:
+                sys.stdout.write("Starting b10-msgq\n")
         try:
             c_channel = ProcessInfo("b10-msgq", ["b10-msgq"], c_channel_env,
                                     True, not self.verbose)
@@ -252,7 +253,7 @@ class BoB:
                 return "Unable to connect to c-channel after 5 seconds"
             # try to connect, and if we can't wait a short while
             try:
-                self.cc_session = isc.cc.Session(self.c_channel_port)
+                self.cc_session = isc.cc.Session(self.msgq_socket_file)
             except isc.cc.session.SessionError:
                 time.sleep(0.1)
         #self.cc_session.group_subscribe("Boss", "boss")
@@ -262,7 +263,7 @@ class BoB:
             sys.stdout.write("[bind10] Starting b10-cfgmgr\n")
         try:
             bind_cfgd = ProcessInfo("b10-cfgmgr", ["b10-cfgmgr"],
-                                    { 'ISC_MSGQ_PORT': str(self.c_channel_port)})
+                                    c_channel_env)
         except Exception as e:
             c_channel.process.kill()
             return "Unable to start b10-cfgmgr; " + str(e)
@@ -292,7 +293,7 @@ class BoB:
             xfrout_args += ['-v']
         try:
             xfrout = ProcessInfo("b10-xfrout", xfrout_args, 
-                                 { 'ISC_MSGQ_PORT': str(self.c_channel_port)})
+                                 c_channel_env )
         except Exception as e:
             c_channel.process.kill()
             bind_cfgd.process.kill()
@@ -310,7 +311,7 @@ class BoB:
             authargs += ['-v']
         try:
             auth = ProcessInfo("b10-auth", authargs,
-                               { 'ISC_MSGQ_PORT': str(self.c_channel_port)})
+                               c_channel_env)
         except Exception as e:
             c_channel.process.kill()
             bind_cfgd.process.kill()
@@ -327,7 +328,7 @@ class BoB:
             xfrin_args += ['-v']
         try:
             xfrind = ProcessInfo("b10-xfrin", xfrin_args,
-                                 { 'ISC_MSGQ_PORT': str(self.c_channel_port)})
+                                 c_channel_env)
         except Exception as e:
             c_channel.process.kill()
             bind_cfgd.process.kill()
@@ -346,7 +347,7 @@ class BoB:
             cmdctl_args += ['-v']
         try:
             cmd_ctrld = ProcessInfo("b10-cmdctl", cmdctl_args,
-                                    { 'ISC_MSGQ_PORT': str(self.c_channel_port)})
+                                    c_channel_env)
         except Exception as e:
             c_channel.process.kill()
             bind_cfgd.process.kill()
@@ -588,9 +589,9 @@ def main():
     parser.add_option("-p", "--port", dest="auth_port", type="string",
                       action="callback", callback=check_port, default="5300",
                       help="port the b10-auth daemon will use (default 5300)")
-    parser.add_option("-m", "--msgq-port", dest="msgq_port", type="string",
-                      action="callback", callback=check_port, default="9912",
-                      help="port the b10-msgq daemon will use (default 9912)")
+    parser.add_option("-m", "--msgq-socket-file", dest="msgq_socket_file",
+                      type="string", default=None,
+                      help="UNIX domain socket file the b10-msgq daemon will use")
     (options, args) = parser.parse_args()
 
     # Announce startup.
@@ -613,7 +614,7 @@ def main():
     signal.signal(signal.SIGTERM, fatal_signal)
 
     # Go bob!
-    boss_of_bind = BoB(int(options.msgq_port), int(options.auth_port),
+    boss_of_bind = BoB(options.msgq_socket_file, int(options.auth_port),
                        options.verbose)
     startup_result = boss_of_bind.startup()
     if startup_result:

+ 3 - 0
src/bin/bind10/run_bind10.sh.in

@@ -29,6 +29,9 @@ export PYTHONPATH
 B10_FROM_SOURCE=@abs_top_srcdir@
 export B10_FROM_SOURCE
 
+BIND10_MSGQ_SOCKET_FILE=@abs_top_srcdir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
 cd ${BIND10_PATH}
 exec ${PYTHON_EXEC} -O bind10 $*
 

+ 4 - 4
src/bin/bind10/tests/bind10_test.py

@@ -75,16 +75,16 @@ class TestBoB(unittest.TestCase):
     def test_init(self):
         bob = BoB()
         self.assertEqual(bob.verbose, False)
-        self.assertEqual(bob.c_channel_port, 9912)
+        self.assertEqual(bob.msgq_socket_file, None)
         self.assertEqual(bob.cc_session, None)
         self.assertEqual(bob.processes, {})
         self.assertEqual(bob.dead_processes, {})
         self.assertEqual(bob.runnable, False)
 
-    def test_init_alternate_port(self):
-        bob = BoB(2199)
+    def test_init_alternate_socket(self):
+        bob = BoB("alt_socket_file")
         self.assertEqual(bob.verbose, False)
-        self.assertEqual(bob.c_channel_port, 2199)
+        self.assertEqual(bob.msgq_socket_file, "alt_socket_file")
         self.assertEqual(bob.cc_session, None)
         self.assertEqual(bob.processes, {})
         self.assertEqual(bob.dead_processes, {})

+ 45 - 21
src/bin/msgq/msgq.py.in

@@ -86,25 +86,33 @@ class SubscriptionManager:
 
 class MsgQ:
     """Message Queue class."""
-    def __init__(self, port=0, verbose=False):
+    # did we find a better way to do this?
+    SOCKET_FILE = os.path.join("@localstatedir@",
+                               "@PACKAGE_NAME@",
+                               "msgq_socket").replace("${prefix}",
+                                                      "@prefix@")
+    
+    def __init__(self, socket_file=None, verbose=False):
         """Initialize the MsgQ master.
         
-        The port specifies the TCP/IP port that the msgq
-        process listens on. If verbose is True, then the MsgQ reports
+        The socket_file specifies the path to the UNIX domain socket
+        that the msgq process listens on. If it is None, the
+        environment variable BIND10_MSGQ_SOCKET_FILE is used. If that
+        is not set, it will default to
+        @localstatedir@/@PACKAGE_NAME@/msg_socket.
+        If verbose is True, then the MsgQ reports
         what it is doing.
         """
 
-        if port == 0:
-	        if 'ISC_MSGQ_PORT' in os.environ:
-	            port = int(os.environ["ISC_MSGQ_PORT"])
-	        else:
-	            port = 9912
-
-
-        print(port)
+        if socket_file is None:
+            if "BIND10_MSGQ_SOCKET_FILE" in os.environ:
+                self.socket_file = os.environ["BIND10_MSGQ_SOCKET_FILE"]
+            else:
+                self.socket_file = self.SOCKET_FILE
+        else:
+            self.socket_file = socket_file
 
         self.verbose = verbose
-        self.c_channel_port = port
         self.poller = None
         self.kqueue = None
         self.runnable = False
@@ -131,10 +139,21 @@ class MsgQ:
 
     def setup_listener(self):
         """Set up the listener socket.  Internal function."""
-        self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        self.listen_socket.bind(("127.0.0.1", self.c_channel_port))
-        self.listen_socket.listen(1024)
+        self.listen_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        
+        if os.path.exists(self.socket_file):
+            os.remove(self.socket_file)
+        try:
+            print("[XX] SOCKET FILE: " + self.socket_file)
+            self.listen_socket.bind(self.socket_file)
+            print("[XX] LISTENING ON SOCKET FILE: " + self.socket_file)
+            self.listen_socket.listen(1024)
+        except Exception as e:
+            # remove the file again if something goes wrong
+            # (note this is a catch-all, but we reraise it)
+            if os.path.exists(self.socket_file):
+                os.remove(self.socket_file)
+            raise e
 
         if self.poller:
             self.poller.register(self.listen_socket, select.POLLIN)
@@ -142,7 +161,10 @@ class MsgQ:
             self.add_kqueue_socket(self.listen_socket)
 
     def setup(self):
-        """Configure listener socket, polling, etc."""
+        """Configure listener socket, polling, etc.
+           Raises a socket.error if the socket_file cannot be
+           created.
+        """
 
         self.setup_poller()
         self.setup_listener()
@@ -366,6 +388,8 @@ class MsgQ:
         if self.verbose:
             sys.stdout.write("Stopping the server.\n")
         self.listen_socket.close()
+        if os.path.exists(self.socket_file):
+            os.remove(self.socket_file)
 
 # can signal handling and calling a destructor be done without a
 # global variable?
@@ -389,9 +413,9 @@ if __name__ == "__main__":
     parser = OptionParser(version=__version__)
     parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                       help="display more about what is going on")
-    parser.add_option("-m", "--msgq-port", dest="msgq_port", type="string",
-                      action="callback", callback=check_port, default="0",
-                      help="port the msgq daemon will use")
+    parser.add_option("-s", "--socket-file", dest="msgq_socket_file",
+                      type="string", default=None,
+                      help="UNIX domain socket file the msgq daemon will use")
     (options, args) = parser.parse_args()
 
     signal.signal(signal.SIGTERM, signal_handler)
@@ -400,7 +424,7 @@ if __name__ == "__main__":
     if options.verbose:
         sys.stdout.write("MsgQ %s\n" % __version__)
 
-    msgq = MsgQ(int(options.msgq_port), options.verbose)
+    msgq = MsgQ(options.msgq_socket_file, options.verbose)
 
     setup_result = msgq.setup()
     if setup_result:

+ 43 - 0
src/bin/msgq/tests/msgq_test.py

@@ -1,6 +1,8 @@
 from msgq import SubscriptionManager, MsgQ
 
 import unittest
+import os
+import socket
 
 #
 # Currently only the subscription part is implemented...  I'd have to mock
@@ -58,5 +60,46 @@ class TestSubscriptionManager(unittest.TestCase):
         self.sm.subscribe('g1', '*', 's2')
         self.assertEqual(self.sm.find_sub("g1", "i1"), [ 's1' ])
 
+    def test_open_socket_parameter(self):
+        self.assertFalse(os.path.exists("./my_socket_file"))
+        msgq = MsgQ("./my_socket_file");
+        msgq.setup()
+        self.assertTrue(os.path.exists("./my_socket_file"))
+        msgq.shutdown();
+        self.assertFalse(os.path.exists("./my_socket_file"))
+
+    def test_open_socket_environment_variable(self):
+        self.assertFalse(os.path.exists("my_socket_file"))
+        os.environ["BIND10_MSGQ_SOCKET_FILE"] = "./my_socket_file"
+        msgq = MsgQ();
+        msgq.setup()
+        self.assertTrue(os.path.exists("./my_socket_file"))
+        msgq.shutdown();
+        self.assertFalse(os.path.exists("./my_socket_file"))
+
+    def test_open_socket_default(self):
+        env_var = None
+        if "BIND10_MSGQ_SOCKET_FILE" in os.environ:
+            env_var = os.environ["BIND10_MSGQ_SOCKET_FILE"]
+            del os.environ["BIND10_MSGQ_SOCKET_FILE"]
+        socket_file = MsgQ.SOCKET_FILE
+        self.assertFalse(os.path.exists(socket_file))
+        msgq = MsgQ();
+        try:
+            msgq.setup()
+            self.assertTrue(os.path.exists(socket_file))
+            msgq.shutdown();
+            self.assertFalse(os.path.exists(socket_file))
+        except socket.error:
+            # ok, the install path doesn't exist at all,
+            # so we can't check any further
+            pass
+        if env_var is not None:
+            os.environ["BIND10_MSGQ_SOCKET_FILE"] = env_var
+
+    def test_open_socket_bad(self):
+        msgq = MsgQ("/does/not/exist")
+        self.assertRaises(socket.error, msgq.setup)
+
 if __name__ == '__main__':
     unittest.main()

+ 13 - 2
src/lib/cc/Makefile.am

@@ -1,4 +1,6 @@
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += -I$(top_srcdir)/ext
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 # ASIO header files used in session.cc will trigger "unused-parameter"
@@ -12,15 +14,24 @@ libcc_a_SOURCES = data.cc data.h session.cc session.h
 
 CLEANFILES = *.gcno *.gcda
 
+session_config.h: session_config.h.pre
+	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" session_config.h.pre >$@
+
+BUILT_SOURCES = session_config.h 
+
 TESTS =
 if HAVE_GTEST
 TESTS += run_unittests
-run_unittests_SOURCES = data_unittests.cc run_unittests.cc
+# (TODO: these need to be completed and moved to tests/)
+run_unittests_SOURCES = data_unittests.cc session_unittests.cc run_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
-run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+# TODO: remove PTHREAD_LDFLAGS (and from configure too)
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) $(PTHREAD_LDFLAGS)
+
 run_unittests_LDADD = libcc.a $(GTEST_LDADD)
 run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/.libs/libdns.a
 run_unittests_LDADD +=  $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+
 endif
 
 noinst_PROGRAMS = $(TESTS)

+ 40 - 29
src/lib/cc/session.cc

@@ -15,6 +15,7 @@
 // $Id$
 
 #include <config.h>
+#include "session_config.h"
 
 #include <stdint.h>
 
@@ -23,6 +24,8 @@
 #include <iostream>
 #include <sstream>
 
+#include <sys/un.h>
+
 #include <boost/bind.hpp>
 #include <boost/function.hpp>
 
@@ -40,7 +43,7 @@ using namespace isc::cc;
 using namespace isc::data;
 
 // some of the asio names conflict with socket API system calls
-// (e.g. write(2)) so we don't import the entire boost::asio namespace.
+// (e.g. write(2)) so we don't import the entire asio namespace.
 using asio::io_service;
 using asio::ip::tcp;
 
@@ -55,7 +58,7 @@ class SessionImpl {
 public:
     SessionImpl() : sequence_(-1) { queue_ = Element::createFromString("[]"); }
     virtual ~SessionImpl() {}
-    virtual void establish() = 0; 
+    virtual void establish(const char& socket_file) = 0;
     virtual int getSocket() = 0;
     virtual void disconnect() = 0;
     virtual void writeData(const void* data, size_t datalen) = 0;
@@ -73,7 +76,7 @@ public:
     ASIOSession(io_service& io_service) :
         io_service_(io_service), socket_(io_service_), data_length_(0)
     {}
-    virtual void establish();
+    virtual void establish(const char& socket_file);
     virtual void disconnect();
     virtual int getSocket() { return (socket_.native()); }
     virtual void writeData(const void* data, size_t datalen);
@@ -86,18 +89,23 @@ private:
 
 private:
     io_service& io_service_;
-    tcp::socket socket_;
+    asio::local::stream_protocol::socket socket_;
     uint32_t data_length_;
     boost::function<void()> user_handler_;
     asio::error_code error_;
 };
 
+
+
 void
-ASIOSession::establish() {
-    socket_.connect(tcp::endpoint(asio::ip::address_v4::loopback(),
-                                  9912), error_);
+ASIOSession::establish(const char& socket_file) {
+    try {
+        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file), error_);
+    } catch (asio::system_error& se) {
+        isc_throw(SessionError, se.what());
+    }
     if (error_) {
-        isc_throw(SessionError, "Unable to connect to message queue");
+        isc_throw(SessionError, "Unable to connect to message queue.");
     }
 }
 
@@ -175,7 +183,7 @@ public:
     SocketSession() : sock_(-1) {}
     virtual ~SocketSession() { disconnect(); }
     virtual int getSocket() { return (sock_); }
-    void establish();
+    void establish(const char& socket_file);
     virtual void disconnect()
     {
         if (sock_ >= 0) {
@@ -210,29 +218,25 @@ public:
 }
 
 void
-SocketSession::establish() {
-    int s;
-    struct sockaddr_in sin;
+SocketSession::establish(const char& socket_file) {
+    struct sockaddr_un sun;
+#ifdef HAVE_SA_LEN
+    sun.sun_len = sizeof(struct sockaddr_un);
+#endif
+
+    if (strlen(&socket_file) >= sizeof(sun.sun_path)) {
+        isc_throw(SessionError, "Unable to connect to message queue; "
+                  "socket file path too long: " << socket_file);
+    }
+    sun.sun_family = AF_UNIX;
+    strncpy(sun.sun_path, &socket_file, sizeof(sun.sun_path) - 1);
 
-    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    int s = socket(AF_UNIX, SOCK_STREAM, 0);
     if (s < 0) {
         isc_throw(SessionError, "socket() failed");
     }
-    
-    int port = atoi(getenv("ISC_MSGQ_PORT"));
-    if (port == 0) {
-        port = 9912;
-    }
-
-    sin.sin_family = AF_INET;
-    sin.sin_port = htons(port);
-    sin.sin_addr.s_addr = INADDR_ANY;
-
-#ifdef HAVE_SIN_LEN
-    sin.sin_len = sizeof(struct sockaddr_in);
-#endif
 
-    if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+    if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
         close(s);
         isc_throw(SessionError, "Unable to connect to message queue");
     }
@@ -291,8 +295,15 @@ Session::startRead(boost::function<void()> read_callback) {
 }
 
 void
-Session::establish() {
-    impl_->establish();
+Session::establish(const char* socket_file) {
+    if (socket_file == NULL) {
+        socket_file = getenv("BIND10_MSGQ_SOCKET_FILE");
+    }
+    if (socket_file == NULL) {
+        socket_file = BIND10_MSGQ_SOCKET_FILE;
+    }
+
+    impl_->establish(*socket_file);
 
     // once established, encapsulate the implementation object so that we
     // can safely release the internal resource when exception happens

+ 2 - 1
src/lib/cc/session.h

@@ -24,6 +24,7 @@
 #include <exceptions/exceptions.h>
 
 #include "data.h"
+#include "session_config.h"
 
 namespace asio {
 class io_service;
@@ -57,7 +58,7 @@ namespace isc {
 
             void startRead(boost::function<void()> read_callback);
 
-            void establish();
+            void establish(const char* socket_file = NULL);
             void disconnect();
             void sendmsg(isc::data::ElementPtr& msg);
             void sendmsg(isc::data::ElementPtr& env,

+ 2 - 0
src/lib/cc/session_config.h.pre.in

@@ -0,0 +1,2 @@
+#define BIND10_MSGQ_SOCKET_FILE "@@LOCALSTATEDIR@@/@PACKAGE@/msgq_socket"
+

+ 63 - 0
src/lib/cc/session_unittests.cc

@@ -0,0 +1,63 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id: data_unittests.cc 1899 2010-05-21 12:03:59Z jelte $
+
+#include "config.h"
+#include <gtest/gtest.h>
+#include <session.h>
+
+#include <asio.hpp>
+#include <exceptions/exceptions.h>
+
+using namespace isc::cc;
+
+TEST(AsioSession, establish) {
+    asio::io_service io_service_;
+    Session sess(io_service_);
+
+    EXPECT_THROW(
+        sess.establish("/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                  ), isc::cc::SessionError
+    );
+                  
+}
+
+TEST(Session, establish) {
+    Session sess;
+
+    EXPECT_THROW(
+        sess.establish("/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
+                  ), isc::cc::SessionError
+    );
+                  
+}

+ 1 - 1
src/lib/config/tests/fake_session.cc

@@ -157,7 +157,7 @@ Session::startRead(boost::function<void()> read_callback UNUSED_PARAM) {
 }
 
 void
-Session::establish() {
+Session::establish(const char* socket_file) {
 }
 
 //

+ 1 - 1
src/lib/config/tests/fake_session.h

@@ -71,7 +71,7 @@ namespace isc {
 
             void startRead(boost::function<void()> read_callback);
 
-            void establish();
+            void establish(const char* socket_file = NULL);
             bool connect();
             void disconnect();
             void sendmsg(isc::data::ElementPtr& msg);

+ 16 - 9
src/lib/python/isc/cc/session.py

@@ -26,7 +26,12 @@ class NetworkError(Exception): pass
 class SessionError(Exception): pass
 
 class Session:
-    def __init__(self, port=0):
+    SOCKET_FILE = os.path.join("@localstatedir@",
+                               "@PACKAGE_NAME@",
+                               "msgq_socket").replace("${prefix}",
+                                                      "@prefix@")
+
+    def __init__(self, socket_file=None):
         self._socket = None
         self._lname = None
         self._recvbuffer = bytearray()
@@ -36,16 +41,18 @@ class Session:
         self._queue = []
         self._lock = threading.RLock()
 
-        if port == 0:
-	        if 'ISC_MSGQ_PORT' in os.environ:
-	            port = int(os.environ["ISC_MSGQ_PORT"])
-	        else:
-	            port = 9912
+        if socket_file is None:
+            if "BIND10_MSGQ_SOCKET_FILE" in os.environ:
+                self.socket_file = os.environ["BIND10_MSGQ_SOCKET_FILE"]
+            else:
+                self.socket_file = self.SOCKET_FILE
+        else:
+            self.socket_file = socket_file
+        
 
         try:
-            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            self._socket.connect(tuple(['127.0.0.1', port]))
-
+            self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            self._socket.connect(self.socket_file)
             self.sendmsg({ "type": "getlname" })
             env, msg = self.recvmsg(False)
             if not env: