diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 42df50de..fd460417 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -950,10 +950,10 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result> = match domain { -// libc::AF_LOCAL => { -// let unix_socket = UnixSocketFile::new(socket_type, protocol)?; -// Arc::new(Box::new(unix_socket)) -// } + libc::AF_LOCAL => { + let unix_socket = UnixSocketFile::new(socket_type, protocol)?; + Arc::new(Box::new(unix_socket)) + } _ => { let socket = SocketFile::new(domain, socket_type, protocol)?; Arc::new(Box::new(socket)) @@ -1022,7 +1022,7 @@ fn do_accept4( let new_file_ref: Arc> = Arc::new(Box::new(new_socket)); let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false); - Ok(0) + Ok(new_fd as isize) } else { errno!(EBADF, "not a socket") } @@ -1147,14 +1147,19 @@ fn do_getpeername( let current_ref = process::get_current(); let mut proc = current_ref.lock().unwrap(); let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; - let socket = file_ref.as_socket()?; - - let ret = try_libc!(libc::ocall::getpeername( - socket.fd(), - addr, - addr_len - )); - Ok(ret as isize) + if let Ok(socket) = file_ref.as_socket() { + let ret = try_libc!(libc::ocall::getpeername( + socket.fd(), + addr, + addr_len + )); + 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( diff --git a/test/Makefile b/test/Makefile index 4d4ca4cb..135435a2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../) # Dependencies: need to be compiled but not to run by any Makefile target TEST_DEPS := dev_null # 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 BENCHES := spawn_and_exit_latency pipe_throughput diff --git a/test/unix_socket/Makefile b/test/unix_socket/Makefile new file mode 100644 index 00000000..8c5a2fb4 --- /dev/null +++ b/test/unix_socket/Makefile @@ -0,0 +1,5 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := -Wno-incompatible-pointer-types-discards-qualifiers +EXTRA_LINK_FLAGS := +BIN_ARGS := diff --git a/test/unix_socket/main.c b/test/unix_socket/main.c new file mode 100644 index 00000000..a00c2eb4 --- /dev/null +++ b/test/unix_socket/main.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +}