11 changed files with 330 additions and 18 deletions
			
			
		| @ -0,0 +1,204 @@ | ||||
| /* cmdsocket.c */ | ||||
| 
 | ||||
| #include <sys/time.h> | ||||
| #include <dev/wscons/wsconsio.h> | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <unistd.h> | ||||
| #include <err.h> | ||||
| #include <errno.h> | ||||
| #include <stdio.h> | ||||
| #include <netinet/in.h> | ||||
| #include <sys/socket.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include "vm.h" | ||||
| 
 | ||||
| #define PORT 15674 | ||||
| #define CMD_MAXSIZE 1024 | ||||
| #define PREFIX_MAXSIZE 1024 | ||||
| 
 | ||||
| #define CMDSOCKET_BANNER "lightscript cmdsocket ready\r\n" | ||||
| 
 | ||||
| int cmd_sock = 0; | ||||
| int cmd_active = 0; | ||||
| int cmd_ignore; | ||||
| int cmd_bytes; | ||||
| int cmdsocket_initialised = 0; | ||||
| char cmd_buf[CMD_MAXSIZE]; | ||||
| char cmd_prefix[PREFIX_MAXSIZE]; | ||||
| 
 | ||||
| int cmdsocket_init(void) | ||||
| { | ||||
| 	cmdsocket_initialised = 1; | ||||
|     	cmd_bytes = 0; | ||||
|     	cmd_ignore = 0; | ||||
| 	cmd_prefix[0] = '\0'; | ||||
| 
 | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| void cmdsocket_close(void) | ||||
| { | ||||
| 	if (cmd_active) | ||||
| 		close(cmd_active); | ||||
| 	if (cmd_sock) | ||||
| 		close(cmd_sock); | ||||
| 	cmdsocket_initialised = 0; | ||||
| } | ||||
| 
 | ||||
| void cmdsocket_prefix(char *prefix) | ||||
| { | ||||
| 	if (!cmdsocket_initialised) | ||||
| 		return; | ||||
| 	if (strlen(prefix) >= PREFIX_MAXSIZE-1) | ||||
| 		return; | ||||
| 	strncpy(cmd_prefix, prefix, PREFIX_MAXSIZE); | ||||
| } | ||||
| 
 | ||||
| #define ERROR(x) do { warn((x)); goto error; } while (0) | ||||
| 
 | ||||
| #define BACKLOG 0 | ||||
| 
 | ||||
| int cmdsocket_listen(int port) { | ||||
| 	int sockopt_on = 1; | ||||
| 	struct sockaddr_in my_addr; | ||||
| 
 | ||||
| 	cmd_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); | ||||
| 	if (cmd_sock == -1) | ||||
| 		ERROR("can't open socket"); | ||||
| 	if (setsockopt(cmd_sock, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, | ||||
| 	    sizeof(int)) == -1) | ||||
| 		ERROR("can't set socket options"); | ||||
| 	memset((char *) &my_addr, 0, sizeof(my_addr)); | ||||
| 	my_addr.sin_family = PF_INET; | ||||
| 	my_addr.sin_port = htons(port); | ||||
| 	my_addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||||
| 	if (bind(cmd_sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1) | ||||
| 		ERROR("can't bind socket"); | ||||
| 	if (listen(cmd_sock, BACKLOG) == -1) | ||||
| 		ERROR("can't listen"); | ||||
| 	vm_register_signal_fd(cmd_sock, VM_CMDLISTENQ); | ||||
| 
 | ||||
| 	return 1; | ||||
| 
 | ||||
| error: | ||||
| 	if (cmd_sock) | ||||
| 	    close(cmd_sock); | ||||
| 	cmd_sock = 0; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int cmdsocket_accept(void) { | ||||
| 	struct sockaddr_in client_addr; | ||||
| 	socklen_t client_addr_size = sizeof(client_addr); | ||||
| 	int c; | ||||
| 
 | ||||
| 	if (!cmdsocket_initialised) | ||||
| 		return 0; | ||||
| 	if (cmd_sock == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* We only accept one active connection at a time */ | ||||
| 	/* XXX can't just return here */ | ||||
| 	if (cmd_active) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	c = accept(cmd_sock, (struct sockaddr *)&client_addr, | ||||
| 	    &client_addr_size); | ||||
| 	if (c == -1) { | ||||
| 		if (errno == EAGAIN) | ||||
| 			return 0; | ||||
| 		warn("Error accepting connection"); | ||||
| 		close(cmd_sock); | ||||
| 		cmd_sock = 0; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	cmd_active = c; | ||||
| 	write(cmd_active, CMDSOCKET_BANNER, sizeof(CMDSOCKET_BANNER)); | ||||
| 
 | ||||
| 	vm_register_signal_fd(cmd_active, VM_CMDREADQ); | ||||
| 	vm_wakeup(VM_CMDREADQ); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| void cmd_parse(char *cmd) { | ||||
| 	char *sp; | ||||
| 	int arg = 0; | ||||
| 	char function[CMD_MAXSIZE + PREFIX_MAXSIZE]; | ||||
| 
 | ||||
| 	*strchr(cmd, '\n') = '\0'; | ||||
| 	printf("DEBUG: Received command: %s\n", cmd); | ||||
| 	fflush(stdout); | ||||
| 
 | ||||
| 	sp = strtok(cmd, " \t\r"); | ||||
| 	sp = strtok(NULL, " \t\r"); | ||||
| 	if (sp) { | ||||
| 	    arg = atoi(sp); | ||||
| 	} | ||||
| 
 | ||||
| 	/* cmd_prefix is guaranteed to be terminated */ | ||||
| 	strcpy(function, cmd_prefix); | ||||
| 	strncat(function, cmd, CMD_MAXSIZE); | ||||
| 
 | ||||
| 	printf("DEBUG: function: %s, arg %d\n", function, arg); | ||||
| 	fflush(stdout); | ||||
| 	if (vm_spawn_args(function, 1, arg)) { | ||||
| 		/* Write an ack here, once a proper function exists */ | ||||
| 	} else { | ||||
| 		/* Write an error, if it's possible. Don't worry about
 | ||||
| 		   missing characters and buffering for now, but we | ||||
| 		   should eventually */ | ||||
| 		write(cmd_active, "ERROR\n", strlen("ERROR\n")); | ||||
| 	} | ||||
| 
 | ||||
| 	printf("Received command: %s\n", cmd); | ||||
| } | ||||
| 
 | ||||
| int cmdsocket_read(void) | ||||
| { | ||||
| 	if (!cmdsocket_initialised) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		int rv; | ||||
| 		int left = sizeof(cmd_buf) - cmd_bytes; | ||||
| 		char *p; | ||||
| 		if (!cmd_active) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		rv = recv(cmd_active, ((char *)&cmd_buf) + cmd_bytes, left, 0); | ||||
| 		if (rv == -1) { | ||||
| 			if (errno == EAGAIN) | ||||
| 				return 0; | ||||
| 			printf("Error reading from socket\n"); | ||||
| 			vm_unregister_signal_fd(cmd_active); | ||||
| 			close(cmd_active); | ||||
| 			cmd_active = 0; | ||||
| 			vm_wakeup(VM_CMDLISTENQ); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if (rv == 0) { | ||||
| 			vm_unregister_signal_fd(cmd_active); | ||||
| 			close(cmd_active); | ||||
| 			cmd_active = 0; | ||||
| 			vm_wakeup(VM_CMDLISTENQ); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		cmd_bytes += rv; | ||||
| 		if ((p = memchr(cmd_buf, '\n', cmd_bytes))) { | ||||
| 		    if (!cmd_ignore) | ||||
| 			cmd_parse(cmd_buf); | ||||
| 		    memmove(cmd_buf, p+1, cmd_bytes - (p - cmd_buf - 1)); | ||||
| 		    cmd_bytes = 0; | ||||
| 		    cmd_ignore = 0; | ||||
| 		} | ||||
| 		if (cmd_bytes == sizeof(cmd_buf)) { | ||||
| 			cmd_bytes = 0; | ||||
| 			cmd_ignore = 1; | ||||
| 			/* Overflow */ | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| /* cmdsocket.h */ | ||||
| 
 | ||||
| int cmdsocket_init(void); | ||||
| void cmdsocket_close(void); | ||||
| int cmdsocket_listen(int port); | ||||
| int cmdsocket_accept(void); | ||||
| int cmdsocket_read(void); | ||||
| int cmdsocket_prefix(char *); | ||||
					Loading…
					
					
				
		Reference in new issue