~crc_/retroforth

15c2e8374513a8fe01a6574fd035e1672f3a8405 — crc 6 months ago 68f2fa9
nga-c: move socket device to separate source file

FossilOrigin-Name: 3a79e0050856cb1ae77c789f2ab302e13e465bce20f617982037fd9cc369d172
2 files changed, 147 insertions(+), 126 deletions(-)

A vm/nga-c/dev-sockets.c
M vm/nga-c/retro.c
A vm/nga-c/dev-sockets.c => vm/nga-c/dev-sockets.c +146 -0
@@ 0,0 1,146 @@
/*---------------------------------------------------------------------
  Copyright (c) 2008 - 2022, Charles Childers

  Portions are based on Ngaro, which was additionally copyright
  by the following:

  Copyright (c) 2009 - 2010, Luke Parrish
  Copyright (c) 2010,        Marc Simpson
  Copyright (c) 2010,        Jay Skeer
  Copyright (c) 2011,        Kenneth Keating
  ---------------------------------------------------------------------*/
#ifdef ENABLE_SOCKETS

#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

/*---------------------------------------------------------------------
  BSD Sockets
  ---------------------------------------------------------------------*/

int SocketID[16];
struct sockaddr_in Sockets[16];

struct addrinfo hints, *res;

void socket_getaddrinfo(NgaState *vm) {
  char host[1025], port[6];
  strlcpy(port, string_extract(vm, stack_pop(vm)), 5);
  strlcpy(host, string_extract(vm, stack_pop(vm)), 1024);
  getaddrinfo(host, port, &hints, &res);
}

void socket_get_host(NgaState *vm) {
  struct hostent *hp;
  struct in_addr **addr_list;

  hp = gethostbyname(string_extract(vm, stack_pop(vm)));
  if (hp == NULL) {
    vm->memory[stack_pop(vm)] = 0;
    return;
  }

  addr_list = (struct in_addr **)hp->h_addr_list;
  string_inject(vm, inet_ntoa(*addr_list[0]), stack_pop(vm));
}

void socket_create(NgaState *vm) {
  int i;
  int sock = socket(PF_INET, SOCK_STREAM, 0);
  for (i = 0; i < 16; i++) {
    if (SocketID[i] == 0 && sock != 0) {
      SocketID[i] = sock;
      stack_push(vm, (CELL)i);
      sock = 0;
    }
  }
}

void socket_bind(NgaState *vm) {
  int sock, port;
  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  sock = stack_pop(vm);
  port = stack_pop(vm);

  getaddrinfo(NULL, string_extract(vm, port), &hints, &res);
  stack_push(vm, (CELL) bind(SocketID[sock], res->ai_addr, res->ai_addrlen));
  stack_push(vm, errno);
}

void socket_listen(NgaState *vm) {
  int sock = stack_pop(vm);
  int backlog = stack_pop(vm);
  stack_push(vm, listen(SocketID[sock], backlog));
  stack_push(vm, errno);
}

void socket_accept(NgaState *vm) {
  int i;
  int sock = stack_pop(vm);
  struct sockaddr_storage their_addr;
  socklen_t addr_size = sizeof their_addr;
  int new_fd = accept(SocketID[sock], (struct sockaddr *)&their_addr, &addr_size);

  for (i = 0; i < 16; i++) {
    if (SocketID[i] == 0 && new_fd != 0) {
      SocketID[i] = new_fd;
      stack_push(vm, (CELL)i);
      new_fd = 0;
    }
  }
  stack_push(vm, errno);
}

void socket_connect(NgaState *vm) {
  stack_push(vm, (CELL)connect(SocketID[stack_pop(vm)], res->ai_addr, res->ai_addrlen));
  stack_push(vm, errno);
}

void socket_send(NgaState *vm) {
  int sock = stack_pop(vm);
  char *buf = string_extract(vm, stack_pop(vm));
  stack_push(vm, send(SocketID[sock], buf, strlen(buf), 0));
  stack_push(vm, errno);
}

void socket_recv(NgaState *vm) {
  char buf[8193];
  int sock = stack_pop(vm);
  int limit = stack_pop(vm);
  int dest = stack_pop(vm);
  int len = recv(SocketID[sock], buf, limit, 0);
  if (len > 0)  buf[len] = '\0';
  if (len > 0)  string_inject(vm, buf, dest);
  stack_push(vm, len);
  stack_push(vm, errno);
}

void socket_close(NgaState *vm) {
  int sock = stack_pop(vm);
  close(SocketID[sock]);
  SocketID[sock] = 0;
}

Handler SocketActions[] = {
  socket_get_host,
  socket_create, socket_bind,    socket_listen,
  socket_accept, socket_connect, socket_send,
  socket_recv,   socket_close,   socket_getaddrinfo
};

void io_socket(NgaState *vm) {
  SocketActions[stack_pop(vm)](vm);
}

void query_socket(NgaState *vm) {
  stack_push(vm, 0);
  stack_push(vm, 7);
}

#endif

M vm/nga-c/retro.c => vm/nga-c/retro.c +1 -126
@@ 1285,132 1285,7 @@ void query_rng(NgaState *vm) {


#ifdef ENABLE_SOCKETS
/*---------------------------------------------------------------------
  BSD Sockets
  ---------------------------------------------------------------------*/

int SocketID[16];
struct sockaddr_in Sockets[16];

struct addrinfo hints, *res;

void socket_getaddrinfo(NgaState *vm) {
  char host[1025], port[6];
  strlcpy(port, string_extract(vm, stack_pop(vm)), 5);
  strlcpy(host, string_extract(vm, stack_pop(vm)), 1024);
  getaddrinfo(host, port, &hints, &res);
}

void socket_get_host(NgaState *vm) {
  struct hostent *hp;
  struct in_addr **addr_list;

  hp = gethostbyname(string_extract(vm, stack_pop(vm)));
  if (hp == NULL) {
    vm->memory[stack_pop(vm)] = 0;
    return;
  }

  addr_list = (struct in_addr **)hp->h_addr_list;
  string_inject(vm, inet_ntoa(*addr_list[0]), stack_pop(vm));
}

void socket_create(NgaState *vm) {
  int i;
  int sock = socket(PF_INET, SOCK_STREAM, 0);
  for (i = 0; i < 16; i++) {
    if (SocketID[i] == 0 && sock != 0) {
      SocketID[i] = sock;
      stack_push(vm, (CELL)i);
      sock = 0;
    }
  }
}

void socket_bind(NgaState *vm) {
  int sock, port;
  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  sock = stack_pop(vm);
  port = stack_pop(vm);

  getaddrinfo(NULL, string_extract(vm, port), &hints, &res);
  stack_push(vm, (CELL) bind(SocketID[sock], res->ai_addr, res->ai_addrlen));
  stack_push(vm, errno);
}

void socket_listen(NgaState *vm) {
  int sock = stack_pop(vm);
  int backlog = stack_pop(vm);
  stack_push(vm, listen(SocketID[sock], backlog));
  stack_push(vm, errno);
}

void socket_accept(NgaState *vm) {
  int i;
  int sock = stack_pop(vm);
  struct sockaddr_storage their_addr;
  socklen_t addr_size = sizeof their_addr;
  int new_fd = accept(SocketID[sock], (struct sockaddr *)&their_addr, &addr_size);

  for (i = 0; i < 16; i++) {
    if (SocketID[i] == 0 && new_fd != 0) {
      SocketID[i] = new_fd;
      stack_push(vm, (CELL)i);
      new_fd = 0;
    }
  }
  stack_push(vm, errno);
}

void socket_connect(NgaState *vm) {
  stack_push(vm, (CELL)connect(SocketID[stack_pop(vm)], res->ai_addr, res->ai_addrlen));
  stack_push(vm, errno);
}

void socket_send(NgaState *vm) {
  int sock = stack_pop(vm);
  char *buf = string_extract(vm, stack_pop(vm));
  stack_push(vm, send(SocketID[sock], buf, strlen(buf), 0));
  stack_push(vm, errno);
}

void socket_recv(NgaState *vm) {
  char buf[8193];
  int sock = stack_pop(vm);
  int limit = stack_pop(vm);
  int dest = stack_pop(vm);
  int len = recv(SocketID[sock], buf, limit, 0);
  if (len > 0)  buf[len] = '\0';
  if (len > 0)  string_inject(vm, buf, dest);
  stack_push(vm, len);
  stack_push(vm, errno);
}

void socket_close(NgaState *vm) {
  int sock = stack_pop(vm);
  close(SocketID[sock]);
  SocketID[sock] = 0;
}

Handler SocketActions[] = {
  socket_get_host,
  socket_create, socket_bind,    socket_listen,
  socket_accept, socket_connect, socket_send,
  socket_recv,   socket_close,   socket_getaddrinfo
};

void io_socket(NgaState *vm) {
  SocketActions[stack_pop(vm)](vm);
}

void query_socket(NgaState *vm) {
  stack_push(vm, 0);
  stack_push(vm, 7);
}
#include "dev-sockets.c"
#endif