Skip to content

Instantly share code, notes, and snippets.

@cablehead
Last active April 7, 2016 17:53
Show Gist options
  • Select an option

  • Save cablehead/f3f4863d8c5647bda5606490ca959554 to your computer and use it in GitHub Desktop.

Select an option

Save cablehead/f3f4863d8c5647bda5606490ca959554 to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
int levee_dialer_fds[2];
int levee_dialer_rc;
struct levee_dialer_request {
uint16_t node_len;
uint16_t service_len;
int type;
int no;
};
struct levee_dialer_response {
int err;
int eai;
int no;
};
void *
levee_dialer_loop(void *arg) {
int rc;
struct levee_dialer_request req;
struct levee_dialer_response res;
char node[8096];
char service[1024];
struct addrinfo hints, *info, *ptr;
int no;
int err;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
while(1) {
memset(&res, 0, sizeof(res));
rc = read(levee_dialer_fds[0], &req, sizeof(req));
assert(rc == sizeof(req));
rc = read(levee_dialer_fds[0], node, req.node_len);
assert(rc == req.node_len);
node[req.node_len] = 0;
rc = read(levee_dialer_fds[0], service, req.service_len);
assert(rc == req.service_len);
service[req.service_len] = 0;
rc = getaddrinfo(node, service, &hints, &info);
if (rc != 0) {
res.eai = rc;
goto respond;
}
no = socket(PF_INET, req.type, 0);
if (no < 0) {
res.err = errno;
goto respond;
}
for (ptr = info; ptr; ptr = ptr->ai_next) {
rc = connect(no, ptr->ai_addr, ptr->ai_addrlen);
if (rc == 0) break;
err = errno;
}
freeaddrinfo(info);
if (ptr == NULL) {
res.err = err;
} else {
res.no = no;
}
respond:
rc = write(req.no, &res, sizeof(res));
assert(rc == sizeof(res));
}
}
int levee_dialer_boot(void) {
pthread_t thr;
pthread_attr_t attr;
int rc;
rc = pipe(levee_dialer_fds);
if (rc != 0) return errno;
rc = pthread_attr_init (&attr);
if (rc != 0) return errno;
rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
if (rc != 0) return errno;
rc = pthread_create (&thr, &attr, &levee_dialer_loop, NULL);
if (rc != 0) return errno;
return 0;
}
pthread_once_t levee_dialer_once = PTHREAD_ONCE_INIT;
void levee_dialer_run_once(void) {
levee_dialer_rc = levee_dialer_boot();
}
int levee_dialer_init(void) {
pthread_once(&levee_dialer_once, levee_dialer_run_once);
return levee_dialer_rc;
}
int
writer(const char *node, const char *service) {
int rc;
struct levee_dialer_request req;
struct levee_dialer_response res;
int fds[2];
rc = pipe(fds);
if (rc != 0) return errno;
req.node_len = (uint16_t) strlen(node);
req.service_len = (uint16_t) strlen(service);
req.type = SOCK_STREAM;
req.no = fds[1];
rc = write(levee_dialer_fds[1], &req, sizeof(req));
assert(rc == sizeof(req));
rc = write(levee_dialer_fds[1], node, strlen(node));
assert(rc == strlen(node));
rc = write(levee_dialer_fds[1], service, strlen(service));
assert(rc == strlen(service));
rc = read(fds[0], &res, sizeof(res));
assert(rc == sizeof(res));
printf("%s \\ %s \\ %d\n", gai_strerror(res.eai), strerror(res.err), res.no);
return 0;
}
int main(int argc, char **argv)
{
levee_dialer_init();
writer("localhost", "8000");
writer("localhost", "8080");
writer("ldld", "8080");
return 0;
}
@kalamay
Copy link
Copy Markdown

kalamay commented Apr 7, 2016

These should be declared static: https://gist.github.com/cablehead/f3f4863d8c5647bda5606490ca959554#file-th-c-L14-L15. Technically, that will happen anyway, but its safer. Without static I would typically assume there is an extern in the header for them, giving them external linkage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment