diff options
-rw-r--r-- | README | 33 | ||||
-rw-r--r-- | src/portal.cc | 255 | ||||
-rw-r--r-- | src/portal.hh | 57 |
3 files changed, 105 insertions, 240 deletions
@@ -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; |