mirror of
https://github.com/vale981/ray
synced 2025-03-06 10:31:39 -05:00
Make it possible to read and write data that is not null-terminated (#9)
* Make it possible to read and write data that is not null-terminated * formating
This commit is contained in:
parent
ff11ee21ef
commit
b18f214d55
6 changed files with 87 additions and 58 deletions
12
Makefile
12
Makefile
|
@ -9,11 +9,11 @@ CFLAGS += -Wmissing-declarations
|
||||||
$(BUILD)/db_tests: hiredis test/db_tests.c thirdparty/greatest.h event_loop.c state/redis.c common.c
|
$(BUILD)/db_tests: hiredis test/db_tests.c thirdparty/greatest.h event_loop.c state/redis.c common.c
|
||||||
$(CC) -o $@ test/db_tests.c event_loop.c state/redis.c common.c thirdparty/hiredis/libhiredis.a $(CFLAGS) -I. -Ithirdparty
|
$(CC) -o $@ test/db_tests.c event_loop.c state/redis.c common.c thirdparty/hiredis/libhiredis.a $(CFLAGS) -I. -Ithirdparty
|
||||||
|
|
||||||
$(BUILD)/socket_tests: test/socket_tests.c thirdparty/greatest.h sockets.c
|
$(BUILD)/io_tests: test/io_tests.c thirdparty/greatest.h io.c
|
||||||
$(CC) -o $@ test/socket_tests.c sockets.c $(CFLAGS) -I. -Ithirdparty
|
$(CC) -o $@ test/io_tests.c io.c $(CFLAGS) -I. -Ithirdparty
|
||||||
|
|
||||||
$(BUILD)/task_tests: test/task_tests.c task.c sockets.c common.h
|
$(BUILD)/task_tests: test/task_tests.c task.c io.c common.h
|
||||||
$(CC) -o $@ test/task_tests.c task.c sockets.c $(CFLAGS) -I. -Ithirdparty
|
$(CC) -o $@ test/task_tests.c task.c io.c $(CFLAGS) -I. -Ithirdparty
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -r $(BUILD)/*
|
rm -r $(BUILD)/*
|
||||||
|
@ -24,8 +24,8 @@ redis:
|
||||||
hiredis:
|
hiredis:
|
||||||
git submodule update --init --recursive -- "thirdparty/hiredis" ; cd thirdparty/hiredis ; make
|
git submodule update --init --recursive -- "thirdparty/hiredis" ; cd thirdparty/hiredis ; make
|
||||||
|
|
||||||
test: hiredis redis $(BUILD)/db_tests $(BUILD)/socket_tests $(BUILD)/task_tests FORCE
|
test: hiredis redis $(BUILD)/db_tests $(BUILD)/io_tests $(BUILD)/task_tests FORCE
|
||||||
./thirdparty/redis-3.2.3/src/redis-server &
|
./thirdparty/redis-3.2.3/src/redis-server &
|
||||||
sleep 1s ; ./build/db_tests ; ./build/socket_tests ; ./build/task_tests
|
sleep 1s ; ./build/db_tests ; ./build/io_tests ; ./build/task_tests
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "sockets.h"
|
#include "io.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -6,6 +6,7 @@
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
@ -74,22 +75,6 @@ int connect_ipc_sock(const char *socket_pathname) {
|
||||||
return socket_fd;
|
return socket_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sends a message on the given socket file descriptor. */
|
|
||||||
void send_ipc_sock(int socket_fd, char *message) {
|
|
||||||
int length = strlen(message);
|
|
||||||
int nbytes;
|
|
||||||
nbytes = write(socket_fd, (char *) &length, sizeof(length));
|
|
||||||
if (nbytes == -1) {
|
|
||||||
LOG_ERR("Error sending to socket.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nbytes = write(socket_fd, (char *) message, length * sizeof(char));
|
|
||||||
if (nbytes == -1) {
|
|
||||||
LOG_ERR("Error sending to socket.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Accept a new client connection on the given socket
|
/* Accept a new client connection on the given socket
|
||||||
* descriptor. Returns a descriptor for the new socket. */
|
* descriptor. Returns a descriptor for the new socket. */
|
||||||
int accept_client(int socket_fd) {
|
int accept_client(int socket_fd) {
|
||||||
|
@ -105,25 +90,52 @@ int accept_client(int socket_fd) {
|
||||||
return client_fd;
|
return client_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receives a message on the given socket file descriptor. Allocates and
|
/* Write a sequence of bytes on a file descriptor. */
|
||||||
* returns a pointer to the message.
|
void write_bytes(int fd, uint8_t *bytes, int64_t length) {
|
||||||
* NOTE: Caller must free the message! */
|
ssize_t nbytes = write(fd, (char *) &length, sizeof(length));
|
||||||
char *recv_ipc_sock(int socket_fd) {
|
if (nbytes == -1) {
|
||||||
int length;
|
LOG_ERR("Error sending to socket.\n");
|
||||||
int nbytes;
|
return;
|
||||||
nbytes = read(socket_fd, &length, sizeof(length));
|
}
|
||||||
|
nbytes = write(fd, (char *) bytes, length * sizeof(char));
|
||||||
|
if (nbytes == -1) {
|
||||||
|
LOG_ERR("Error sending to socket.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a sequence of bytes written by write_bytes from a file descriptor.
|
||||||
|
* Allocates and returns a pointer to the bytes.
|
||||||
|
* NOTE: Caller must free the memory! */
|
||||||
|
void read_bytes(int fd, uint8_t **bytes, int64_t *length) {
|
||||||
|
ssize_t nbytes = read(fd, length, sizeof(int64_t));
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
LOG_ERR("Error reading length of message from socket.");
|
LOG_ERR("Error reading length of message from socket.");
|
||||||
return NULL;
|
*bytes = NULL;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *message = malloc((length + 1) * sizeof(char));
|
*bytes = malloc(*length * sizeof(uint8_t));
|
||||||
nbytes = read(socket_fd, message, length);
|
nbytes = read(fd, *bytes, *length);
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
LOG_ERR("Error reading message from socket.");
|
LOG_ERR("Error reading message from socket.");
|
||||||
free(message);
|
free(*bytes);
|
||||||
return NULL;
|
*bytes = NULL;
|
||||||
}
|
}
|
||||||
message[length] = '\0';
|
}
|
||||||
return message;
|
|
||||||
|
/* Write a null-terminated string to a file descriptor. */
|
||||||
|
void write_string(int fd, char *message) {
|
||||||
|
/* Account for the \0 at the end of the string. */
|
||||||
|
write_bytes(fd, (uint8_t *) message, strlen(message) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads a null-terminated string from the file descriptor that has been
|
||||||
|
* written by write_string. Allocates and returns a pointer to the string.
|
||||||
|
* NOTE: Caller must free the memory! */
|
||||||
|
char *read_string(int fd) {
|
||||||
|
uint8_t *bytes;
|
||||||
|
int64_t length;
|
||||||
|
read_bytes(fd, &bytes, &length);
|
||||||
|
return (char *) bytes;
|
||||||
}
|
}
|
21
io.h
Normal file
21
io.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef IO_H
|
||||||
|
#define IO_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Helper functions for socket communication. */
|
||||||
|
|
||||||
|
int bind_ipc_sock(const char *socket_pathname);
|
||||||
|
int connect_ipc_sock(const char *socket_pathname);
|
||||||
|
|
||||||
|
int accept_client(int socket_fd);
|
||||||
|
|
||||||
|
/* Reading and writing data */
|
||||||
|
|
||||||
|
void write_bytes(int fd, uint8_t *bytes, int64_t length);
|
||||||
|
void read_bytes(int fd, uint8_t **bytes, int64_t *length);
|
||||||
|
|
||||||
|
void write_string(int fd, char *message);
|
||||||
|
char *read_string(int fd);
|
||||||
|
|
||||||
|
#endif
|
11
sockets.h
11
sockets.h
|
@ -1,11 +0,0 @@
|
||||||
#ifndef SOCKETS_H
|
|
||||||
#define SOCKETS_H
|
|
||||||
|
|
||||||
/* Helper functions for socket communication. */
|
|
||||||
int bind_ipc_sock(const char* socket_pathname);
|
|
||||||
int connect_ipc_sock(const char* socket_pathname);
|
|
||||||
void send_ipc_sock(int socket_fd, char* message);
|
|
||||||
int accept_client(int socket_fd);
|
|
||||||
char* recv_ipc_sock(int socket_fd);
|
|
||||||
|
|
||||||
#endif
|
|
2
task.c
2
task.c
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "sockets.h"
|
#include "io.h"
|
||||||
|
|
||||||
/* Tasks are stored in a consecutive chunk of memory, the first
|
/* Tasks are stored in a consecutive chunk of memory, the first
|
||||||
* sizeof(task_spec) bytes are arranged according to the struct
|
* sizeof(task_spec) bytes are arranged according to the struct
|
||||||
|
|
|
@ -2,32 +2,39 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "sockets.h"
|
#include "io.h"
|
||||||
|
|
||||||
SUITE(socket_tests);
|
SUITE(io_tests);
|
||||||
|
|
||||||
TEST ipc_socket_test(void) {
|
TEST ipc_socket_test(void) {
|
||||||
const char* socket_pathname = "test-socket";
|
const char *socket_pathname = "test-socket";
|
||||||
int socket_fd = bind_ipc_sock(socket_pathname);
|
int socket_fd = bind_ipc_sock(socket_pathname);
|
||||||
ASSERT(socket_fd >= 0);
|
ASSERT(socket_fd >= 0);
|
||||||
|
|
||||||
char* test_string = "hello world";
|
char *test_string = "hello world";
|
||||||
|
char *test_bytes = "another string";
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
close(socket_fd);
|
close(socket_fd);
|
||||||
socket_fd = connect_ipc_sock(socket_pathname);
|
socket_fd = connect_ipc_sock(socket_pathname);
|
||||||
ASSERT(socket_fd >= 0);
|
ASSERT(socket_fd >= 0);
|
||||||
send_ipc_sock(socket_fd, test_string);
|
write_string(socket_fd, test_string);
|
||||||
|
write_bytes(socket_fd, (uint8_t *) test_bytes, strlen(test_bytes));
|
||||||
close(socket_fd);
|
close(socket_fd);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else {
|
} else {
|
||||||
int client_fd = accept_client(socket_fd);
|
int client_fd = accept_client(socket_fd);
|
||||||
ASSERT(client_fd >= 0);
|
ASSERT(client_fd >= 0);
|
||||||
char* message = recv_ipc_sock(client_fd);
|
char *message = read_string(client_fd);
|
||||||
ASSERT(message != NULL);
|
ASSERT(message != NULL);
|
||||||
ASSERT_STR_EQ(test_string, message);
|
ASSERT_STR_EQ(test_string, message);
|
||||||
free(message);
|
free(message);
|
||||||
|
int64_t len;
|
||||||
|
uint8_t *bytes;
|
||||||
|
read_bytes(client_fd, &bytes, &len);
|
||||||
|
ASSERT(memcmp(test_bytes, bytes, len) == 0);
|
||||||
close(client_fd);
|
close(client_fd);
|
||||||
close(socket_fd);
|
close(socket_fd);
|
||||||
unlink(socket_pathname);
|
unlink(socket_pathname);
|
||||||
|
@ -36,14 +43,14 @@ TEST ipc_socket_test(void) {
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
SUITE(socket_tests) {
|
SUITE(io_tests) {
|
||||||
RUN_TEST(ipc_socket_test);
|
RUN_TEST(ipc_socket_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
GREATEST_MAIN_DEFS();
|
GREATEST_MAIN_DEFS();
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char **argv) {
|
||||||
GREATEST_MAIN_BEGIN();
|
GREATEST_MAIN_BEGIN();
|
||||||
RUN_SUITE(socket_tests);
|
RUN_SUITE(io_tests);
|
||||||
GREATEST_MAIN_END();
|
GREATEST_MAIN_END();
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue