Example #1
0
    def _update_peer_version(self, response):
        vser = None

        server_header = response.headers.get("server", None)
        if server_header is not None:
            server_name, server_ver = http.parse_user_agent(server_header)
            if (server_name != FEAT_IDENT
                or len(server_ver) != 1
                or not isinstance(server_ver[0], int)):
                raise TunnelError("Unsupported server %r" % server_header)
            vser = server_ver[0]

        vin = self._tunnel._version
        vout = vser if vser is not None and vser < vin else vin
        self._peer_version = vser
        self._target_version = vout

        self._headers["user-agent"] = http.compose_user_agent(FEAT_IDENT, vout)

        return response
Example #2
0
 def parse_user_agent(self):
     agent = self.get_received_header("user-agent")
     if not agent:
         return "unknown", None
     return http.parse_user_agent(agent)
Example #3
0
    def onAllContentReceived(self):
        vout = self.channel.owner._version

        ctype = self.get_received_header("content-type")
        if ctype != "application/json":
            self._error(http.Status.UNSUPPORTED_MEDIA_TYPE,
                        "Message content type not supported, "
                        "only application/json is.")
            return

        agent_header = self.get_received_header("user-agent")
        if agent_header is None:
            self._error(http.Status.BAD_REQUEST, "No user agent specified.")
            return

        agent_name, agent_ver = http.parse_user_agent(agent_header)
        if ((agent_name != FEAT_IDENT)
            or len(agent_ver) != 1
            or not isinstance(agent_ver[0], int)):
            self._error(http.Status.BAD_REQUEST, "User agent not supported.")
            return

        vcli = agent_ver[0]

        if self.method is http.Methods.HEAD:
            vin = vcli if vcli is not None and vcli < vout else vout
            server_header = http.compose_user_agent(FEAT_IDENT, vin)
            self.set_header("server", server_header)
            self.set_length(0)
            self.finish()
            return

        if self.method is http.Methods.POST:
            if vcli is not None and vcli > vout:
                # not safe, better fail
                self._error(http.Status.UNSUPPORTED_MEDIA_TYPE,
                            "Message version not supported.")
                return

            host_header = self.get_received_header("host")
            if host_header is None:
                self._error(http.Status.BAD_REQUEST,
                            "Message without host header.")
                return

            scheme = self.channel.owner._scheme
            host, port = http.parse_host(host_header, scheme)
            uri = http.compose(self.uri, host=host, port=port, scheme=scheme)

            vin = vcli if vcli is not None else vout
            unserializer = json.Unserializer(registry=self._registry,
                                             source_ver=vin, target_ver=vout)
            body = "".join(self._buffer)
            try:
                data = unserializer.convert(body)
            except Exception as e:
                msg = "Error while unserializing tunnel message"
                error.handle_exception(self, e, msg)
                self._error(http.Status.BAD_REQUEST,
                            "Invalid message, unserialization failed.")
                return

            self.channel.owner._dispatch(uri, data)

            self.set_response_code(http.Status.OK)
            server_header = http.compose_user_agent(FEAT_IDENT, vin)
            self.set_header("server", server_header)
            self.set_length(0)
            self.finish()
            return

        self.set_response_code(http.Status.NOT_ALLOWED)
        self.set_header("content-type", "plain/text")
        self.write("Method not allowed, only POST and HEAD.")
        self.finish()