#include #include #include #include #include static bool write_char(RdbResponse *res, char out) { if (res->len >= res->buflen) { return false; } if (out == '#' || out == '$' || out == '}' || out == '*') { res->buf[res->len++] = '}'; res->chk += '}'; if (res->len >= res->buflen) { return false; } out ^= 0x20; } res->buf[res->len++] = out; res->chk += out; return true; } bool char_to_hex_digit(char in, char *out) { if (in & 0xf0) { return false; } in &= 0x0f; if (in > 9) { *out = 'a' + in - 10; } else { *out = '0' + in; } return true; } bool char_to_hex_digits(char in, char *hi, char *lo) { return char_to_hex_digit((in & 0xf0) >> 4, hi) && char_to_hex_digit(in & 0x0f, lo); } void rdb_response_init(RdbResponse *res, int connfd, char *buf, size_t buflen) { res->connfd = connfd; res->buf = buf; res->buflen = buflen; res->len = 0; res->chk = 0; res->should_ack = true; } void rdb_response_begin_packet(RdbResponse *res) { res->len = 0; res->chk = 0; if (res->should_ack) { res->buf[res->len++] = '+'; } res->buf[res->len++] = '$'; } bool rdb_response_write_str(RdbResponse *res, const char *str) { size_t i, len = strlen(str); for (i = 0; i < len; ++i) { if (!write_char(res, str[i])) { return false; } } return true; } bool rdb_response_write_str_hex(RdbResponse *res, const char *str) { size_t i, len = strlen(str); for (i = 0; i < len; ++i) { char hi, lo; if (!char_to_hex_digits(str[i], &hi, &lo) || !write_char(res, hi) || !write_char(res, lo)) { return false; } } return true; } bool rdb_response_write_i8_hex(RdbResponse *res, uint8_t value) { char hi, lo; return char_to_hex_digits(value, &hi, &lo) && write_char(res, hi) && write_char(res, lo); } bool rdb_response_write_i32_hex(RdbResponse *res, uint32_t value) { return rdb_response_write_i8_hex(res, (uint8_t) value) && rdb_response_write_i8_hex(res, (uint8_t) (value >> 8)) && rdb_response_write_i8_hex(res, (uint8_t) (value >> 16)) && rdb_response_write_i8_hex(res, (uint8_t) (value >> 24)); } int rdb_response_send_packet(RdbResponse *res) { char hi, lo; ssize_t rwrite; if (res->len + 3 > res->buflen) { return -1; } res->buf[res->len++] = '#'; if (!char_to_hex_digits(res->chk, &hi, &lo)) { return -1; } res->buf[res->len++] = hi; res->buf[res->len++] = lo; printf("sending command \"%.*s\" %d\n", (int) res->len, res->buf, (int)res->len); rwrite = write(res->connfd, res->buf, res->len); if (rwrite == -1) { return -1; } return 0; }