static void do_udp_peer_onwrite(void *userdata) { struct udp_peer_notify *notify; udp_peer_t* peer; notify = (struct udp_peer_notify *)userdata; peer = notify->peer; peer->writecb = notify->writecb; peer->write_userdata = notify->write_userdata; free(notify); if (atomic_dec(&peer->ref_count) > 1) { if (NULL == peer->writecb) { channel_clearevent(peer->channel, POLLOUT); peer->message_userdata = NULL; } else { channel_setevent(peer->channel, POLLOUT); } } else { delete_udp_peer(peer); } return; }
static void do_tcp_connection_destroy(void *userdata) { tcp_connection_t* connection = (tcp_connection_t*)userdata; if (buffer_readablebytes(connection->out_buffer) > 0) { channel_clearevent(connection->channel, EPOLLIN); channel_setevent(connection->channel, EPOLLOUT); connection->need_closed_after_sent_done = 1; } else { if (connection->is_in_callback) { connection->is_alive = 0; } else { delete_connection(connection); } } return; }
tcp_connection_t* tcp_connection_new ( loop_t *loop, int fd, on_data_f datacb, on_close_f closecb, void* userdata, const inetaddr_t *peer_addr ) { tcp_connection_t *connection; struct sockaddr_in addr; socklen_t addr_len; struct linger linger_info; int flag; if (NULL == loop || fd < 0 || NULL == datacb || NULL == closecb || NULL == peer_addr) { log_error("tcp_connection_new: bad loop(%p) or bad fd(%d) or bad datacb(%p) or bad closecb(%p) or bad peer_addr(%p)", loop, fd, datacb, closecb, peer_addr); return NULL; } connection = (tcp_connection_t*)malloc(sizeof(*connection)); memset(connection, 0, sizeof(*connection)); flag = 1; setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag)); memset(&linger_info, 0, sizeof(linger_info)); linger_info.l_onoff = 1; linger_info.l_linger = 3; setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger_info, sizeof(linger_info)); connection->loop = loop; connection->fd = fd; connection->datacb = datacb; connection->closecb = closecb; connection->userdata = userdata; connection->channel = channel_new(fd, loop, connection_onevent, connection); connection->in_buffer = buffer_new(4096); connection->out_buffer = buffer_new(4096); connection->is_in_callback = 0; connection->is_alive = 1; connection->is_connected = 1; connection->need_closed_after_sent_done = 0; connection->peer_addr = *peer_addr; memset(&addr, 0, sizeof(addr)); addr_len = sizeof(addr); getsockname(fd, (struct sockaddr*)&addr, &addr_len); inetaddr_init(&connection->local_addr, &addr); channel_setevent(connection->channel, EPOLLIN); return connection; }
static void init_udp_peer_event(void *userdata) { udp_peer_t* peer = (udp_peer_t*)userdata; short event; event = POLLIN; if (NULL != peer->writecb) { event |= POLLOUT; } channel_setevent(peer->channel, event); return; }
async_task_queue_t* async_task_queue_create(loop_t* loop) { async_task_queue_t* task_queue = (async_task_queue_t*)malloc(sizeof(async_task_queue_t)); memset(task_queue, 0, sizeof(*task_queue)); task_queue->loop = loop; socketpair(task_queue->fds); task_queue->channel = channel_new(task_queue->fds[0], loop, async_task_event, task_queue); channel_setevent(task_queue->channel, POLLIN); task_queue->async_task = NULL; task_queue->async_task_end = NULL; lock_init(&task_queue->task_lock); return task_queue; }
static void do_tcp_server_start(void* userdata) { tcp_server_t *server = (tcp_server_t*)userdata; do { server->fd = create_server_socket(server->addr.port, server->addr.ip); if (server->fd < 0) { log_error("do_tcp_server_start: create_server_socket() failed, local addr: %s:%u", server->addr.ip, server->addr.port); break; } server->channel = channel_new(server->fd, server->loop, server_onevent, server); if (listen(server->fd, 512) != 0) { log_error("do_tcp_server_start: listen() failed, errno: %d, local addr: %s:%u", errno, server->addr.ip, server->addr.port); break; } if (channel_setevent(server->channel, EPOLLIN)) { log_error("do_tcp_server_start: channel_setevent() failed, local addr: %s:%u", server->addr.ip, server->addr.port); break; } return; } while(0); if (server->fd >= 0) { close(server->fd); server->fd = -1; } channel_destroy(server->channel); server->channel = NULL; server->is_started = 0; return; }
static int tcp_connection_sendInLoop(tcp_connection_t* connection, const void* data, unsigned size) { inetaddr_t *peer_addr = &connection->peer_addr; int fd; void* buffer_data; channel_t *channel; buffer_t* out_buffer; int written; unsigned buffer_left_data_size; struct iovec vecs[2]; int error; out_buffer = connection->out_buffer; channel = connection->channel; fd = connection->fd; buffer_left_data_size = buffer_readablebytes(out_buffer); if (buffer_left_data_size > 0) { buffer_data = buffer_peek(out_buffer); vecs[0].iov_base = buffer_data; vecs[0].iov_len = buffer_left_data_size; vecs[1].iov_base = (void*)data; vecs[1].iov_len = size; written = writev(fd, vecs, 2); if (written < 0) { error = errno; if (error != EAGAIN) { log_error("tcp_connection_sendInLoop: writev() failed, errno: %d, peer addr: %s:%u", errno, peer_addr->ip, peer_addr->port); return -1; } } else if (written == (buffer_left_data_size+size)) { /* 当前所有的数据都发送完毕,一切安好则去除EPOLLOUT事件 */ channel_clearevent(channel, EPOLLOUT); } else if (written < buffer_left_data_size) { /* out_buffer中的数据尚未发送完毕,则将本次的数据放入out_buffer后再发送 */ buffer_retrieve(out_buffer, written); buffer_append(out_buffer, data, size); channel_setevent(channel, EPOLLOUT); } else if (written < (buffer_left_data_size+size)) { buffer_retrieveall(out_buffer); buffer_append(out_buffer, ((const char*)data+written-buffer_left_data_size), ((buffer_left_data_size+size)-written)); channel_setevent(channel, EPOLLOUT); } } else { written = write(fd, data, size); if (written < 0) { log_error("tcp_connection_sendInLoop: write() failed, errno: %d, peer addr: %s:%u", errno, peer_addr->ip, peer_addr->port); return -1; } else if (written < size) { buffer_append(out_buffer, ((const char*)data+written), (size-written)); channel_setevent(channel, EPOLLOUT); } } return 0; }