2024-10-01 22:48:28 +00:00
|
|
|
#include <client.h>
|
|
|
|
#include <stdio.h>
|
2024-10-02 01:24:48 +00:00
|
|
|
#include <stdint.h>
|
2024-10-01 22:48:28 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-10-02 01:24:48 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2024-10-01 22:48:28 +00:00
|
|
|
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;
|
|
|
|
}
|