Ejemplo n.º 1
0
 def connection_made(self, sock, rtt=0):
     if rtt:
         LOG.debug("ClientHTTP: latency: %s" % utils.time_formatter(rtt))
         self.rtt = rtt
     stream = ClientStream(self.poller)
     stream.attach(self, sock, self.conf, self.measurer)
     self.connection_ready(stream)
Ejemplo n.º 2
0
    def check_response(self, response):

        if response.code != "200":
            raise ValueError("Bad HTTP response code")
        if response["content-type"] != "application/json":
            raise ValueError("Unexpected contenty type")

        octets = response.body.read()
        dictionary = json.loads(octets)

        LOG.debug("APIStateTracker: received JSON: " +
            json.dumps(dictionary, ensure_ascii=True))

        if not "events" in dictionary:
            return

        if not "current" in dictionary:
            raise ValueError("Incomplete dictionary")

        t = dictionary["t"]
        if not type(t) == types.IntType and not type(t) == types.LongType:
            raise ValueError("Invalid type for current event time")
        if t < 0:
            raise ValueError("Invalid value for current event time")

        self.timestamp = t
        self.process_dictionary(dictionary)
Ejemplo n.º 3
0
 def _send_handshake(self):
     ''' Convenience function to send handshake '''
     LOG.debug("> HANDSHAKE infohash=%s id=%s" %
               (self.parent.infohash.encode("hex"),
                self.parent.my_id.encode("hex")))
     self.start_send("".join((chr(len(PROTOCOL_NAME)), PROTOCOL_NAME,
       FLAGS, self.parent.infohash, self.parent.my_id)))
Ejemplo n.º 4
0
    def attach(self, parent, sock, conf):

        self.parent = parent
        self.conf = conf

        self.filenum = sock.fileno()
        self.myname = sock.getsockname()
        self.peername = sock.getpeername()
        self.logname = str((self.myname, self.peername))

        LOG.debug("* Connection made %s" % str(self.logname))

        if conf["net.stream.secure"]:
            if not ssl:
                raise RuntimeError("SSL support not available")

            server_side = conf["net.stream.server_side"]
            certfile = conf["net.stream.certfile"]

            # wrap_socket distinguishes between None and ''
            if not certfile:
                certfile = None

            ssl_sock = ssl.wrap_socket(sock, do_handshake_on_connect=False,
              certfile=certfile, server_side=server_side)
            self.sock = SSLWrapper(ssl_sock)

            self.recv_ssl_needs_kickoff = not server_side

        else:
            self.sock = SocketWrapper(sock)

        self.connection_made()
Ejemplo n.º 5
0
    def closed(self, exception=None):
        if self.close_complete:
            return

        self.close_complete = True

        if exception:
            LOG.error("* Connection %s: %s" % (self.logname, exception))
        elif self.eof:
            LOG.debug("* Connection %s: EOF" % (self.logname))
        else:
            LOG.debug("* Closed connection %s" % (self.logname))

        self.connection_lost(exception)
        self.parent.connection_lost(self)

        atclosev, self.atclosev = self.atclosev, set()
        for func in atclosev:
            try:
                func(self, exception)
            except (KeyboardInterrupt, SystemExit):
                raise
            except:
                LOG.oops("Error in atclosev")

        if self.measurer:
            self.measurer.unregister_stream(self)

        self.send_octets = None
        self.send_ticks = 0
        self.recv_ticks = 0
        self.sock.soclose()
Ejemplo n.º 6
0
    def got_response_negotiating(self, stream, request, response):
        m = json.loads(response.body.read())

        PROPERTIES = ("authorization", "queue_pos", "real_address", "unchoked")
        for k in PROPERTIES:
            self.conf["_%s" % k] = m[k]

        if not self.conf["_unchoked"]:
            LOG.complete("done (queue_pos %d)" % m["queue_pos"])
            STATE.update("negotiate", {"queue_pos": m["queue_pos"]})
            self.connection_ready(stream)
        else:
            LOG.complete("done (unchoked)")

            sha1 = hashlib.sha1()
            sha1.update(m["authorization"])
            self.conf["bittorrent.my_id"] = sha1.digest()
            LOG.debug("* My ID: %s" % sha1.hexdigest())
            self.http_stream = stream
            self.negotiating = False
            peer = PeerNeubot(self.poller)
            peer.complete = self.peer_test_complete
            peer.connection_lost = self.peer_connection_lost
            peer.connection_failed = self.peer_connection_failed
            peer.configure(self.conf)
            peer.connect((self.http_stream.peername[0],
                          self.conf["bittorrent.port"]))
Ejemplo n.º 7
0
    def prettyprintbody(self, prefix):
        ''' Pretty print body '''
        if self["content-type"] not in ("application/json", "text/xml",
                                        "application/xml"):
            return

        # Grab the whole body
        if not isinstance(self.body, basestring):
            body = self.body.read()
        else:
            body = self.body

        # Decode the body
        if self["content-type"] == "application/json":
            string = compat.json.dumps(compat.json.loads(body),
              indent=4, sort_keys=True)
        elif self["content-type"] in ("text/xml", "application/xml"):
            string = body

        # Prettyprint
        for line in string.split("\n"):
            LOG.debug("%s %s" % (prefix, line.rstrip()))

        # Seek to the beginning if needed
        if not isinstance(self.body, basestring):
            utils.safe_seek(self.body, 0)
Ejemplo n.º 8
0
 def merge_api(self, dictlike, database=None):
     # enforce all-or-nothing
     LOG.debug("config: reading properties from /api/config")
     map(lambda t: self.merge_kv(t, dry=True), dictlike.iteritems())
     map(self.merge_kv, dictlike.iteritems())
     if database:
         table_config.update(database, dictlike.iteritems())
Ejemplo n.º 9
0
 def connection_lost(self, stream):
     if runner_core.test_is_running():
         LOG.debug("RendezVous: don't _schedule(): test in progress")
         return
     if self._task:
         LOG.debug("RendezVous: don't _schedule(): we already have a task")
         return
     self._schedule()
Ejemplo n.º 10
0
 def connection_lost(self, stream):
     if NOTIFIER.is_subscribed("testdone"):
         LOG.debug("RendezVous: don't _schedule(): test in progress")
         return
     if self._task:
         LOG.debug("RendezVous: don't _schedule(): we already have a task")
         return
     self._schedule()
Ejemplo n.º 11
0
 def connection_made(self, sock, rtt=0):
     ''' Invoked when the connection is created '''
     if rtt:
         LOG.debug("ClientHTTP: latency: %s" % utils.time_formatter(rtt))
         self.rtt = rtt
     stream = ClientStream(self.poller)
     stream.attach(self, sock, self.conf)
     self.connection_ready(stream)
Ejemplo n.º 12
0
 def __setitem__(self, key, value):
     if key in self:
         ovalue = self[key]
         cast = utils.smart_cast(ovalue)
     else:
         ovalue = "(none)"
         cast = utils.smart_cast(value)
     value = cast(value)
     LOG.debug("config: %s: %s -> %s" % (key, ovalue, value))
     dict.__setitem__(self, key, value)
Ejemplo n.º 13
0
    def recv_complete(self, s):
        while s and not (self.close_pending or self.close_complete):

            # If we don't know the length then read it
            if self.left == 0:
                amt = min(len(s), 4 - self.count)
                self.buff.append(s[:amt])
                s = buffer(s, amt)
                self.count += amt

                if self.count == 4:
                    self.left = toint("".join(self.buff))
                    if self.left == 0:
                        LOG.debug("< KEEPALIVE")
                    del self.buff[:]
                    self.count = 0

                elif self.count > 4:
                    raise RuntimeError("Invalid self.count")

            # Bufferize and pass upstream messages
            elif self.left > 0:
                amt = min(len(s), self.left)
                if self.count <= self.smallmessage:
                    self.buff.append(s[:amt])
                else:
                    if self.buff:
                        self._got_message_start("".join(self.buff))
                        # This means "big message"
                        del self.buff[:]
                    mp = buffer(s, 0, amt)
                    self._got_message_part(mp)
                s = buffer(s, amt)
                self.left -= amt
                self.count += amt

                if self.left == 0:
                    # Small or big message?
                    if self.buff:
                        self._got_message("".join(self.buff))
                    else:
                        self._got_message_end()
                    del self.buff[:]
                    self.count = 0

                elif self.left < 0:
                    raise RuntimeError("Invalid self.left")

            # Something's wrong
            else:
                raise RuntimeError("Invalid self.left")

        if not (self.close_pending or self.close_complete):
            self.start_recv()
Ejemplo n.º 14
0
    def update(self, name, event=None, publish=True):
        if not event:
            event = {}

        if name in STATES:
            self._current = name
        self._t = self._T()
        self._events[name] = event

        LOG.debug("state: %s %s" % (name, event))

        if publish:
            self._publish(STATECHANGE, self._t)
Ejemplo n.º 15
0
    def send_piece(self, index, begin, block):
        if not isinstance(block, basestring):
            length = utils.file_length(block)
            LOG.debug("> PIECE %d %d len=%d" % (index, begin, length))
            preamble = struct.pack("!cII", PIECE, index, begin)
            l = len(preamble) + length
            d = [tobinary(l), ]
            d.extend(preamble)
            s = "".join(d)
            self.start_send(s)
            self.start_send(block)
            return

        LOG.debug("> PIECE %d %d len=%d" % (index, begin, len(block)))
        self._send_message(struct.pack("!cII%ss" % len(block), PIECE,
          index, begin, block))
Ejemplo n.º 16
0
    def recv_complete(self, s):

        ''' Invoked when recv() completes '''

        while s and not (self.close_pending or self.close_complete):

            # If we don't know the length then read it
            if self.left == 0:
                amt = min(len(s), 4 - self.count)
                self.buff.append(s[:amt])
                s = buffer(s, amt)
                self.count += amt

                if self.count == 4:
                    self.left = toint("".join(self.buff))
                    if self.left == 0:
                        LOG.debug("< KEEPALIVE")
                    elif self.left > MAXMESSAGE:
                        raise RuntimeError('Message too big')
                    del self.buff[:]
                    self.count = 0

                elif self.count > 4:
                    raise RuntimeError("Invalid self.count")

            # Bufferize and pass upstream messages
            elif self.left > 0:
                amt = min(len(s), self.left)
                self.buff.append(s[:amt])
                s = buffer(s, amt)
                self.left -= amt
                self.count += amt

                if self.left == 0:
                    self._got_message("".join(self.buff))
                    del self.buff[:]
                    self.count = 0

                elif self.left < 0:
                    raise RuntimeError("Invalid self.left")

            # Something's wrong
            else:
                raise RuntimeError("Invalid self.left")

        if not (self.close_pending or self.close_complete):
            self.start_recv()
Ejemplo n.º 17
0
    def connect(self, endpoint, conf):

        # Connect first address in a list
        if ' ' in endpoint[0]:
            LOG.debug('* Connecting to %s' % str(endpoint))
            for address in endpoint[0].split():
                epnt = (address.strip(), endpoint[1])
                self.epnts.append(epnt)
            endpoint = self.epnts.popleft()

        self.endpoint = endpoint

        sock = utils_net.connect(endpoint)
        if not sock:
            self._connection_failed()
            return

        self.sock = sock
        self.timestamp = utils.ticks()
        self.poller.set_writable(self)
Ejemplo n.º 18
0
def main(args):
    common.main("agent", "Run in background, periodically run tests", args)

    conf = CONFIG.copy()

    privacy.complain_if_needed()

    if conf["agent.api"]:
        server = HTTP_SERVER
        LOG.debug("* API server root directory: %s" % WWW)
        conf["http.server.rootdir"] = WWW
        conf["http.server.ssi"] = True
        conf["http.server.bind_or_die"] = True
        server.configure(conf)
        server.register_child(ServerAPI(POLLER), "/api")
        server.listen((conf["agent.api.address"], conf["agent.api.port"]))

    if conf["agent.daemonize"]:
        system.change_dir()
        system.go_background()
        system.write_pidfile()
        LOG.redirect()

    if conf["agent.use_syslog"]:
        LOG.redirect()

    system.drop_privileges(LOG.error)

    #
    # When we run as an agent we also save logs into
    # the database, to easily access and show them via
    # the web user interface.
    #
    LOG.use_database()

    if conf["agent.rendezvous"]:
        client = ClientRendezvous(POLLER)
        client.configure(conf)
        client.connect_uri()

    POLLER.loop()
Ejemplo n.º 19
0
    def attach(self, parent, sock, conf, measurer=None):

        self.parent = parent
        self.conf = conf

        self.filenum = sock.fileno()
        self.myname = sock.getsockname()
        self.peername = sock.getpeername()
        self.logname = str((self.myname, self.peername))

        self.measurer = measurer
        if self.measurer:
            self.measurer.register_stream(self)

        LOG.debug("* Connection made %s" % str(self.logname))

        if conf.get("net.stream.secure", False):
            if not ssl:
                raise RuntimeError("SSL support not available")

            server_side = conf.get("net.stream.server_side", False)
            certfile = conf.get("net.stream.certfile", None)

            so = ssl.wrap_socket(sock, do_handshake_on_connect=False,
              certfile=certfile, server_side=server_side)
            self.sock = SSLWrapper(so)

            self.recv_ssl_needs_kickoff = not server_side

        else:
            self.sock = SocketWrapper(sock)

        if conf.get("net.stream.obfuscate", False):
            key = conf.get("net.stream.key", None)
            self.encrypt = arcfour_new(key).encrypt
            self.decrypt = arcfour_new(key).decrypt

        self.connection_made()
Ejemplo n.º 20
0
    def serialize_headers(self):
        ''' Serialize message headers '''
        vector = []

        if self.method:
            vector.append(self.method)
            vector.append(" ")
            if self.pathquery:
                vector.append(self.pathquery)
            elif self.uri:
                vector.append(self.uri)
            else:
                vector.append("/")
            vector.append(" ")
            vector.append(self.protocol)

        else:
            vector.append(self.protocol)
            vector.append(" ")
            vector.append(self.code)
            vector.append(" ")
            vector.append(self.reason)

        LOG.debug("> %s" % ("".join(vector)))
        vector.append("\r\n")

        for key, value in self.headers.items():
            key = "-".join(map(lambda s: s.capitalize(), key.split("-")))
            vector.append(key)
            vector.append(": ")
            vector.append(value)

            LOG.debug("> %s: %s" % (key, value))
            vector.append("\r\n")

        LOG.debug(">")
        vector.append("\r\n")

        string = "".join(vector)
        string = utils.stringify(string)
        return StringIO.StringIO(string)
Ejemplo n.º 21
0
 def _got_line(self, line):
     """ We've got a line... what do we do? """
     if self.state == FIRSTLINE:
         line = line.strip()
         LOG.debug("< %s" % line)
         vector = line.split(None, 2)
         if len(vector) == 3:
             if line.startswith("HTTP"):
                 protocol, code, reason = vector
                 if protocol in PROTOCOLS:
                     self.got_response_line(protocol, code, reason)
             else:
                 method, uri, protocol = vector
                 if protocol in PROTOCOLS:
                     self.got_request_line(method, uri, protocol)
             if protocol not in PROTOCOLS:
                 raise RuntimeError("Invalid protocol")
             else:
                 self.state = HEADER
         else:
             raise RuntimeError("Invalid first line")
     elif self.state == HEADER:
         if line.strip():
             LOG.debug("< %s" % line)
             # not handling mime folding
             index = line.find(":")
             if index >= 0:
                 key, value = line.split(":", 1)
                 self.got_header(key.strip(), value.strip())
             else:
                 raise RuntimeError("Invalid header line")
         else:
             LOG.debug("<")
             self.state, self.left = self.got_end_of_headers()
             if self.state == ERROR:
                 # allow upstream to filter out unwanted requests
                 self.close()
             elif self.state == FIRSTLINE:
                 # this is the case of an empty body
                 self.got_end_of_body()
     elif self.state == CHUNK_LENGTH:
         vector = line.split()
         if vector:
             length = int(vector[0], 16)
             if length < 0:
                 raise RuntimeError("Negative chunk-length")
             elif length == 0:
                 self.state = TRAILER
             else:
                 self.left = length
                 self.state = CHUNK
         else:
             raise RuntimeError("Invalid chunk-length line")
     elif self.state == CHUNK_END:
         if line.strip():
             raise RuntimeError("Invalid chunk-end line")
         else:
             self.state = CHUNK_LENGTH
     elif self.state == TRAILER:
         if not line.strip():
             self.state = FIRSTLINE
             self.got_end_of_body()
         else:
             # Ignoring trailers
             pass
     else:
         raise RuntimeError("Not expecting a line")
Ejemplo n.º 22
0
    def recv_complete(self, data):
        """ We've received successfully some data """
        if self.close_complete or self.close_pending:
            return

        # This one should be debug2 as well
        # LOG.debug("HTTP receiver: got %d bytes" % len(data))

        # merge with previous fragments (if any)
        if self.incoming:
            self.incoming.append(data)
            data = "".join(self.incoming)
            del self.incoming[:]

        # consume the current fragment
        offset = 0
        length = len(data)
        while length > 0:
            # ostate = self.state        # needed by commented-out code below

            # when we know the length we're looking for a piece
            if self.left > 0:
                count = min(self.left, length)
                piece = buffer(data, offset, count)
                self.left -= count
                offset += count
                length -= count
                self._got_piece(piece)

            # otherwise we're looking for the next line
            elif self.left == 0:
                index = data.find("\n", offset)
                if index == -1:
                    if length > MAXLINE:
                        raise RuntimeError("Line too long")
                    break
                index = index + 1
                line = data[offset:index]
                length -= index - offset
                offset = index
                self._got_line(line)

            # robustness
            else:
                raise RuntimeError("Left become negative")

            # robustness
            if self.close_complete or self.close_pending:
                return

        #           Should be debug2() not debug()
        #           LOG.debug("HTTP receiver: %s -> %s" %
        #             (STATES[ostate], STATES[self.state]))

        # keep the eventual remainder for later
        if length > 0:
            remainder = data[offset:]
            self.incoming.append(remainder)
            LOG.debug("HTTP receiver: remainder %d" % len(remainder))

        # get the next fragment
        self.start_recv()
Ejemplo n.º 23
0
 def send_unchoke(self):
     ''' Send the UNCHOKE message '''
     LOG.debug("> UNCHOKE")
     self._send_message(UNCHOKE)
Ejemplo n.º 24
0
 def send_request(self, index, begin, length):
     ''' Send the REQUEST message '''
     LOG.debug("> REQUEST %d %d %d" % (index, begin, length))
     self._send_message(struct.pack("!cIII", REQUEST, index, begin, length))
Ejemplo n.º 25
0
    def _got_message(self, message):

        ''' Invoked when we receive a complete message '''

        if not self.complete:
            if (len(message) != 68 or message[0] != chr(19) or
               message[1:20] != PROTOCOL_NAME):
                raise RuntimeError("Invalid handshake")
            self.id = message[-20:]
            infohash = message[-40:-20]
            LOG.debug("< HANDSHAKE infohash=%s id=%s" %
              (infohash.encode("hex"), self.id.encode("hex")))

            #
            # In Neubot the listener does not have an infohash
            # and handshakes, including connector infohash, after
            # it receives the connector handshake.
            #
            if not self.parent.infohash:
                self.parent.infohash = infohash
                self._send_handshake()
            elif infohash != self.parent.infohash:
                raise RuntimeError("Invalid infohash")

            self.complete = True
            self.parent.connection_ready(self)
            return

        t = message[0]
        if t not in MESSAGESET:
            raise RuntimeError("Invalid message type")
        if INVALID_LENGTH[t](len(message)):
            raise RuntimeError("Invalid message length")
        if t in [BITFIELD] and self.got_anything:
            raise RuntimeError("Bitfield after we got something")
        self.got_anything = True

        if t == CHOKE:
            LOG.debug("< CHOKE")
            self.parent.got_choke(self)

        elif t == UNCHOKE:
            LOG.debug("< UNCHOKE")
            self.parent.got_unchoke(self)

        elif t == INTERESTED:
            LOG.debug("< INTERESTED")
            self.parent.got_interested(self)

        elif t == NOT_INTERESTED:
            LOG.debug("< NOT_INTERESTED")
            self.parent.got_not_interested(self)

        elif t == HAVE:
            i = struct.unpack("!xI", message)[0]
            if i >= self.parent.numpieces:
                raise RuntimeError("HAVE: index out of bounds")
            LOG.debug("< HAVE %d" % i)
            self.parent.got_have(i)

        elif t == BITFIELD:
            LOG.debug("< BITFIELD {bitfield}")
            self.parent.got_bitfield(message[1:])

        elif t == REQUEST:
            i, a, b = struct.unpack("!xIII", message)
            LOG.debug("< REQUEST %d %d %d" % (i, a, b))
            if i >= self.parent.numpieces:
                raise RuntimeError("REQUEST: index out of bounds")
            self.parent.got_request(self, i, a, b)

        elif t == CANCEL:
            i, a, b = struct.unpack("!xIII", message)
            LOG.debug("< CANCEL %d %d %d" % (i, a, b))
            if i >= self.parent.numpieces:
                raise RuntimeError("CANCEL: index out of bounds")
            # NOTE Ignore CANCEL message

        elif t == PIECE:
            n = len(message) - 9
            i, a, b = struct.unpack("!xII%ss" % n, message)
            LOG.debug("< PIECE %d %d len=%d" % (i, a, n))
            if i >= self.parent.numpieces:
                raise RuntimeError("PIECE: index out of bounds")
            self.parent.got_piece(self, i, a, b)
Ejemplo n.º 26
0
 def send_piece(self, index, begin, block):
     ''' Send the PIECE message '''
     LOG.debug("> PIECE %d %d len=%d" % (index, begin, len(block)))
     self._send_message(struct.pack("!cII%ss" % len(block), PIECE,
       index, begin, block))
Ejemplo n.º 27
0
 def send_keepalive(self):
     ''' Send the KEEPALIVE message '''
     LOG.debug("> KEEPALIVE")
     self._send_message('')
Ejemplo n.º 28
0
 def send_have(self, index):
     ''' Send the HAVE message '''
     LOG.debug("> HAVE %d" % index)
     self._send_message(struct.pack("!cI", HAVE, index))
Ejemplo n.º 29
0
 def send_bitfield(self, bitfield):
     ''' Send the BITFIELD message '''
     LOG.debug("> BITFIELD {bitfield}")
     self._send_message(BITFIELD, bitfield)
Ejemplo n.º 30
0
 def send_cancel(self, index, begin, length):
     ''' Send the CANCEL message '''
     LOG.debug("> CANCEL %d %d %d" % (index, begin, length))
     self._send_message(struct.pack("!cIII", CANCEL, index, begin, length))