commit - 58c75fabb676904383f4b1bc176518cbc563d1bf
commit + cc4953ef55207880f2363213450274581b44b0db
blob - 5c8d2187a97b6002a08ac45a907bc7f907fff67b
blob + cb4bb1355f7f51704a0b2af48c7bad9a498b709b
--- configure.ac
+++ configure.ac
AC_LIBOBJ(imsg-buffer)
])
+AC_CHECK_FUNCS([asr_run])
+
# check compiler flags
AC_DEFUN([CC_ADD_CHECK_FLAGS], [
AC_MSG_CHECKING([if $CC supports $1 flag])
blob - 48a1aa827cfed24d77aab48a2f07a126eb4b9543
blob + fe9fdd24ee551c9f088d78a9f8353545bab5ba39
--- gemini.c
+++ gemini.c
#include <tls.h>
#include <unistd.h>
+#if HAVE_ASR_RUN
+# include <asr.h>
+#endif
+
static struct event imsgev;
static struct tls_config *tlsconf;
static struct imsgbuf *ibuf;
struct req;
static void die(void) __attribute__((__noreturn__));
+
+#if HAVE_ASR_RUN
+static void try_to_connect(int, short, void*);
+static void query_done(struct asr_result*, void*);
+static void async_conn_towards(struct req*);
+#else
static char *xasprintf(const char*, ...);
-static int conn_towards(struct url*, char**);
+static int blocking_conn_towards(struct url*, char**);
+#endif
static void close_with_err(struct req*, const char*);
static void close_with_errf(struct req*, const char*, ...) __attribute__((format(printf, 2, 3)));
static struct req *req_by_id(uint32_t);
static struct req *req_by_id_try(uint32_t);
+static void setup_tls(struct req*);
static void do_handshake(int, short, void*);
static void write_request(int, short, void*);
static void read_reply(int, short, void*);
struct tls *ctx;
char buf[1024];
size_t off;
+
+#if HAVE_ASR_RUN
+ struct addrinfo hints, *servinfo, *p;
+ struct event_asr *asrev;
+#endif
+
TAILQ_ENTRY(req) reqs;
};
die(void)
{
abort(); /* TODO */
+}
+
+#if HAVE_ASR_RUN
+static void
+try_to_connect(int fd, short ev, void *d)
+{
+ struct req *req = d;
+ int error = 0;
+ socklen_t len = sizeof(error);
+
+ if (req->p == NULL)
+ goto err;
+
+ if (req->fd != -1) {
+ if (getsockopt(req->fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1)
+ goto err;
+ if (error != 0) {
+ errno = error;
+ goto err;
+ }
+ goto done;
+ }
+
+ req->fd = socket(req->p->ai_family, req->p->ai_socktype, req->p->ai_protocol);
+ if (req->fd == -1)
+ req->p = req->p->ai_next;
+ else {
+ mark_nonblock(req->fd);
+ if (connect(req->fd, req->p->ai_addr, req->p->ai_addrlen) == 0)
+ goto done;
+ }
+ try_to_connect(fd, ev, req);
+ return;
+
+err:
+ freeaddrinfo(req->servinfo);
+ close_with_errf(req, "failed to connect to %s",
+ req->url.host);
+ return;
+
+done:
+ freeaddrinfo(req->servinfo);
+ setup_tls(req);
+}
+
+static void
+query_done(struct asr_result *res, void *d)
+{
+ struct req *req = d;
+
+ req->asrev = NULL;
+ if (res->ar_gai_errno != 0) {
+ close_with_errf(req, "failed to resolve %s: %s",
+ req->url.host, gai_strerror(res->ar_gai_errno));
+ return;
+ }
+
+ req->fd = -1;
+ req->servinfo = res->ar_addrinfo;
+ req->p = res->ar_addrinfo;
+ try_to_connect(0, 0, req);
}
+static void
+async_conn_towards(struct req *req)
+{
+ struct asr_query *q;
+ const char *proto = "1965";
+
+ if (*req->url.port != '\0')
+ proto = req->url.port;
+
+ req->hints.ai_family = AF_UNSPEC;
+ req->hints.ai_socktype = SOCK_STREAM;
+ q = getaddrinfo_async(req->url.host, proto, &req->hints, NULL);
+ req->asrev = event_asr_run(q, query_done, req);
+}
+#else
static char *
xasprintf(const char *fmt, ...)
{
}
static int
-conn_towards(struct url *url, char **err)
+blocking_conn_towards(struct url *url, char **err)
{
struct addrinfo hints, *servinfo, *p;
int status, sock;
freeaddrinfo(servinfo);
return sock;
}
+#endif
static struct req *
req_by_id(uint32_t id)
{
struct req *req = d;
+#if HAVE_ASR_RUN
+ if (req->asrev != NULL)
+ event_asr_abort(req->asrev);
+#endif
+
if (req->ctx != NULL) {
switch (tls_close(req->ctx)) {
case TLS_WANT_POLLIN:
}
static void
+setup_tls(struct req *req)
+{
+ if ((req->ctx = tls_client()) == NULL) {
+ close_with_errf(req, "tls_client: %s", strerror(errno));
+ return;
+ }
+ if (tls_configure(req->ctx, tlsconf) == -1) {
+ close_with_errf(req, "tls_configure: %s", tls_error(req->ctx));
+ return;
+ }
+ if (tls_connect_socket(req->ctx, req->fd, req->url.host) == -1) {
+ close_with_errf(req, "tls_connect_socket: %s", tls_error(req->ctx));
+ return;
+ }
+ yield_w(req, do_handshake, &timeout_for_handshake);
+}
+
+static void
do_handshake(int fd, short ev, void *d)
{
struct req *req = d;
{
struct req *req;
const char *e;
- char *data, *err = NULL;
+ char *data;
data = imsg->data;
return;
}
- if ((req->fd = conn_towards(&req->url, &err)) == -1)
- goto err;
- if ((req->ctx = tls_client()) == NULL)
- goto err;
- if (tls_configure(req->ctx, tlsconf) == -1) {
- err = xasprintf("tls_configure: %s", tls_error(req->ctx));
- goto err;
- }
- if (tls_connect_socket(req->ctx, req->fd, req->url.host) == -1) {
- err = xasprintf("tls_connect_socket: %s", tls_error(req->ctx));
- goto err;
- }
+#if HAVE_ASR_RUN
+ async_conn_towards(req);
+#else
+ {
+ char *e = NULL;
- yield_w(req, do_handshake, &timeout_for_handshake);
- return;
-
-err:
- close_with_err(req, err);
- free(err);
+ if ((req->fd = blocking_conn_towards(&req->url, &err)) == -1) {
+ close_with_err(req, err);
+ free(err);
+ }
+ setup_tls(req);
+ }
+#endif
}
static void