int VSS_open(const char *str, double tmo) { int retval = -1; int nvaddr, n, i; struct vss_addr **vaddr; struct pollfd pfd; nvaddr = VSS_resolve(str, NULL, &vaddr); for (n = 0; n < nvaddr; n++) { retval = VSS_connect(vaddr[n], tmo != 0.0); if (retval >= 0 && tmo != 0.0) { pfd.fd = retval; pfd.events = POLLOUT; i = poll(&pfd, 1, tmo * 1e3); if (i == 0 || pfd.revents != POLLOUT) { (void)close(retval); retval = -1; } } if (retval >= 0) break; } for (n = 0; n < nvaddr; n++) free(vaddr[n]); free(vaddr); return (retval); }
static int Marg_poker(const struct vev *e, int what) { struct vsb *vsb; int s, k; socklen_t l; (void)what; /* XXX: ??? */ if (e == M_conn) { /* Our connect(2) returned, check result */ l = sizeof k; AZ(getsockopt(M_fd, SOL_SOCKET, SO_ERROR, &k, &l)); if (k) { errno = k; syslog(LOG_INFO, "Could not connect to CLI-master: %m"); (void)close(M_fd); M_fd = -1; /* Try next address */ if (++M_nxt >= M_nta) { M_nxt = 0; if (M_poll < 10) M_poll *= 2; } return (1); } vsb = sock_id("master", M_fd); mgt_cli_setup(M_fd, M_fd, 0, VSB_data(vsb), Marg_closer, NULL); VSB_delete(vsb); M_poll = 1; return (1); } assert(e == M_poker); M_poker->timeout = M_poll; /* XXX nasty ? */ if (M_fd >= 0) return (0); /* Try to connect asynchronously */ s = VSS_connect(M_ta[M_nxt], 1); if (s < 0) return (0); mgt_got_fd(s); M_conn = vev_new(); AN(M_conn); M_conn->callback = Marg_poker; M_conn->name = "-M connector"; M_conn->fd_flags = EV_WR; M_conn->fd = s; M_fd = s; AZ(vev_add(mgt_evb, M_conn)); return (0); }
static void * replay_thread(void *arg) { struct iovec iov[6]; char space[1] = " ", crlf[2] = "\r\n"; struct replay_thread *thr = arg; struct message *msg; enum shmlogtag tag; size_t len; char *ptr; const char *next; int i; int reopen = 1; while ((msg = mailbox_get(&thr->mbox)) != NULL) { tag = msg->tag; len = msg->len; ptr = msg->ptr; thread_log(2, 0, "%s(%s)", VSL_tags[tag], msg->ptr); switch (tag) { case SLT_RxRequest: if (thr->method != NULL) thr->bogus = 1; else thr->method = trimline(thr, ptr); break; case SLT_RxURL: if (thr->url != NULL) thr->bogus = 1; else thr->url = trimline(thr, ptr); break; case SLT_RxProtocol: if (thr->proto != NULL) thr->bogus = 1; else thr->proto = trimline(thr, ptr); break; case SLT_RxHeader: if (thr->nhdr >= sizeof thr->hdr / sizeof *thr->hdr) { thr->bogus = 1; } else { thr->hdr[thr->nhdr++] = trimline(thr, ptr); if (isprefix(ptr, "connection:", &next)) thr->conn = trimline(thr, next); } break; default: break; } freez(msg->ptr); freez(msg); if (tag != SLT_ReqEnd) continue; if (!thr->method || !thr->url || !thr->proto) { thr->bogus = 1; } else if (strcmp(thr->method, "GET") != 0 && strcmp(thr->method, "HEAD") != 0) { thr->bogus = 1; } else if (strcmp(thr->proto, "HTTP/1.0") == 0) { reopen = !(thr->conn && strcasecmp(thr->conn, "keep-alive") == 0); } else if (strcmp(thr->proto, "HTTP/1.1") == 0) { reopen = (thr->conn && strcasecmp(thr->conn, "close") == 0); } else { thr->bogus = 1; } if (thr->bogus) { thread_log(1, 0, "bogus"); goto clear; } if (thr->sock == -1) { for (;;) { thread_log(1, 0, "sleeping before connect..."); usleep(1000 * (thr->fd % 3001)); if ((thr->sock = VSS_connect(addr_info)) >= 0) break; thread_log(0, errno, "connect failed"); } } thread_log(1, 0, "%s %s %s", thr->method, thr->url, thr->proto); iov[0].iov_base = thr->method; iov[0].iov_len = strlen(thr->method); iov[2].iov_base = thr->url; iov[2].iov_len = strlen(thr->url); iov[4].iov_base = thr->proto; iov[4].iov_len = strlen(thr->proto); iov[1].iov_base = iov[3].iov_base = space; iov[1].iov_len = iov[3].iov_len = 1; iov[5].iov_base = crlf; iov[5].iov_len = 2; if (writev(thr->sock, iov, 6) == -1) { thread_log(0, errno, "writev()"); goto close; } for (i = 0; i < thr->nhdr; ++i) { thread_log(2, 0, "%d %s", i, thr->hdr[i]); iov[0].iov_base = thr->hdr[i]; iov[0].iov_len = strlen(thr->hdr[i]); iov[1].iov_base = crlf; iov[1].iov_len = 2; if (writev(thr->sock, iov, 2) == -1) { thread_log(0, errno, "writev()"); goto close; } } if (write(thr->sock, crlf, 2) == -1) { thread_log(0, errno, "writev()"); goto close; } if (receive_response(thr) || reopen) { close: thread_log(1, 0, "close"); assert(thr->sock != -1); close(thr->sock); thr->sock = -1; } sleep(1); clear: /* clean up */ thread_clear(thr); } /* leftovers */ thread_clear(thr); return (0); }