#include <sys/types.h> #include <inttypes.h> #include "nodes.h" #include "commands.h" #include "bitwise.h" enum GetnodeData { GN_DATA_SIZE }; /* Creates data and metadata for a getnodes packet. * Returns data size. */ ssize_t EncodeGetNodes( struct metadata *m, /* Out */ uint8_t *data, /* Out */ size_t data_size, /* Data buffer max size */ const char * msg) /* Value is not used; only IDs */ { m->msg_type = GETNODES_ID; m->data_len = GN_DATA_SIZE; return GN_DATA_SIZE; } enum AddnodeData { AN_TYPE_ID_L, AN_TYPE_ID_H, AN_NAME, AN_MIN_DATA_SIZE }; /* Creates data and metadata for a addnode packet * Returns data size. */ ssize_t EncodeAddNode( struct metadata * m, /* data_len and msg_type will be populated*/ uint8_t * data, /* Output buffer */ size_t data_size, /* Max buffer size */ const char * msg) /* Message to encode */ { m->msg_type = ADDNODE_ID; if (data_size < AN_MIN_DATA_SIZE) { return -1; } int16_t type; char name[512]; memset(name, 0, 512); sscanf(msg, "addnode %" SCNd16 " %512c", &type, name); printf("found name '%s'\n", name); data[AN_TYPE_ID_L] = LSByte16(type); data[AN_TYPE_ID_H] = MSByte16(type); memcpy(&data[AN_NAME], name, strlen(name) + 1); // We want to include the null byte m->data_len = AN_MIN_DATA_SIZE + strlen(name); return m->data_len; } enum ResponseGetnodesData { RESP_GN_NUM_NODES_L, RESP_GN_NUM_NODES_H, RESP_GN_MIN_DATA_SIZE }; static int resizeMsg(char **msg_ptr, int *curr_max, int check_val) { /* resize the msg if necessary */ if (*curr_max < check_val) { *curr_max = *curr_max * 4; *msg_ptr = realloc(*msg_ptr, sizeof(**msg_ptr) * *curr_max); if (!msg_ptr) { return -1; } } return 0; } /* Decode a metadata and data to populate a. * Returns bytes written to msg, -1 on failure. */ int DecodeResponseGetNodes( char * msg, /* Out */ size_t max_len, /* msg buffer max size */ const struct metadata *m, /* In */ const uint8_t * data) /* In */ { /* See if we have the min. amount */ if (m->data_len < RESP_GN_MIN_DATA_SIZE) { return -1; } if (m->msg_type != RESPNODES_ID) { return -1; } uint16_t num_nodes = BytesTo16(data[RESP_GN_NUM_NODES_L], data[RESP_GN_NUM_NODES_H]); if (resizeMsg(&msg, (int *)&max_len, (m->data_len *2)) == -1) { return -1; } int16_t val; char name[512] = "";/* Corresponding to the maximum name len that the frontend will accept */ size_t i; int msg_len = 0, msg_offset = 0, data_offset = RESP_GN_MIN_DATA_SIZE; sprintf(msg, "getnodes %hu %n", num_nodes, &msg_offset); msg_len += msg_offset; for(i = 0; i < num_nodes * 3; ++i) { if (i < num_nodes * 2) { val = BytesTo16(data[data_offset], data[data_offset+1]); data_offset += 2; sprintf(&msg[msg_len], "%" PRId16 " %n", val, &msg_offset); } else { strncpy(name, (char *) (data + data_offset), 512); data_offset += strlen(name) + 1; sprintf(&msg[msg_len], "'%s' %n", name, &msg_offset); } msg_len += msg_offset; if (resizeMsg(&msg, (int *)&max_len, msg_len + (msg_offset *2)) == -1) { return -1; } } strcat(&msg[msg_len], "\n"); return strlen(msg); } enum ResponseAddnodeData { RESP_AN_BLOCK_ID_L, RESP_AN_BLOCK_ID_H, RESP_AN_DATA_SIZE }; /* Decode a metadata and data to populate a controller. * Returns bytes written to msg, -1 on failure. */ int DecodeResponseAddNode( char * msg, /* Out */ size_t max_len, /* msg buffer max size */ const struct metadata *m, /* In */ const uint8_t * data) /* In */ { if (m->data_len < RESP_AN_DATA_SIZE) { return -1; } if (m->msg_type != RESPADDNODE_ID) { return -1; } return sprintf(msg, "addnode %d\n", BytesTo16(data[RESP_AN_BLOCK_ID_L], data[RESP_AN_BLOCK_ID_H])); }