gdb-server/response.c

115 lines
2.9 KiB
C
Raw Normal View History

2024-10-08 02:18:42 +00:00
#include <response.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
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 len = strlen(str);
for (size_t 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 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(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) {
if (res->len + 3 > res->buflen) {
return -1;
}
res->buf[res->len++] = '#';
char hi, lo;
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);
ssize_t rwrite = write(res->connfd, res->buf, res->len);
if (rwrite == -1) {
return -1;
}
return 0;
}