static gboolean angel_connection_read(liAngelConnection *acon, GError **err) { for ( ;; ) { if (!acon->parse.have_header) { gint32 magic; if (!angel_fill_buffer(acon, 8*4, err)) return FALSE; if (acon->in.data->len - acon->in.pos < 8*4) return TRUE; /* need more data */ if (!li_angel_data_read_int32(&acon->in, &magic, err)) return FALSE; if (!li_angel_data_read_int32(&acon->in, &acon->parse.type, err)) return FALSE; if (!li_angel_data_read_int32(&acon->in, &acon->parse.id, err)) return FALSE; if (!li_angel_data_read_int32(&acon->in, &acon->parse.mod_len, err)) return FALSE; if (!li_angel_data_read_int32(&acon->in, &acon->parse.action_len, err)) return FALSE; if (!li_angel_data_read_int32(&acon->in, &acon->parse.error_len, err)) return FALSE; if (!li_angel_data_read_int32(&acon->in, &acon->parse.data_len, err)) return FALSE; if (!li_angel_data_read_int32(&acon->in, &acon->parse.missing_fds, err)) return FALSE; if (ANGEL_MAGIC != magic) { g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA, "Invalid magic: 0x%x (should be 0x%x)", (gint) magic, (gint) ANGEL_MAGIC); return FALSE; } acon->parse.body_size = acon->parse.mod_len + acon->parse.action_len + acon->parse.error_len + acon->parse.data_len; acon->parse.have_header = TRUE; } if (!angel_fill_buffer(acon, acon->parse.body_size, err)) return FALSE; if (acon->in.data->len - acon->in.pos < acon->parse.body_size) return TRUE; /* need more data */ while (acon->parse.missing_fds > 0) { int fd = -1; switch (li_receive_fd(acon->fd, &fd)) { case 0: g_array_append_val(acon->parse.fds, fd); acon->parse.missing_fds--; break; case -1: g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_CLOSED, "receive fd error: %s", g_strerror(errno)); return FALSE; case -2: return TRUE; /* need more data */ } } acon->parse.have_header = FALSE; if (!li_angel_data_read_mem(&acon->in, &acon->parse.mod, acon->parse.mod_len, err)) return FALSE; if (!li_angel_data_read_mem(&acon->in, &acon->parse.action, acon->parse.action_len, err)) return FALSE; if (!li_angel_data_read_mem(&acon->in, &acon->parse.error, acon->parse.error_len, err)) return FALSE; if (!li_angel_data_read_mem(&acon->in, &acon->parse.data, acon->parse.data_len, err)) return FALSE; if (!angel_dispatch(acon, err)) return FALSE; g_string_truncate(acon->parse.error, 0); g_string_truncate(acon->parse.data, 0); g_array_set_size(acon->parse.fds, 0); } }
gboolean li_angel_data_read_str (liAngelBuffer *buf, GString **val, GError **err) { gint32 ilen; g_return_val_if_fail(err == NULL || *err == NULL, FALSE); if (buf->data->len - buf->pos < sizeof(gint32)) { return error_eof(err, "string-length"); } memcpy(&ilen, buf->data->str + buf->pos, sizeof(ilen)); buf->pos += sizeof(gint32); if (ilen < 0 || ilen > LI_ANGEL_DATA_MAX_STR_LEN) { buf->pos -= sizeof(gint32); g_set_error(err, LI_ANGEL_DATA_ERROR, LI_ANGEL_DATA_ERROR_INVALID_STRING_LENGTH, "String length in buffer invalid: %i", (gint) ilen); return FALSE; } if (!li_angel_data_read_mem(buf, val, (gsize) ilen, err)) { buf->pos -= sizeof(gint32); return FALSE; } return TRUE; }