X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=testing%2Fweb2io%2Fnetwork.c;fp=testing%2Fweb2io%2Fnetwork.c;h=1a1b8620cde1164918076ac6831ee55bc6718c31;hb=64b0cd994eea9ee7e95bcd1a1d6dc06d84b83b84;hp=0000000000000000000000000000000000000000;hpb=00d35586e8c044ae64e14d1b39a03ec0371929d9;p=matches%2FMCTX3420.git diff --git a/testing/web2io/network.c b/testing/web2io/network.c new file mode 100644 index 0000000..1a1b862 --- /dev/null +++ b/testing/web2io/network.c @@ -0,0 +1,174 @@ +#include "network.h" +#include +#include +#include +#include "log.h" + +#define h_addr h_addr_list[0] + + + + + +int Network_get_port(int sfd) +{ + static struct sockaddr_in sin; + static socklen_t len = sizeof(struct sockaddr_in); + + if (getsockname(sfd, (struct sockaddr *)&sin, &len) != 0) + error("Network_port", "getsockname : %s", strerror(errno)); + return ntohs(sin.sin_port); +} + +int Network_server_bind(int port, int * bound) +{ + int sfd = socket(PF_INET, SOCK_STREAM, 0); + if (sfd < 0) + { + error("Network_server", "Creating socket on port %d : %s", port, strerror(errno)); + } + + struct sockaddr_in name; + + name.sin_family = AF_INET; + name.sin_addr.s_addr = htonl(INADDR_ANY); + name.sin_port = htons(port); + + if (bind( sfd, (struct sockaddr *) &name, sizeof(name) ) < 0) + { + error("Network_server", "Binding socket on port %d : %s", port, strerror(errno)); + } + + if (bound != NULL) + *bound = Network_get_port(sfd); + return sfd; +} + +int Network_server_listen(int sfd, char * addr) +{ + int port = Network_get_port(sfd); + if (listen(sfd, 1) < 0) + { + error("Network_server", "Listening on port %d : %s", port, strerror(errno)); + } + + int psd; + if (addr == NULL) + psd = accept(sfd, 0, 0); + else + { + struct sockaddr_in client; + struct hostent *hp; + + client.sin_family = AF_INET; + hp = gethostbyname(addr); + bcopy ( hp->h_addr, &(client.sin_addr.s_addr), hp->h_length); + client.sin_port = htons(port); + socklen_t len = sizeof(client); + + psd = accept(sfd, (struct sockaddr*)&client, &len); + } + //close(sfd); // don't close the bind socket here; we might want to reuse the port + assert(psd >= 0); + return psd; +} + +int Network_server(char * addr, int port) +{ + int bind = Network_server_bind(port, &port); + int sfd = Network_server_listen(bind, addr); + close(bind); // won't be able to reuse the port (it goes into TIME_WAIT) + return sfd; +} + +int Network_client(const char * addr, int port, int timeout) +{ + int sfd = socket(PF_INET, SOCK_STREAM, 0); + + //log_print(2, "Network_client", "Created socket"); + long arg = fcntl(sfd, F_GETFL, NULL); + arg |= O_NONBLOCK; + fcntl(sfd, F_SETFL, arg); + + if (sfd < 0) + { + error("Network_client", "Creating socket for address %s:%d : %s", addr, port, strerror(errno)); + } + struct sockaddr_in server; + struct hostent *hp; + + + server.sin_family = AF_INET; + hp = gethostbyname(addr); + if (hp == NULL) + { + error("Network_client", "Can't get host by name %s", addr); + } + bcopy ( hp->h_addr, &(server.sin_addr.s_addr), hp->h_length); + server.sin_port = htons(port); + + + int res = connect(sfd, (struct sockaddr *) &server, sizeof(server)); + + + if (res < 0 && errno == EINPROGRESS) + { + + fd_set writeSet; + FD_ZERO(&writeSet); + FD_SET(sfd, &writeSet); + + struct timeval tv; + tv.tv_sec = timeout; + tv.tv_usec = 0; + + struct timeval * tp; + tp = (timeout < 0) ? NULL : &tv; + + int err = select(sfd+1, NULL, &writeSet, NULL, tp); + + if (err == 0) + { + error("Network_client", "Timed out trying to connect to %s:%d after %d seconds", addr, port, timeout); + } + else if (err < 0) + { + error("Network_client", "Connecting to %s:%d - Error in select(2) call : %s", addr, port, strerror(errno)); + } + else if (FD_ISSET(sfd, &writeSet)) + { + int so_error; + socklen_t len = sizeof so_error; + getsockopt(sfd, SOL_SOCKET, SO_ERROR, &so_error, &len); + if (so_error != 0) + { + error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(so_error)); + } + } + else + { + error("Network_client", "select(2) returned %d but the socket is not writable!?", err); + } + } + else + { + error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(errno)); + } + + arg = fcntl(sfd, F_GETFL, NULL); + arg &= (~O_NONBLOCK); + fcntl(sfd, F_SETFL, arg); + + + + return sfd; +} + +void Network_close(int sfd) +{ + if (shutdown(sfd, 2) != 0) + { + error("Network_close", "Closing socket : %s", strerror(errno)); + } + close(sfd); +}