#include "msg.h" #include #include #include #include #include #include #include #include struct connection_t { int s; }; int send_message(struct connection_t *c, int i_len, int *i_msg) { char *msg = (char *)i_msg; int len = i_len * sizeof(int), part_len; int offset = 0; int r; part_len = len; while (offset < len) { r = send(c->s, msg + offset, part_len, 0); if (r < 0) { if (r == EINTR) { /* try again */ } else if (r == EMSGSIZE) { /* try smaller piece */ part_len /= 2; if (!part_len) part_len = 1; } else { fprintf(stderr, "send failure (%d)\n", errno); abort(); } } else { offset += r; part_len = len - offset; } } return i_len; } int recv_message(struct connection_t *c, int i_len, int *i_msg) { char *msg = (char *)i_msg; int len = i_len * sizeof(int), part_len; int offset = 0; int r; part_len = len; while (offset < len) { r = recv(c->s, msg + offset, part_len, 0); if (r < 0) { if (r == EINTR) { /* try again */ } else { fprintf(stderr, "recv failure (%d)\n", errno); abort(); } } else { offset += r; part_len = len - offset; } } return i_len; } static void failure(char *when) { fprintf(stderr, "failed %s: %d\n", when, errno); abort(); } static int new_socket(char *host, char *portno, struct sockaddr_in *addr) { int s; struct protoent *proto; struct hostent *h; proto = getprotobyname("tcp"); do { s = socket(AF_INET, SOCK_STREAM, proto->p_proto); } while (!s && (errno == EINTR)); if (!s) failure("creating socket"); memset(addr, 0, sizeof(*addr)); addr->sin_family = AF_INET; addr->sin_port = htons(atoi(portno)); memset(&(addr->sin_addr), 0, sizeof(addr->sin_addr)); memset(&(addr->sin_zero), 0, sizeof(addr->sin_zero)); if (host) { h = gethostbyname(host); if (h) memcpy(&addr->sin_addr, h->h_addr_list[0], h->h_length); else { errno = h_errno; failure("getting host"); } } return s; } static struct connection_t *alloc_connection(int s) { struct connection_t *c; c = (struct connection_t *)malloc(sizeof(struct connection_t)); c->s = s; return c; } struct connection_t *wait_for_connection(char *portno) { int ls, s, r; struct sockaddr_in addr; socklen_t slen; ls = new_socket(NULL, portno, &addr); do { int reuse = 1; r = setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuse), sizeof(int)); } while (r && (errno == EINTR)); if (r) failure("setting socket option"); do { r = bind(ls, (struct sockaddr *)&addr, sizeof(addr)); } while (r && (errno == EINTR)); if (r) failure("binding address"); do { r = listen(ls, 5); } while (r && (errno == EINTR)); if (r) failure("listening"); do { slen = sizeof(addr); s = accept(ls, (struct sockaddr *)&addr, &slen); } while (!s && (errno == EINTR)); if (!s) failure("accepting"); do { r = close(ls); } while (r && (errno == EINTR)); return alloc_connection(s); } struct connection_t *make_connection(char *host_addr, char *portno) { int s, r; struct sockaddr_in addr; s = new_socket(host_addr, portno, &addr); do { r = connect(s, (struct sockaddr *)&addr, sizeof(addr)); } while (r && (errno == EINTR)); if (r) failure("connecting"); return alloc_connection(s); } void close_connection(struct connection_t *c) { int r; do { r = close(c->s); } while (r && (errno == EINTR)); free(c); }