Example #1
0
    async def _recv_response(self, reader, writer):
        """
        wait response and put it in response_mapping, than notify the invoke coro
        :param reader:
        :return:
        """
        while True:
            pkg = None
            try:
                fixed_header_bs = await reader.readexactly(
                    BoltResponse.bolt_header_size())
                header = BoltResponse.bolt_header_from_stream(fixed_header_bs)
                bs = await reader.readexactly(header['class_len'] +
                                              header['header_len'] +
                                              header['content_len'])
                pkg = BoltResponse.bolt_content_from_stream(bs, header)
                if pkg.class_name != BoltResponse.class_name:
                    raise ServerError("wrong class_name:[{}]".format(
                        pkg.class_name))
                if pkg.cmdcode == CMDCODE.HEARTBEAT:
                    continue
                elif pkg.cmdcode == CMDCODE.REQUEST:
                    # raise error, the connection will be dropped
                    raise ServerError("wrong cmdcode:[{}]".format(pkg.cmdcode))
                if pkg.respstatus != RESPSTATUS.SUCCESS:
                    raise ServerError.from_statuscode(pkg.respstatus)
                if pkg.request_id not in self.request_mapping:
                    continue
                self.response_mapping[pkg.request_id] = pkg

            except PyboltError as e:
                logger.error(e)
            except (asyncio.CancelledError, EOFError,
                    ConnectionResetError) as e:
                logger.error(e)
                writer.close()
                break
            except Exception:
                logger.error(traceback.format_exc())
                writer.close()
                break
            finally:
                with suppress(AttributeError, KeyError):
                    # wake up the coro
                    event = self.request_mapping.pop(pkg.request_id)
                    event.set()
    def test_repr(self):
        p = BoltResponse(SofaHeader(a='1', b='2'), b"cdefgab", ptype=PTYPE.ONEWAY, request_id=0,
                         cmdcode=CMDCODE.HEARTBEAT,
                         respstatus=1)
        print(p)
        s = p.to_stream()
        pr = BoltResponse.from_stream(s)
        self.assertNotEqual(id(p), id(pr))
        self.assertEqual(p.header, pr.header)
        self.assertEqual(p.content, pr.content)
        self.assertEqual(p.cmdcode, pr.cmdcode)
        self.assertEqual(p.request_id, pr.request_id)
        print(pr)

        p = BoltRequest(SofaHeader(a='1', b='2'), b"jklmnhi", ptype=PTYPE.ONEWAY, request_id=0,
                        cmdcode=CMDCODE.HEARTBEAT,
                        timeout=-1)
        print(p)
        s = p.to_stream()
        pr = BoltRequest.from_stream(s)
        self.assertNotEqual(id(p), id(pr))
        self.assertEqual(p.header, pr.header)
        self.assertEqual(p.content, pr.content)
        self.assertEqual(p.cmdcode, pr.cmdcode)
        self.assertEqual(p.request_id, pr.request_id)
        print(pr)
Example #3
0
    def handle(self):
        try:
            fixed_header_bs = self._readexactly(BoltRequest.bolt_header_size())
            header = BoltRequest.bolt_header_from_stream(fixed_header_bs)
            call_type = header['ptype']
            cmdcode = header['cmdcode']

            class_name = self._readexactly(header['class_len'])
            bs = self._readexactly(header['header_len'])
            sofa_header = SofaHeader.from_bytes(bs)
            body = self._readexactly(header['content_len'])

            request_id = header['request_id']

            if cmdcode == CMDCODE.HEARTBEAT:
                self.wfile.write(HeartbeatResponse.response_to(request_id).to_stream())
                self.wfile.flush()
                return

            if cmdcode == CMDCODE.RESPONSE:
                raise ClientError("wrong cmdcode:[{}]".format(cmdcode))

            if class_name != "com.alipay.sofa.rpc.core.request.SofaRequest".encode():
                raise ClientError("wrong class_name:[{}]".format(class_name))

            service = sofa_header.get('sofa_head_target_service') or sofa_header.get('service')
            if not service:
                self.wfile.write(FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR).to_stream())
                self.wfile.flush()
                logger.error("Missing service name in sofa header [{}]".format(sofa_header))
                return
            method = sofa_header.get('sofa_head_method_name')
            if not method:
                self.wfile.write(FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR).to_stream())
                self.wfile.flush()
                logger.error("Missing method name in sofa header [{}]".format(sofa_header))
                return

            spanctx = tracer.extract(opentracing.Format.TEXT_MAP, sofa_header)
            # call servicehandler
            ret = self.service_handler.handle_request(spanctx, service, method, body)
            self.wfile.write(BoltResponse.response_to(ret, request_id=request_id).to_stream())
            self.wfile.flush()

        except OSError as e:
            if e.errno != ECONNRESET:
                raise

        except Exception as e:
            logger.error(traceback.format_exc())
    def test_from_stream(self):
        bs = b'\x01\x00\x00\x02\x01\x00\x00\x00\x84\x0b\x00\x00\x00\x2e\x00\x00\x00\x00\x00\x03\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x73\x6f\x66\x61\x2e\x72\x70\x63\x2e\x63\x6f\x72\x65\x2e\x72\x65\x73\x70\x6f\x6e\x73\x65\x2e\x53\x6f\x66\x61\x52\x65\x73\x70\x6f\x6e\x73\x65\x0a\x01\x61'
        p = BoltResponse.from_stream(bs)
        self.assertEqual(p.body_len, len(bs) - p.bolt_header_size())
        print(p.content)
        re = SampleServicePbResult_pb2.SampleServicePbResult()
        re.ParseFromString(p.content)
        # print(p)
        print(re.result)
        self.assertEqual(re.result, 'a')

        bs = b'\x01\x01\x00\x01\x01\x00\x00\x00\x6d\x0b\x00\x00\x00\x64\x00\x2c\x02\xe6\x00\x00\x00\x03\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x73\x6f\x66\x61\x2e\x72\x70\x63\x2e\x63\x6f\x72\x65\x2e\x72\x65\x71\x75\x65\x73\x74\x2e\x53\x6f\x66\x61\x52\x65\x71\x75\x65\x73\x74\x00\x00\x00\x18\x73\x6f\x66\x61\x5f\x68\x65\x61\x64\x5f\x74\x61\x72\x67\x65\x74\x5f\x73\x65\x72\x76\x69\x63\x65\x00\x00\x00\x3b\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x72\x70\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x73\x65\x72\x76\x69\x63\x65\x2e\x66\x61\x63\x61\x64\x65\x2e\x70\x62\x2e\x53\x61\x6d\x70\x6c\x65\x53\x65\x72\x76\x69\x63\x65\x50\x62\x3a\x31\x2e\x30\x00\x00\x00\x1b\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x52\x70\x63\x49\x64\x00\x00\x00\x01\x30\x00\x00\x00\x1f\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x7a\x70\x72\x6f\x78\x79\x54\x69\x6d\x65\x6f\x75\x74\x00\x00\x00\x03\x31\x30\x30\x00\x00\x00\x1d\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x54\x72\x61\x63\x65\x49\x64\x00\x00\x00\x1e\x30\x62\x61\x36\x31\x36\x61\x31\x31\x35\x32\x33\x32\x35\x31\x38\x31\x39\x31\x31\x34\x31\x30\x30\x32\x31\x38\x37\x33\x38\x00\x00\x00\x1f\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x49\x64\x63\x00\x00\x00\x03\x64\x65\x76\x00\x00\x00\x1e\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x49\x70\x00\x00\x00\x0d\x31\x31\x2e\x31\x36\x36\x2e\x32\x32\x2e\x31\x36\x31\x00\x00\x00\x1e\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x50\x65\x6e\x41\x74\x74\x72\x73\x00\x00\x00\x00\x00\x00\x00\x1b\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x7a\x70\x72\x6f\x78\x79\x55\x49\x44\x00\x00\x00\x00\x00\x00\x00\x20\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x5a\x6f\x6e\x65\x00\x00\x00\x05\x47\x5a\x30\x30\x42\x00\x00\x00\x14\x73\x6f\x66\x61\x5f\x68\x65\x61\x64\x5f\x74\x61\x72\x67\x65\x74\x5f\x61\x70\x70\x00\x00\x00\x04\x62\x61\x72\x31\x00\x00\x00\x07\x73\x65\x72\x76\x69\x63\x65\x00\x00\x00\x3b\x63\x6f\x6d\x2e\x61\x6c\x69\x70\x61\x79\x2e\x72\x70\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x73\x65\x72\x76\x69\x63\x65\x2e\x66\x61\x63\x61\x64\x65\x2e\x70\x62\x2e\x53\x61\x6d\x70\x6c\x65\x53\x65\x72\x76\x69\x63\x65\x50\x62\x3a\x31\x2e\x30\x00\x00\x00\x19\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x45\x6c\x61\x73\x74\x69\x63\x00\x00\x00\x01\x46\x00\x00\x00\x1d\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x79\x73\x50\x65\x6e\x41\x74\x74\x72\x73\x00\x00\x00\x00\x00\x00\x00\x22\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x7a\x70\x72\x6f\x78\x79\x54\x61\x72\x67\x65\x74\x5a\x6f\x6e\x65\x00\x00\x00\x00\x00\x00\x00\x1f\x72\x70\x63\x5f\x74\x72\x61\x63\x65\x5f\x63\x6f\x6e\x74\x65\x78\x74\x2e\x73\x6f\x66\x61\x43\x61\x6c\x6c\x65\x72\x41\x70\x70\x00\x00\x00\x03\x66\x6f\x6f\x00\x00\x00\x15\x73\x6f\x66\x61\x5f\x68\x65\x61\x64\x5f\x6d\x65\x74\x68\x6f\x64\x5f\x6e\x61\x6d\x65\x00\x00\x00\x05\x68\x65\x6c\x6c\x6f\x0a\x01\x61'
        p = BoltRequest.from_stream(bs)
        print(p.header)
        re = SampleServicePbRequest_pb2.SampleServicePbRequest()
        re.ParseFromString(p.content)
        print(re)
        self.assertEqual(re.name, "a")
Example #5
0
    async def _dispatch(self, call_type, request_id, sofa_header, body, *,
                        timeout_ms, codec, writer):
        """send request to handler"""
        service = sofa_header.get(
            'sofa_head_target_service') or sofa_header.get('service')
        if not service:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.CLIENT_SEND_ERROR,
                                         codec=codec).to_stream(),
            )
            logger.error(
                "Missing service name in sofa header [{}]".format(sofa_header))
            return
        method = sofa_header.get('sofa_head_method_name')
        if not method:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.CLIENT_SEND_ERROR,
                                         codec=codec).to_stream())
            logger.error(
                "Missing method name in sofa header [{}]".format(sofa_header))
            return

        spanctx = tracer.extract(opentracing.Format.TEXT_MAP, sofa_header)

        try:
            future = self.handler.handle_request(spanctx, service, method,
                                                 body)
        except NoProcessorError:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.NO_PROCESSOR,
                                         codec=codec).to_stream(),
            )
            return
        except Exception:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.SERVER_EXCEPTION,
                                         codec=codec).to_stream(),
            )
            return
        if PTYPE.ONEWAY == call_type:
            # Just return future
            return future

        try:
            afut = asyncio.wrap_future(future)
            result = await asyncio.wait_for(
                afut, timeout_ms / 1000 if timeout_ms > 0 else None)
        except (asyncio.CancelledError, asyncio.TimeoutError) as e:
            logger.error(
                "Task run cancelled/timeout in {}ms, service:[{}]: error:[{}]".
                format(timeout_ms, service, e))
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.TIMEOUT,
                                         codec=codec).to_stream(),
            )
            return
        except Exception:
            logger.error(traceback.format_exc())
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.UNKNOWN,
                                         codec=codec).to_stream(),
            )
            return

        if result:
            header = dict()
            tracer.inject(spanctx, opentracing.Format.TEXT_MAP, header)
            pkg = BoltResponse.response_to(result,
                                           request_id=request_id,
                                           codec=codec)
            try:
                await self._write_msg(writer, pkg.to_stream())
            except Exception:
                logger.error(traceback.format_exc())