00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <unistd.h>
00014 #include <fcntl.h>
00015 #include <sys/types.h>
00016 #if defined(__MINGW__) || defined(__MINGW32__)
00017 # include <winsock.h>
00018 # undef ERROR
00019 #else
00020 # include <sys/wait.h>
00021 # include <netinet/in.h>
00022 # include <netdb.h>
00023 # include <arpa/inet.h>
00024 #endif
00025 #include <basix/posix_port.hpp>
00026
00028
00029 namespace mmx {
00030
00031
00032
00033
00034
00035 class socket_port_rep: public posix_port_rep {
00036 string host;
00037 int pnr;
00038 int role;
00039
00040 public:
00041 syntactic expression () const {
00042 if (role == 0)
00043 return syn ("socket_server_port", syntactic (host), syntactic (pnr));
00044 else if (role == 1)
00045 return syn ("socket_accept_port", syntactic (host), syntactic (pnr));
00046 else
00047 return syn ("socket_client_port", syntactic (host), syntactic (pnr));
00048 }
00049
00050 void send (const char* s, nat len) {
00051 if (this->alive) {
00052 nat total= 0;
00053 nat bytes_left= len;
00054 nat n= 0;
00055 while (total < len) {
00056 n= ::send (this->fd, s+total, bytes_left, 0);
00057 if (n == ((nat) -1)) break;
00058 total += n;
00059 bytes_left -= n;
00060 }
00061 }
00062 }
00063
00064 void feed () {
00065 if (this->pos > ((N(this->buffer) >> 1) + 1024)) {
00066 this->buffer= this->buffer (this->pos, N(this->buffer));
00067 this->pos= 0;
00068 }
00069 while (this->alive && wait (0)) {
00070 char tempout[1024];
00071 int r= recv (this->fd, tempout, 1024, 0);
00072 if (r <= 0) { this->alive= false; break; }
00073 else this->buffer << string (tempout, r);
00074 }
00075 }
00076
00077 port accept ();
00078
00079 public:
00080 inline socket_port_rep (const string& host2, int pnr2, int role2, int fd):
00081 posix_port_rep (3, fd),
00082 host (host2), pnr (pnr2), role (role2) {}
00083 inline ~socket_port_rep () {
00084 close (this->fd); }
00085 };
00086
00087 port
00088 socket_port (const string& host, int pnr, int role, int fd) {
00089 return (port_rep*) new socket_port_rep (host, pnr, role, fd);
00090 }
00091
00092
00093
00094
00095
00096 port
00097 socket_server_port (const string& host, int pnr) {
00098
00099 int fd;
00100 if ((fd = socket (PF_INET, SOCK_STREAM, 0)) == -1)
00101 return error_port ("call to 'socket' failed");
00102
00103
00104 #if defined(__MINGW__) || defined(__MINGW32__)
00105 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, NULL, 0) == -1)
00106 return error_port ("call to 'setsockopt' failed");
00107 #else
00108 int yes= 1;
00109 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
00110 &yes, sizeof (int)) == -1)
00111 return error_port ("call to 'setsockopt' failed");
00112 #endif
00113
00114
00115 struct sockaddr_in local_address;
00116 local_address.sin_family = AF_INET;
00117 local_address.sin_addr.s_addr = INADDR_ANY;
00118 local_address.sin_port = htons (pnr);
00119 memset (local_address.sin_zero, '\0', sizeof local_address.sin_zero);
00120 if (bind (fd, (struct sockaddr *) &local_address,
00121 sizeof (local_address)) == -1)
00122 return error_port ("call to 'bind' failed");
00123
00124
00125 if (::listen (fd, 10) == -1)
00126 return error_port ("call to 'listen' failed");
00127 return socket_port (host, pnr, 0, fd);
00128 }
00129
00130
00131
00132
00133
00134 port
00135 socket_port_rep::accept () {
00136 ASSERT (role == 0, "socket server port expected");
00137 if (!this->alive || !wait (0)) return error_port ("no incoming connection");
00138 struct sockaddr_in remote_address;
00139 #if defined(__MINGW__) || defined(__MINGW32__)
00140 int addrlen= sizeof (remote_address);
00141 #else
00142 socklen_t addrlen= sizeof (remote_address);
00143 #endif
00144 int client=
00145 ::accept (this->fd, (struct sockaddr *) &remote_address, &addrlen);
00146 if (client == -1)
00147 return error_port ("Call to 'accept' failed");
00148 else {
00149 string addr= inet_ntoa (remote_address.sin_addr);
00150 return socket_port (host, pnr, 1, client);
00151 }
00152 }
00153
00154
00155
00156
00157
00158 port
00159 socket_client_port (const string& host, int pnr) {
00160
00161 char* _host= as_charp (host);
00162 struct hostent *hp = gethostbyname (_host);
00163 free_charp (_host);
00164 if (hp == NULL) return error_port ("no connection for '" * host * "'");
00165
00166
00167 int fd= socket (AF_INET, SOCK_STREAM, 0);
00168 if (fd < 0) return error_port ("socket could not be created");
00169
00170
00171 struct sockaddr_in insock;
00172 string where= host * ":" * as_string (pnr);
00173 memset ((char*) &insock, 0, sizeof (insock));
00174 insock.sin_family = AF_INET;
00175 insock.sin_port = htons ((unsigned short) pnr);
00176 memcpy ((char*) &insock.sin_addr, hp->h_addr, hp->h_length);
00177 if (connect (fd, (struct sockaddr*) &insock, sizeof (insock)) < 0)
00178 return error_port ("refused connection to '" * where * "'");
00179
00180
00181 #if defined(__MINGW__) || defined(__MINGW32__)
00182 unsigned long flags = -1;
00183 if (ioctlsocket (fd, FIONBIO, &flags) == SOCKET_ERROR)
00184 return error_port ("non working connection to '" * where * "'");
00185 #else
00186 int flags = O_NONBLOCK;
00187 if (fcntl (fd, F_SETFL, flags) < 0)
00188 return error_port ("non working connection to '" * where * "'");
00189 #endif
00190 return socket_port (host, pnr, 2, fd);
00191 }
00192
00193 }