enable unix socket and add test for it
This commit is contained in:
parent
9106bd46f2
commit
9797a64f06
@ -950,10 +950,10 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize
|
|||||||
);
|
);
|
||||||
|
|
||||||
let file_ref: Arc<Box<File>> = match domain {
|
let file_ref: Arc<Box<File>> = match domain {
|
||||||
// libc::AF_LOCAL => {
|
libc::AF_LOCAL => {
|
||||||
// let unix_socket = UnixSocketFile::new(socket_type, protocol)?;
|
let unix_socket = UnixSocketFile::new(socket_type, protocol)?;
|
||||||
// Arc::new(Box::new(unix_socket))
|
Arc::new(Box::new(unix_socket))
|
||||||
// }
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let socket = SocketFile::new(domain, socket_type, protocol)?;
|
let socket = SocketFile::new(domain, socket_type, protocol)?;
|
||||||
Arc::new(Box::new(socket))
|
Arc::new(Box::new(socket))
|
||||||
@ -1022,7 +1022,7 @@ fn do_accept4(
|
|||||||
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
|
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
|
||||||
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
|
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
|
||||||
|
|
||||||
Ok(0)
|
Ok(new_fd as isize)
|
||||||
} else {
|
} else {
|
||||||
errno!(EBADF, "not a socket")
|
errno!(EBADF, "not a socket")
|
||||||
}
|
}
|
||||||
@ -1147,14 +1147,19 @@ fn do_getpeername(
|
|||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
let socket = file_ref.as_socket()?;
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
|
||||||
let ret = try_libc!(libc::ocall::getpeername(
|
let ret = try_libc!(libc::ocall::getpeername(
|
||||||
socket.fd(),
|
socket.fd(),
|
||||||
addr,
|
addr,
|
||||||
addr_len
|
addr_len
|
||||||
));
|
));
|
||||||
Ok(ret as isize)
|
Ok(ret as isize)
|
||||||
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
warn!("getpeername for unix socket is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_sendto(
|
fn do_sendto(
|
||||||
|
@ -4,7 +4,7 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../)
|
|||||||
# Dependencies: need to be compiled but not to run by any Makefile target
|
# Dependencies: need to be compiled but not to run by any Makefile target
|
||||||
TEST_DEPS := dev_null
|
TEST_DEPS := dev_null
|
||||||
# Tests: need to be compiled and run by test-% target
|
# Tests: need to be compiled and run by test-% target
|
||||||
TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread uname rlimit client server server_epoll
|
TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread uname rlimit client server server_epoll unix_socket
|
||||||
# Benchmarks: need to be compiled and run by bench-% target
|
# Benchmarks: need to be compiled and run by bench-% target
|
||||||
BENCHES := spawn_and_exit_latency pipe_throughput
|
BENCHES := spawn_and_exit_latency pipe_throughput
|
||||||
|
|
||||||
|
5
test/unix_socket/Makefile
Normal file
5
test/unix_socket/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS := -Wno-incompatible-pointer-types-discards-qualifiers
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
117
test/unix_socket/main.c
Normal file
117
test/unix_socket/main.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <spawn.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
const char SOCK_PATH[] = "echo_socket";
|
||||||
|
|
||||||
|
int create_server_socket() {
|
||||||
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd == -1) {
|
||||||
|
printf("ERROR: failed to create a unix socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un local;
|
||||||
|
local.sun_family = AF_UNIX;
|
||||||
|
strcpy(local.sun_path, SOCK_PATH);
|
||||||
|
socklen_t len = strlen(local.sun_path) + sizeof(local.sun_family);
|
||||||
|
|
||||||
|
if (bind(fd, (struct sockaddr *)&local, len) == -1) {
|
||||||
|
printf("ERROR: failed to bind\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(fd, 5) == -1) {
|
||||||
|
printf("ERROR: failed to listen\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_client_socket() {
|
||||||
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd == -1) {
|
||||||
|
printf("ERROR: failed to create a unix socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un remote;
|
||||||
|
remote.sun_family = AF_UNIX;
|
||||||
|
strcpy(remote.sun_path, SOCK_PATH);
|
||||||
|
socklen_t len = strlen(remote.sun_path) + sizeof(remote.sun_family);
|
||||||
|
|
||||||
|
if (connect(fd, (struct sockaddr *)&remote, len) == -1) {
|
||||||
|
printf("ERROR: failed to connect\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
// XXX: this is a hack! remove this in the future
|
||||||
|
void* ptr = malloc(64);
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
|
int listen_fd = create_server_socket();
|
||||||
|
if (listen_fd == -1) {
|
||||||
|
printf("ERROR: failed to create server socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_rd_fd = create_client_socket();
|
||||||
|
if (socket_rd_fd == -1) {
|
||||||
|
printf("ERROR: failed to create client socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un remote;
|
||||||
|
socklen_t len = sizeof(remote);
|
||||||
|
int socket_wr_fd = accept(listen_fd, (struct sockaddr *)&remote, &len);
|
||||||
|
if (socket_wr_fd == -1) {
|
||||||
|
printf("ERROR: failed to accept socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following is same as 'pipe'
|
||||||
|
|
||||||
|
posix_spawn_file_actions_t file_actions;
|
||||||
|
posix_spawn_file_actions_init(&file_actions);
|
||||||
|
posix_spawn_file_actions_adddup2(&file_actions, socket_wr_fd, STDOUT_FILENO);
|
||||||
|
posix_spawn_file_actions_addclose(&file_actions, socket_rd_fd);
|
||||||
|
|
||||||
|
const char* msg = "Echo!\n";
|
||||||
|
const char* child_prog = "hello_world";
|
||||||
|
const char* child_argv[3] = { child_prog, msg, NULL };
|
||||||
|
int child_pid;
|
||||||
|
if (posix_spawn(&child_pid, child_prog, &file_actions,
|
||||||
|
NULL, child_argv, NULL) < 0) {
|
||||||
|
printf("ERROR: failed to spawn a child process\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(socket_wr_fd);
|
||||||
|
|
||||||
|
const char* expected_str = msg;
|
||||||
|
size_t expected_len = strlen(expected_str);
|
||||||
|
char actual_str[32] = {0};
|
||||||
|
ssize_t actual_len;
|
||||||
|
do {
|
||||||
|
actual_len = read(socket_rd_fd, actual_str, sizeof(actual_str) - 1);
|
||||||
|
} while (actual_len == 0);
|
||||||
|
if (strncmp(expected_str, actual_str, expected_len) != 0) {
|
||||||
|
printf("ERROR: received string is not as expected\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
if (wait4(child_pid, &status, 0, NULL) < 0) {
|
||||||
|
printf("ERROR: failed to wait4 the child process\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user