91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
|
import logging
|
||
|
from twisted.internet import interfaces, error
|
||
|
from twisted.internet.protocol import Protocol, ServerFactory
|
||
|
from twisted.python import failure
|
||
|
from zope.interface import implements
|
||
|
from lbrynet.core.server.ServerRequestHandler import ServerRequestHandler
|
||
|
|
||
|
|
||
|
class ServerProtocol(Protocol):
|
||
|
"""ServerProtocol needs to:
|
||
|
|
||
|
1) Receive requests from its transport
|
||
|
2) Pass those requests on to its request handler
|
||
|
3) Tell the request handler to pause/resume producing
|
||
|
4) Tell its transport to pause/resume producing
|
||
|
5) Hang up when the request handler is done producing
|
||
|
6) Tell the request handler to stop producing if the connection is lost
|
||
|
7) Upon creation, register with the rate limiter
|
||
|
8) Upon connection loss, unregister with the rate limiter
|
||
|
9) Report all uploaded and downloaded bytes to the rate limiter
|
||
|
10) Pause/resume production when told by the rate limiter
|
||
|
"""
|
||
|
|
||
|
implements(interfaces.IConsumer)
|
||
|
|
||
|
#Protocol stuff
|
||
|
|
||
|
def connectionMade(self):
|
||
|
logging.debug("Got a connection")
|
||
|
peer_info = self.transport.getPeer()
|
||
|
self.peer = self.factory.peer_manager.get_peer(peer_info.host, peer_info.port)
|
||
|
self.request_handler = ServerRequestHandler(self)
|
||
|
for query_handler_factory, enabled in self.factory.query_handler_factories.iteritems():
|
||
|
if enabled is True:
|
||
|
query_handler = query_handler_factory.build_query_handler()
|
||
|
query_handler.register_with_request_handler(self.request_handler, self.peer)
|
||
|
logging.debug("Setting the request handler")
|
||
|
self.factory.rate_limiter.register_protocol(self)
|
||
|
|
||
|
def connectionLost(self, reason=failure.Failure(error.ConnectionDone())):
|
||
|
if self.request_handler is not None:
|
||
|
self.request_handler.stopProducing()
|
||
|
self.factory.rate_limiter.unregister_protocol(self)
|
||
|
if not reason.check(error.ConnectionDone):
|
||
|
logging.warning("Closing a connection. Reason: %s", reason.getErrorMessage())
|
||
|
|
||
|
def dataReceived(self, data):
|
||
|
logging.debug("Receiving %s bytes of data from the transport", str(len(data)))
|
||
|
self.factory.rate_limiter.report_dl_bytes(len(data))
|
||
|
if self.request_handler is not None:
|
||
|
self.request_handler.data_received(data)
|
||
|
|
||
|
#IConsumer stuff
|
||
|
|
||
|
def registerProducer(self, producer, streaming):
|
||
|
logging.debug("Registering the producer")
|
||
|
assert streaming is True
|
||
|
|
||
|
def unregisterProducer(self):
|
||
|
self.request_handler = None
|
||
|
self.transport.loseConnection()
|
||
|
|
||
|
def write(self, data):
|
||
|
logging.debug("Writing %s bytes of data to the transport", str(len(data)))
|
||
|
self.transport.write(data)
|
||
|
self.factory.rate_limiter.report_ul_bytes(len(data))
|
||
|
|
||
|
#Rate limiter stuff
|
||
|
|
||
|
def throttle_upload(self):
|
||
|
if self.request_handler is not None:
|
||
|
self.request_handler.pauseProducing()
|
||
|
|
||
|
def unthrottle_upload(self):
|
||
|
if self.request_handler is not None:
|
||
|
self.request_handler.resumeProducing()
|
||
|
|
||
|
def throttle_download(self):
|
||
|
self.transport.pauseProducing()
|
||
|
|
||
|
def unthrottle_download(self):
|
||
|
self.transport.resumeProducing()
|
||
|
|
||
|
|
||
|
class ServerProtocolFactory(ServerFactory):
|
||
|
protocol = ServerProtocol
|
||
|
|
||
|
def __init__(self, rate_limiter, query_handler_factories, peer_manager):
|
||
|
self.rate_limiter = rate_limiter
|
||
|
self.query_handler_factories = query_handler_factories
|
||
|
self.peer_manager = peer_manager
|