#include #include #include #include #include static bool write_char(RdbClient *self, char out) { if (self->len >= RDB_CLIENT_BUFLEN) { return false; } if (out == '#' || out == '$' || out == '}' || out == '*') { self->full_buf[self->len++] = '}'; self->chk += '}'; if (self->len >= RDB_CLIENT_BUFLEN) { return false; } out ^= 0x20; } self->full_buf[self->len++] = out; self->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_client_init(RdbClient *self, int connfd) { self->connfd = connfd; self->len = 0; self->chk = 0; self->should_ack = true; } void rdb_client_begin_packet(RdbClient *self) { self->len = 0; self->chk = 0; if (self->should_ack) { self->full_buf[self->len++] = '+'; } self->full_buf[self->len++] = '$'; } bool rdb_client_write_str(RdbClient *self, const char *str) { size_t len = strlen(str); for (size_t i = 0; i < len; ++i) { if (!write_char(self, str[i])) { return false; } } return true; } bool rdb_client_write_str_hex(RdbClient *self, const char *str) { size_t len = strlen(str); for (size_t i = 0; i < len; ++i) { char hi, lo; if (!char_to_hex_digits(str[i], &hi, &lo) || !write_char(self, hi) || !write_char(self, lo)) { return false; } } return true; } bool rdb_client_write_i8_hex(RdbClient *self, uint8_t value) { char hi, lo; return char_to_hex_digits(value, &hi, &lo) && write_char(self, hi) && write_char(self, lo); } bool rdb_client_write_i32_hex(RdbClient *self, uint32_t value) { return rdb_client_write_i8_hex(self, (uint8_t) value) && rdb_client_write_i8_hex(self, (uint8_t) (value >> 8)) && rdb_client_write_i8_hex(self, (uint8_t) (value >> 16)) && rdb_client_write_i8_hex(self, (uint8_t) (value >> 24)); } int rdb_client_send_packet(RdbClient *self) { if (self->len + 3 > RDB_CLIENT_BUFLEN) { return -1; } self->full_buf[self->len++] = '#'; char hi, lo; if (!char_to_hex_digits(self->chk, &hi, &lo)) { return -1; } self->full_buf[self->len++] = hi; self->full_buf[self->len++] = lo; printf("sending command \"%.*s\" %d\n", (int) self->len, self->full_buf, (int)self->len); ssize_t rwrite = write(self->connfd, self->full_buf, self->len); if (rwrite == -1) { return -1; } return 0; }