message-part-serialize.c revision 2fe48617ce6a8d296afbbb84c9f53943b48ed8c3
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "message-parser.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "message-part-serialize.h"
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen/*
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen Serialized a series of SerializedMessageParts:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen root part
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen root's first children
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen children's first children
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ...
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen root's next children
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ...
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen*/
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* struct is 8 byte aligned */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainentypedef struct {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uoff_t physical_pos;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uoff_t header_physical_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uoff_t header_virtual_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uoff_t body_physical_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uoff_t body_virtual_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int header_lines;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int body_lines;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int children_count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int flags;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen} SerializedMessagePart;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void message_part_serialize_part(MessagePart *part,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen unsigned int *children_count,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen SerializedMessagePart **spart_base,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen size_t *pos, size_t *size)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen{
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen SerializedMessagePart *spart;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen size_t buf_size;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen while (part != NULL) {
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen /* make sure we have space */
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen if (*pos == *size) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen *size *= 2;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buf_size = sizeof(SerializedMessagePart) * (*size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *spart_base = t_buffer_reget(*spart_base, buf_size);
104318260228780a5c6b3181b3401e8e504e2776Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* create serialized part */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen spart = (*spart_base) + (*pos);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen memset(spart, 0, sizeof(SerializedMessagePart));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen spart->physical_pos = part->physical_pos;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen spart->header_physical_size = part->header_size.physical_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen spart->header_virtual_size = part->header_size.virtual_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen spart->header_lines = part->header_size.lines;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen spart->body_physical_size = part->body_size.physical_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen spart->body_virtual_size = part->body_size.virtual_size;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen spart->body_lines = part->body_size.lines;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen spart->children_count = 0;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen spart->flags = part->flags;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen if (children_count != NULL)
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen (*children_count)++;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen (*pos)++;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen if (part->children != NULL) {
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen message_part_serialize_part(part->children,
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen &spart->children_count,
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen spart_base, pos, size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen part = part->next;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst void *message_part_serialize(MessagePart *part, size_t *size)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen SerializedMessagePart *spart_base;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen size_t pos, buf_size;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen buf_size = 32;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen spart_base = t_buffer_get(sizeof(SerializedMessagePart) * buf_size);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen pos = 0;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen message_part_serialize_part(part, NULL, &spart_base, &pos, &buf_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *size = sizeof(SerializedMessagePart) * pos;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen t_buffer_alloc(*size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return spart_base;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainenstatic MessagePart *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmessage_part_deserialize_part(Pool pool, MessagePart *parent,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const SerializedMessagePart **spart_pos,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t *count, unsigned int child_count)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const SerializedMessagePart *spart;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen MessagePart *part, *first_part, **next_part;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen first_part = NULL;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen next_part = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < child_count && *count > 0; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen spart = *spart_pos;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (*spart_pos)++;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen (*count)--;
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen part = p_new(pool, MessagePart, 1);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen part->physical_pos = spart->physical_pos;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen part->header_size.physical_size = spart->header_physical_size;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen part->header_size.virtual_size = spart->header_virtual_size;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen part->header_size.lines = spart->header_lines;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen part->body_size.physical_size = spart->body_physical_size;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen part->body_size.virtual_size = spart->body_virtual_size;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen part->body_size.lines = spart->body_lines;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen part->flags = spart->flags;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen part->parent = parent;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen part->children = message_part_deserialize_part(pool, part,
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen spart_pos, count,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen spart->children_count);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (first_part == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen first_part = part;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (next_part != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *next_part = part;
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen next_part = &part->next;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen return first_part;
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen}
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo SirainenMessagePart *message_part_deserialize(Pool pool, const void *data,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t size)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
cd2ed64888b42b481cde6bb9548c8520516fa3e9Timo Sirainen const SerializedMessagePart *spart;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen size_t count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen /* make sure it looks valid */
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen if (size == 0 || (size % sizeof(SerializedMessagePart)) != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return NULL;
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen spart = data;
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen count = size / sizeof(SerializedMessagePart);
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen if (count > UINT_MAX)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return message_part_deserialize_part(pool, NULL, &spart, &count,
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen (unsigned int)count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainenint message_part_serialize_update_header(void *data, size_t size,
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen MessageSize *hdr_size)
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen{
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen SerializedMessagePart *spart = data;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uoff_t first_pos;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen off_t pos_diff;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t i, count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* make sure it looks valid */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (size == 0 || (size % sizeof(SerializedMessagePart)) != 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (hdr_size->physical_size >= OFF_T_MAX ||
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen spart->physical_pos >= OFF_T_MAX ||
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen spart->header_physical_size >= OFF_T_MAX)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return FALSE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen first_pos = spart->physical_pos;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen pos_diff = (off_t)hdr_size->physical_size - spart->header_physical_size;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen spart->header_physical_size = hdr_size->physical_size;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen spart->header_virtual_size = hdr_size->virtual_size;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen spart->header_lines = hdr_size->lines;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen if (pos_diff != 0) {
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen /* have to update all positions */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen count = size / sizeof(SerializedMessagePart);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < count; i++, spart++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (spart->physical_pos < first_pos ||
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen spart->physical_pos >= OFF_T_MAX) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* invalid offset, might cause overflow */
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen return FALSE;
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen }
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen spart->physical_pos += pos_diff;
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return TRUE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainenint message_part_deserialize_size(const void *data, size_t size,
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen MessageSize *hdr_size,
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen MessageSize *body_size)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen const SerializedMessagePart *spart = data;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* make sure it looks valid */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (size == 0 || (size % sizeof(SerializedMessagePart)) != 0)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return FALSE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen hdr_size->physical_size = spart->header_physical_size;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen hdr_size->virtual_size = spart->header_virtual_size;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen hdr_size->lines = spart->header_lines;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen body_size->physical_size = spart->body_physical_size;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen body_size->virtual_size = spart->body_virtual_size;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen body_size->lines = spart->body_lines;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return TRUE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen