radare2/libr/socket/socket_rap_server.c
pancake 54617455de
Initial refactoring of the rap:// protocol (-75 LOC) ##socket (#16534)
* It's implemented in IO, Socket and Core
* Remove duplicated apis and defines, everything in in RSocket now
* RIO now owns an RCoreBind instead of 3 fcn pointers + 1 void*
* Use proper filenames in libr/socket following public api names
* Use RSocket.block apis in the rap client + server apis
2020-04-12 16:40:55 +02:00

140 lines
3.7 KiB
C

/* radare - LGPL - Copyright 2014-2019 - pancake, condret */
#include <r_socket.h>
#include <r_util.h>
R_API RSocketRapServer *r_socket_rap_server_new(bool use_ssl, const char *port) {
r_return_val_if_fail (port, NULL);
RSocketRapServer *s = R_NEW0 (RSocketRapServer);
if (s) {
s->port = strdup (port);
s->fd = r_socket_new (use_ssl);
if (s->fd) {
return s;
}
r_socket_free (s->fd);
free (s);
}
return NULL;
}
R_API RSocketRapServer *r_socket_rap_server_create(const char *pathname) {
r_return_val_if_fail (pathname, NULL);
if (strlen (pathname) < 11) {
return NULL;
}
if (strncmp (pathname, "rap", 3)) {
return NULL;
}
bool is_ssl = (pathname[3] == 's');
const char *port = &pathname[7 + is_ssl];
return r_socket_rap_server_new (is_ssl, port);
}
R_API void r_socket_rap_server_free(RSocketRapServer *s) {
if (s) {
r_socket_free (s->fd);
free (s);
}
}
R_API bool r_socket_rap_server_listen(RSocketRapServer *s, const char *certfile) {
r_return_val_if_fail (s && s->port && *s->port, false);
return r_socket_listen (s->fd, s->port, certfile);
}
R_API RSocket* r_socket_rap_server_accept(RSocketRapServer *s) {
r_return_val_if_fail (s && s->fd, NULL);
return r_socket_accept (s->fd);
}
R_API bool r_socket_rap_server_continue(RSocketRapServer *s) {
r_return_val_if_fail (s && s->fd, false);
int i;
char *ptr = NULL;
if (!r_socket_is_connected (s->fd)) {
return false;
}
r_socket_read_block (s->fd, s->buf, 1);
switch (s->buf[0]) {
case RAP_PACKET_OPEN:
r_socket_read_block (s->fd, &s->buf[1], 2);
r_socket_read_block (s->fd, &s->buf[3], (int)s->buf[2]);
{
int fd = s->open (s->user, (const char *)&s->buf[3], (int)s->buf[1], 0);
s->buf[0] = RAP_PACKET_OPEN | RAP_PACKET_REPLY;
eprintf ("REPLY BACK %d\n", fd);
r_write_be32 (s->buf + 1, fd);
}
r_socket_write (s->fd, s->buf, 5);
r_socket_flush (s->fd);
break;
case RAP_PACKET_READ:
r_socket_read_block (s->fd, &s->buf[1], 4);
i = r_read_be32 (&s->buf[1]);
if (i > RAP_PACKET_MAX || i < 0) {
i = RAP_PACKET_MAX;
}
s->read (s->user, &s->buf[5], i);
s->buf[0] = RAP_PACKET_READ | RAP_PACKET_REPLY;
r_socket_write (s->fd, s->buf, i + 5);
r_socket_flush (s->fd);
break;
case RAP_PACKET_WRITE:
r_socket_read_block (s->fd, s->buf + 1, 4);
i = r_read_be32 (s->buf + 1);
if (i > RAP_PACKET_MAX || i < 0) {
i = RAP_PACKET_MAX;
}
r_socket_read_block (s->fd, s->buf + 5, i);
r_write_be32 (s->buf + 1, s->write (s->user, s->buf + 5, i));
s->buf[0] = RAP_PACKET_WRITE | RAP_PACKET_REPLY;
r_socket_write (s->fd, s->buf, 5);
r_socket_flush (s->fd);
break;
case RAP_PACKET_SEEK:
{
r_socket_read_block (s->fd, &s->buf[1], 9);
int whence = s->buf[0];
ut64 offset = r_read_be64 (s->buf + 1);
offset = s->seek (s->user, offset, whence);
/* prepare reply */
s->buf[0] = RAP_PACKET_SEEK | RAP_PACKET_REPLY;
r_write_be64 (s->buf + 1, offset);
r_socket_write (s->fd, s->buf, 9);
r_socket_flush (s->fd);
}
break;
case RAP_PACKET_CMD:
r_socket_read_block (s->fd, &s->buf[1], 4);
i = r_read_be32 (&s->buf[1]);
r_socket_read_block (s->fd, &s->buf[5], i);
ptr = s->cmd (s->user, (const char *)&s->buf[5]);
i = (ptr)? strlen (ptr) + 1: 0;
r_write_be32 (&s->buf[1], i);
s->buf[0] = RAP_PACKET_CMD | RAP_PACKET_REPLY;
r_socket_write (s->fd, s->buf, 5);
if (i) {
r_socket_write (s->fd, ptr, i);
}
r_socket_flush (s->fd);
R_FREE (ptr);
break;
case RAP_PACKET_CLOSE:
r_socket_read_block (s->fd, &s->buf[1], 4);
i = r_read_be32 (&s->buf[1]);
s->close (s->user, i);
s->buf[0] = RAP_PACKET_CLOSE | RAP_PACKET_REPLY;
r_socket_write (s->fd, s->buf, 5);
r_socket_flush (s->fd);
break;
default:
eprintf ("unknown command 0x%02x\n", (ut8)(s->buf[0] & 0xff));
r_socket_close (s->fd);
return false;
}
return true;
}