#include #include #include #include #include static bool writeChar(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 charToHexDigit(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 charToHexDigits(char in, char *hi, char *lo) { return charToHexDigit((in & 0xf0) >> 4, hi) && charToHexDigit(in & 0x0f, lo); } void rdbResponseInit(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 rdbResponseBeginPacket(RdbResponse *res) { res->len = 0; res->chk = 0; if (res->should_ack) { res->buf[res->len++] = '+'; } res->buf[res->len++] = '$'; } bool rdbResponseWriteStr(RdbResponse *res, const char *str) { size_t i, len = strlen(str); for (i = 0; i < len; ++i) { if (!writeChar(res, str[i])) { return false; } } return true; } bool rdbResponseWriteStrHex(RdbResponse *res, const char *str) { size_t i, len = strlen(str); for (i = 0; i < len; ++i) { char hi, lo; if (!charToHexDigits(str[i], &hi, &lo) || !writeChar(res, hi) || !writeChar(res, lo)) { return false; } } return true; } bool rdbResponseWriteI8Hex(RdbResponse *res, uint8_t value) { char hi, lo; return charToHexDigits(value, &hi, &lo) && writeChar(res, hi) && writeChar(res, lo); } bool rdbResponseWriteI32Hex(RdbResponse *res, uint32_t value) { return rdbResponseWriteI8Hex(res, (uint8_t) value) && rdbResponseWriteI8Hex(res, (uint8_t) (value >> 8)) && rdbResponseWriteI8Hex(res, (uint8_t) (value >> 16)) && rdbResponseWriteI8Hex(res, (uint8_t) (value >> 24)); } int rdbResponseSendPacket(RdbResponse *res) { char hi, lo; ssize_t rwrite; if (res->len + 3 > res->buflen) { return -1; } res->buf[res->len++] = '#'; if (!charToHexDigits(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; }