int rd_kafka_sasl_io_event (rd_kafka_transport_t *rktrans, int events, char *errstr, int errstr_size) { if (events & POLLIN) { rd_kafka_buf_t *rkbuf; int r; r = rd_kafka_transport_framed_recvmsg(rktrans, &rkbuf, errstr, errstr_size); if (r == -1) return -1; else if (r == 0) return 0; return rd_kafka_sasl_handle_recv(rktrans, rkbuf, errstr, errstr_size); } return 0; }
/** * Length framed receive handling. * Currently only supports a the following framing: * [int32_t:big_endian_length_of_payload][payload] * * To be used on POLLIN event, will return: * -1: on fatal error (errstr will be updated, *rkbufp remains unset) * 0: still waiting for data (*rkbufp remains unset) * 1: data complete, (buffer returned in *rkbufp) */ int rd_kafka_transport_framed_recvmsg (rd_kafka_transport_t *rktrans, rd_kafka_buf_t **rkbufp, char *errstr, size_t errstr_size) { rd_kafka_buf_t *rkbuf = rktrans->rktrans_recv_buf; ssize_t r; const int log_decode_errors = 0; /* States: * !rktrans_recv_buf: initial state; set up buf to receive header. * rkbuf_len == 0: awaiting header * rkbuf_len > 0: awaiting payload */ if (!rkbuf) { rkbuf = rd_kafka_buf_new(NULL, 1, 4); /* Point read buffer to main buffer. */ rkbuf->rkbuf_rbuf = rkbuf->rkbuf_buf; rd_kafka_buf_push(rkbuf, rkbuf->rkbuf_buf, 4); rktrans->rktrans_recv_buf = rkbuf; } r = rd_kafka_transport_recvmsg(rktrans, &rkbuf->rkbuf_msg, errstr, errstr_size); if (r == 0) return 0; else if (r == -1) return -1; rkbuf->rkbuf_wof += r; if (rkbuf->rkbuf_len == 0) { /* Frame length not known yet. */ int32_t frame_len; if (rkbuf->rkbuf_wof < sizeof(frame_len)) { /* Wait for entire frame header. */ return 0; } /* Reader header: payload length */ rd_kafka_buf_read_i32(rkbuf, &frame_len); if (frame_len < 0 || frame_len > rktrans->rktrans_rkb-> rkb_rk->rk_conf.recv_max_msg_size) { rd_snprintf(errstr, errstr_size, "Invalid frame size %"PRId32, frame_len); return -1; } rkbuf->rkbuf_len = frame_len; if (frame_len == 0) { /* Payload is empty, we're done. */ rktrans->rktrans_recv_buf = NULL; *rkbufp = rkbuf; return 1; } /* Allocate memory to hold entire frame payload in contigious * memory. */ rd_kafka_buf_alloc_recvbuf(rkbuf, frame_len); /* Try reading directly, there is probably more data available*/ return rd_kafka_transport_framed_recvmsg(rktrans, rkbufp, errstr, errstr_size); } if (rkbuf->rkbuf_wof == rkbuf->rkbuf_len) { /* Payload is complete. */ rktrans->rktrans_recv_buf = NULL; *rkbufp = rkbuf; return 1; } /* Wait for more data */ return 0; err: if (rkbuf) rd_kafka_buf_destroy(rkbuf); rd_snprintf(errstr, errstr_size, "Frame header parsing failed"); return -1; }