From 51ae6e61e2d14354e66b95cc028b8d1ebddfdc74 Mon Sep 17 00:00:00 2001 From: Stephen Malina Date: Sun, 18 Sep 2016 05:05:19 -0700 Subject: 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. --- 091socket.cc | 72 +++++++++++++++++++++++++++++++++++++++++++------------- server-socket.mu | 24 ++++++++++++++++--- 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(server); products.resize(1); - products.at(0).push_back(server.fd); + products.at(0).push_back(static_cast(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(ingredients.at(0).at(0)); + socket_t* socket = reinterpret_cast(x); + socket_t* session = new socket_t(); + session_socket(socket->fd, session); + products.resize(2); + long long int result = reinterpret_cast(session); + products.at(0).push_back(static_cast(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(ingredients.at(0).at(0)); + socket_t* socket = reinterpret_cast(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(ingredients.at(0).at(0)); + socket_t* session = reinterpret_cast(x); + // Write one character to a session at a time. + long long int y = static_cast(ingredients.at(1).at(0)); + char c = static_cast(y); + char payload[2] = { c }; + write(session->fd, payload, 1); + long long int result = reinterpret_cast(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 + } +] -- cgit 1.4.1-2-gfad0