you can allocate a big memory buffer on heap and remember the content
length of the already received data in buffer,
every time when alloc_buf_cb is triggered, give the pointer that points to
the end of the content to uv_buf.
In Read callback, check the content length against the value of the frame
header
#define THRIFT_FRAME_MAX_LEN 65536
#define THRIFT_FRAME_HEADER_LEN 4
class ThriftFrame
{
public:
char buf_[THRIFT_FRAME_MAX_LEN] = {0};
char *data_buf_ = buf_ + THRIFT_FRAME_HEADER_LEN;
size_t content_len_ = 0;
};
// uv_alloc_cb alloc buffer for receiving data in a frame.
// if frame is already allocated, receive data at the end of frame buffer
void AllocBufForFrameCB(uv_handle_t* handle, size_t suggested_size,
uv_buf_t* buf) {
UvContext *ctx = (UvContext *) handle->data;
ThriftFrame *frame;
unordered_map<uv_stream_t *, ThriftFrame *>::const_iterator it =
ctx->stream_frame_map.find((uv_stream_t *)handle);
if (it == ctx->stream_frame_map.end() || it->second == NULL) {
// allocate a new frame
frame = new ThriftFrame;
ctx->stream_frame_map[(uv_stream_t *)handle] = frame;
} else {
// a frame is already allocated, use the partically filled frame
frame = it->second;
}
buf->base = frame->data_buf_ + frame->content_len_;
int frame_len = *(int *)frame->buf_;
buf->len = frame_len ? frame_len - frame->content_len_:
THRIFT_FRAME_MAX_LEN - THRIFT_FRAME_HEADER_LEN -
frame->content_len_;
}
// uv_read_cb Read Call back for parsing raw data to thrift frame
// It might be called multiple times to receive a compelte thrift frame
// On receival of a complete thrift frame, this call back function will call
// ProcessThriftFrame() to process the received frame
void ProcessIncomingRawDataCB(uv_stream_t *stream, ssize_t nread, const
uv_buf_t *buf) {
UvContext *ctx = (UvContext *) stream->data;
ThriftFrame *frame = ctx->stream_frame_map[stream];
if (nread <= 0) {
LOG(ERROR) << "Read error: " << uv_err_name(nread);
LOG(INFO) << "Connection to client ("
<< UvIPUtil::get_sock_host_from_uv_tcp_t((uv_tcp_t *)stream) << " <=> "
<<") closed. ";
// close stream
uv_close((uv_handle_t*) stream, NULL);
// release memory allocated for receiving frame
delete ctx->stream_frame_map[stream];
ctx->stream_frame_map.erase(stream);
} else if (nread > 0) {
frame->content_len_ += nread;
// check if frame has complete data
int frame_len = *(int *)frame->buf_;
if (frame_len == frame->content_len_ - THRIFT_FRAME_HEADER_LEN) {
DLOG(INFO) << "Received a complete frame, frame length:" << frame_len;
UvConnection *connection =
ctx->client_stream_to_connection_map[stream];
ProcessThriftMessage(connection, frame);
}
}
}
On Sunday, December 8, 2013 at 11:03:50 AM UTC-8, Thiago Arruda wrote:
>
> Hi
>
> I'm writing a small program that reads messages from a stream. Before each
> message, an integer will arrive specifying the size of the following
> message.
>
> I understand libuv will call my own function to allocate buffers with a
> suggested size, but since I know the size of the incoming message, I think
> it makes more sense to use that as the buffer size(Please correct if my
> assumption is wrong, I'm not an expert C programmer).
>
> What would be the 'pretty' way to handle this in libuv? I would rather not
> use global variables to store the size of the next message.
>
> Thiago
>
>
>
--
You received this message because you are subscribed to the Google Groups
"libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/libuv.
For more options, visit https://groups.google.com/d/optout.