mirror of
				https://github.com/django/daphne.git
				synced 2025-11-04 09:37:32 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			102 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import time
 | 
						|
 | 
						|
from channels import Channel, channel_backends, DEFAULT_CHANNEL_BACKEND
 | 
						|
 | 
						|
 | 
						|
def get_protocol(base):
 | 
						|
 | 
						|
    class InterfaceProtocol(base):
 | 
						|
        """
 | 
						|
        Protocol which supports WebSockets and forwards incoming messages to
 | 
						|
        the websocket channels.
 | 
						|
        """
 | 
						|
 | 
						|
        def onConnect(self, request):
 | 
						|
            self.channel_backend = channel_backends[DEFAULT_CHANNEL_BACKEND]
 | 
						|
            self.request_info = {
 | 
						|
                "path": request.path,
 | 
						|
                "get": request.params,
 | 
						|
            }
 | 
						|
 | 
						|
        def onOpen(self):
 | 
						|
            # Make sending channel
 | 
						|
            self.reply_channel = Channel.new_name("!websocket.send")
 | 
						|
            self.request_info["reply_channel"] = self.reply_channel
 | 
						|
            self.last_keepalive = time.time()
 | 
						|
            self.factory.protocols[self.reply_channel] = self
 | 
						|
            # Send news that this channel is open
 | 
						|
            Channel("websocket.connect").send(self.request_info)
 | 
						|
 | 
						|
        def onMessage(self, payload, isBinary):
 | 
						|
            if isBinary:
 | 
						|
                Channel("websocket.receive").send({
 | 
						|
                    "reply_channel": self.reply_channel,
 | 
						|
                    "content": payload,
 | 
						|
                    "binary": True,
 | 
						|
                })
 | 
						|
            else:
 | 
						|
                Channel("websocket.receive").send({
 | 
						|
                    "reply_channel": self.reply_channel,
 | 
						|
                    "content": payload.decode("utf8"),
 | 
						|
                    "binary": False,
 | 
						|
                })
 | 
						|
 | 
						|
        def serverSend(self, content, binary=False, **kwargs):
 | 
						|
            """
 | 
						|
            Server-side channel message to send a message.
 | 
						|
            """
 | 
						|
            if binary:
 | 
						|
                self.sendMessage(content, binary)
 | 
						|
            else:
 | 
						|
                self.sendMessage(content.encode("utf8"), binary)
 | 
						|
 | 
						|
        def serverClose(self):
 | 
						|
            """
 | 
						|
            Server-side channel message to close the socket
 | 
						|
            """
 | 
						|
            self.sendClose()
 | 
						|
 | 
						|
        def onClose(self, wasClean, code, reason):
 | 
						|
            if hasattr(self, "reply_channel"):
 | 
						|
                del self.factory.protocols[self.reply_channel]
 | 
						|
                Channel("websocket.disconnect").send({
 | 
						|
                    "reply_channel": self.reply_channel,
 | 
						|
                })
 | 
						|
 | 
						|
        def sendKeepalive(self):
 | 
						|
            """
 | 
						|
            Sends a keepalive packet on the keepalive channel.
 | 
						|
            """
 | 
						|
            Channel("websocket.keepalive").send({
 | 
						|
                "reply_channel": self.reply_channel,
 | 
						|
            })
 | 
						|
            self.last_keepalive = time.time()
 | 
						|
 | 
						|
    return InterfaceProtocol
 | 
						|
 | 
						|
 | 
						|
def get_factory(base):
 | 
						|
 | 
						|
    class InterfaceFactory(base):
 | 
						|
        """
 | 
						|
        Factory which keeps track of its open protocols' receive channels
 | 
						|
        and can dispatch to them.
 | 
						|
        """
 | 
						|
 | 
						|
        # TODO: Clean up dead protocols if needed?
 | 
						|
 | 
						|
        def __init__(self, *args, **kwargs):
 | 
						|
            super(InterfaceFactory, self).__init__(*args, **kwargs)
 | 
						|
            self.protocols = {}
 | 
						|
 | 
						|
        def reply_channels(self):
 | 
						|
            return self.protocols.keys()
 | 
						|
 | 
						|
        def dispatch_send(self, channel, message):
 | 
						|
            if message.get("content", None):
 | 
						|
                self.protocols[channel].serverSend(**message)
 | 
						|
            if message.get("close", False):
 | 
						|
                self.protocols[channel].serverClose()
 | 
						|
 | 
						|
    return InterfaceFactory
 |