# Send the other endpoint to the TUN channel
tun.tun_socket = sock2
+
+ # With this kind of tun_socket, NS3 will expect a PI header
+ # (sockets don't support the TUNGETIFF ioctl, so it will assume
+ # the default presence of PI headers)
+ tun.with_pi = True
### Connector information ###
pybindgen_source_url = "http://pybindgen.googlecode.com/files/pybindgen-0.15.0.zip"
pygccxml_source_url = "http://leaseweb.dl.sourceforge.net/project/pygccxml/pygccxml/pygccxml-1.0/pygccxml-1.0.0.zip"
ns3_source_url = "http://yans.pl.sophia.inria.fr/code/hgwebdir.cgi/ns-3-dev/archive/tip.tar.gz"
+ passfd_source_url = "http://yans.pl.sophia.inria.fr/code/hgwebdir.cgi/python-passfd/archive/tip.tar.gz"
self.build =(
" ( "
" cd .. && "
- " python -c 'import pygccxml, pybindgen' && "
+ " python -c 'import pygccxml, pybindgen, passfd' && "
" test -f lib/_ns3.so && "
" test -f lib/libns3.so "
" ) || ( "
# Not working, rebuild
"wget -q -c -O pybindgen-src.zip %(pybindgen_source_url)s && " # continue, to exploit the case when it has already been dl'ed
"wget -q -c -O pygccxml-1.0.0.zip %(pygccxml_source_url)s && "
+ "wget -q -c -O passfd-src.tar.gz %(passfd_source_url)s && "
"wget -q -c -O ns3-src.tar.gz %(ns3_source_url)s && "
"unzip -n pybindgen-src.zip && " # Do not overwrite files, to exploit the case when it has already been built
"unzip -n pygccxml-1.0.0.zip && "
"mkdir -p ns3-src && "
+ "mkdir -p passfd-src && "
"tar xzf ns3-src.tar.gz --strip-components=1 -C ns3-src && "
+ "tar xzf passfd-src.tar.gz --strip-components=1 -C passfd-src && "
"rm -rf target && " # mv doesn't like unclean targets
"mkdir -p target && "
"cd pygccxml-1.0.0 && "
"./waf clean && "
"mv -f ${BUILD}/target/lib/python*/site-packages/pybindgen ${BUILD}/target/. && "
"rm -rf ${BUILD}/target/lib && "
+ "cd ../passfd-src && "
+ "python setup.py build && "
+ "python setup.py install --install-lib ${BUILD}/target && "
+ "python setup.py clean && "
"cd ../ns3-src && "
"./waf configure --prefix=${BUILD}/target -d release --disable-examples --high-precision-as-double && "
"./waf &&"
pybindgen_source_url = server.shell_escape(pybindgen_source_url),
pygccxml_source_url = server.shell_escape(pygccxml_source_url),
ns3_source_url = server.shell_escape(ns3_source_url),
+ passfd_source_url = server.shell_escape(passfd_source_url),
))
# Just move ${BUILD}/target
self.install = (
" ( "
" cd .. && "
- " python -c 'import pygccxml, pybindgen' && "
+ " python -c 'import pygccxml, pybindgen, passfd' && "
" test -f lib/_ns3.so && "
" test -f lib/libns3.so "
" ) || ( "
# Cannot access cross peers
self.peer_proto_impl = None
+
+ def __str__(self):
+ return "%s%r" % (
+ self.__class__.__name__,
+ ( self.tun_proto,
+ self.tun_addr,
+ self.tun_port )
+ )
class TunIface(object):
_PROTO_MAP = tunproto.TUN_PROTO_MAP
"box_attributes": [
"up", "device_name", "mtu", "snat",
"txqueuelen",
- "tun_proto", "tun_addr", "tun_port"
+ "tun_proto", "tun_addr", "tun_port", "tun_key"
],
"traces": ["packets"],
"connector_types": ["node","udp","tcp","fd->"]
if check_proto != peer_proto:
raise RuntimeError, "Peering protocol mismatch: %s != %s" % (check_proto, peer_proto)
- if not listen and (not peer_port or not peer_addr):
+ if not listen and ((peer_proto != 'fd' and not peer_port) or not peer_addr):
raise RuntimeError, "Misconfigured peer: %s" % (peer,)
- if listen and (not local_port or not local_addr or not local_mask):
+ if listen and ((peer_proto != 'fd' and not local_port) or not local_addr or not local_mask):
raise RuntimeError, "Misconfigured TUN: %s" % (local,)
args = ["python", "tun_connect.py",
import threading
import socket
import select
+import weakref
+
+from tunchannel import tun_fwd
class TunChannel(object):
"""
ethernet_mode: set if the incoming packet stream is
composed of ethernet frames (as opposed of IP packets).
+ udp: set to use UDP datagrams instead of TCP connections.
+
tun_socket: a socket or file object that can be read
from and written to. Packets will be read when available,
remote packets will be forwarded as writes.
# some state
self.prepared = False
self._terminate = [] # terminate signaller
+ self._exc = [] # exception store, to relay exceptions from the forwarder thread
self._connected = threading.Event()
self._forwarder_thread = None
def __str__(self):
- return "%s<ip:%s/%s %s%s>" % (
+ return "%s<%s %s:%s %s %s:%s>" % (
self.__class__.__name__,
- self.address, self.netprefix,
- " up" if self.up else " down",
- " snat" if self.snat else "",
+ self.tun_proto,
+ self.tun_addr, self.tun_port,
+ self.peer_proto,
+ self.peer_addr, self.peer_port,
)
def Prepare(self):
- if not self.udp and self.listen and not self._forwarder_thread:
- if self.listen or (self.peer_addr and self.peer_port and self.peer_proto):
- self._launch()
+ if self.tun_proto:
+ udp = self.tun_proto == "udp"
+ if not udp and self.listen and not self._forwarder_thread:
+ if self.listen or (self.peer_addr and self.peer_port and self.peer_proto):
+ self._launch()
def Setup(self):
- if not self._forwarder_thread:
- self._launch()
+ if self.tun_proto:
+ if not self._forwarder_thread:
+ self._launch()
def Cleanup(self):
if self._forwarder_thread:
def Wait(self):
if self._forwarder_thread:
self._connected.wait()
+ for exc in self._exc:
+ # Relay exception
+ eTyp, eVal, eLoc = exc
+ raise eTyp, eVal, eLoc
def Kill(self):
if self._forwarder_thread:
# to self, so that we don't create any strong cycles
# and automatic refcounting works as expected
self._forwarder_thread = threading.Thread(
- self._forwarder,
+ target = self._forwarder,
args = (weakref.ref(self),) )
self._forwarder_thread.start()
-
+
@staticmethod
def _forwarder(weak_self):
+ try:
+ weak_self().__forwarder(weak_self)
+ except:
+ self = weak_self()
+
+ # store exception and wake up anyone waiting
+ self._exc.append(sys.exc_info())
+ self._connected.set()
+
+ @staticmethod
+ def __forwarder(weak_self):
# grab strong reference
self = weak_self()
if not self:
if udp:
# listen on udp port
- if remaining_args and not remaining_args[0].startswith('-'):
- rsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
- rsock.bind((local_addr,local_port))
- rsock.connect((peer_addr,peer_port))
+ rsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
+ rsock.bind((local_addr,local_port))
+ rsock.connect((peer_addr,peer_port))
remote = os.fdopen(rsock.fileno(), 'r+b', 0)
elif listen:
# accept tcp connections