message-part-serialize.c revision def516ea503a60f20d510c14d5070b7ff5bbddf4
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb/* Copyright (C) 2002 Timo Sirainen */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb#include "lib.h"
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb#include "buffer.h"
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb#include "message-parser.h"
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb#include "message-part-serialize.h"
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb/*
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb Serialized a series of SerializedMessageParts:
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb root part
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb root's first children
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb children's first children
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb ...
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb root's next children
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb ...
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb*/
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb/* struct is 8 byte aligned */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbbtypedef struct {
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb uoff_t physical_pos;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb uoff_t header_physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb uoff_t header_virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb uoff_t body_physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb uoff_t body_virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb unsigned int header_lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb unsigned int body_lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb unsigned int children_count;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb unsigned int flags;
f288a6057cdb68efbdd8bac4b4387d75da42b2a2rbb} SerializedMessagePart;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbbvoid message_part_serialize(MessagePart *part, Buffer *dest)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb{
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb SerializedMessagePart *spart;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb while (part != NULL) {
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb /* create serialized part */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart = buffer_append_space(dest,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb sizeof(SerializedMessagePart));
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb memset(spart, 0, sizeof(SerializedMessagePart));
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->physical_pos = part->physical_pos;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->header_physical_size = part->header_size.physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->header_virtual_size = part->header_size.virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->header_lines = part->header_size.lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->body_physical_size = part->body_size.physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->body_virtual_size = part->body_size.virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->body_lines = part->body_size.lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->children_count = 0;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->flags = part->flags;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (part->children != NULL)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb message_part_serialize(part, dest);
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part = part->next;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb }
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb}
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbbstatic MessagePart *
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbbmessage_part_deserialize_part(Pool pool, MessagePart *parent,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb const SerializedMessagePart **spart_pos,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb size_t *count, unsigned int child_count)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb{
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb const SerializedMessagePart *spart;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb MessagePart *part, *first_part, **next_part;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb unsigned int i;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb first_part = NULL;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb next_part = NULL;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb for (i = 0; i < child_count && *count > 0; i++) {
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart = *spart_pos;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb (*spart_pos)++;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb (*count)--;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part = p_new(pool, MessagePart, 1);
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->physical_pos = spart->physical_pos;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->header_size.physical_size = spart->header_physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->header_size.virtual_size = spart->header_virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->header_size.lines = spart->header_lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->body_size.physical_size = spart->body_physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->body_size.virtual_size = spart->body_virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->body_size.lines = spart->body_lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->flags = spart->flags;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->parent = parent;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb part->children = message_part_deserialize_part(pool, part,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart_pos, count,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->children_count);
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (first_part == NULL)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb first_part = part;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (next_part != NULL)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb *next_part = part;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb next_part = &part->next;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb }
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return first_part;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb}
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbbMessagePart *message_part_deserialize(Pool pool, const void *data,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb size_t size)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb{
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb const SerializedMessagePart *spart;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb size_t count;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb /* make sure it looks valid */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (size < sizeof(SerializedMessagePart))
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return NULL;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart = data;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb count = size / sizeof(SerializedMessagePart);
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (count > UINT_MAX)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return NULL;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return message_part_deserialize_part(pool, NULL, &spart, &count,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb (unsigned int)count);
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb}
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbbint message_part_serialize_update_header(void *data, size_t size,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb MessageSize *hdr_size)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb{
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb SerializedMessagePart *spart = data;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb uoff_t first_pos;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb off_t pos_diff;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb size_t i, count;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb /* make sure it looks valid */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (size < sizeof(SerializedMessagePart))
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return FALSE;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (hdr_size->physical_size >= OFF_T_MAX ||
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->physical_pos >= OFF_T_MAX ||
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->header_physical_size >= OFF_T_MAX)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return FALSE;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb first_pos = spart->physical_pos;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb pos_diff = (off_t)hdr_size->physical_size - spart->header_physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->header_physical_size = hdr_size->physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->header_virtual_size = hdr_size->virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->header_lines = hdr_size->lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (pos_diff != 0) {
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb /* have to update all positions, but skip the first one */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb count = (size / sizeof(SerializedMessagePart))-1;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart++;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb for (i = 0; i < count; i++, spart++) {
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (spart->physical_pos < first_pos ||
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->physical_pos >= OFF_T_MAX) {
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb /* invalid offset, might cause overflow */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return FALSE;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb }
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb spart->physical_pos += pos_diff;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb }
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb }
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return TRUE;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb}
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbbint message_part_deserialize_size(const void *data, size_t size,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb MessageSize *hdr_size,
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb MessageSize *body_size)
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb{
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb const SerializedMessagePart *spart = data;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb /* make sure it looks valid */
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb if (size < sizeof(SerializedMessagePart))
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return FALSE;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb hdr_size->physical_size = spart->header_physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb hdr_size->virtual_size = spart->header_virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb hdr_size->lines = spart->header_lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb body_size->physical_size = spart->body_physical_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb body_size->virtual_size = spart->body_virtual_size;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb body_size->lines = spart->body_lines;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb return TRUE;
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb}
8043e7591c0a8c5d08e3d52c99dd2579cc8edb41rbb