1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
#include "state.h"
#include <string.h>
/* state load/save */
int state_load(const Logger *log, state_load_cb *state_load_callback, void *outer,
const uint8_t *data, uint32_t length, uint16_t cookie_inner)
{
if (state_load_callback == nullptr || data == nullptr) {
LOGGER_ERROR(log, "state_load() called with invalid args.\n");
return -1;
}
const uint32_t size_head = sizeof(uint32_t) * 2;
while (length >= size_head) {
uint32_t length_sub;
lendian_bytes_to_host32(&length_sub, data);
uint32_t cookie_type;
lendian_bytes_to_host32(&cookie_type, data + sizeof(uint32_t));
data += size_head;
length -= size_head;
if (length < length_sub) {
/* file truncated */
LOGGER_ERROR(log, "state file too short: %u < %u\n", length, length_sub);
return -1;
}
if (lendian_to_host16((cookie_type >> 16)) != cookie_inner) {
/* something is not matching up in a bad way, give up */
LOGGER_ERROR(log, "state file garbled: %04x != %04x\n", cookie_type >> 16, cookie_inner);
return -1;
}
const uint16_t type = lendian_to_host16(cookie_type & 0xFFFF);
switch (state_load_callback(outer, data, length_sub, type)) {
case STATE_LOAD_STATUS_CONTINUE:
data += length_sub;
length -= length_sub;
break;
case STATE_LOAD_STATUS_ERROR:
LOGGER_ERROR(log, "Error occcured in state file (type: %u).", type);
return -1;
case STATE_LOAD_STATUS_END:
return 0;
}
}
if (length != 0) {
LOGGER_ERROR(log, "unparsed data in state file of length %u\n", length);
return -1;
}
return 0;
}
uint8_t *state_write_section_header(uint8_t *data, uint16_t cookie_type, uint32_t len, uint32_t section_type)
{
host_to_lendian_bytes32(data, len);
data += sizeof(uint32_t);
host_to_lendian_bytes32(data, (host_to_lendian16(cookie_type) << 16) | host_to_lendian16(section_type));
data += sizeof(uint32_t);
return data;
}
uint16_t lendian_to_host16(uint16_t lendian)
{
#ifdef WORDS_BIGENDIAN
return (lendian << 8) | (lendian >> 8);
#else
return lendian;
#endif
}
uint16_t host_to_lendian16(uint16_t host)
{
return lendian_to_host16(host);
}
void host_to_lendian_bytes64(uint8_t *dest, uint64_t num)
{
#ifdef WORDS_BIGENDIAN
num = ((num << 8) & 0xFF00FF00FF00FF00) | ((num >> 8) & 0xFF00FF00FF00FF);
num = ((num << 16) & 0xFFFF0000FFFF0000) | ((num >> 16) & 0xFFFF0000FFFF);
num = (num << 32) | (num >> 32);
#endif
memcpy(dest, &num, sizeof(uint64_t));
}
void lendian_bytes_to_host64(uint64_t *dest, const uint8_t *lendian)
{
uint64_t d;
memcpy(&d, lendian, sizeof(uint64_t));
#ifdef WORDS_BIGENDIAN
d = ((d << 8) & 0xFF00FF00FF00FF00) | ((d >> 8) & 0xFF00FF00FF00FF);
d = ((d << 16) & 0xFFFF0000FFFF0000) | ((d >> 16) & 0xFFFF0000FFFF);
d = (d << 32) | (d >> 32);
#endif
*dest = d;
}
void host_to_lendian_bytes32(uint8_t *dest, uint32_t num)
{
#ifdef WORDS_BIGENDIAN
num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF);
num = (num << 16) | (num >> 16);
#endif
memcpy(dest, &num, sizeof(uint32_t));
}
void lendian_bytes_to_host32(uint32_t *dest, const uint8_t *lendian)
{
uint32_t d;
memcpy(&d, lendian, sizeof(uint32_t));
#ifdef WORDS_BIGENDIAN
d = ((d << 8) & 0xFF00FF00) | ((d >> 8) & 0xFF00FF);
d = (d << 16) | (d >> 16);
#endif
*dest = d;
}
void host_to_lendian_bytes16(uint8_t *dest, uint16_t num)
{
#ifdef WORDS_BIGENDIAN
num = (num << 8) | (num >> 8);
#endif
memcpy(dest, &num, sizeof(uint16_t));
}
void lendian_bytes_to_host16(uint16_t *dest, const uint8_t *lendian)
{
uint16_t d;
memcpy(&d, lendian, sizeof(uint16_t));
#ifdef WORDS_BIGENDIAN
d = (d << 8) | (d >> 8);
#endif
*dest = d;
}
|