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