/* Initialise the UDP socket and router worker thread. * Aborts on failure. */ void router_init(void) { /* Event object used for notification of new packets and exit signal. */ if((router_event = WSACreateEvent()) == WSA_INVALID_EVENT) { log_printf(LOG_ERROR, "Error creating WSA event object: %s", w32_error(WSAGetLastError())); abort(); } if(ipx_use_pcap) { if((private_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { log_printf(LOG_ERROR, "Error creating retransmit socket: %s", w32_error(WSAGetLastError())); abort(); } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(0); if(bind(private_socket, (struct sockaddr*)(&addr), sizeof(addr)) == -1) { log_printf(LOG_ERROR, "Error binding retransmit socket: %s", w32_error(WSAGetLastError())); abort(); } } else{ _init_socket(&shared_socket, main_config.udp_port, TRUE); _init_socket(&private_socket, 0, FALSE); } router_running = true; if(!(router_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(&router_main), NULL, 0, NULL))) { log_printf(LOG_ERROR, "Cannot create router worker thread: %s", w32_error(GetLastError())); abort(); } }
acceptor::acc_impl::acc_impl(const char* port) noexcept(false) { _listen_socket = INVALID_SOCKET; _result = NULL; ZeroMemory(&_hints, sizeof(_hints)); _hints.ai_family = AF_INET; _hints.ai_socktype = SOCK_STREAM; _hints.ai_protocol = IPPROTO_TCP; _hints.ai_flags = AI_PASSIVE; error_code err = _init_socket(port); if (err != error_code::NO_ERR) throw tool::exception(err); }
int cnn_start(struct connection_info *ci, bool join) { _init_socket(ci); ci->is_running = 1; if (0 != pthread_create(&ci->tid, NULL, _working, ci)) { log_fatal("failed to create thread"); return 1; } if (join) { if (pthread_join(ci->tid, NULL)) { log_fatal("failed to wait the thread"); return 2; } } return 0; }
static void *_working(void *arg) { pthread_detach(pthread_self()); __lock; _connection_num++; __unlock; struct connection_info *ci = (struct connection_info *) arg; ci->is_connected = 0; struct sockaddr_in server_addr; bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(ci->port); if (0 == inet_aton(ci->ip, &server_addr.sin_addr)) { log_fatal("failed to initialize socket ip"); exit(1); } while (ci->is_running) { int ret = connect(ci->socket, (struct sockaddr *) &server_addr, sizeof(server_addr)); if (0 == ret) { ci->callback_funs.on_connected(ci->id); ci->is_connected = 1; } else if (0 > ret && EINPROGRESS != errno) { log_info("failed to connect to destination"); goo_sleep(ci->reconnect_interval, 0); _fini_socket(ci); _init_socket(ci); continue; } ci->needs_reconnect = 0; struct epoll_event events[EPOLL_EVENT_NUM]; int ret_fds = 0; while (ci->is_running && !ci->needs_reconnect) { ret_fds = epoll_wait(ci->epoll_container, events, EPOLL_EVENT_NUM, ci->reconnect_interval); if (-1 == ret_fds) { switch (errno) { case EBADF: log_fatal("failed to call epoll_wait - EBADF"); exit(1); case EFAULT: log_fatal("failed to call epoll_wait - EFAULT"); exit(1); case EINTR: continue; case EINVAL: log_fatal("failed to call epoll_wait - EINVAL"); exit(1); default: log_fatal("failed to call epoll_wait - Unknown"); exit(1); } } int i = 0; for (; i < ret_fds; i++) { if ((events[i].events & EPOLLERR) && EINPROGRESS != errno) { ci->is_connected = 0; ci->needs_reconnect = 1; ci->callback_funs.on_error(ci->id, errno, strerror(errno)); goo_sleep(ci->reconnect_interval, 0); _fini_socket(ci); _init_socket(ci); break; } if (events[i].events & EPOLLRDHUP) { ci->is_connected = 0; ci->needs_reconnect = 1; ci->callback_funs.on_closed(ci->id); goo_sleep(ci->reconnect_interval, 0); _fini_socket(ci); _init_socket(ci); break; } if (events[i].events & EPOLLOUT) { if (!ci->is_connected) { ci->is_connected = 1; ci->callback_funs.on_connected(ci->id); continue; } } if (events[i].events & EPOLLIN) { unsigned char buffer[RECEIVE_BUFFER_SIZE]; int offset = 0; for (;;) { unsigned char tmp_buf[512]; int len = recv(events[i].data.fd, tmp_buf, 512, 0); if (0 < len) { // read data from socket buffer if (len + offset > RECEIVE_BUFFER_SIZE) { log_fatal("the socket receiving buffer is too " "small"); exit(1); } memcpy(buffer + offset, tmp_buf, len); offset += len; } else if (0 > len) { if (EAGAIN == errno || EWOULDBLOCK == errno) { // socket read buffer is empty if (0 < offset) { buffer[offset] = 0; ci->callback_funs.on_received(ci->id, buffer, offset); offset = 0; } } else { // error happened } break; } else { // the socket has been closed break; } } } } } } ci->is_connected = 0; ci->callback_funs.on_closed(ci->id); _fini_socket(ci); __lock; _connection_num--; __unlock; ci->tid = 0; return NULL; }