--- a/Makefile Thu Jun 26 03:31:59 2008 +0300
+++ b/Makefile Sun Jul 06 23:33:24 2008 +0300
@@ -7,10 +7,13 @@
common.o: common.c common.h
http.o: http.c http.h common.h
-remote_node.o: remote_node.c remote_node.h common.h
+config.o: config.c config.h
+socket.o: socket.c socket.h config.h common.h
+
+remote_node.o: remote_node.c remote_node.h common.h render_net.h socket.h config.h
remote_pool.o: remote_pool.c remote_pool.h common.h
render.o: render.c render.h common.h
-render_remote.o: render_remote.c render_remote.h common.h
+render_remote.o: render_remote.c render_remote.h common.h socket.h remote_node.h remote_pool.h
render_png.o: render_png.c render_png.h common.h
render_raw.o: render_raw.c render_raw.h common.h
render_local.o: render_local.c render_local.h common.h render_png.h render_raw.h render_mandelbrot.h
@@ -21,12 +24,12 @@
render_thread.o: render_thread.c render_thread.h common.h render_local.h
file_main.o: file_main.c
-node_main.o: node_main.c render_net.h
-web_main.o: web_main.c
+node_main.o: node_main.c common.h render.h render_struct.h render_thread.h render_thread_struct.h render_net.h socket.h
+web_main.o: web_main.c common.h render.h render_struct.h remote_node.h remote_pool.h render_remote.h config.h
file_main: file_main.o common.o render.o render_raw.o render_png.o render_local.o render_mandelbrot.o
-node_main: node_main.o common.o render.o render_thread.o render_local.o render_png.o render_raw.o render_mandelbrot.o
-web_main: web_main.o common.o http.o render.o render_png.o remote_node.o remote_pool.o render_remote.o render_multi.o render_slices.o
+node_main: node_main.o common.o config.o socket.o render.o render_thread.o render_local.o render_png.o render_raw.o render_mandelbrot.o
+web_main: web_main.o common.o config.o socket.o http.o render.o render_png.o remote_node.o remote_pool.o render_remote.o render_multi.o render_slices.o
clean :
rm *.o ${EXECS}
--- a/common.c Thu Jun 26 03:31:59 2008 +0300
+++ b/common.c Sun Jul 06 23:33:24 2008 +0300
@@ -1,9 +1,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <string.h>
#include <errno.h>
-#include <string.h>
-#include <ctype.h>
#include "common.h"
@@ -39,97 +38,3 @@
exit(EXIT_FAILURE);
}
-int parse_hostport (char *hostport, char **host, char **port) {
- char *c;
-
- char brace = 0, colon = 0;
-
- *host = *port = NULL;
-
- for (c = hostport; *c != '\0'; c++) {
- if (isspace(*c))
- continue;
-
- switch (*c) {
- case '[':
- if (c > hostport) {
- error("parse_hostport: %c must be first char, if any: %s", *c, hostport);
- return -1;
- }
-
- brace = *c;
- break;
-
- case ']':
- if (!brace) {
- error("parse_hostport: %c without matching brace: %s", *c, hostport);
- return -1;
- }
-
- if (!*host) {
- error("parse_hostport: empty hostname: %s", hostport);
- return -1;
- }
-
- brace = 0;
- break;
-
- case ':':
- if (brace) {
- // colons inside braces are left as-is
- continue;
- }
-
- if (!*host) {
- error("parse_hostport: colon before hostname: %s", hostport);
- return -1;
- }
-
- if (*port) {
- error("parse_hostport: colon after port: %s", hostport);
- return -1;
- }
-
- if (colon) {
- error("parse_hostport: too many colons: %s", hostport);
- return -1;
- };
-
- // finished parsing the host part, move on to the port part
- colon = ':';
- *c = '\0';
- break;
-
- default:
- if (!*host) {
- // first char of the host
- *host = c;
-
- } else if (colon && !*port) {
- // first char of the port
- *port = c;
-
- } // else a part of either, don't care about it
-
- break;
- }
- }
-
- if (!*host) {
- error("parse_hostport: missing hostname: %s", hostport);
- return -1;
- }
-
- if (brace) {
- error("parse_hostport: missing close-brace for %c: %s", brace, hostport);
- return -1;
- }
-
- if (colon && !*port) {
- error("parse_hostport: missing port: %s", hostport);
- return -1;
- }
-
- return 0;
-}
-
--- a/common.h Thu Jun 26 03:31:59 2008 +0300
+++ b/common.h Sun Jul 06 23:33:24 2008 +0300
@@ -62,21 +62,3 @@
#define INFO(...) (void) (0)
#endif
-/*
- * Parse a host:port string.
- *
- * Valid formats:
- * host
- * host:port
- * [host]
- * [host]:port
- *
- * The contents of the given hostport string *will* be modified.
- *
- * The value of *port will be set to NULL if no port was given.
- *
- * Returns 0 and sets *host if succesfull, nonzero otherwise.
- *
- */
-int parse_hostport (char *hostport, char **host, char **port);
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config.c Sun Jul 06 23:33:24 2008 +0300
@@ -0,0 +1,153 @@
+#include <stdio.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "common.h"
+
+void endpoint_init (struct config_endpoint *endpoint, unsigned short default_port) {
+ // snprintf the default port as a string
+ snprintf(endpoint->_data.default_port, PORT_TEXT_LEN, "%hu", default_port);
+
+ // set up defaults
+ endpoint->family = PF_INET;
+ endpoint->af.inet.addr = NULL;
+ endpoint->af.inet.port = endpoint->_data.default_port;
+}
+
+/*
+ * Parse an endpoint address in human-readable format into the given endpoint. You can then use the socket_*
+ * functions to work with endpoints and sockets.
+ *
+ * Formats supported:
+ * =foo.sock, =/quux/bar.sock
+ * hostname, 12.34.56.78, [::1]
+ * hostname:port, 12.34.56.78:port, [::1]:port
+ */
+int endpoint_parse (struct config_endpoint *endpoint, const char *addr_spec) {
+ // for empty addr specs, just return
+ if (!addr_spec || *addr_spec == '\0')
+ return 1;
+
+ if (sscanf(addr_spec, "=%" PATH_TEXT_LEN_STR "s", endpoint->_data.path) == 1) {
+ // local unix socket
+ endpoint->family = PF_LOCAL;
+ endpoint->af.local.path = endpoint->_data.path;
+
+ } else if (
+ sscanf(addr_spec, "[%" ADDR_TEXT_LEN_STR "[^]] ]:%" PORT_TEXT_LEN_STR "s", endpoint->_data.addr, endpoint->_data.port) == 2
+ || sscanf(addr_spec, "%" ADDR_TEXT_LEN_STR "[^:] :%" PORT_TEXT_LEN_STR "s", endpoint->_data.addr, endpoint->_data.port) == 2
+ ) {
+ endpoint->family = PF_INET;
+ endpoint->af.inet.addr = endpoint->_data.addr;
+ endpoint->af.inet.port = endpoint->_data.port;
+
+ } else if (
+ sscanf(addr_spec, "[%" ADDR_TEXT_LEN_STR "[^]] ]", endpoint->_data.addr) == 1
+ || sscanf(addr_spec, "%" ADDR_TEXT_LEN_STR "[^:]", endpoint->_data.addr) == 1
+ ) {
+ endpoint->family = PF_INET;
+ endpoint->af.inet.addr = endpoint->_data.addr;
+
+ } else {
+ // unknown foramt
+ ERROR("unkown address format: %s", addr_spec);
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+int parse_hostport (char *hostport, char **host, char **port) {
+ char *c;
+
+ int brace = 0, colon = 0;
+ *host = *port = NULL;
+
+ for (c = hostport; *c != '\0'; c++) {
+ if (isspace(*c))
+ continue;
+
+ switch (*c) {
+ case '[':
+ if (c > hostport) {
+ error("parse_hostport: %c must be first char, if any: %s", *c, hostport);
+ return -1;
+ }
+
+ brace = *c;
+ break;
+
+ case ']':
+ if (!brace) {
+ error("parse_hostport: %c without matching brace: %s", *c, hostport);
+ return -1;
+ }
+
+ if (!*host) {
+ error("parse_hostport: empty hostname: %s", hostport);
+ return -1;
+ }
+
+ brace = 0;
+ break;
+
+ case ':':
+ if (brace) {
+ // colons inside braces are left as-is
+ continue;
+ }
+
+ if (!*host) {
+ error("parse_hostport: colon before hostname: %s", hostport);
+ return -1;
+ }
+
+ if (*port) {
+ error("parse_hostport: colon after port: %s", hostport);
+ return -1;
+ }
+
+ if (colon) {
+ error("parse_hostport: too many colons: %s", hostport);
+ return -1;
+ };
+
+ // finished parsing the host part, move on to the port part
+ colon = ':';
+ *c = '\0';
+ break;
+
+ default:
+ if (!*host) {
+ // first char of the host
+ *host = c;
+
+ } else if (colon && !*port) {
+ // first char of the port
+ *port = c;
+
+ } // else a part of either, don't care about it
+
+ break;
+ }
+ }
+
+ if (!*host) {
+ error("parse_hostport: missing hostname: %s", hostport);
+ return -1;
+ }
+
+ if (brace) {
+ error("parse_hostport: missing close-brace for %c: %s", brace, hostport);
+ return -1;
+ }
+
+ if (colon && !*port) {
+ error("parse_hostport: missing port: %s", hostport);
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h Sun Jul 06 23:33:24 2008 +0300
@@ -0,0 +1,64 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define ADDR_TEXT_LEN 128
+#define ADDR_TEXT_LEN_STR "128"
+#define PORT_TEXT_LEN 32
+#define PORT_TEXT_LEN_STR "32"
+#define PATH_TEXT_LEN 108 /* from sys/un.h */
+#define PATH_TEXT_LEN_STR "108" /* from sys/un.h */
+
+struct config_endpoint {
+ // one of AF_LOCAL, AF_INET, AF_INET6
+ int family;
+
+ // buffers to store the extracted textual addres/port into
+ // these /should/ be long enough
+ union {
+ // PF_INET - may be a numeric IPv4 address, numeric IPv6 address, or hostname
+ struct {
+ const char *addr;
+ const char *port;
+ } inet;
+
+ // PF_LOCAL
+ struct {
+ const char *path;
+ } local;
+
+ } af;
+
+ struct {
+ char addr[ADDR_TEXT_LEN];
+ char port[PORT_TEXT_LEN];
+ char default_port[PORT_TEXT_LEN];
+ char path[PATH_TEXT_LEN];
+ } _data;
+};
+
+void endpoint_init (struct config_endpoint *endpoint, unsigned short default_port);
+int endpoint_parse (struct config_endpoint *endpoint, const char *addr_spec);
+
+/*
+ * Parse a host:port string.
+ *
+ * Valid formats:
+ * host
+ * host:port
+ * [host]
+ * [host]:port
+ *
+ * The contents of the given hostport string *will* be modified.
+ *
+ * The value of *port will be set to NULL if no port was given.
+ *
+ * Returns 0 and sets *host if succesfull, nonzero otherwise.
+ *
+ */
+int parse_hostport (char *hostport, char **host, char **port);
+
+#endif /* CONFIG_H */
+
--- a/node_main.c Thu Jun 26 03:31:59 2008 +0300
+++ b/node_main.c Sun Jul 06 23:33:24 2008 +0300
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <sys/types.h>
#include <arpa/inet.h>
-#include <sys/socket.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
@@ -15,6 +14,7 @@
#include <event2/bufferevent.h>
#include "common.h"
+#include "socket.h"
#include "render.h"
#include "render_struct.h"
#include "render_net.h"
@@ -242,22 +242,21 @@
int main (int argc, char** argv) {
struct event_base *ev_base;
+ struct config_endpoint endpoint;
int ssock;
- struct sockaddr_in addr;
-
+
// parse arguments
int opt;
- const char *port_name = NULL;
+ const char *listen_spec = NULL;
int enable_debug = 0;
- unsigned short port;
while ((opt = getopt(argc, argv, "l:")) != -1) {
switch (opt) {
case 'l':
- if (port_name)
+ if (listen_spec)
ERROR("only specify -l once");
- port_name = optarg;
+ listen_spec = optarg;
break;
case 'd':
@@ -266,7 +265,7 @@
break;
default:
- err_exit("Usage: %s [-l port] [-d]", argv[0]);
+ err_exit("Usage: %s [-l addr_spec] [-d]", argv[0]);
}
}
@@ -274,31 +273,19 @@
if (!(ev_base = event_init()))
FATAL("event_init");
- // post-process arguments
- if (!port_name)
- port_name = RENDER_PORT_NAME;
-
- if (!(port = atoi(port_name)))
- ERROR("invalid port: %s", port_name);
-
// per default it is enabled
if (!enable_debug)
event_set_log_callback(&log_null);
// create the socket
- if ((ssock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
- PERROR("socket");
+ endpoint_init(&endpoint, RENDER_PORT);
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = INADDR_ANY;
+ if (endpoint_parse(&endpoint, listen_spec))
+ goto error;
- if (bind(ssock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1)
- PERROR("bind");
-
- if (listen(ssock, 1) == -1)
- PERROR("listen");
-
+ if ((ssock = socket_listen(&endpoint, SOCK_STREAM)) == -1)
+ goto error;
+
// create the listen event
struct event listen_ev;
@@ -311,7 +298,7 @@
sigpipe_ignore();
// run the libevent mainloop
- INFO("run: %s:%hu", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+ INFO("run");
if (event_base_dispatch(ev_base))
WARNING("event_dispatch");
--- a/remote_node.c Thu Jun 26 03:31:59 2008 +0300
+++ b/remote_node.c Sun Jul 06 23:33:24 2008 +0300
@@ -4,45 +4,23 @@
#include <netdb.h>
#include <assert.h>
+#include "remote_node.h"
#include "common.h"
#include "render_net.h"
-#include "remote_node.h"
+#include "socket.h"
-int remote_node_init (struct remote_node *node_info, const char *hostname, const char *portname) {
+int remote_node_init (struct remote_node *node_info, const char *addr_spec) {
// zero out the struct
memset(node_info, 0, sizeof(*node_info));
// XXX: currently, this is hardcoded to one, but should be automagically discovered
node_info->parallel_renders = 1;
- // lookup the host:port
- portname = portname ? portname : RENDER_PORT_NAME;
-
- // XXX: stat it and look for a PF_UNIX socket!
-
- // PF_INET
-
- struct addrinfo hints, *results, *result;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_ADDRCONFIG; // attempt to get a working address as the first result
+ // build the endpoint
+ endpoint_init(&node_info->endpoint, RENDER_PORT);
- int err = getaddrinfo(hostname, portname, &hints, &results);
-
- if (err != 0) {
- error("getaddrinfo: [%s].%s: %s", hostname, portname, gai_strerror(err));
-
+ if (endpoint_parse(&node_info->endpoint, addr_spec))
return -1;
- }
-
- assert(results != NULL); // we expect at least one result
-
- // XXX: only use the first result, discard the rest.
- result = results;
- memcpy(&node_info->addr, result->ai_addr, result->ai_addrlen);
-
- freeaddrinfo(results);
// success!
node_info->valid = 1;
--- a/remote_node.h Thu Jun 26 03:31:59 2008 +0300
+++ b/remote_node.h Sun Jul 06 23:33:24 2008 +0300
@@ -3,6 +3,8 @@
#include <sys/socket.h>
+#include "config.h"
+
/*
* Information about a single remote render node.
*/
@@ -13,9 +15,9 @@
/*
* Static information
*/
-
- // the remote address, note how this can both AF_INET and AF_LOCAL
- struct sockaddr_storage addr;
+
+ // the remote endpoint
+ struct config_endpoint endpoint;
// how many render requests this node can process concurrently
int parallel_renders;
@@ -29,14 +31,12 @@
};
/*
- * Initialize the given remote_node struct to work with the render node at the given host/port.
- *
- * Portname may also be NULL, in which case the default port is used.
+ * Initialize the given remote_node struct to work with the render node at the given address (à la parse_address).
*
* Note that this is a blocking function, and should only be called at startup.
*
* returns nonzero on error, zero on success.
*/
-int remote_node_init (struct remote_node *node_info, const char *hostname, const char *portname);
+int remote_node_init (struct remote_node *node_info, const char *addr_spec);
#endif /* REMOTE_NODE_H */
--- a/remote_pool.c Thu Jun 26 03:31:59 2008 +0300
+++ b/remote_pool.c Sun Jul 06 23:33:24 2008 +0300
@@ -9,7 +9,7 @@
memset(pool_info, 0, sizeof(*pool_info));
}
-int remote_pool_add (struct remote_pool *pool_info, const char *hostname, const char *portname) {
+int remote_pool_add (struct remote_pool *pool_info, const char *addr_spec) {
int i;
struct remote_node *node_info = NULL;
@@ -21,12 +21,13 @@
}
}
- if (!node_info) {
- error("remote_pool_add: pool full, consider increasing REMOTE_POOL_MAX");
- return -1;
- }
+ if (!node_info)
+ ERROR("remote_pool_add: pool full, consider increasing REMOTE_POOL_MAX");
- return remote_node_init(node_info, hostname, portname);
+ return remote_node_init(node_info, addr_spec);
+
+error:
+ return -1;
}
int remote_pool_load (struct remote_pool *pool_info, const char *filename) {
@@ -39,7 +40,7 @@
}
// read it in line-by-line
- char line_buf[POOL_FILE_LINE_LENGTH], *hostname, *portname, *c;
+ char line_buf[POOL_FILE_LINE_LENGTH], *c;
// non-ferror error indicator
int error_flag = 0;
@@ -64,15 +65,9 @@
if (*c == '\0')
continue;
-
- // parse
- if (!parse_hostport(line_buf, &hostname, &portname)) {
- error_flag = 1;
- break;
- }
// add it to the pool
- if (remote_pool_add(pool_info, hostname, portname)) {
+ if (remote_pool_add(pool_info, line_buf)) {
error_flag = 1;
break;
}
--- a/remote_pool.h Thu Jun 26 03:31:59 2008 +0300
+++ b/remote_pool.h Sun Jul 06 23:33:24 2008 +0300
@@ -22,7 +22,7 @@
/*
* Add a remote_node to the pool, see remote_node_init
*/
-int remote_pool_add (struct remote_pool *pool_info, const char *hostname, const char *portname);
+int remote_pool_add (struct remote_pool *pool_info, const char *addr_spec);
/*
* Adds remote_nodes to the pool based on the contents of the given file
--- a/render_net.h Thu Jun 26 03:31:59 2008 +0300
+++ b/render_net.h Sun Jul 06 23:33:24 2008 +0300
@@ -1,5 +1,6 @@
#include <sys/types.h>
+#define RENDER_PORT 6159
#define RENDER_PORT_NAME "6159"
#pragma pack(push)
--- a/render_remote.c Thu Jun 26 03:31:59 2008 +0300
+++ b/render_remote.c Sun Jul 06 23:33:24 2008 +0300
@@ -5,14 +5,17 @@
#include <errno.h>
#include <assert.h>
+#include <sys/un.h> /* XXX: for SUN_LEN */
+
#include <event2/event.h>
#include <event2/event_struct.h>
#include <event2/bufferevent.h>
-#include "render_struct.h"
#include "render_remote.h"
+#include "common.h"
+#include "render_struct.h"
#include "render_net.h"
-#include "common.h"
+#include "socket.h"
struct render_remote {
// the socket fd
@@ -201,18 +204,8 @@
ctx->render_cmd.y2 = render->y2;
// create the socket
- if ((ctx->sock = socket(node_info->addr.ss_family, SOCK_STREAM, 0)) < 0)
- PERROR("socket");
-
- // mark it as nonblocking
- if (fcntl(ctx->sock, F_SETFL, O_NONBLOCK) == -1)
- PERROR("fcntl");
-
- // initiate the connect
- int err = connect(ctx->sock, (struct sockaddr *) &node_info->addr, sizeof(node_info->addr));
-
- if (err != -1 || errno != EINPROGRESS)
- PERROR("connect");
+ if ((ctx->sock = socket_connect_async(&node_info->endpoint, SOCK_STREAM)) == -1)
+ goto error;
// return the raw ctx
return ctx;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/socket.c Sun Jul 06 23:33:24 2008 +0300
@@ -0,0 +1,184 @@
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+
+
+#include "socket.h"
+#include "common.h"
+
+#define _SOCKOP_SOCKET 0x01
+#define _SOCKOP_ENDPOINT_BIND 0x02
+#define _SOCKOP_ENDPOINT_CONNECT 0x04
+#define _SOCKOP_LISTEN 0x08
+#define _SOCKOP_FLAGS_PASSIVE 0x10
+#define _SOCKOP_FCNTL_NONBLOCK 0x20
+
+enum socket_op {
+ /*
+ * Just resolve the address, don't create a socket
+ */
+ SOCKOP_RESOLVE = _SOCKOP_FLAGS_PASSIVE,
+
+ /*
+ * Create a socket whose local end is bound to the given endpoint, and listening
+ */
+ SOCKOP_LISTEN = _SOCKOP_FLAGS_PASSIVE | _SOCKOP_SOCKET | _SOCKOP_ENDPOINT_BIND | _SOCKOP_LISTEN,
+
+ /*
+ * Create a socket whose remote end is connected to the given endpoint, and connected
+ */
+ SOCKOP_CONNECT = _SOCKOP_SOCKET | _SOCKOP_ENDPOINT_CONNECT,
+
+ /*
+ * Create a socket and initiate a nonblocking connect to the given endpoint
+ */
+ SOCKOP_CONNECT_ASYNC = _SOCKOP_SOCKET | _SOCKOP_FCNTL_NONBLOCK | _SOCKOP_ENDPOINT_CONNECT,
+};
+
+static int _socket_do (struct config_endpoint *endpoint, int *sock, int sock_type, struct sockaddr_storage *addr, enum socket_op sockop);
+
+/*
+ * Create a socket of the given type that's listening on the given endpoint
+ */
+int socket_listen (struct config_endpoint *endpoint, int sock_type) {
+ int sock = -1;
+ struct sockaddr_storage addr;
+
+ // and then _socket_do
+ if (_socket_do(endpoint, &sock, sock_type, &addr, SOCKOP_LISTEN))
+ return -1;
+
+ // just return the socket, discard addr
+ return sock;
+}
+
+/*
+ * Initiate an async connect to the given endpoint for the given socket type. This should work for
+ * PF_INET and PF_LOCAL sockets, and in both cases, socket writeability should indicate that the
+ * connect succeeded.
+ *
+ * XXX: Currently it looks up the endpoint each time - the working addrinfo should be cached
+ */
+int socket_connect_async (struct config_endpoint *endpoint, int sock_type) {
+ int sock = -1;
+ struct sockaddr_storage addr;
+
+ // and then _socket_do
+ if (_socket_do(endpoint, &sock, sock_type, &addr, SOCKOP_CONNECT_ASYNC))
+ return -1;
+
+ // return the socket
+ return sock;
+}
+
+
+/*
+ * Do something to apply an endpoint to a socket
+ */
+static int _socket_do (struct config_endpoint *endpoint, int *sock, int sock_type, struct sockaddr_storage *addr, enum socket_op sockop) {
+ struct addrinfo *res = NULL, *info, _fake_res;
+ struct sockaddr_un _fake_addr_un;
+
+ if (endpoint->family == PF_UNIX) {
+ // getaddrinfo doesn't handle PF_UNIX, so we need to build a fake result
+
+ // build the sockaddr_un
+ _fake_addr_un.sun_family = endpoint->family;
+ memcpy(_fake_addr_un.sun_path, endpoint->af.local.path, sizeof(_fake_addr_un.sun_path));
+
+ // build the fake addrinfo res
+ _fake_res.ai_flags = 0;
+ _fake_res.ai_family = PF_UNIX;
+ _fake_res.ai_socktype = sock_type;
+ _fake_res.ai_protocol = 0;
+ _fake_res.ai_addrlen = SUN_LEN(&_fake_addr_un);
+ _fake_res.ai_addr = (struct sockaddr *) &_fake_addr_un;
+ _fake_res.ai_canonname = (char *) endpoint->af.local.path; /* XXX: not const */
+ _fake_res.ai_next = NULL;
+
+ res = &_fake_res;
+
+ } else if (endpoint->family == PF_INET) {
+ // use the real getaddrinfo
+
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_socktype = sock_type;
+ hints.ai_protocol = 0;
+ hints.ai_flags = (sockop & _SOCKOP_FLAGS_PASSIVE ? AI_PASSIVE : 0) | AI_CANONNAME;
+
+ int err;
+
+ // check that we have a service, doesn't make any sense without
+ if (!endpoint->af.inet.port)
+ ERROR("no service specified");
+
+ if ((err = getaddrinfo(endpoint->af.inet.addr, endpoint->af.inet.port, &hints, &res)) != 0)
+ ERROR("getaddrinfo: %s#%s: %s", endpoint->af.inet.addr, endpoint->af.inet.port, gai_strerror(err));
+
+ } else {
+ ERROR("invalid endpoint");
+ }
+
+ for (info = res; info; info = info->ai_next) {
+ if (sockop & _SOCKOP_SOCKET && (*sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol)) == -1) {
+ PWARNING("socket(%d, %s)", info->ai_family, info->ai_canonname);
+ continue;
+ }
+
+ if (sockop & _SOCKOP_FCNTL_NONBLOCK && fcntl(*sock, F_SETFL, O_NONBLOCK) == -1) {
+ PWARNING("fcntl(%d, %s, F_SETFL O_NONBLOCK)", info->ai_family, info->ai_canonname);
+ close(*sock); *sock = -1;
+ continue;
+ }
+
+ if (sockop & _SOCKOP_ENDPOINT_BIND && bind(*sock, info->ai_addr, info->ai_addrlen) == -1) {
+ PWARNING("bind(%d, %s)", info->ai_family, info->ai_canonname);
+ close(*sock); *sock = -1;
+ continue;
+ }
+
+ if (sockop & _SOCKOP_LISTEN && listen(*sock, SOCKET_LISTEN_BACKLOG) == -1) {
+ PWARNING("listen(%d, %s)", info->ai_family, info->ai_canonname);
+ close(*sock); *sock = -1;
+ continue;
+ }
+
+ if (sockop & _SOCKOP_ENDPOINT_CONNECT && connect(*sock, info->ai_addr, info->ai_addrlen) == -1) {
+ if (sockop & _SOCKOP_FCNTL_NONBLOCK && errno == EINPROGRESS) {
+ /* to be expected */
+
+ } else {
+ PWARNING("listen(%d, %s)", info->ai_family, info->ai_canonname);
+ close(*sock); *sock = -1;
+ continue;
+ }
+ }
+
+ // copy the succesfull address over
+ memcpy(addr, info->ai_addr, info->ai_addrlen);
+
+ // exit the loop with a valid socket
+ assert(*sock != -1);
+ break;
+ }
+
+ if (*sock == -1)
+ ERROR("no working results from getaddrinfo: %s#%s", endpoint->af.inet.addr, endpoint->af.inet.port);
+
+ return 0;
+
+error:
+ if (res != 0 && res != &_fake_res)
+ freeaddrinfo(res);
+
+ return -1;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/socket.h Sun Jul 06 23:33:24 2008 +0300
@@ -0,0 +1,11 @@
+#ifndef SOCKET_H
+#define SOCKET_H
+
+#include "config.h"
+
+#define SOCKET_LISTEN_BACKLOG 2
+
+int socket_listen (struct config_endpoint *endpoint, int sock_type);
+int socket_connect_async (struct config_endpoint *endpoint, int sock_type);
+
+#endif /* SOCKET_H */
--- a/web_main.c Thu Jun 26 03:31:59 2008 +0300
+++ b/web_main.c Sun Jul 06 23:33:24 2008 +0300
@@ -21,10 +21,8 @@
#include "render.h"
#include "remote_node.h"
#include "remote_pool.h"
-
-// XXX: replace with a common one
#include "render_remote.h"
-#include "render_multi.h"
+#include "config.h"
#define MIN_CHUNK_SIZE 4096
#define OVERFLOW_BUFFER 4096
@@ -276,7 +274,6 @@
// process arguments
int opt;
int enable_debug = 0;
- char *host, *port;
while ((opt = getopt(argc, argv, "dp:r:")) != -1) {
switch (opt) {
@@ -289,10 +286,7 @@
case 'r':
// add the given render node to the pool
- if (
- parse_hostport(optarg, &host, &port)
- || remote_pool_add(&remote_pool, host, port)
- )
+ if (remote_pool_add(&remote_pool, optarg))
return 1;
break;