int encode_fields(lua_sandbox* lsb, output_data* d, char id, const char* name,
                  int index)
{
  int result = 0;
  lua_getfield(lsb->lua, index, name);
  if (!lua_istable(lsb->lua, -1)) {
    return result;
  }

  size_t len_pos, len;
  lua_checkstack(lsb->lua, 2);
  lua_pushnil(lsb->lua);
  while (result == 0 && lua_next(lsb->lua, -2) != 0) {
    if (pb_write_tag(d, id, 2)) return 1;
    len_pos = d->pos;
    if (pb_write_varint(d, 0)) return 1;  // length tbd later
    if (lua_isstring(lsb->lua, -2)) {
      const char* s = lua_tolstring(lsb->lua, -2, &len);
      if (pb_write_string(d, 1, s, len)) return 1;
    } else {
      snprintf(lsb->error_message, LSB_ERROR_SIZE,
               "field name must be a string");
      return 1;
    }
    if (encode_field_value(lsb, d, 1, NULL)) return 1;
    if (update_field_length(d, len_pos)) return 1;
    lua_pop(lsb->lua, 1); // Remove the value leaving the key on top for
                          // the next interation.
  }
  lua_pop(lsb->lua, 1); // remove the fields table
  return result;
}
Example #2
0
int encode_int(lua_sandbox* lsb, output_data* d, char id, const char* name)
{
    int result = 0;
    lua_getfield(lsb->m_lua, 1, name);
    if (lua_isnumber(lsb->m_lua, -1)) {
        long long i = (long long)lua_tonumber(lsb->m_lua, -1);
        if (!(result = pb_write_tag(d, id, 0))) {
            result = pb_write_varint(d, i);
        }
    }
    lua_pop(lsb->m_lua, 1);
    return result;
}
Example #3
0
int pb_write_string(output_data* d, char id, const char* s, size_t len)
{

    if (pb_write_tag(d, id, 2)) return 1;
    if (pb_write_varint(d, len)) return 1;

    size_t needed = len;
    if (needed > d->m_size - d->m_pos) {
        if (realloc_output(d, needed)) return 1;
    }
    memcpy(&d->m_data[d->m_pos], s, len);
    d->m_pos += len;
    return 0;
}
int serialize_table_as_pb(lua_sandbox* lsb, int index)
{
  output_data* d = &lsb->output;
  d->pos = 0;
  size_t needed = 18;
  if (needed > d->size) {
    if (realloc_output(d, needed)) return 1;
  }

  // create a type 4 uuid
  d->data[d->pos++] = 2 | (1 << 3);
  d->data[d->pos++] = 16;
  for (int x = 0; x < 16; ++x) {
    d->data[d->pos++] = rand() % 255;
  }
  d->data[8] = (d->data[8] & 0x0F) | 0x40;
  d->data[10] = (d->data[10] & 0x0F) | 0xA0;

  // use existing or create a timestamp
  lua_getfield(lsb->lua, index, "Timestamp");
  long long ts;
  if (lua_isnumber(lsb->lua, -1)) {
    ts = (long long)lua_tonumber(lsb->lua, -1);
  } else {
    ts = (long long)(time(NULL) * 1e9);
  }
  lua_pop(lsb->lua, 1);
  if (pb_write_tag(d, 2, 0)) return 1;
  if (pb_write_varint(d, ts)) return 1;

  if (encode_string(lsb, d, 3, "Type", index)) return 1;
  if (encode_string(lsb, d, 4, "Logger", index)) return 1;
  if (encode_int(lsb, d, 5, "Severity", index)) return 1;
  if (encode_string(lsb, d, 6, "Payload", index)) return 1;
  if (encode_string(lsb, d, 7, "EnvVersion", index)) return 1;
  if (encode_int(lsb, d, 8, "Pid", index)) return 1;
  if (encode_string(lsb, d, 9, "Hostname", index)) return 1;
  if (encode_fields(lsb, d, 10, "Fields", index)) return 1;
  // if we go above 15 pb_write_tag will need to start varint encoding
  needed = 1;
  if (needed > d->size - d->pos) {
    if (realloc_output(d, needed)) return 1;
  }
  d->data[d->pos] = 0; // NULL terminate incase someone tries to treat this
                       // as a string

  return 0;
}
int update_field_length(output_data* d, size_t len_pos)
{
  size_t len = d->pos - len_pos - 1;
  if (len < 128) {
    d->data[len_pos] = (char)len;
    return 0;
  }
  size_t l = len, cnt = 0;
  while (l) {
    l >>= 7;
    ++cnt;  // compute the number of bytes needed for the varint length
  }
  size_t needed = cnt - 1;
  if (needed > d->size - d->pos) {
    if (realloc_output(d, needed)) return 1;
  }
  size_t end_pos = d->pos + needed;
  memmove(&d->data[len_pos + cnt], &d->data[len_pos + 1], len);
  d->pos = len_pos;
  if (pb_write_varint(d, len)) return 1;
  d->pos = end_pos;
  return 0;
}
int encode_field_value(lua_sandbox* lsb, output_data* d, int first,
                       const char* representation)
{
  int result = 1;
  size_t len;
  const char* s;

  int t = lua_type(lsb->lua, -1);
  switch (t) {
  case LUA_TSTRING:
    if (first && representation) { // this uglyness keeps the protobuf
                                   // fields in order without additional
                                   // lookups
      if (pb_write_string(d, 3, representation, strlen(representation))) {
        return 1;
      }
    }
    s = lua_tolstring(lsb->lua, -1, &len);
    result = pb_write_string(d, 4, s, len);
    break;
  case LUA_TNUMBER:
    if (first) {
      if (pb_write_tag(d, 2, 0)) return 1;
      if (pb_write_varint(d, 3)) return 1;
      if (representation) {
        if (pb_write_string(d, 3, representation,
                            strlen(representation))) {
          return 1;
        }
      }
    }
    result = encode_double(lsb, d, 7);
    break;
  case LUA_TBOOLEAN:
    if (first) {
      if (pb_write_tag(d, 2, 0)) return 1;
      if (pb_write_varint(d, 4)) return 1;
      if (representation) {
        if (pb_write_string(d, 3, representation,
                            strlen(representation))) {
          return 1;
        }
      }
    }
    if (pb_write_tag(d, 8, 0)) return 1;
    result = pb_write_bool(d, lua_toboolean(lsb->lua, -1));
    break;
  case LUA_TTABLE:
    {
      lua_rawgeti(lsb->lua, -1, 1);
      int t = lua_type(lsb->lua, -1);
      lua_pop(lsb->lua, 1); // remove the array test value
      if (LUA_TNIL == t) {
        result = encode_field_object(lsb, d);
      } else {
        result = encode_field_array(lsb, d, t, representation);
      }
    }
    break;
  default:
    snprintf(lsb->error_message, LSB_ERROR_SIZE, "unsupported type %d", t);
    result = 1;
  }
  return result;
}