1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18
19#ifndef BRPC_PROGRESSIVE_READER_H
20#define BRPC_PROGRESSIVE_READER_H
21
22#include "brpc/shared_object.h"
23
24
25namespace brpc {
26
27// [Implement by user]
28// To read a very long or infinitely long response progressively.
29// Client-side usage:
30// cntl.response_will_be_read_progressively(); // before RPC
31// ...
32// channel.CallMethod(NULL, &cntl, NULL, NULL, NULL/*done*/);
33// ...
34// cntl.ReadProgressiveAttachmentBy(new MyProgressiveReader); // after RPC
35// ...
36class ProgressiveReader {
37public:
38 // Called when one part was read.
39 // Error returned is treated as *permenant* and the socket where the
40 // data was read will be closed.
41 // A temporary error may be handled by blocking this function, which
42 // may block the HTTP parsing on the socket.
43 virtual butil::Status OnReadOnePart(const void* data, size_t length) = 0;
44
45 // Called when there's nothing to read anymore. The `status' is a hint for
46 // why this method is called.
47 // - status.ok(): the message is complete and successfully consumed.
48 // - otherwise: socket was broken or OnReadOnePart() failed.
49 // This method will be called once and only once. No other methods will
50 // be called after. User can release the memory of this object inside.
51 virtual void OnEndOfMessage(const butil::Status& status) = 0;
52
53protected:
54 virtual ~ProgressiveReader() {}
55};
56
57// [Implement by protocol handlers]
58// Share ProgressiveReader between protocol handlers and controllers.
59// Take chunked HTTP response as an example:
60// 1. The protocol handler parses headers and goes to ProcessHttpResponse
61// before reading all body.
62// 2. ProcessHttpResponse sets controller's RPA which is just the HttpContext
63// in this case. The RPC ends at the end of ProcessHttpResponse.
64// 3. When the RPC ends, user may call Controller.ReadProgressiveAttachmentBy()
65// to read the body. If user does not set a reader, controller sets one
66// ignoring all bytes read before self's destruction.
67// The call chain:
68// Controller.ReadProgressiveAttachmentBy()
69// -> ReadableProgressiveAttachment.ReadProgressiveAttachmentBy()
70// -> HttpMesage.SetBodyReader()
71// -> ProgressiveReader.OnReadOnePart()
72// Already-read body will be fed immediately and the reader is remembered.
73// 4. The protocol handler also sets a reference to the RPA in the socket.
74// When new part arrives, HttpMessage.on_body is called, which calls
75// ProgressiveReader.OnReadOnePart() when reader is set.
76// 5. When all body is read, the socket releases the reference to the RPA.
77// If controller is deleted after all body is read, the RPA should be
78// destroyed at controller's deletion. If controller is deleted before
79// all body is read, the RPA should be destroyed when all body is read
80// or the socket is destroyed.
81class ReadableProgressiveAttachment : public SharedObject {
82public:
83 // Read the constantly-appending attachment by a ProgressiveReader.
84 // Any error occurred should destroy the reader by calling r->Destroy().
85 // r->Destroy() should be guaranteed to be called once and only once.
86 virtual void ReadProgressiveAttachmentBy(ProgressiveReader* r) = 0;
87};
88
89} // namespace brpc
90
91
92#endif // BRPC_PROGRESSIVE_READER_H
93