message-part-serialize.c revision 6697a923d6768bf8d71f87f80b90747cf6870753
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "message-parser.h"
65cca8364f483126b396aeb2036dc879ad45ab8dTimo Sirainen#include "message-part-serialize.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen/*
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen Serialized a series of SerializedMessageParts:
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen root part
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen root's first children
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen children's first children
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen ...
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen root's next children
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen ...
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen*/
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen/* struct is 8 byte aligned */
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainentypedef struct {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uoff_t physical_pos;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uoff_t header_physical_size;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen uoff_t header_virtual_size;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uoff_t body_physical_size;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen uoff_t body_virtual_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int header_lines;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int body_lines;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int children_count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int flags;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen} SerializedMessagePart;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void message_part_serialize_part(MessagePart *part,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen unsigned int *children_count,
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen SerializedMessagePart **spart_base,
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen size_t *pos, size_t *size)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen SerializedMessagePart *spart;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen size_t buf_size;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen while (part != NULL) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen /* make sure we have space */
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (*pos == *size) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen *size *= 2;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen buf_size = sizeof(SerializedMessagePart) * (*size);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen *spart_base = t_buffer_reget(*spart_base, buf_size);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* create serialized part */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart = (*spart_base) + (*pos);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen memset(spart, 0, sizeof(SerializedMessagePart));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->physical_pos = part->physical_pos;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->header_physical_size = part->header_size.physical_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->header_virtual_size = part->header_size.virtual_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->header_lines = part->header_size.lines;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->body_physical_size = part->body_size.physical_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->body_virtual_size = part->body_size.virtual_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->body_lines = part->body_size.lines;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart->children_count = 0;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen spart->flags = part->flags;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (children_count != NULL)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen (*children_count)++;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen (*pos)++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (part->children != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen message_part_serialize_part(part->children,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen &spart->children_count,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen spart_base, pos, size);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen part = part->next;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst void *message_part_serialize(MessagePart *part, size_t *size)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen SerializedMessagePart *spart_base;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t pos, buf_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen buf_size = 32;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen spart_base = t_buffer_get(sizeof(SerializedMessagePart) * buf_size);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen pos = 0;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen message_part_serialize_part(part, NULL, &spart_base, &pos, &buf_size);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen *size = sizeof(SerializedMessagePart) * pos;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen t_buffer_alloc(*size);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return spart_base;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstatic MessagePart *
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenmessage_part_deserialize_part(Pool pool, MessagePart *parent,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const SerializedMessagePart **spart_pos,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t *count, unsigned int child_count)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen const SerializedMessagePart *spart;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen MessagePart *part, *first_part, **next_part;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen first_part = NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen next_part = NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < child_count && *count > 0; i++) {
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen spart = *spart_pos;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen (*spart_pos)++;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen (*count)--;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen part = p_new(pool, MessagePart, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen part->physical_pos = spart->physical_pos;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen part->header_size.physical_size = spart->header_physical_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen part->header_size.virtual_size = spart->header_virtual_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen part->header_size.lines = spart->header_lines;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen part->body_size.physical_size = spart->body_physical_size;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen part->body_size.virtual_size = spart->body_virtual_size;
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen part->body_size.lines = spart->body_lines;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen part->flags = spart->flags;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen part->parent = parent;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen part->children = message_part_deserialize_part(pool, part,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen spart_pos, count,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen spart->children_count);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (first_part == NULL)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen first_part = part;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (next_part != NULL)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen *next_part = part;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen next_part = &part->next;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return first_part;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
76b91bac787101e6b0075122ab6478dd98c8a884Timo SirainenMessagePart *message_part_deserialize(Pool pool, const void *data,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen size_t size)
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen{
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen const SerializedMessagePart *spart;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen /* make sure it looks valid */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (size == 0 || (size % sizeof(SerializedMessagePart)) != 0)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen return NULL;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen spart = data;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen count = size / sizeof(SerializedMessagePart);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (count > UINT_MAX)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return NULL;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen return message_part_deserialize_part(pool, NULL, &spart, &count,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen (unsigned int)count);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint message_part_serialize_update_header(void *data, size_t size,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MessageSize *hdr_size)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen SerializedMessagePart *spart = data;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen uoff_t first_pos;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen off_t pos_diff;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t i, count;
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen /* make sure it looks valid */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (size == 0 || (size % sizeof(SerializedMessagePart)) != 0)
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen return FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (hdr_size->physical_size >= OFF_T_MAX ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen spart->physical_pos >= OFF_T_MAX ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen spart->header_physical_size >= OFF_T_MAX)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen spart->header_physical_size = hdr_size->physical_size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen spart->header_virtual_size = hdr_size->virtual_size;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen spart->header_lines = hdr_size->lines;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen first_pos = spart->physical_pos;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen pos_diff = (off_t)hdr_size->physical_size - spart->header_physical_size;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (pos_diff != 0) {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen /* have to update all positions */
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen count = size / sizeof(SerializedMessagePart);
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen for (i = 0; i < count; i++, spart++) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (spart->physical_pos < first_pos ||
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen spart->physical_pos >= OFF_T_MAX) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* invalid offset, might cause overflow */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk return FALSE;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen spart->physical_pos += pos_diff;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk }
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk }
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk return TRUE;
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen}
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint message_part_deserialize_size(const void *data, size_t size,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen MessageSize *hdr_size,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen MessageSize *body_size)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen{
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen const SerializedMessagePart *spart = data;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen /* make sure it looks valid */
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen if (size == 0 || (size % sizeof(SerializedMessagePart)) != 0)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen return FALSE;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen hdr_size->physical_size = spart->header_physical_size;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen hdr_size->virtual_size = spart->header_virtual_size;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen hdr_size->lines = spart->header_lines;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen body_size->physical_size = spart->body_physical_size;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen body_size->virtual_size = spart->body_virtual_size;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen body_size->lines = spart->body_lines;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return TRUE;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen}
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen