|
|
| version 1.1.2.1, 2011/08/29 14:58:50 | version 1.3.2.1, 2011/12/13 10:40:05 |
|---|---|
| Line 46 SUCH DAMAGE. | Line 46 SUCH DAMAGE. |
| #include "global.h" | #include "global.h" |
| /* | |
| * io_vars2buffer() Marshaling data from array with variables to buffer | |
| * @buf = Buffer | |
| * @buflen = Size of buffer | |
| * @vars = Variable array | |
| * return: -1 error, 0 nothing done or >0 size of marshaled data | |
| */ | |
| int | |
| io_vars2buffer(u_char *buf, int buflen, array_t *vars) | |
| { | |
| int Limit = 0; | |
| register int i; | |
| ait_val_t *v, *val; | |
| u_char *data; | |
| assert(buf); | |
| assert(vars); | |
| if (!buf || !vars) | |
| return -1; | |
| if (!buflen || !io_arraySize(vars)) | |
| return 0; | |
| Limit = sizeof(ait_val_t) * io_arraySize(vars); | |
| if (Limit > buflen) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", | |
| buflen, Limit); | |
| return -1; | |
| } else { | |
| memset(buf, 0, buflen); | |
| v = (ait_val_t*) buf; | |
| data = buf + Limit; | |
| } | |
| /* marshaling */ | |
| for (i = 0; i < io_arraySize(vars); i++) { | |
| val = io_array(vars, i, ait_val_t*); | |
| v[i].val_type = val->val_type; | |
| AIT_LEN(&v[i]) = htobe32(AIT_LEN(val)); | |
| switch (AIT_TYPE(val)) { | |
| case blob: | |
| case f32: | |
| case f64: | |
| case i8: | |
| case i16: | |
| case i32: | |
| case i64: | |
| case u8: | |
| case u16: | |
| case u32: | |
| case u64: | |
| v[i].val.net = htobe64(val->val.net); | |
| break; | |
| case buffer: | |
| case string: | |
| if (AIT_LEN(val) > buflen - Limit) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | |
| "needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | |
| return -1; | |
| } else | |
| Limit += AIT_LEN(val); | |
| memcpy(data, val->val.buffer, AIT_LEN(val)); | |
| /* Debug:: data offset in packet, not matter for anything! */ | |
| v[i].val.net = data - buf; | |
| data += AIT_LEN(val); | |
| break; | |
| default: | |
| io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | |
| AIT_TYPE(val), i); | |
| return -1; | |
| } | |
| } | |
| return Limit; | |
| } | |
| /* | |
| * io_buffer2vars() De-marshaling data from buffer to array with variables | |
| * @buf = Buffer | |
| * @buflen = Size of buffer | |
| * @vnum = Number of variables into buffer | |
| * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and | |
| *DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy() | |
| * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy() | |
| */ | |
| array_t * | |
| io_buffer2vars(u_char *buf, int buflen, int vnum, int zcpy) | |
| { | |
| array_t *vars; | |
| int Limit = 0; | |
| register int i; | |
| ait_val_t *v, *val; | |
| u_char *data; | |
| assert(buf); | |
| if (!buf || !buflen || !vnum) | |
| return NULL; | |
| Limit = sizeof(ait_val_t) * vnum; | |
| if (Limit > buflen) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", | |
| buflen, Limit); | |
| return NULL; | |
| } else { | |
| if (!(vars = io_arrayInit(vnum))) | |
| return NULL; | |
| v = (ait_val_t*) buf; | |
| data = buf + Limit; | |
| } | |
| /* de-marshaling */ | |
| for (i = 0; i < io_arraySize(vars); i++) { | |
| if (!zcpy) { | |
| val = malloc(sizeof(ait_val_t)); | |
| if (!val) { | |
| LOGERR; | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } | |
| } else | |
| val = v + i; | |
| io_arraySet(vars, i, val); | |
| val->val_type = v[i].val_type; | |
| #if defined(__OpenBSD__) | |
| AIT_LEN(val) = betoh32(AIT_LEN(&v[i])); | |
| #else | |
| AIT_LEN(val) = be32toh(AIT_LEN(&v[i])); | |
| #endif | |
| switch (AIT_TYPE(val)) { | |
| case blob: | |
| case f32: | |
| case f64: | |
| case i8: | |
| case i16: | |
| case i32: | |
| case i64: | |
| case u8: | |
| case u16: | |
| case u32: | |
| case u64: | |
| #if defined(__OpenBSD__) | |
| val->val.net = betoh64(v[i].val.net); | |
| #else | |
| val->val.net = be64toh(v[i].val.net); | |
| #endif | |
| break; | |
| case buffer: | |
| case string: | |
| if (AIT_LEN(val) > buflen - Limit) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | |
| "needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | |
| if (!zcpy) | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } else | |
| Limit += AIT_LEN(val); | |
| if (!zcpy) { | |
| val->val.buffer = malloc(AIT_LEN(val)); | |
| if (!val->val.buffer) { | |
| LOGERR; | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } else | |
| memcpy(val->val.buffer, data, AIT_LEN(val)); | |
| } else | |
| val->val.buffer = data; | |
| data += AIT_LEN(val); | |
| break; | |
| default: | |
| io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | |
| AIT_TYPE(val), i); | |
| if (!zcpy) | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } | |
| } | |
| return vars; | |
| } | |
| /* buffer marshaling without swapping bytes to network order */ | |
| /* | |
| * io_vars2map() Marshaling data from array with variables to memory map | |
| * @buf = Buffer | |
| * @buflen = Size of buffer | |
| * @vars = Variable array | |
| * return: -1 error, 0 nothing done or >0 size of marshaled data | |
| */ | |
| int | |
| io_vars2map(u_char *buf, int buflen, array_t *vars) | |
| { | |
| int Limit = 0; | |
| register int i; | |
| ait_val_t *v, *val; | |
| u_char *data; | |
| assert(buf); | |
| assert(vars); | |
| if (!buf || !vars) | |
| return -1; | |
| if (!buflen || !io_arraySize(vars)) | |
| return 0; | |
| Limit = sizeof(ait_val_t) * io_arraySize(vars); | |
| if (Limit > buflen) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", | |
| buflen, Limit); | |
| return -1; | |
| } else { | |
| memset(buf, 0, buflen); | |
| v = (ait_val_t*) buf; | |
| data = buf + Limit; | |
| } | |
| /* marshaling */ | |
| for (i = 0; i < io_arraySize(vars); i++) { | |
| val = io_array(vars, i, ait_val_t*); | |
| v[i].val_type = val->val_type; | |
| AIT_LEN(&v[i]) = AIT_LEN(val); | |
| switch (AIT_TYPE(val)) { | |
| case blob: | |
| case f32: | |
| case f64: | |
| case i8: | |
| case i16: | |
| case i32: | |
| case i64: | |
| case u8: | |
| case u16: | |
| case u32: | |
| case u64: | |
| v[i].val.net = val->val.net; | |
| break; | |
| case buffer: | |
| case string: | |
| if (AIT_LEN(val) > buflen - Limit) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | |
| "needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | |
| return -1; | |
| } else | |
| Limit += AIT_LEN(val); | |
| memcpy(data, val->val.buffer, AIT_LEN(val)); | |
| /* Debug:: data offset in packet, not matter for anything! */ | |
| v[i].val.net = data - buf; | |
| data += AIT_LEN(val); | |
| break; | |
| default: | |
| io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | |
| AIT_TYPE(val), i); | |
| return -1; | |
| } | |
| } | |
| return Limit; | |
| } | |
| /* | |
| * io_map2vars() De-marshaling data from memory map to array with variables | |
| * @buf = Buffer | |
| * @buflen = Size of buffer | |
| * @vnum = Number of variables into buffer | |
| * @zcpy = Zero-copy for variables, if !=0 don't use io_arrayFree() for free variables and | |
| *DON'T MODIFY OR DESTROY BUFFER*. =0 call io_arrayFree() before io_arrayDestroy() | |
| * return: =NULL error, !=NULL allocated variable array, after use must free with io_arrayDestroy() | |
| */ | |
| array_t * | |
| io_map2vars(u_char *buf, int buflen, int vnum, int zcpy) | |
| { | |
| array_t *vars; | |
| int Limit = 0; | |
| register int i; | |
| ait_val_t *v, *val; | |
| u_char *data; | |
| assert(buf); | |
| if (!buf || !buflen || !vnum) | |
| return NULL; | |
| Limit = sizeof(ait_val_t) * vnum; | |
| if (Limit > buflen) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d needed min %d ...\n", | |
| buflen, Limit); | |
| return NULL; | |
| } else { | |
| if (!(vars = io_arrayInit(vnum))) | |
| return NULL; | |
| v = (ait_val_t*) buf; | |
| data = buf + Limit; | |
| } | |
| /* de-marshaling */ | |
| for (i = 0; i < io_arraySize(vars); i++) { | |
| if (!zcpy) { | |
| val = malloc(sizeof(ait_val_t)); | |
| if (!val) { | |
| LOGERR; | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } | |
| } else | |
| val = v + i; | |
| io_arraySet(vars, i, val); | |
| val->val_type = v[i].val_type; | |
| AIT_LEN(val) = AIT_LEN(&v[i]); | |
| switch (AIT_TYPE(val)) { | |
| case blob: | |
| case f32: | |
| case f64: | |
| case i8: | |
| case i16: | |
| case i32: | |
| case i64: | |
| case u8: | |
| case u16: | |
| case u32: | |
| case u64: | |
| val->val.net = v[i].val.net; | |
| break; | |
| case buffer: | |
| case string: | |
| if (AIT_LEN(val) > buflen - Limit) { | |
| io_SetErr(EMSGSIZE, "Error:: too short buffer buflen=%d " | |
| "needed min %d ...\n", buflen, Limit + AIT_LEN(val)); | |
| if (!zcpy) | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } else | |
| Limit += AIT_LEN(val); | |
| if (!zcpy) { | |
| val->val.buffer = malloc(AIT_LEN(val)); | |
| if (!val->val.buffer) { | |
| LOGERR; | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } else | |
| memcpy(val->val.buffer, data, AIT_LEN(val)); | |
| } else | |
| val->val.buffer = data; | |
| data += AIT_LEN(val); | |
| break; | |
| default: | |
| io_SetErr(EINVAL, "Error:: unsupported variable type=%d at element #%d ...\n", | |
| AIT_TYPE(val), i); | |
| if (!zcpy) | |
| io_arrayFree(vars); | |
| io_arrayDestroy(&vars); | |
| return NULL; | |
| } | |
| } | |
| return vars; | |
| } | |
| /* | |
| * io_allocVars() Allocate ait_val_t array | |
| * @varnum = Number of variables | |
| * return: =NULL error or !=NULL allocated array | |
| */ | |
| inline array_t * | |
| io_allocVars(int varnum) | |
| { | |
| array_t *arr; | |
| register int i; | |
| ait_val_t *v; | |
| if (!varnum || !(arr = io_arrayInit(varnum))) | |
| return NULL; | |
| for (i = 0; i < io_arraySize(arr); i++) { | |
| v = malloc(sizeof(ait_val_t)); | |
| if (!v) { | |
| LOGERR; | |
| io_freeVars(&arr); | |
| return NULL; | |
| } else { | |
| memset(v, 0, sizeof(ait_val_t)); | |
| io_arraySet(arr, i, v); | |
| } | |
| } | |
| return arr; | |
| } | |
| /* | |
| * io_clrVars() Clear ait_val_t elements from array | |
| * @vars = Variable array | |
| * return: -1 error or size of array | |
| */ | |
| inline int | |
| io_clrVars(array_t * __restrict vars) | |
| { | |
| register int i; | |
| if (!vars) | |
| return -1; | |
| for (i = 0; i < io_arraySize(vars); i++) | |
| if (io_arrayGet(vars, i)) | |
| AIT_FREE_VAL(io_array(vars, i, ait_val_t*)); | |
| return io_arraySize(vars); | |
| } | |
| /* | |
| * io_freeVars() Free ait_val_t array | |
| * @vars = Variable array | |
| * return: none | |
| */ | |
| inline void | |
| io_freeVars(array_t ** __restrict vars) | |
| { | |
| if (!vars || !*vars) | |
| return; | |
| io_clrVars(*vars); | |
| io_arrayFree(*vars); | |
| io_arrayDestroy(vars); | |
| } | |
| /* | |
| * io_allocVar() Allocate memory for variable | |
| * return: NULL error or new variable, after use free variable with io_freeVar() | |
| */ | |
| inline ait_val_t * | |
| io_allocVar(void) | |
| { | |
| ait_val_t *v = NULL; | |
| v = malloc(sizeof(ait_val_t)); | |
| if (!v) { | |
| LOGERR; | |
| return NULL; | |
| } else | |
| memset(v, 0, sizeof(ait_val_t)); | |
| v->val_type = empty; | |
| return v; | |
| } | |
| /* | |
| * io_freeVar() Free allocated memory for variable | |
| * @val = Variable | |
| * return: none | |
| */ | |
| inline void | |
| io_freeVar(ait_val_t ** __restrict val) | |
| { | |
| if (val && *val) { | |
| AIT_FREE_VAL(*val); | |
| free(*val); | |
| *val = NULL; | |
| } | |
| } |