about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStephen Malina <stephenmalina@gmail.com>2016-09-18 05:05:19 -0700
committerStephen Malina <stephenmalina@gmail.com>2016-09-18 05:10:24 -0700
commit51ae6e61e2d14354e66b95cc028b8d1ebddfdc74 (patch)
treeab942d86a5b4967188c3ef44da6f7a30357a41a8
parentb28aae5740d3bd4fb4e33dd568c7eba6d4f6e7f8 (diff)
downloadmu-51ae6e61e2d14354e66b95cc028b8d1ebddfdc74.tar.gz
3399 - Update network primitives.
$write-to-socket, $read-from-socket, and $accept now pass around
references to socket pointers.

$read-from-socket handles EOF explicitly.
-rw-r--r--091socket.cc72
-rw-r--r--server-socket.mu24
2 files changed, 77 insertions, 19 deletions
diff --git a/091socket.cc b/091socket.cc
index 97f0a6c6..3ffca8f4 100644
--- a/091socket.cc
+++ b/091socket.cc
@@ -56,13 +56,14 @@ case _SOCKET: {
 :(before "End Primitive Recipe Implementations")
 case _SOCKET: {
   int port = ingredients.at(0).at(0);
-  socket_t server;
-  server_socket(port, &server);
-  if (server.fd < 0) {
+  socket_t* server = new socket_t();
+  server_socket(port, server);
+  if (server->fd < 0) {
     break;
   }
+  long long int result = reinterpret_cast<long long int>(server);
   products.resize(1);
-  products.at(0).push_back(server.fd);
+  products.at(0).push_back(static_cast<double>(result));
   break;
 }
 
@@ -97,11 +98,14 @@ case _ACCEPT: {
 }
 :(before "End Primitive Recipe Implementations")
 case _ACCEPT: {
-  double socket_fd = ingredients.at(0).at(0);
-  socket_t session;
-  session_socket(socket_fd, &session);
-  products.resize(1);
-  products.at(0).push_back(session.fd);
+  long long int x = static_cast<long long int>(ingredients.at(0).at(0));
+  socket_t* socket = reinterpret_cast<socket_t*>(x);
+  socket_t* session = new socket_t();
+  session_socket(socket->fd, session);
+  products.resize(2);
+  long long int result = reinterpret_cast<long long int>(session);
+  products.at(0).push_back(static_cast<double>(result));
+  products.at(1).push_back(ingredients.at(0).at(0));
   break;
 }
 
@@ -119,7 +123,7 @@ case _READ_FROM_SOCKET: {
     raise << maybe(get(Recipe, r).name) << "first ingredient of '$read-from-socket' should be a number, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end();
     break;
   }
-  if (SIZE(inst.products) != 1) {
+  if (SIZE(inst.products) != 2) {
     raise << maybe(get(Recipe, r).name) << "'$read-from-socket' requires exactly one product, but got '" << inst.original_string << "'\n" << end();
     break;
   }
@@ -127,21 +131,57 @@ case _READ_FROM_SOCKET: {
     raise << maybe(get(Recipe, r).name) << "first product of '$read-from-socket' should be a character, but got '" << to_string(inst.products.at(0)) << "'\n" << end();
     break;
   }
+  if (!is_mu_boolean(inst.products.at(1))) {
+    raise << maybe(get(Recipe, r).name) << "second product of '$read-from-socket' should be a boolean but got '" << to_string(inst.products.at(1)) << "'\n" << end();
+    break;
+  }
   break;
 }
 :(before "End Primitive Recipe Implementations")
 case _READ_FROM_SOCKET: {
-  products.resize(1);
-  double socket_fd = ingredients.at(0).at(0);
+  long long int x = static_cast<long long int>(ingredients.at(0).at(0));
+  socket_t* socket = reinterpret_cast<socket_t*>(x);
+  int socket_fd = socket->fd;
   char single_char[2];
   bzero(single_char, 2);
-  if (read(socket_fd, single_char, 1) < 0) {
-    raise << maybe(current_recipe_name()) << "read from socket failed\n" << end();
-    products.at(0).push_back(0);
-    break;
+  int bytes_read = read(socket_fd, single_char, 1);
+  products.resize(2);
+  if (single_char[0]== EOF || bytes_read == 0) {
+    products.at(1).push_back(1);  // eof
+  }
+  else {
+    products.at(1).push_back(0);
   }
   products.at(0).push_back(single_char[0]);
   break;
+  break;
+}
+
+:(before "End Primitive Recipe Declarations")
+_WRITE_TO_SOCKET,
+:(before "End Primitive Recipe Numbers")
+put(Recipe_ordinal, "$write-to-socket", _WRITE_TO_SOCKET);
+:(before "End Primitive Recipe Checks")
+case _WRITE_TO_SOCKET: {
+  if (SIZE(inst.ingredients) != 2) {
+    raise << maybe(get(Recipe, r).name) << "'$write-to-socket' requires exactly two ingredient, but got '" << inst.original_string << "'\n" << end();
+    break;
+  }
+  break;
+}
+:(before "End Primitive Recipe Implementations")
+case _WRITE_TO_SOCKET: {
+  long long int x = static_cast<long long int>(ingredients.at(0).at(0));
+  socket_t* session = reinterpret_cast<socket_t*>(x);
+  // Write one character to a session at a time.
+  long long int y = static_cast<long long int>(ingredients.at(1).at(0));
+  char c = static_cast<char>(y);
+  char payload[2] = { c };
+  write(session->fd, payload, 1);
+  long long int result = reinterpret_cast<long long int>(session);
+  products.resize(1);
+  products.at(0).push_back(result);
+  break;
 }
 
 :(before "End Primitive Recipe Declarations")
diff --git a/server-socket.mu b/server-socket.mu
index d7be418e..dbdf1ef7 100644
--- a/server-socket.mu
+++ b/server-socket.mu
@@ -3,12 +3,30 @@ def main [
   socket:num <- $socket 8080/port
   $print [Mu socket creation returned ], socket, 10/newline
   session:num <- $accept socket
+  write-to-socket session, [HTTP/1.0 200 OK
+
+OK]
   {
-    client-message:&:buffer <- new-buffer 1024
-    c:char <- $read-from-socket session
-    break-unless c
+    c:char, eof?:boolean <- $read-from-socket session
     $print c
+    break-if eof?
     loop
   }
+  $print 10/newline, [Hit end of socket, closing...], 10/newline
   $close-socket socket, session
 ]
+
+def write-to-socket session-socket:number, s:address:array:character [
+  local-scope
+  load-ingredients
+  len:number <- length *s
+  i:number <- copy 0
+  {
+    done?:boolean <- greater-or-equal i, len
+    break-if done?
+    c:character <- index *s, i
+    $write-to-socket session-socket, c
+    i <- add i, 1
+    loop
+  }
+]