Ejemplo n.º 1
0
    def _load_ticket(self, stream_slug, destination_uuid):
        stream = Stream.get_by(slug=stream_slug)
        if not destination_uuid:
            return Ticket.get_by(stream=stream, destination=Node.me())

        node = Node.get_by(uuid=destination_uuid)
        return Ticket.query.filter_by(stream=stream, destination=node).first()
Ejemplo n.º 2
0
    def _load_ticket(self, stream_slug, destination_uuid):
        stream = Stream.get_by(slug=stream_slug)
        if not destination_uuid:
            return Ticket.get_by(stream=stream, destination=Node.me())

        node = Node.get_by(uuid=destination_uuid)
        return Ticket.query.filter_by(stream=stream, destination=node).first()
Ejemplo n.º 3
0
 def test_delete(self):
     node = Node.me()
     ticket = TicketFactory(destination=node)
     self.http_client.fetch(HTTPRequest(
         self.get_url(ticket.absolute_url()), 'DELETE'), self.stop)
     response = self.wait()
     eq_(response.code, 200)
     eq_(Ticket.get_by(id=ticket.id), None)
     ok_(Stream.get_by(slug=ticket.stream.slug))
Ejemplo n.º 4
0
 def test_get_tickets(self):
     response = self.fetch("/tickets")
     eq_(response.code, 200)
     result = json.loads(response.body)
     ok_("tickets" in result)
     eq_(len(result["tickets"]), 3)
     for ticket in result["tickets"]:
         source = Node.get_by(uuid=ticket["source"])
         destination = Node.get_by(uuid=ticket["destination"])
         ok_(Ticket.get_by(stream=Stream.get_by(slug=ticket["stream"]), source=source, destination=destination))
Ejemplo n.º 5
0
 def test_delete(self):
     node = Node.me()
     ticket = TicketFactory(destination=node)
     self.http_client.fetch(
         HTTPRequest(self.get_url(ticket.absolute_url()), 'DELETE'),
         self.stop)
     response = self.wait()
     eq_(response.code, 200)
     eq_(Ticket.get_by(id=ticket.id), None)
     ok_(Stream.get_by(slug=ticket.stream.slug))
Ejemplo n.º 6
0
    def _offer_ourselves(cls, stream, destination):
        tickets = Ticket.query.filter_by(source=Node.me())
        if (tickets.count() >= settings.OUTGOING_STREAM_LIMIT
                or Node.me().upstream and tickets.count() *
                settings.STREAM_BITRATE > Node.me().upstream):
            log.info("Can't stream %s to %s, already at limit", stream,
                     destination)
            raise HTTPError(412)

        ticket = Ticket.get_by(stream=stream, destination=Node.me())
        if ticket:
            new_ticket = Ticket(stream=stream,
                                destination=destination,
                                source_port=ticket.source_port,
                                hops=ticket.hops + 1)
            log.info(
                "We are receiving %s and have room to forward -- "
                "created %s to potentially forward to %s", stream, new_ticket,
                destination)
            return new_ticket
Ejemplo n.º 7
0
 def _handle_ticket(self, ticket):
     # reload to get a new database session
     ticket = Ticket.get_by(id=ticket.id)
     if ticket.source == Node.me():
         source_ip = "127.0.0.1"
     else:
         source_ip = ticket.source.ip_address
     try:
         port = self.create_tunnel(ticket.id, source_ip, ticket.source_port,
                                   self.tunnels)
     except Exception, e:
         log.warning("Couldn't create a tunnel for %s: %s", ticket, e)
Ejemplo n.º 8
0
 def _handle_ticket(self, ticket):
     # reload to get a new database session
     ticket = Ticket.get_by(id=ticket.id)
     if ticket.source == Node.me():
         source_ip = "127.0.0.1"
     else:
         source_ip = ticket.source.ip_address
     try:
         port = self.create_tunnel(ticket.id, source_ip,
                 ticket.source_port, self.tunnels)
     except Exception, e:
         log.warning("Couldn't create a tunnel for %s: %s",
                 ticket, e)
Ejemplo n.º 9
0
    def handle_ticket_request(cls, stream, destination):
        log.debug("Trying to create a ticket to serve %s to %s", stream,
                  destination)
        new_ticket = cls._already_streaming(stream, destination)
        if new_ticket:
            log.info("%s already has a ticket for %s (%s)", destination,
                     stream, new_ticket)
            if not new_ticket.source == Node.me():
                log.info("Refreshing with source %s to be sure",
                         new_ticket.source)
                existing_ticket = cls._request_stream_from_node(
                    stream, new_ticket.source, destination)
            else:
                existing_ticket = new_ticket
            if existing_ticket:
                existing_ticket.refreshed = datetime.datetime.now()
                # In case we lost the tunnel, just make sure it exists
                existing_ticket.queue_tunnel_creation()
                session.commit()
                return existing_ticket
            log.info(
                "%s didn't confirm our old ticket %s, must get a new "
                "one", new_ticket.source, new_ticket)

        if stream.source != Node.me():
            new_ticket = cls._offer_ourselves(stream, destination)
            if new_ticket:
                log.info("We can stream %s to %s, created %s", stream,
                         destination, new_ticket)
                # In case we lost the tunnel, just make sure it exists
                new_ticket.queue_tunnel_creation()
            elif Node.me().supernode or destination == Node.me():
                log.info(
                    "Propagating the request for streaming %s to %s to "
                    "our other known nodes", stream, destination)
                new_ticket = cls._request_stream_from_others(
                    stream, destination)
            else:
                raise HTTPError(412)
        else:
            new_ticket = Ticket(stream=stream,
                                source_port=stream.source_port,
                                destination=destination)
            log.info("%s is the source of %s, created %s", Node.me(), stream,
                     new_ticket)
        session.commit()
        return new_ticket
Ejemplo n.º 10
0
    def _offer_ourselves(cls, stream, destination):
        tickets = Ticket.query.filter_by(source=Node.me())
        if (tickets.count() >= settings.OUTGOING_STREAM_LIMIT
                or Node.me().upstream and tickets.count()
                    * settings.STREAM_BITRATE > Node.me().upstream):
            log.info("Can't stream %s to %s, already at limit", stream,
                    destination)
            raise HTTPError(412)

        ticket = Ticket.get_by(stream=stream, destination=Node.me())
        if ticket:
            new_ticket = Ticket(stream=stream, destination=destination,
                    source_port=ticket.source_port, hops=ticket.hops + 1)
            log.info("We are receiving %s and have room to forward -- "
                "created %s to potentially forward to %s", stream, new_ticket,
                destination)
            return new_ticket
Ejemplo n.º 11
0
 def close_expired_tunnels(self):
     for ticket_id, tunnel in self.tunnels.items():
         if not Ticket.get_by(id=ticket_id):
             self.destroy_tunnel(ticket_id, self.tunnels)
Ejemplo n.º 12
0
 def _already_streaming(cls, stream, destination):
     return Ticket.get_by(stream=stream, destination=destination)
Ejemplo n.º 13
0
 def _cleanup_unconfirmed_tickets(self):
     query = Ticket.unconfirmed()
     query = Ticket.old(query=query)
     for ticket in query:
         log.info("Expiring unconfirmed ticket %s", ticket)
         ticket.delete()
Ejemplo n.º 14
0
 def close_expired_tunnels(self):
     for ticket_id, tunnel in self.tunnels.items():
         if not Ticket.get_by(id=ticket_id):
             self.destroy_tunnel(ticket_id, self.tunnels)
Ejemplo n.º 15
0
 def _already_streaming(cls, stream, destination):
     return Ticket.get_by(stream=stream, destination=destination)
Ejemplo n.º 16
0
        except RequestFailed, e:
            if e.response.status_int == 412:
                log.debug("%s didn't have room to forward %s to us", node,
                          stream)
        else:
            if existing_ticket:
                return existing_ticket
            if ticket_data:
                source = Node.get_by(uuid=ticket_data['source'])
                if not source:
                    source_node_data = NodesAPI(node.uri()).get(
                        Node.absolute_url(source))
                    source = Node.from_dict(source_node_data)
                return Ticket(stream=stream,
                              source=source,
                              source_port=ticket_data['source_port'],
                              destination=destination,
                              hops=ticket_data['hops'] + 1)

    @classmethod
    def _request_stream_from_watchers(cls,
                                      stream,
                                      destination,
                                      unconfirmed_tickets=None):
        tickets = []
        for ticket in Ticket.query.filter_by(stream=stream):
            if cls._already_seeding(ticket):
                return [ticket]
            else:
                if not cls._already_ticketed(unconfirmed_tickets,
                                             ticket.destination):
Ejemplo n.º 17
0
 def _cleanup_unconfirmed_tickets(self):
     query = Ticket.unconfirmed()
     query = Ticket.old(query=query)
     for ticket in query:
         log.info("Expiring unconfirmed ticket %s", ticket)
         ticket.delete()