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