bool lsb_find_heka_message(lsb_heka_message *m, lsb_input_buffer *ib, bool decode, size_t *discarded_bytes, lsb_logger *logger) { if (!m || !ib || !discarded_bytes) { if (logger && logger->cb) { logger->cb(logger->context, __func__, 4, LSB_ERR_UTIL_NULL); } return false; } *discarded_bytes = 0; if (ib->readpos == ib->scanpos) { return false; // empty buffer } char *p = memchr(&ib->buf[ib->scanpos], 0x1e, ib->readpos - ib->scanpos); if (p) { if (p != ib->buf + ib->scanpos) { // partial buffer skipped before locating a possible header *discarded_bytes += p - ib->buf - ib->scanpos; } ib->scanpos = p - ib->buf; if (ib->readpos - ib->scanpos < 2) { return false; // header length is not buf } size_t hlen = (unsigned char)ib->buf[ib->scanpos + 1]; size_t hend = ib->scanpos + hlen + 3; if (hend > ib->readpos) { return false; // header is not in buf } if (ib->buf[hend - 1] != 0x1f) { // invalid header length ++ib->scanpos; ++*discarded_bytes; size_t db; bool b = lsb_find_heka_message(m, ib, decode, &db, logger); *discarded_bytes += db; return b; } if (!ib->msglen) { ib->msglen = decode_header(&ib->buf[ib->scanpos + 2], hlen, ib->maxsize - LSB_MAX_HDR_SIZE); } if (ib->msglen) { size_t mend = hend + ib->msglen; if (mend > ib->readpos) { return false; // message is not in buf } if (decode) { if (lsb_decode_heka_message(m, &ib->buf[hend], ib->msglen, logger)) { ib->scanpos = mend; ib->msglen = 0; return true; } else { // message decode failure ++ib->scanpos; ++*discarded_bytes; ib->msglen = 0; size_t db; bool b = lsb_find_heka_message(m, ib, decode, &db, logger); *discarded_bytes += db; return b; } } else { // allow a framed message is non Heka protobuf format lsb_clear_heka_message(m); m->raw.s = &ib->buf[hend]; m->raw.len = ib->msglen; ib->scanpos = mend; ib->msglen = 0; return true; } } else { // header decode failure ++ib->scanpos; ++*discarded_bytes; size_t db; bool b = lsb_find_heka_message(m, ib, decode, &db, logger); *discarded_bytes += db; return b; } } else { // full buffer skipped since no header was located *discarded_bytes += ib->readpos - ib->scanpos; ib->scanpos = ib->readpos = 0; } return false; }
static int inject_message_input(lua_State *lua) { lsb_lua_sandbox *lsb = lua_touserdata(lua, lua_upvalueindex(1)); if (NULL == lsb) { return luaL_error(lua, "%s() invalid lightuserdata", im_func_name); } const char *scp = NULL; double ncp = NAN; int t = lua_type(lua, 2); switch (t) { case LUA_TNUMBER: ncp = lua_tonumber(lua, 2); break; case LUA_TSTRING: scp = lua_tostring(lua, 2); break; case LUA_TNONE: case LUA_TNIL: break; default: return luaL_error(lua, "%s() unsupported checkpoint type: %s", im_func_name, lua_typename(lua, t)); } lsb_const_string output; t = lua_type(lua, 1); switch (t) { case LUA_TUSERDATA: { heka_stream_reader *hsr = luaL_checkudata(lua, 1, mozsvc_heka_stream_reader); if (hsr->msg.raw.s) { output.len = hsr->msg.raw.len; output.s = hsr->msg.raw.s; } else { return luaL_error(lua, "%s() attempted to inject a nil message", im_func_name); } } break; case LUA_TSTRING: { lsb_heka_message m; lsb_init_heka_message(&m, 8); output.s = lua_tolstring(lua, 1, &output.len); bool ok = lsb_decode_heka_message(&m, output.s, output.len, NULL); lsb_free_heka_message(&m); if (!ok) { return luaL_error(lua, "%s() attempted to inject a invalid protobuf " "string", im_func_name); } } break; case LUA_TTABLE: if (heka_encode_message_table(lsb, 1)) { const char *err = lsb_get_error(lsb); if (strlen(err) == 0) err = "exceeded output_limit"; return luaL_error(lua, "%s() failed: %s", im_func_name, err); } output.len = 0; output.s = lsb_get_output(lsb, &output.len); break; default: return luaL_error(lua, "%s() unsupported message type: %s", im_func_name, lua_typename(lua, t)); } lsb_heka_sandbox *hsb = lsb_get_parent(lsb); if (hsb->cb.iim(hsb->parent, output.s, output.len, ncp, scp) != 0) { return luaL_error(lua, "%s() failed: rejected by the callback", im_func_name); } ++hsb->stats.im_cnt; hsb->stats.im_bytes += output.len; return 0; }