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
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
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):