int fd_collection::addpipe(int fdrd, int fdwr) { fdcoll_logfunc("fdrd=%d, fdwr=%d", fdrd, fdwr); if (!is_valid_fd(fdrd) || !is_valid_fd(fdwr)) return -1; lock(); // Sanity check to remove any old objects using the same fd!! socket_fd_api* p_fdrd_api_obj = get_sockfd(fdrd); BULLSEYE_EXCLUDE_BLOCK_START if (p_fdrd_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate object (%p)", fdrd, p_fdrd_api_obj); unlock(); handle_close(fdrd, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END socket_fd_api* p_fdwr_api_obj = get_sockfd(fdwr); BULLSEYE_EXCLUDE_BLOCK_START if (p_fdwr_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate object (%p)", fdwr, p_fdwr_api_obj); unlock(); handle_close(fdwr, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END unlock(); p_fdrd_api_obj = new pipeinfo(fdrd); p_fdwr_api_obj = new pipeinfo(fdwr); lock(); BULLSEYE_EXCLUDE_BLOCK_START if (p_fdrd_api_obj == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new pipeinfo (%m)", fdrd); } if (p_fdwr_api_obj == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new pipeinfo (%m)", fdwr); } BULLSEYE_EXCLUDE_BLOCK_END m_p_sockfd_map[fdrd] = p_fdrd_api_obj; m_p_sockfd_map[fdwr] = p_fdwr_api_obj; unlock(); return 0; }
void run() { while(1) { int fd_client; get_sockfd(fd_client); handle_chat(fd_client); } }
int fd_collection::add_cq_channel_fd(int cq_ch_fd, ring* p_ring) { fdcoll_logfunc("cq_ch_fd=%d", cq_ch_fd); if (!is_valid_fd(cq_ch_fd)) return -1; lock(); epfd_info* p_fd_info = get_epfd(cq_ch_fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_fd_info) { fdcoll_logwarn("[fd=%d] Deleting old duplicate sockinfo object (%p)", cq_ch_fd, p_fd_info); unlock(); handle_close(cq_ch_fd, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END // Sanity check to remove any old objects using the same fd!! socket_fd_api* p_cq_ch_fd_api_obj = get_sockfd(cq_ch_fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_cq_ch_fd_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate object (%p)", cq_ch_fd, p_cq_ch_fd_api_obj); unlock(); handle_close(cq_ch_fd, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END // Check if cq_channel_info was already created cq_channel_info* p_cq_ch_info = get_cq_channel_fd(cq_ch_fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_cq_ch_info) { fdcoll_logwarn("cq channel fd already exists in fd_collection"); m_p_cq_channel_map[cq_ch_fd] = NULL; delete p_cq_ch_info; p_cq_ch_info = NULL; } BULLSEYE_EXCLUDE_BLOCK_END unlock(); p_cq_ch_info = new cq_channel_info(p_ring); lock(); BULLSEYE_EXCLUDE_BLOCK_START if (p_cq_ch_info == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new cq_channel_info (%m)", cq_ch_fd); } BULLSEYE_EXCLUDE_BLOCK_END m_p_cq_channel_map[cq_ch_fd] = p_cq_ch_info; unlock(); return 0; }
void private_chat(sLoginInfo *send, int newfd) { char dest[BUF_SIZE] = {0}; char no_user_online[] = {"user on online!"}; if(get_sockfd(send->login_name) == OK) write(newfd, no_user_online, strlen(no_user_online)+1);//error newfd else // format_buf(dest,send->buf, newfd); ; write(newfd, dest, strlen(dest)+1);//error newfd }
//Triggers connection close of all handled fds. //This is important for TCP connection which needs some time to terminate the connection, //before the connection can be finally and properly closed. void fd_collection::prepare_to_close() { lock(); for (int fd = 0; fd < m_n_fd_map_size; ++fd) { if (m_p_sockfd_map[fd]) { if(!g_is_forked_child) { socket_fd_api *p_sfd_api = get_sockfd(fd); if (p_sfd_api) { p_sfd_api->prepare_to_close(true); } } } } unlock(); }
int fd_collection::del_sockfd(int fd, bool b_cleanup /*=false*/) { int ret_val = -1; socket_fd_api *p_sfd_api; p_sfd_api = get_sockfd(fd); if (p_sfd_api) { //TCP socket need some timer to before it can be deleted, //in order to gracefuly terminate TCP connection //so we have to stages: //1. Prepare to close: kikstarts TCP connection termination //2. Socket deletion when TCP connection == CLOSED if (p_sfd_api->prepare_to_close()) { //the socket is already closable ret_val = del(fd, b_cleanup, m_p_sockfd_map); } else { lock(); //The socket is not ready for close. //Delete it from fd_col and add it to pending_to_remove list. //This socket will be handled and destroyed now by fd_col. //This will be done from fd_col timer handler. if (m_p_sockfd_map[fd] == p_sfd_api) { m_p_sockfd_map[fd] = NULL; m_pendig_to_remove_lst.push_front(p_sfd_api); } if (m_pendig_to_remove_lst.size() == 1) { //Activate timer try { m_timer_handle = g_p_event_handler_manager->register_timer_event(250, this, PERIODIC_TIMER, 0); } catch (vma_exception &error) { fdcoll_logdbg("recovering from %s", error.what()); unlock(); return -1; } } unlock(); ret_val = 0; } } return ret_val; }
void fd_collection::statistics_print_helper(int fd, vlog_levels_t log_level) { socket_fd_api* socket_fd; epfd_info* epoll_fd; if ((socket_fd = get_sockfd(fd))) { vlog_printf(log_level, "==================== SOCKET FD ===================\n"); socket_fd->statistics_print(log_level); goto found_fd; } if ((epoll_fd = get_epfd(fd))) { vlog_printf(log_level, "==================== EPOLL FD ====================\n"); epoll_fd->statistics_print(log_level); goto found_fd; } return; found_fd: vlog_printf(log_level, "==================================================\n"); }
int fd_collection::addsocket(int fd, int domain, int type, bool check_offload /*= false*/) { transport_t transport; const int SOCK_TYPE_MASK = 0xf; int sock_type = type & SOCK_TYPE_MASK; int sock_flags = type & ~SOCK_TYPE_MASK; if (check_offload && !create_offloaded_sockets()) { fdcoll_logdbg("socket [fd=%d, domain=%d, type=%d] is not offloaded by thread rules or by VMA_OFFLOADED_SOCKETS", fd, domain, type); return -1; } // IPV4 domain only (at least today) if (domain != AF_INET) return -1; fdcoll_logfunc("fd=%d", fd); if (!is_valid_fd(fd)) return -1; lock(); // Sanity check to remove any old sockinfo object using the same fd!! socket_fd_api* p_sfd_api_obj = get_sockfd(fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_sfd_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate sockinfo object (%p)", fd, p_sfd_api_obj); unlock(); handle_close(fd); lock(); } BULLSEYE_EXCLUDE_BLOCK_END unlock(); try { switch (sock_type) { case SOCK_DGRAM: { transport = __vma_match_by_program(PROTO_UDP, safe_mce_sys().app_id); if (transport == TRANS_OS) { fdcoll_logdbg("All UDP rules are consistent and instructing to use OS. TRANSPORT: OS"); return -1; } fdcoll_logdbg("UDP rules are either not consistent or instructing to use VMA. TRANSPORT: VMA"); p_sfd_api_obj = new sockinfo_udp(fd); break; } case SOCK_STREAM: { transport = __vma_match_by_program(PROTO_TCP, safe_mce_sys().app_id); if (transport == TRANS_OS) { fdcoll_logdbg("All TCP rules are consistent and instructing to use OS.transport == USE_OS"); return -1; } fdcoll_logdbg("TCP rules are either not consistent or instructing to use VMA.transport == USE_VMA"); p_sfd_api_obj = new sockinfo_tcp(fd); break; } default: fdcoll_logdbg("unsupported socket type=%d", sock_type); return -1; } } catch (vma_exception& e) { fdcoll_logdbg("recovering from %s", e.what()); return -1; } lock(); BULLSEYE_EXCLUDE_BLOCK_START if (p_sfd_api_obj == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new sockinfo (%m)", fd); } BULLSEYE_EXCLUDE_BLOCK_END if (sock_flags) { if (sock_flags & SOCK_NONBLOCK) p_sfd_api_obj->fcntl(F_SETFL, O_NONBLOCK); if (sock_flags & SOCK_CLOEXEC) p_sfd_api_obj->fcntl(F_SETFD, FD_CLOEXEC); } m_p_sockfd_map[fd] = p_sfd_api_obj; unlock(); return fd; }
void fd_collection::clear() { int fd; fdcoll_logfunc(""); if (!m_p_sockfd_map) return; lock(); if (m_timer_handle) { g_p_event_handler_manager->unregister_timer_event(this, m_timer_handle); m_timer_handle = 0; } //internal thread should be already dead and these sockets should have been deleted through the internal thread. sock_fd_api_list_t::iterator itr; for (itr = m_pendig_to_remove_lst.begin(); itr != m_pendig_to_remove_lst.end(); itr++) { (*itr)->force_close(); } // Clean up all left overs sockinfo for (fd = 0; fd < m_n_fd_map_size; ++fd) { if (m_p_sockfd_map[fd]) { if(!g_is_forked_child) { socket_fd_api *p_sfd_api = get_sockfd(fd); if (p_sfd_api) { p_sfd_api->statistics_print(); p_sfd_api->destructor_helper(); } } /**** Problem here - if one sockinfo is in a blocked call rx()/tx() then this will block too!!! * also - statistics_print() and destructor_helper() should not be called in two lines above, because they are called from the dtor delete m_p_sockfd_map[fd]; */ m_p_sockfd_map[fd] = NULL; fdcoll_logdbg("destroyed fd=%d", fd); } if (m_p_epfd_map[fd]) { epfd_info *p_epfd = get_epfd(fd); if (p_epfd) { delete p_epfd; } m_p_epfd_map[fd] = NULL; fdcoll_logdbg("destroyed epfd=%d", fd); } if (m_p_cq_channel_map[fd]) { cq_channel_info *p_cq_ch_info = get_cq_channel_fd(fd); if (p_cq_ch_info) { delete p_cq_ch_info; } m_p_cq_channel_map[fd] = NULL; fdcoll_logdbg("destroyed cq_channel_fd=%d", fd); } if (m_p_tap_map[fd]) { m_p_tap_map[fd] = NULL; fdcoll_logdbg("destroyed tapfd=%d", fd); } } unlock(); fdcoll_logfunc("done"); }