aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README33
-rw-r--r--src/portal.cc255
-rw-r--r--src/portal.hh57
3 files changed, 105 insertions, 240 deletions
diff --git a/README b/README
index 3c017d2..7225e3c 100644
--- a/README
+++ b/README
@@ -44,41 +44,8 @@ implement reductions
implement missing data types
output only if value has changed
-put stuff into namespace
- (move from C to C++?)
rename "file", "storage" do something more unique
update the source tarballs not only when the thorn library changes,
but also when a *.ccl or make.* file changes.
do not necessarily update them all when the bindings change.
-
-
-
-Here is a suggestion for handling sockets in perl.
-This is from "http://www.infocopter.com/perl/socket-server.htm".
-
-#!/usr/bin/perl -w
-use strict;
-################################################
-# Socket Client
-# (c) retoh :)
-################################################
-use Socket;
-
-my $host = 'localhost';
-my $port = 7890;
-
-my $proto = getprotobyname('tcp');
-socket(my $FS, PF_INET, SOCK_STREAM, $proto);
-my $sin = sockaddr_in($port, inet_aton($host));
-connect($FS, $sin) || exit -1;
-
-my $old_fh = select($FS); $| = 1; select($old_fh);
-
-print $FS "Hello at ", scalar localtime(), "\n\n";
-
-while(<$FS>) {
- print;
-}
-
-close $FS;
diff --git a/src/portal.cc b/src/portal.cc
index 6bdb7a0..8ade326 100644
--- a/src/portal.cc
+++ b/src/portal.cc
@@ -3,7 +3,9 @@
#include <cassert>
#include <cerrno>
#include <cstdio>
+#include <cstdlib>
#include <cstring>
+#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
@@ -16,12 +18,6 @@
-#ifndef MSG_NOSIGNAL
-# define MSG_NOSIGNAL 0
-#endif
-
-
-
namespace Formaline
{
@@ -32,55 +28,10 @@ namespace Formaline
portal::
portal (char const * const id,
enum state const st)
- : storage (st),
- errorcount (0)
+ : storage (st)
{
DECLARE_CCTK_PARAMETERS;
-
- sock = socket (PF_INET, SOCK_STREAM, 0);
- if (sock < 0)
- {
- CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
- "%s", strerror (errno));
- }
-
- struct hostent * hostinfo;
- hostinfo = gethostbyname (portal_hostname);
- if (hostinfo == 0)
- {
- switch (h_errno)
- {
- case HOST_NOT_FOUND:
- CCTK_WARN (1, "The specified host is unknown.");
- break;
- case NO_ADDRESS:
- // case NO_DATA:
- CCTK_WARN (1, "The requested name is valid but does not have an IP address.");
- break;
- case NO_RECOVERY:
- CCTK_WARN (1, "A non-recoverable name server error occurred.");
- break;
- case TRY_AGAIN:
- CCTK_WARN (1, "A temporary error occurred on an authoritative name server. Try again later.");
- break;
- default:
- CCTK_WARN (1, "unknown error");
- }
- }
-
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons (portal_port);
- addr.sin_addr = * (struct in_addr *) hostinfo->h_addr;
-
- int const ierr
- = connect (sock, (struct sockaddr const *) (& addr), sizeof addr);
- if (ierr < 0)
- {
- CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
- "%s", strerror (errno));
- }
-
+
msgbuf << "<?xml version='1.0' ?>"
<< "<methodCall><methodName>";
switch (get_state())
@@ -110,20 +61,107 @@ namespace Formaline
portal::
~ portal ()
{
+ DECLARE_CCTK_PARAMETERS;
+
+ string const socket_script = "socket-client.pl";
+ string const socket_data = "socket-data";
+
+
+
+ // Write the data
msgbuf << "</struct></value></param></params>";
msgbuf << "</methodCall>";
string const msgstr = msgbuf.str();
-
- ostringstream buf;
- buf << "POST HTTP/1.0 200\r\n"
- << "Content-Type: text/xml\r\n"
- << "Content-Length: " << msgstr.length() << "\r\n"
- << "\r\n"
- << msgstr << "\r\n"
- << "\r\n";
- write (buf.str());
-
- CLOSESOCKET (sock);
+
+ ostringstream databuf;
+ databuf << "POST HTTP/1.0 200\r\n"
+ << "Content-Type: text/xml\r\n"
+ << "Content-Length: " << msgstr.length() << "\r\n"
+ << "\r\n"
+ << msgstr
+ << "\r\n"
+ << "\r\n";
+ string const datastr = databuf.str();
+
+ ostringstream datafilenamebuf;
+ datafilenamebuf << out_dir << "/" << socket_data;
+ string const datafilenamestr = datafilenamebuf.str();
+ char const * const datafilename = datafilenamestr.c_str();
+
+ ofstream datafile;
+ datafile.open (datafilename, ios::out);
+ datafile << datastr;
+ datafile.close ();
+
+
+
+ // Write the script
+ ostringstream scriptbuf;
+ scriptbuf
+<< "#! /usr/bin/perl -w" << endl
+<< endl
+<< "use strict;" << endl
+<< "use Socket;" << endl
+<< endl
+<< "my $input = '" << datafilename << "';" << endl
+<< "my $host = '" << portal_hostname << "';" << endl
+<< "my $port = '" << portal_port << "';" << endl
+<< endl
+<< "open (my $FH, '<' . $input);" << endl
+<< endl
+<< "socket (my $SH, PF_INET, SOCK_STREAM, getprotobyname ('tcp'));" << endl
+<< "my $sin = sockaddr_in ($port, inet_aton ($host));" << endl
+<< "connect ($SH, $sin) || exit -1;" << endl
+<< endl
+<< "while (my $line = <$FH>)" << endl
+<< "{" << endl
+<< " print $SH $line;" << endl
+<< "}" << endl
+<< endl
+<< "close $SH;" << endl;
+ string const scriptstr = scriptbuf.str();
+
+ ostringstream scriptfilenamebuf;
+ scriptfilenamebuf << out_dir << "/" << socket_script;
+ string const scriptfilenamestr = scriptfilenamebuf.str();
+ char const * const scriptfilename = scriptfilenamestr.c_str();
+
+ ofstream scriptfile;
+ scriptfile.open (scriptfilename, ios::out);
+ scriptfile << scriptstr;
+ scriptfile.close ();
+
+
+
+ // Make the script executable
+ ostringstream chmodbuf;
+ chmodbuf << "chmod a+x '" << scriptfilenamestr << "'"
+ << " < /dev/null > /dev/null 2> /dev/null";
+ string const chmodstr = chmodbuf.str();
+ char const * const chmod = chmodstr.c_str();
+ system (chmod);
+
+
+
+ // Send the data
+ ostringstream cmdbuf;
+ cmdbuf << scriptfilenamestr << " < /dev/null > /dev/null 2> /dev/null";
+ string const cmdstr = cmdbuf.str();
+ char const * const cmd = cmdstr.c_str();
+
+ int const ierr = system (cmd);
+ if (ierr != 0)
+ {
+ static bool did_complain = false;
+ if (! did_complain)
+ {
+ CCTK_WARN (1, "Failed to send data to the portal");
+ did_complain = true;
+ }
+ }
+
+ remove (datafilename);
+ remove (scriptfilename);
}
@@ -204,95 +242,6 @@ namespace Formaline
- void portal::
- write (string const & msg0)
- {
- // cout << "[" << msg0 << "]" << endl;
- string msg = msg0;
- for (;;)
- {
-
- char const * const cmsg = msg.c_str();
- size_t const len = msg.length();
-
- // TODO: Make sure that we don't wait forever here. Maybe use
- // MSG_DONTWAIT.
- ssize_t const nelems = send (sock, cmsg, len, MSG_NOSIGNAL);
- if (nelems < 0)
- {
-#ifdef EMSGSIZE
- if (nelems == EMSGSIZE)
- {
- // The socket type requires that message be sent atomically,
- // and the size of the message to be sent made this
- // impossible.
- // Try to send the message as two smaller messages.
- if (len > 0)
- {
- string const msg1 = msg.substr (0, len/2);
- string const msg2 = msg.substr (len/2);
- write (msg1);
- write (msg2);
- }
- else
- {
- // There is a limit. In order to not be too inefficient,
- // just do nothing if even small messages cannot be sent.
- }
- }
- else
-#endif
- {
- int const maxerrors = 10;
- ++ errorcount;
- if (errorcount <= maxerrors)
- {
- CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
- "%s", strerror (errno));
- if (errorcount == maxerrors)
- {
- CCTK_WARN (1, "Too many errors. Suppressing further error messages.");
- }
- }
- }
- return;
- }
-
- if (nelems == len) return;
-
- // Wait until can write
- fd_set fds;
- FD_ZERO (& fds);
- assert (sock >= 0 and sock < FD_SETSIZE);
- FD_SET (sock, & fds);
- struct timeval timeout;
- timeout.tv_sec = 10; // wait no more than ten seconds
- timeout.tv_usec = 0;
- // TODO: Make sure that we don't wait forever here.
- int const icnt = select (FD_SETSIZE, 0, & fds, 0, & timeout);
- if (icnt == 0)
- {
- // There was a timeout
- CCTK_WARN (1, "Timeout: could not send message");
- return;
- }
- else if (icnt < 0)
- {
- // There was an error
- CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
- "%s", strerror (errno));
- return;
- }
-
- // Remove the characters that have been sent
- assert (nelems < len);
- msg = msg.substr (nelems);
-
- }
- }
-
-
-
string portal::
clean (string const & txt)
const
diff --git a/src/portal.hh b/src/portal.hh
index c6237a7..a91fa6d 100644
--- a/src/portal.hh
+++ b/src/portal.hh
@@ -3,53 +3,9 @@
#ifndef FORMALINE_PORTAL_HH
#define FORMALINE_PORTAL_HH
-
-
#include <sstream>
#include <string>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-#ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-#endif
-#include <errno.h>
-
-#ifndef SOCKET
-# define SOCKET int
-#endif
-
-#ifdef SOCKET_ERROR
-# define ERROR_CHECK(a) ((a) == SOCKET_ERROR)
-#else
-# define ERROR_CHECK(a) ((a) < 0)
-#endif
-
-#ifdef HAVE_WINSOCK2_H
-# define CLOSESOCKET(a) closesocket(a)
-#else
-# define CLOSESOCKET(a) close(a)
-#endif
-
#include "storage.hh"
@@ -61,13 +17,9 @@ namespace Formaline
class portal : public storage
{
-
- SOCKET sock;
-
+
std::ostringstream msgbuf;
-
- int errorcount;
-
+
public:
portal (char const * id,
@@ -93,10 +45,7 @@ namespace Formaline
char const * value);
private:
-
- void
- write (std::string const & msg);
-
+
std::string
clean (std::string const & txt)
const;