Example #1
0
    def _on_source_connect(self, sock, host, port):
        """Explicitly defined connect Event Handler

        This evens is triggered by the underlying TCPServer Component when
        a new client connection has been made.

        Here we dynamically create a Client instance, registere it and add
        custom event handlers to handle the events of the newly created
        client. The client is registered with a unique channel per connection.
        """

        bind = 0
        channel = uuid()

        client = TCPClient(bind, channel=channel)
        client.register(self)

        self.addHandler(
            handler("disconnected", channel=channel)(_on_target_disconnected)
        )

        self.addHandler(
            handler("ready", channel=channel)(_on_target_ready)
        )

        self.addHandler(
            handler("read", channel=channel)(_on_target_read)
        )

        self._clients[sock] = client
        self._sockets[client.channel] = sock
Example #2
0
    def _on_source_connect(self, sock, host, port):
        """Explicitly defined connect Event Handler

        This evens is triggered by the underlying TCPServer Component when
        a new client connection has been made.

        Here we dynamically create a Client instance, registere it and add
        custom event handlers to handle the events of the newly created
        client. The client is registered with a unique channel per connection.
        """

        bind = 0
        channel = uuid()

        client = TCPClient(bind, channel=channel)
        client.register(self)

        self.addHandler(
            handler("disconnected", channel=channel)(_on_target_disconnected))

        self.addHandler(handler("ready", channel=channel)(_on_target_ready))

        self.addHandler(handler("read", channel=channel)(_on_target_read))

        self._clients[sock] = client
        self._sockets[client.channel] = sock
Example #3
0
    def init(self, host="irc.freenode.net", port="6667", channel=channel):
        self.host = host
        self.port = int(port)

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)
Example #4
0
    def __init__(self, *args, **opts):
        super(Telnet, self).__init__()

        self.args = args
        self.opts = opts

        if len(args) == 1:
            if os.path.exists(args[0]):
                UNIXClient(channel=self.channel).register(self)
                host = dest = port = args[0]
                dest = (dest, )
            else:
                raise OSError("Path %s not found" % args[0])
        else:
            if not opts["udp"]:
                TCPClient(channel=self.channel).register(self)
            else:
                UDPClient(0, channel=self.channel).register(self)

            host, port = args
            port = int(port)
            dest = host, port

        self.host = host
        self.port = port

        print("Trying %s ..." % host)

        if not opts["udp"]:
            self.fire(connect(*dest, secure=opts["secure"]))
        else:
            self.fire(write((host, port), b"\x00"))
Example #5
0
    def __init__(self, channel=channel):
        super(Client, self).__init__(channel=channel)
        self._response = None

        self._transport = TCPClient(channel=channel).register(self)

        HTTP(channel=channel).register(self._transport)
Example #6
0
 def __init__(self, xmpp_client, hostname, port):
     Component.__init__(self)
     self.client = xmpp_client
     
     self.tcp = TCPClient()
     self += self.tcp
     self.push(Connect(hostname, port))
Example #7
0
    def __init__(self, *args):
        ConfigurableComponent.__init__(self, "IRCBOT", *args)
        if self.config.get('password', None) is None:
            self.config.password = std_uuid()
            self.config.save()

        self.channel = 'ircbot'

        self.fireEvent(cli_register_event('test_irc_send', cli_test_irc_send), "isomer-web")
        self.log("Started")

        self.host = self.config.host
        self.port = self.config.port

        self.hostname = gethostname()

        self.nick = self.config.nick
        self.irc_channels = self.config.channels

        # Mapping of IRC Channel -> Set of Nicks
        self.channel_map = defaultdict(set)

        # Mapping of Nick -> Set of IRC Channels
        self.nick_map = defaultdict(set)

        # Add TCPClient and IRC to the system.
        self.transport = TCPClient(channel=self.channel).register(self)
        self.protocol = IRC(channel=self.channel).register(self)

        # Keep-Alive Timer
        Timer(60, Event.create("keepalive"), persist=True).register(self)
Example #8
0
def test_tcp_lookup_failure(manager, watcher, Poller, ipv6):
    poller = Poller().register(manager)

    if ipv6:
        tcp_client = TCP6Client()
    else:
        tcp_client = TCPClient()

    client = Client() + tcp_client
    client.register(manager)

    try:
        assert watcher.wait("ready", "client")

        client.fire(connect("foo.bar.baz", 1234))
        assert watcher.wait("error", "client")

        if pytest.PLATFORM == "win32":
            assert client.error.errno == 11004
        else:
            assert client.error.errno in (
                EAI_NODATA,
                EAI_NONAME,
            )
    finally:
        poller.unregister()
        client.unregister()
Example #9
0
def test_tcp_lookup_failure(Poller, ipv6):
    m = Manager() + Poller()

    if ipv6:
        tcp_client = TCP6Client()
    else:
        tcp_client = TCPClient()
    client = Client() + tcp_client

    client.register(m)

    m.start()

    try:
        assert pytest.wait_for(client, "ready")

        client.fire(connect("foo", 1234))
        assert pytest.wait_for(
            client, "error", lambda obj, attr: isinstance(getattr(obj, attr), SocketError))
        if pytest.PLATFORM == "win32":
            assert client.error.errno == 11004
        else:
            assert client.error.errno in (EAI_NODATA, EAI_NONAME,)
    finally:
        m.stop()
Example #10
0
 def _on_connect(self,
                 host=None,
                 port=None,
                 secure=None,
                 certfile=None,
                 keyfile=None,
                 ca_certs=None):
     try:
         socket = self._socket_map[(host, port, secure)]
         if not socket.connected:
             raise KeyError
     except KeyError:
         socket = TCPClient(
             channel='%s_%d' %
             (self.channel, len(self._buffers))).register(self)
         self._buffers[socket] = {
             'parser': ClientStateMachine(),
             'socket': socket,
             'requests': [],
             'responses': [],
         }
         self._socket_map[(host, port, secure)] = socket
         self._channel_sock[socket.channel] = socket
     if not socket.connected:
         self.fire(
             connect(host,
                     port,
                     secure,
                     certfile=certfile,
                     keyfile=keyfile,
                     ca_certs=ca_certs), socket)
     # event.stop()  # FIXME: self.call does conflict with this
     return socket
Example #11
0
def test_tcp_reconnect(Poller, ipv6):
    # XXX: Apparently this doesn't work on Windows either?
    # XXX: UPDATE: Apparently Broken on Windows + Python 3.2
    # TODO: Need to look into this. Find out why...

    if pytest.PLATFORM == "win32" and pytest.PYVER[:2] >= (3, 2):
        pytest.skip("Broken on Windows on Python 3.2")

    m = Manager() + Poller()

    if ipv6:
        tcp_server = TCP6Server(("::1", 0))
        tcp_client = TCP6Client()
    else:
        tcp_server = TCPServer(0)
        tcp_client = TCPClient()
    server = Server() + tcp_server
    client = Client() + tcp_client

    server.register(m)
    client.register(m)

    m.start()

    try:
        assert pytest.wait_for(client, "ready")
        assert pytest.wait_for(server, "ready")
        wait_host(server)

        # 1st connect
        client.fire(connect(server.host, server.port))
        assert pytest.wait_for(client, "connected")
        assert pytest.wait_for(server, "connected")
        assert pytest.wait_for(client, "data", b"Ready")

        client.fire(write(b"foo"))
        assert pytest.wait_for(server, "data", b"foo")

        # disconnect
        client.fire(close())
        assert pytest.wait_for(client, "disconnected")

        # 2nd reconnect
        client.fire(connect(server.host, server.port))
        assert pytest.wait_for(client, "connected")
        assert pytest.wait_for(server, "connected")
        assert pytest.wait_for(client, "data", b"Ready")

        client.fire(write(b"foo"))
        assert pytest.wait_for(server, "data", b"foo")

        client.fire(close())
        assert pytest.wait_for(client, "disconnected")
        assert pytest.wait_for(server, "disconnected")

        server.fire(close())
        assert pytest.wait_for(server, "closed")
    finally:
        m.stop()
Example #12
0
    def init(self, host, port="6667", channel=channel):
        self.host = host
        self.port = int(port)

        self.connected = False
        self.events = []

        self.transport = TCPClient(channel=self.channel).register(self)
        self.protocol = IRC(channel=self.channel).register(self)
Example #13
0
 def request(self, event, method, url, body=None, headers={}, timeout=None):
     timeout = timeout or self._timeout
     if self._transport == None or not self._transport.connected:
         self._transport = TCPClient(channel=self.channel).register(self)
         HTTP(channel=self.channel).register(self._transport)
         self.fire(connect(self._host, self._port, self._secure),
                   self._transport)
         self._pending.append((method, url, body, headers, timeout))
     else:
         self._send_request(method, url, body, headers, timeout)
Example #14
0
    def __init__(self, url, channel=channel, wschannel="ws", headers=None):
        """
        :param url: the URL to connect to.
        :param channel: the channel used by this component
        :param wschannel: the channel used for the actual WebSocket
            communication (read, write, close events)
        :param headers: additional headers to be passed with the
            WebSocket setup HTTP request
        """
        super(WebSocketClient, self).__init__(channel=channel)

        self._url = url
        self._headers = headers or {}
        self._response = None
        self._pending = 0
        self._wschannel = wschannel

        self._transport = TCPClient(channel=self.channel).register(self)
        HTTP(channel=self.channel).register(self._transport)
Example #15
0
    def __init__(self, host="irc.sudo-rmrf.net", port="6667", channel="#csb", nick="testbot", realname='IRC Bot'):
        super(IRCBot, self).__init__()
        self.host = host
        self.port = int(port)
        self.nick = nick
        self.channel = channel
        self.realname = realname

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)
        self.fire(debugalert("Initialized!"))
Example #16
0
    def init(self, host, port=6667, opts=None):
        self.host = host
        self.port = port
        self.opts = opts
        self.hostname = gethostname()

        self.nick = opts.nick
        self.ircchannel = opts.channel

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)
Example #17
0
def test_tcp_bind(Poller, ipv6):
    m = Manager() + Poller()

    if ipv6:
        sock = socket(AF_INET6, SOCK_STREAM)
        sock.bind(("::1", 0))
        sock.listen(5)
        _, bind_port, _, _ = sock.getsockname()
        sock.close()
        server = Server() + TCP6Server(("::1", 0))
        client = Client() + TCP6Client()
    else:
        sock = socket(AF_INET, SOCK_STREAM)
        sock.bind(("", 0))
        sock.listen(5)
        _, bind_port = sock.getsockname()
        sock.close()
        server = Server() + TCPServer(0)
        client = Client() + TCPClient()

    server.register(m)
    client.register(m)

    m.start()

    try:
        assert pytest.wait_for(client, "ready")
        assert pytest.wait_for(server, "ready")
        wait_host(server)

        client.fire(connect(server.host, server.port))
        assert pytest.wait_for(client, "connected")
        assert pytest.wait_for(server, "connected")
        assert pytest.wait_for(client, "data", b"Ready")

        # assert server.client[1] == bind_port

        client.fire(write(b"foo"))
        assert pytest.wait_for(server, "data", b"foo")

        client.fire(close())
        assert pytest.wait_for(client, "disconnected")
        assert pytest.wait_for(server, "disconnected")

        server.fire(close())
        assert pytest.wait_for(server, "closed")
    finally:
        m.stop()
Example #18
0
def test():
    m = Manager()

    poller = Poller().register(m)

    TCPServer(0).register(m)
    TCPClient().register(m)

    m.start()

    try:
        pollers = findtype(m, BasePoller, all=True)
        assert len(pollers) == 1
        assert pollers[0] is poller
    finally:
        m.stop()
Example #19
0
def test_tcp_connect_closed_port(Poller, ipv6):
    ### FIXME: This test is wrong.
    ### We need to figure out the sequence of events on Windows
    ### for this scenario. I think if you attempt to connect to
    ### a shutdown listening socket (tcp server) you should get
    ### an error event as response.

    if pytest.PLATFORM == "win32":
        pytest.skip("Broken on Windows")

    m = Manager() + Poller()
    if ipv6:
        tcp_server = TCP6Server(("::1", 0))
        tcp_client = TCP6Client()
    else:
        tcp_server = TCPServer(0)
        tcp_client = TCPClient()
    server = Server() + tcp_server
    client = Client() + tcp_client

    server.register(m)
    client.register(m)

    m.start()

    try:
        assert pytest.wait_for(client, "ready")
        assert pytest.wait_for(server, "ready")
        wait_host(server)

        host, port = server.host, server.port
        tcp_server._sock.close()

        # 1st connect
        client.fire(connect(host, port))
        assert pytest.wait_for(client, "connected")
        assert isinstance(client.error, SocketError)

        client.fire(write(b"foo"))
        assert pytest.wait_for(client, "disconnected")

        client.disconnected = False
        client.fire(write(b"foo"))
        assert pytest.wait_for(client, "disconnected", timeout=1.0) is None
    finally:
        m.stop()
Example #20
0
def test_http_1_1_no_host_headers(webapp):
    transport = TCPClient()
    client = Client()
    client += transport
    client.start()

    host, port, resource, secure = parse_url(webapp.server.http.base)
    client.fire(connect(host, port))
    assert pytest.wait_for(transport, "connected")

    client.fire(write(b"GET / HTTP/1.1\r\n\r\n"))
    assert pytest.wait_for(client, "done")

    client.stop()

    s = client.buffer().decode('utf-8').split('\r\n')[0]
    assert s == "HTTP/1.1 400 Bad Request"
Example #21
0
    def __init__(self,
                 nick=NICKNAME,
                 ircchannel=IRCCHANNEL,
                 host=IRCSERVER,
                 port=PORT):
        super(Client, self).__init__()

        self.host = host
        self.port = port
        self.hostname = gethostname()

        self.nick = nick
        self.ircchannel = ircchannel

        self += (TCPClient(channel=self.channel) + IRC(channel=self.channel))
        if DEBUG:
            self += Debugger()
Example #22
0
    def init(self,
             nick="Botivator",
             command_char="!",
             owners=["Motivator", "MotivatorAFK"],
             password_file="password.py",
             host_file="host",
             host="irc.snoonet.org",
             port="6667",
             channel="##arctantest"):

        self.host = host
        self.port = int(port)

        self.nick = nick
        self.password = open(password_file).read().strip()

        self.command_char = command_char

        self.owners = owners
        self.owner_host = open(host_file).read().strip()

        self.linkresolver = LinkResolver()

        self.commands = {
            #'command_name': [CommandClass, CanAnyoneUseIt?]
            'commands': [Commands(), True],
            'help': [Commands(), True],
            'join': [Join(), True],
            'part': [Part(), True],
            'ban': [Ban(), False],
            'allow': [Allow(), False],
            'source': [Source(), True],
            '4chan': [WatchFourChan(self), False],
            'hn': [WatchHackerNews(self), False],
            'reddit': [WatchReddit(self), False],
            '8ch': [WatchEightChan(self), False],
            'pastebin': [WatchPasteBin(self), False],
            'quote': [Quote(), True],
        }

        # Add owner to whitelist
        self.commands['allow'][0].whitelist.append(self.owner_host)

        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)
Example #23
0
    def __init__(self,
                 host,
                 port,
                 channel=channel,
                 receive_event_firewall=None,
                 send_event_firewall=None,
                 **kwargs):
        """Create new connection for a node.

        :param hostname:    hostname to connect.
        :type hostname:     str

        :param port:    port to connect.
        :type port:     int

        :param channel: An optional keyword argument which if defined,
                        set channel used for node event.
                        **Default:** ``node_client``
        :type channel:  str

        :param receive_event_firewall:  An optional keyword argument which if
                                        defined, function or method to call for
                                        check if event is allowed for sending.
                                        **Default:** ``None`` (no firewall)
        :type receive_event_firewall:   function
        :type receive_event_firewall:   method

        :param send_event_firewall:  An optional keyword argument which if
                                    defined, function or method to call for
                                    check if event is allowed for executing
                                    **Default:** ``None`` (no firewall)
        :type send_event_firewall:   function
        :type send_event_firewall:   method
        """
        super(Client, self).__init__(channel=channel, **kwargs)

        self.related_handlers = []
        self.__host = host
        self.__port = port
        self.__protocol = Protocol(
            receive_event_firewall=receive_event_firewall,
            send_event_firewall=send_event_firewall,
            channel=channel).register(self)

        self.__client = TCPClient(channel=channel, **kwargs).register(self)
Example #24
0
def test(webapp):
    transport = TCPClient()
    client = Client()
    client += transport
    client.start()

    host, port, resource, secure = parse_url(webapp.server.http.base)
    client.fire(connect(host, port))
    assert pytest.wait_for(transport, "connected")

    client.fire(write(b"GET / HTTP/1.1\r\n"))
    client.fire(write(b"Content-Type: text/plain\r\n\r\n"))
    assert pytest.wait_for(client, "done")

    client.stop()

    s = client.buffer().decode('utf-8').split('\r\n')[0]
    assert s == "HTTP/1.1 200 OK"
Example #25
0
    def __init__(self, url, channel=channel, wschannel="ws", headers=None):
        """
        :param url: the URL to connect to.
        :param channel: the channel used by this component
        :param wschannel: the channel used for the actual WebSocket
            communication (read, write, close events)
        :param headers: additional headers to be passed with the
            WebSocket setup HTTP request
        """
        super(WebSocketClient, self).__init__(channel=channel)

        self._url = url
        self._headers = headers or {}
        self._response = None
        self._pending = 0
        self._wschannel = wschannel

        self._transport = TCPClient(channel=self.channel).register(self)
        HTTP(channel=self.channel).register(self._transport)
Example #26
0
    def init(self,
             host,
             port=None,
             secure=False,
             nick=None,
             ircchannels=None,
             channel=channel):
        self.host = host
        self.port = port or 6667
        self.hostname = gethostname()

        self.nick = nick
        self.ircchannel = ircchannels

        TCPClient(secure=secure, channel=self.channel).register(self)
        self.irc = IRC(channel=self.channel).register(self)

        self.last_called = 0
        self.max_rate = 1
        self.privmsg_queue = []
Example #27
0
def test_tcps_basic(Poller, ipv6):
    from circuits import Debugger
    m = Manager() + Debugger() + Poller()

    if ipv6:
        tcp_server = TCP6Server(("::1", 0), secure=True, certfile=CERT_FILE)
        tcp_client = TCP6Client()
    else:
        tcp_server = TCPServer(0, secure=True, certfile=CERT_FILE)
        tcp_client = TCPClient()
    server = Server() + tcp_server
    client = Client() + tcp_client

    server.register(m)
    client.register(m)

    m.start()

    try:
        assert pytest.wait_for(client, "ready")
        assert pytest.wait_for(server, "ready")
        wait_host(server)

        client.fire(connect(server.host, server.port, secure=True))
        assert pytest.wait_for(client, "connected")
        assert pytest.wait_for(server, "connected")
        assert pytest.wait_for(client, "data", b"Ready")

        client.fire(write(b"foo"))
        assert pytest.wait_for(server, "data", b"foo")
        assert pytest.wait_for(client, "data", b"foo")

        client.fire(close())
        assert pytest.wait_for(client, "disconnected")
        assert pytest.wait_for(server, "disconnected")

        server.fire(close())
        assert pytest.wait_for(server, "closed")
    finally:
        m.stop()
Example #28
0
def test_tcp_basic(Poller, ipv6):
    m = Manager() + Poller()

    if ipv6:
        tcp_server = TCP6Server(("::1", 0))
        tcp_client = TCP6Client()
    else:
        tcp_server = TCPServer(0)
        tcp_client = TCPClient()
    server = Server() + tcp_server
    client = Client() + tcp_client

    server.register(m)
    client.register(m)

    m.start()

    try:
        assert pytest.wait_for(client, "ready")
        assert pytest.wait_for(server, "ready")
        wait_host(server)

        client.fire(connect(server.host, server.port))
        assert pytest.wait_for(client, "connected")
        assert pytest.wait_for(server, "connected")
        assert pytest.wait_for(client, "data", b"Ready")

        client.fire(write(b"foo"))
        assert pytest.wait_for(server, "data", b"foo")
        assert pytest.wait_for(client, "data", b"foo")

        client.fire(close())
        assert pytest.wait_for(client, "disconnected")
        assert pytest.wait_for(server, "disconnected")

        server.fire(close())
        assert pytest.wait_for(server, "closed")
    finally:
        m.stop()
Example #29
0
def test_tcp_connect_closed_port(Poller, ipv6):

    if pytest.PLATFORM == "win32":
        pytest.skip("Broken on Windows")

    m = Manager() + Poller() + Debugger()

    if ipv6:
        tcp_server = TCP6Server(("::1", 0))
        tcp_client = TCP6Client(connect_timeout=1)
    else:
        tcp_server = TCPServer(0)
        tcp_client = TCPClient(connect_timeout=1)
    server = Server() + tcp_server
    client = Client() + tcp_client

    server.register(m)
    client.register(m)

    m.start()

    try:
        assert pytest.wait_for(client, "ready")
        assert pytest.wait_for(server, "ready")
        wait_host(server)

        host, port = server.host, server.port
        tcp_server._sock.close()

        # 1st connect
        client.fire(connect(host, port))
        waiter = WaitEvent(m, "unreachable", channel='client')
        assert waiter.wait()
    finally:
        server.unregister()
        client.unregister()
        m.stop()
Example #30
0
    def init(self, host, port=6667, opts=None):
        self.host = host
        self.port = port
        self.opts = opts
        self.hostname = gethostname()

        self.nick = opts.nick
        self.ircchannels = opts.channels

        # Mapping of IRC Channel -> Set of Nicks
        self.chanmap = defaultdict(set)

        # Mapping of Nick -> Set of IRC Channels
        self.nickmap = defaultdict(set)

        # Debugger
        Debugger(events=opts.verbose).register(self)

        # Add TCPClient and IRC to the system.
        self.transport = TCPClient(channel=self.channel).register(self)
        self.protocol = IRC(channel=self.channel).register(self)

        # Logger(s)
        for ircchannel in self.ircchannels:
            if not path.exists(path.join(opts.output, ircchannel)):
                makedirs(path.join(opts.output, ircchannel))

            Logger(path.join(opts.output, generate_logfile(ircchannel)),
                   "a",
                   channel="logger.{0:s}".format(ircchannel)).register(self)

        # Daemon?
        if self.opts.daemon:
            Daemon(opts.pidfile).register(self)

        # Keep-Alive Timer
        Timer(60, Event.create("keepalive"), persist=True).register(self)
Example #31
0
File: nmea.py Project: ri0t/hfos
    def _setup_connection(self):
        portup = False

        if self.config.connectiontype == 'USB/Serial':
            self.log("Connecting to serial port:", self.config.serialfile,
                     lvl=debug)
            try:
                self.serial = Serial(self.config.serialfile,
                                     channel=self.channel).register(self)
                self.bus = self.config.serialfile
                portup = True
            except serial.SerialException as e:
                self.log("Could not open configured serial port:", e,
                         lvl=error)
        elif self.config.connectiontype == 'TCP':
            self.tcpclient = TCPClient(channel=self.channel).register(self)
            self.bus = self.config.host + ":" + self.config.port
            portup = True

        if portup:
            self.log("Connection type", self.config.connectiontype,
                     "running. Bus known as ", self.bus)
        else:
            self.log("No port connected!", lvl=error)
Example #32
0
class WebSocketClient(BaseComponent):
    """
    An RFC 6455 compliant WebSocket client component. Upon receiving a
    :class:`circuits.web.client.Connect` event, the component tries to
    establish the connection to the server in a two stage process. First, a
    :class:`circuits.net.events.connect` event is sent to a child
    :class:`~.sockets.TCPClient`. When the TCP connection has been established,
    the HTTP request for opening the WebSocket is sent to the server.
    A failure in this setup process is signaled by raising an
    :class:`~.client.NotConnected` exception.

    When the server accepts the request, the WebSocket connection is
    established and can be used very much like an ordinary socket
    by handling :class:`~.net.events.read` events on and sending
    :class:`~.net.events.write` events to the channel
    specified as the ``wschannel`` parameter of the constructor. Firing
    a :class:`~.net.events.close` event on that channel closes the
    connection in an orderly fashion (i.e. as specified by the
    WebSocket protocol).
    """

    channel = "wsclient"

    def __init__(self, url, channel=channel, wschannel="ws", headers=None):
        """
        :param url: the URL to connect to.
        :param channel: the channel used by this component
        :param wschannel: the channel used for the actual WebSocket
            communication (read, write, close events)
        :param headers: additional headers to be passed with the
            WebSocket setup HTTP request
        """
        super(WebSocketClient, self).__init__(channel=channel)

        self._url = url
        self._headers = headers or {}
        self._response = None
        self._pending = 0
        self._wschannel = wschannel

        self._transport = TCPClient(channel=self.channel).register(self)
        HTTP(channel=self.channel).register(self._transport)

    @handler("ready")
    def _on_ready(self, event, *args, **kwargs):
        p = urlparse(self._url)
        if not p.hostname:
            raise ValueError("URL must be absolute")
        self._host = p.hostname
        if p.scheme == "ws":
            self._secure = False
            self._port = p.port or 80
        elif p.scheme == "wss":
            self._secure = True
            self._port = p.port or 443
        else:
            raise NotConnected()
        self._resource = p.path or "/"
        if p.query:
            self._resource += "?" + p.query
        self.fire(connect(self._host, self._port, self._secure),
                  self._transport)

    @handler("connected")
    def _on_connected(self, host, port):
        headers = Headers([(k, v) for k, v in self._headers.items()])
        # Clients MUST include Host header in HTTP/1.1 requests (RFC 2616)
        if not "Host" in headers:
            headers["Host"] = self._host \
                + (":" + str(self._port)) if self._port else ""
        headers["Upgrade"] = "websocket"
        headers["Connection"] = "Upgrade"
        try:
            sec_key = os.urandom(16)
        except NotImplementedError:
            sec_key = "".join([chr(random.randint(0, 255)) for i in range(16)])
        headers["Sec-WebSocket-Key"] = base64.b64encode(sec_key).decode("latin1")
        headers["Sec-WebSocket-Version"] = "13"
        command = "GET %s HTTP/1.1" % self._resource
        message = "%s\r\n%s" % (command, headers)
        self._pending += 1
        self.fire(write(message.encode('utf-8')), self._transport)
        return True

    @handler("response")
    def _on_response(self, response):
        self._response = response
        self._pending -= 1
        if response.headers.get("Connection") == "Close" \
                or response.status != 101:
            self.fire(close(), self._transport)
            raise NotConnected()
        WebSocketCodec(data=response.body.read(), channel=self._wschannel).register(self)

    @handler("error", priority=10)
    def _on_error(self, event, error, *args, **kwargs):
        # For HTTP 1.1 we leave the connection open. If the peer closes
        # it after some time and we have no pending request, that's OK.
        if isinstance(error, SocketError) and error.args[0] == ECONNRESET \
                and self._pending == 0:
            event.stop()

    def close(self):
        if self._transport is not None:
            self._transport.close()

    @property
    def connected(self):
        return getattr(self._transport, "connected", False) \
            if hasattr(self, "_transport") else False
Example #33
0
    def init(self, host, port):
        hfoslog("[NMEA] Started")
        self.host = host
        self.port = port

        TCPClient(channel=self.channel).register(self)