static const char* process_varint(int wiretype, const char *p, const char *e, long long *val) { if (wiretype != 0) { return NULL; } p = lsb_pb_read_varint(p, e, val); return p ? p : NULL; }
static const char* read_string(int wiretype, const char *p, const char *e, lsb_const_string *s) { if (wiretype != LSB_PB_WT_LENGTH) { return NULL; } long long vi; p = lsb_pb_read_varint(p, e, &vi); if (!p || vi < 0 || p + vi > e) { return NULL; } s->s = p; s->len = (size_t)vi; return p + vi; }
static bool read_integer_value(const char *p, const char *e, int ai, lsb_read_value *val) { int acnt = 0; long long ll = 0; while (p && p < e) { p = lsb_pb_read_varint(p, e, &ll); if (p) { if (ai == acnt++) { val->type = LSB_READ_NUMERIC; val->u.d = (double)ll; return true; } } } return false; }
static size_t decode_header(char *buf, size_t len, size_t max_message_size) { if (*buf != 0x08) { return 0; } char *p = buf; if (p && p < buf + len - 1) { long long vi; if (lsb_pb_read_varint(p + 1, buf + len, &vi)) { if (vi > 0 && vi <= (long long)max_message_size) { return (size_t)vi; } } } return 0; }
static const char* read_string(lua_State *lua, int wiretype, const char *p, const char *e) { if (wiretype != LSB_PB_WT_LENGTH) { return NULL; } long long len = 0; p = lsb_pb_read_varint(p, e, &len); if (!p || len < 0 || p + len > e) { return NULL; } lua_pushlstring(lua, p, (size_t)len); p += len; return p; }
static const char* process_varint(lua_State *lua, const char *name, int wiretype, int stack_index, const char *p, const char *e) { if (wiretype != LSB_PB_WT_VARINT) { return NULL; } long long val = 0; p = lsb_pb_read_varint(p, e, &val); if (!p) { return NULL; } lua_pushnumber(lua, (lua_Number)val); lua_setfield(lua, stack_index, name); return p; }
static const char* process_fields(lsb_heka_field *f, const char *p, const char *e) { int tag = 0; int wiretype = 0; long long vi = 0; p = lsb_pb_read_varint(p, e, &vi); if (!p || vi < 0 || p + vi > e) { return NULL; } e = p + vi; // only process to the end of the current field record do { p = lsb_pb_read_key(p, &tag, &wiretype); switch (tag) { case LSB_PB_NAME: p = read_string(wiretype, p, e, &f->name); break; case LSB_PB_VALUE_TYPE: p = process_varint(wiretype, p, e, &vi); if (p) { f->value_type = (int)vi; } break; case LSB_PB_REPRESENTATION: p = read_string(wiretype, p, e, &f->representation); break; // don't bother with the value(s) until we actually need them // since this stream is created by Hindsight // - tags are guaranteed to be properly ordered (values at the end) // - there won't be repeated tags for packed values case LSB_PB_VALUE_STRING: case LSB_PB_VALUE_BYTES: if (wiretype != 2) { p = NULL; break; } f->value.s = p - 1; f->value.len = e - f->value.s; p = e; break; case LSB_PB_VALUE_INTEGER: case LSB_PB_VALUE_BOOL: if (wiretype != 0 && wiretype != 2) { p = NULL; break; } // fall thru case LSB_PB_VALUE_DOUBLE: if (tag == 7 && wiretype != 1 && wiretype != 2) { p = NULL; break; } if (wiretype == 2) { p = lsb_pb_read_varint(p, e, &vi); if (!p || vi < 0 || p + vi > e) { p = NULL; break; } } f->value.s = p; f->value.len = e - f->value.s; p = e; break; default: p = NULL; // don't allow unknown tags break; } } while (p && p < e); return p && f->name.s ? p : NULL; }
static void output_text(lsb_heka_message *msg) { static char tstr[64]; if (!msg->raw.s) return; fprintf(stdout, ":Uuid: %02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx" "-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n", msg->uuid.s[0], msg->uuid.s[1], msg->uuid.s[2], msg->uuid.s[3], msg->uuid.s[4], msg->uuid.s[5], msg->uuid.s[6], msg->uuid.s[7], msg->uuid.s[8], msg->uuid.s[9], msg->uuid.s[10], msg->uuid.s[11], msg->uuid.s[12], msg->uuid.s[13], msg->uuid.s[14], msg->uuid.s[15]); fprintf(stdout, ":Timestamp: "); time_t t = floor(msg->timestamp / 1e9); double frac = msg->timestamp - t * 1e9; struct tm *tms = gmtime(&t); strftime(tstr, sizeof(tstr) - 1, "%Y-%m-%dT%H:%M:%S", tms); fprintf(stdout, "%s.%09lldZ\n", tstr, (long long)frac); output_cs(":Type", &msg->type, true); output_cs(":Logger", &msg->logger, true); fprintf(stdout, ":Severity: %d\n", msg->severity); output_cs(":Payload", &msg->payload, true); output_cs(":EnvVersion", &msg->env_version, true); if (msg->pid == INT_MIN) { fprintf(stdout, ":Pid: <nil>\n"); } else { fprintf(stdout, ":Pid: %d\n", msg->pid); } output_cs(":Hostname", &msg->hostname, true); fprintf(stdout, ":Fields:\n"); for (int i = 0; i < msg->fields_len; ++i) { fprintf(stdout, " | name: %.*s type: %d ", (int)msg->fields[i].name.len, msg->fields[i].name.s, msg->fields[i].value_type); output_cs("representation", &msg->fields[i].representation, false); fprintf(stdout, " value: "); const char *p = msg->fields[i].value.s; const char *e = msg->fields[i].value.s + msg->fields[i].value.len; switch (msg->fields[i].value_type) { case LSB_PB_STRING: { lsb_const_string cs; int tag = 0; int wiretype = 0; while (p && p < e) { p = lsb_pb_read_key(p, &tag, &wiretype); p = read_string(wiretype, p, e, &cs); if (p) { fprintf(stdout, "%.*s", (int)cs.len, cs.s); } } } break; case LSB_PB_BYTES: { lsb_const_string cs; int tag = 0; int wiretype = 0; while (p && p < e) { p = lsb_pb_read_key(p, &tag, &wiretype); p = read_string(wiretype, p, e, &cs); if (p) { for (size_t i = 0; i < cs.len; ++i) { if (isprint(cs.s[i])) { if (cs.s[i] == '\\') { fwrite("\\\\", 2, 1, stdout); } else { putchar(cs.s[i]); } } else { fprintf(stdout, "\\x%02hhx", (unsigned char)cs.s[i]); } } } } } break; case LSB_PB_INTEGER: { long long ll = 0; while (p && p < e) { p = lsb_pb_read_varint(p, e, &ll); if (p) { fprintf(stdout, "%lld", ll); } } } break; case LSB_PB_DOUBLE: { double d; for (int i = 0; p <= (e - sizeof(double)); p += sizeof(double), ++i) { memcpy(&d, p, sizeof(double)); if (i > 0) { fprintf(stdout, ","); } fprintf(stdout, "%.17g", d); } } break; case LSB_PB_BOOL: { long long ll = 0; while (p && p < e) { p = lsb_pb_read_varint(p, e, &ll); if (p) { fprintf(stdout, "%s", ll == 0 ? "false" : "true"); } } } break; } fprintf(stdout, "\n"); } fprintf(stdout, "\n"); return; }
static const char* process_fields(lua_State *lua, const char *p, const char *e) { int tag = 0; int wiretype = 0; int has_name = 0; int value_count = 0; long long len = 0; p = lsb_pb_read_varint(p, e, &len); if (!p || len < 0 || p + len > e) { return NULL; } e = p + len; // only process to the end of the current field record lua_newtable(lua); // Table to be added to the Fields array index 4 lua_newtable(lua); // Table to hold the value(s) index 5 do { p = lsb_pb_read_key(p, &tag, &wiretype); switch (tag) { case 1: p = read_string(lua, wiretype, p, e); if (p) { lua_setfield(lua, 4, "name"); has_name = 1; } break; case 2: p = process_varint(lua, "value_type", wiretype, 4, p, e); break; case 3: p = read_string(lua, wiretype, p, e); if (p) { lua_setfield(lua, 4, "representation"); } break; case 4: // value_string case 5: // value_bytes p = read_string(lua, wiretype, p, e); if (p) { lua_rawseti(lua, 5, ++value_count); } break; case 6: // value_integer { long long val = 0; switch (wiretype) { case 0: p = lsb_pb_read_varint(p, p + len, &val); if (!p) break; lua_pushnumber(lua, (lua_Number)val); lua_rawseti(lua, 5, ++value_count); break; case 2: p = lsb_pb_read_varint(p, e, &len); if (!p || len < 0 || p + len > e) { p = NULL; break; } do { p = lsb_pb_read_varint(p, p + len, &val); if (!p) break; lua_pushnumber(lua, (lua_Number)val); lua_rawseti(lua, 5, ++value_count); } while (p < e); break; default: p = NULL; break; } } break; case 7: // value_double { double val = 0; switch (wiretype) { case 1: if (p + sizeof(double) > e) { p = NULL; break; } memcpy(&val, p, sizeof(double)); p += sizeof(double); lua_pushnumber(lua, val); lua_rawseti(lua, 5, ++value_count); break; case 2: p = lsb_pb_read_varint(p, e, &len); if (!p || len < 0 || p + len > e || len % sizeof(double) != 0) { p = NULL; break; } do { memcpy(&val, p, sizeof(double)); p += sizeof(double); lua_pushnumber(lua, val); lua_rawseti(lua, 5, ++value_count); } while (p < e); break; default: p = NULL; break; } } break; case 8: // value_bool { long long val = 0; switch (wiretype) { case 0: p = lsb_pb_read_varint(p, p + len, &val); if (!p) break; lua_pushboolean(lua, (int)val); lua_rawseti(lua, 5, ++value_count); break; case 2: p = lsb_pb_read_varint(p, e, &len); if (!p || len < 0 || p + len > e) { p = NULL; break; } do { p = lsb_pb_read_varint(p, p + len, &val); if (!p) break; lua_pushboolean(lua, (int)val); lua_rawseti(lua, 5, ++value_count); } while (p < e); break; default: p = NULL; break; } } break; default: p = NULL; // don't allow unknown tags break; } } while (p && p < e); lua_setfield(lua, 4, "value"); return has_name ? p : NULL; }