// 返回发送链元素数 // -1,连接状态异常,需要清空事件 // 0, 发送链空,需要清除写事件 int connector_send(int fd) { connector_t *con = connector_get_ptr(fd); while(1) { send_q_t **curr = &con->send_q_head; send_q_t *q_entry = *curr; if(q_entry == NULL) break; int num = net_write_n(fd, (char *)(q_entry->send_buf) + q_entry->send_len, q_entry->buf_len - q_entry->send_len); logging_trace("%s:%d %d write %d bytes", con->ip, con->port, fd, num); if(num == 0) { break; } else if(num == -1) { con->closed_flag = 1; if(con->processing_count == 0) connector_destroy(fd); return -1; } else { (*curr)->send_len += num; logging_trace("%s:%d %d send_buf_len %d, send_len %d", con->ip, con->port, fd, q_entry->buf_len, q_entry->send_len); if(q_entry->send_len == q_entry->buf_len) { *curr = (*curr)->next; mem_free(q_entry->send_buf); mem_free(q_entry); // 发送队列计数 con->send_q_count --; logging_trace("%s:%d %d send_q_count %d", con->ip, con->port, fd, con->send_q_count); } } } if(con->send_q_count == 0 && con->closing_flag && con->processing_count) connector_destroy(fd); return con->send_q_count; }
// 返回-1,发送过慢异常,清空事件 // 返回 1,发送链刚刚建立,需要建立写事件 int connector_push_packet(int fd, void *data, int len) { connector_t *con = connector_get_ptr(fd); // 连接引用计数 con->processing_count --; logging_trace("%s:%d %d push_packet %d bytes, processing_count %d", con->ip, con->port, fd, con->processing_count); if(con->closed_flag) { if(len) mem_free(data); if(con->processing_count == 0) { logging_trace("%s:%d %d check closed_flag processing_count 0", con->ip, con->port, fd); connector_destroy(fd); } return 0; } if(!len && con->closing_flag && con->processing_count == 0 && con->send_q_count == 0) { logging_trace("%s:%d %d check closing_flag processing_count 0, send_q_count 0", con->ip, con->port, fd); connector_destroy(fd); return -1; } if(!len) { return 0; } // 发送队列计数 con->send_q_count ++; if(con->send_q_count > MAX_SEND_Q_COUNT) { logging_trace("%s:%d %d send_q_count %d overflow", con->ip, con->port, fd, con->send_q_count); con->closed_flag = 1; mem_free(data); con->send_q_count --; return -1; } logging_trace("%s:%d %d send_q_count %d", con->ip, con->port, fd, con->send_q_count); send_q_t *q_entry = (send_q_t *)mem_malloc(sizeof(send_q_t)); q_entry->send_buf = data; q_entry->buf_len = len; q_entry->send_len = 0; q_entry->next = NULL; send_q_t **curr = &con->send_q_head; while(*curr) *curr = (*curr)->next; *curr = q_entry; return con->send_q_count; }
static void finish_connecting(void *v_c) { struct connector *c = v_c; struct client_socket *s = c->socket; for (;;) { if (!wait_list_down(&c->connecting, 1, &c->tasklet)) return; if (c->connected) { int fd = c->fd; struct watched_fd *watched_fd = c->watched_fd; c->fd = -1; connector_destroy(c); s->connector = NULL; simple_socket_set_fd(&s->base, fd, watched_fd); /* Access to the ops pointer is not locked. * But it is fine if some threads continue to * use the old client_socket_ops value. */ s->base.base.ops = &simple_socket_ops; /* Tasklet got destroyed, so we are still holding the associated lock. */ mutex_unlock(&s->base.mutex); return; } else { /* Got POLLERR */ int e; socklen_t len = sizeof e; const char *syscall = "connect"; if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &e, &len)) { e = errno; syscall = "getsockopt"; } if (e) { /* Stash the error and try another address */ error_errno_val(&c->err, e, "%s", syscall); start_connecting(c); } /* Strange, no error. Continue to poll. */ else if (!watched_fd_set_interest(c->watched_fd, WATCHED_FD_OUT, &c->err)) { simple_socket_wake_all(&c->socket->base); } } } }
static void client_socket_destroy(struct stream *gs) { struct client_socket *s = (struct client_socket *)gs; assert(((struct socket *)gs)->ops == &client_socket_ops); mutex_lock(&s->base.mutex); if (s->connector) connector_destroy(s->connector); simple_socket_fini(&s->base); free(s); }
// -1,连接状态异常,需要清空事件 int connector_recv(int fd) { connector_t *con = connector_get_ptr(fd); // 缓冲区满继续期望读,返回异常 if(con->recv_len == MAX_RECV_BUF_LEN) { logging_trace("%s:%d %d recv_buf overflow", con->ip, con->port, fd); con->closed_flag = 1; if(con->processing_count == 0) connector_destroy(fd); return -1; } int num = net_read_n(fd, con->recv_buf + con->recv_len, MAX_RECV_BUF_LEN - con->recv_len); logging_trace("%s:%d %d read %d bytes", con->ip, con->port, fd, num); if(num == -1) { con->closed_flag = 1; if(con->processing_count == 0) connector_destroy(fd); return -1; } gettimeofday(&(con->updated_at), NULL); con->recv_len += num; logging_trace("%s:%d %d recv_len %d", con->ip, con->port, fd); return 0; }
// -1,超时异常,需要清空事件 int connector_check_timeout(int fd, struct timeval *tv, int idle_timeout_ms) { connector_t *con = connector_get_ptr(fd); if(con->closed_flag) return 0; int milliseconds = 1000 * (tv->tv_sec - con->updated_at.tv_sec) + (tv->tv_usec - con->updated_at.tv_usec) / 1000; if(milliseconds > idle_timeout_ms) { logging_trace("%s:%d %d check idle_timeout", con->ip, con->port, fd); con->closed_flag = 1; if(con->processing_count == 0) connector_destroy(fd); return -1; } return 0; }
static enum stream_result client_socket_close(struct stream *gs, struct tasklet *t, struct error *e) { struct client_socket *s = (struct client_socket *)gs; assert(((struct socket *)gs)->ops == &client_socket_ops); mutex_lock(&s->base.mutex); if (!s->connector) { mutex_unlock(&s->base.mutex); return simple_socket_close(gs, t, e); } else { connector_destroy(s->connector); s->connector = NULL; mutex_unlock(&s->base.mutex); return STREAM_OK; } }