void echo_server_wcb_accept(EV_P_ ev_io *w, int tev) { int sd, rc; struct sockaddr_in addr; socklen_t addrlen; echo_server_t *s = aux_memberof(echo_server_t, wev_accept, w); addrlen = sizeof(addr); pthread_mutex_lock(&accept_mtx); sd = accept(w->fd, (struct sockaddr *) &addr, &addrlen); pthread_mutex_unlock(&accept_mtx); /* fprintf(stderr, "accept in thread=%d fd=%d (%d: %s)\n", (int) pthread_self(), sd, errno, strerror(errno)); */ if (0 > sd) { return; } if (0 > (rc = aux_set_nonblk(sd, 1))) { return; } #if 0 if (0 > (rc = aux_set_sckopt(sd, IPPROTO_TCP, TCP_NODELAY, 1))) { fprintf(stderr, "sockopt TCP_NODELAY error\n"); } #endif echo_client_add(s, sd, &addr); }
int echo_socket_listen(const char *host, const char *port) { int sd, rc; struct sockaddr_in addr; sd = socket(AF_INET, SOCK_STREAM, 0); if (0 > sd) return -1; rc = aux_set_nonblk(sd, 1); if (0 > rc) return -1; rc = aux_set_sckopt(sd, SOL_SOCKET, SO_REUSEADDR, 1); if (0 > rc) return -1; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(host); addr.sin_port = htons(atoi(port)); rc = bind(sd, (struct sockaddr *) &addr, sizeof(addr)); if (0 > rc) return -1; rc = listen(sd, LISTEN_BACKLOG); if (0 > rc) return -1; return sd; }
int client_add() { int sd, rc; client_t *c; if (NULL == (c = calloc(1, sizeof(*c)))) { return -1; } if (0 > (sd = socket(AF_INET, SOCK_STREAM, 0))) { fprintf(stderr, "sock error\n"); return -1; } if (0 > (rc = aux_set_nonblk(sd, 1))) { close(sd); return -1; } rc = connect(sd, (struct sockaddr *) &addr, sizeof(addr)); if (0 > rc && EINPROGRESS != errno) { fprintf(stderr, "conn error fd=%d\n", sd); close(sd); return -1; } ev_io_init(&c->wev_recv, wcb_recv, sd, EV_READ); ev_io_init(&c->wev_send, wcb_send, sd, EV_WRITE); ev_io_init(&c->wev_connect, wcb_connect, sd, EV_READ | EV_WRITE); ev_timer_init(&c->wev_timeout, wcb_timeout, 0, RESEND_INTERVAL); ev_timer_again(loop, &c->wev_timeout); ev_io_start(loop, &c->wev_connect); return 0; }
static int ugh_subreq_connect(void *data, in_addr_t addr) { ugh_subreq_t *r = (ugh_subreq_t *) data; /* XXX this is needed temporarily, so if we del this subrequest due to * resov error, we will not close any valid file descriptor inside * ugh_subreq_del routine */ r->wev_recv.fd = -1; /* start calculating response_time from the first try */ if (r->response_time == 0) { r->response_time = ev_now(loop); } /* reset connection_time */ r->connection_time = 0; if (INADDR_NONE == addr) { ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR, ENXIO); return -1; } r->addr.sin_addr.s_addr = addr; log_debug("ugh_subreq_connect(%s:%u)", inet_ntoa(r->addr.sin_addr), ntohs(r->addr.sin_port)); int sd, rc; if (0 > (sd = socket(AF_INET, SOCK_STREAM, 0))) { ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR, errno); return -1; } if (0 > (rc = aux_set_nonblk(sd, 1))) { close(sd); ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR, errno); return -1; } rc = connect(sd, (struct sockaddr *) &r->addr, sizeof(r->addr)); if (0 > rc && EINPROGRESS != errno) { close(sd); ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR, errno); return -1; } /* errno = 0; */ ev_io_init(&r->wev_recv, ugh_subreq_wcb_recv, sd, EV_READ); ev_io_init(&r->wev_send, ugh_subreq_wcb_send, sd, EV_WRITE); ev_io_init(&r->wev_connect, ugh_subreq_wcb_connect, sd, EV_READ | EV_WRITE); if (UGH_TIMEOUT_FULL == r->timeout_type) { ev_tstamp new_timeout = r->timeout - (ev_now(loop) - r->response_time); if (new_timeout != r->timeout) { /* XXX this is just temporarily on info level */ log_info("updating timeout from %f to %f (%.*s:%.*s%.*s%s%.*s, addr=%s:%u)" , r->timeout , new_timeout , (int) r->u.host.size, r->u.host.data , (int) r->u.port.size, r->u.port.data , (int) r->u.uri.size, r->u.uri.data , r->u.args.size ? "?" : "" , (int) r->u.args.size, r->u.args.data , inet_ntoa(r->addr.sin_addr) , ntohs(r->addr.sin_port) ); } if (new_timeout < 0) { ugh_subreq_del(r, UGH_UPSTREAM_FT_TIMEOUT, 0); return -1; } ev_timer_init(&r->wev_timeout, ugh_subreq_wcb_timeout, 0, new_timeout); } else { ev_timer_init(&r->wev_timeout, ugh_subreq_wcb_timeout, 0, r->timeout); } ev_timer_init(&r->wev_timeout_connect, ugh_subreq_wcb_timeout_connect, 0, r->timeout_connect); ev_timer_again(loop, &r->wev_timeout); ev_timer_again(loop, &r->wev_timeout_connect); ev_io_start(loop, &r->wev_connect); return 0; }