Gavan Fantom
17 years ago
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