void handle_accept(struct net_service* service, int ret, int err, struct accept_session* asession) { struct net_session* session; unsigned int session_index; // asession = (struct accept_session*)ov_data; if( !asession || asession->id == 0) { release_accept_session(asession); return; } session_index = ffid_index(service->socket_ids, asession->id); net_lock(&service->session_lock[session_index]); session = service->sessions[session_index]; if (!ret && err) { net_close_fd(asession->accept_socket); if (!session || !session->lsession || session->id != asession->id) { net_unlock(&service->session_lock[session_index]); push_queue_with_lock(service, asession->id, Eve_Post_Listen_Error); release_accept_session(asession); return; } } else { if (!session || !session->lsession || session->id != asession->id) { net_unlock(&service->session_lock[session_index]); push_queue_with_lock(service, asession->id, Eve_Post_Listen_Error); release_accept_session(asession); return; } if (!push_queue(service, session, Eve_Accept)) { net_close_fd(asession->accept_socket); } else if (msg_buff_write(session->lsession->socket_queue, (void*)&asession->accept_socket) != 1) { net_close_fd(asession->accept_socket); } else { setsockopt(asession->accept_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&session->fd, sizeof(session->fd)); } } net_unlock(&service->session_lock[session_index]); asession->accept_socket = 0; if(post_listen(service, session, asession)) { release_accept_session(asession); push_queue_with_lock(service, session->id, Eve_Post_Listen_Error); } }
NET_API net_socket net_accept(struct net_service* service, net_socket fd) { struct net_session* session; struct net_session* accept_session; unsigned short index; NET_SOCKET s; if(!service || fd == 0) { return 0; } index = ffid_index(service->socket_ids, fd); net_lock(&service->session_lock[index]); session = service->sessions[index]; if(!session || !session->lsession || session->id != fd) { net_unlock(&service->session_lock[index]); return 0; } if(msg_buff_read(session->lsession->socket_queue, &s, 1) != 1) { net_unlock(&service->session_lock[index]); return 0; } net_unlock(&service->session_lock[index]); accept_session = create_and_add_net_session(service, s); if(!accept_session) { net_close_fd(s); return 0; } return accept_session->id; }
NET_API net_socket net_accept(struct net_service* service, net_socket nd) { unsigned short index; struct net_session* session; struct net_session* new_session; int fd; ffid_vtype id; if(!service || !nd) return 0; index = ffid_index(service->socket_ids, nd); net_lock(&service->session_lock[index]); session = service->sessions[index]; if(!session || !session->lsession || session->id != nd) { net_unlock(&service->session_lock[index]); return 0; } fd = accept(session->fd, 0, 0); if(fd < 0) { net_unlock(&service->session_lock[index]); return 0; } ctl_socket_async(fd); new_session = create_net_session(); if(!new_session) { net_close_fd(fd); net_unlock(&service->session_lock[index]); return 0; } net_unlock(&service->session_lock[index]); new_session->fd = fd; id = add_net_session(service, new_session); if(!id) { release_net_session(new_session); net_close_fd(fd); return 0; } return id; }
NET_API void net_socket_close(struct net_service* service, net_socket nd, char send_rest) { unsigned short index; struct net_session* session; sb_tree_value v; if(!service) { return; } if(!nd) { return; } index = ffid_index(service->socket_ids, nd); net_lock(&service->session_lock[index]); session = service->sessions[index]; if(!session || session->id != nd) { net_unlock(&service->session_lock[index]); return; } // epoll_ctl(service->net_service_fd, EPOLL_CTL_DEL, session->fd, 0); clean_epoll_op(service, session); if(send_rest) { post_write(service, session); } service->sessions[index] = 0; // release read session release_read_session(session->rsession); session->rsession = 0; if(session->wsession && session->wsession->op == OP_NET_WRITE) { session->wsession->send_rest = send_rest; shutdown(session->fd, 0); release_listen_session(session->lsession); session->lsession = 0; // join to close_root sb_tree net_lock(&service->close_lock); v.ptr = session; sb_tree_insert(&service->close_root , nd, v); net_unlock(&service->close_lock); } else { net_close_fd(session->fd); release_net_session(session); } net_unlock(&service->session_lock[index]); net_lock(&service->id_lock); ffid_del_id(service->socket_ids, nd); net_unlock(&service->id_lock); }
void daemon_terminate( int sig, const char *name ) { alarm(0); printf("daemon_terminate: %s\n", name); net_close_fd(); exit(0); }
void release_rest_session(struct net_service* service, struct net_session* session) { net_lock(&service->close_lock); sb_tree_delete(&service->close_root, session->id); net_unlock(&service->close_lock); clean_epoll_op(service, session); net_close_fd(session->fd); release_net_session(session); }
void release_accept_session(struct accept_session* asession) { if(!asession) { return; } if(asession->accept_socket) { net_close_fd(asession->accept_socket); } free(asession); }
NET_API void net_socket_close(struct net_service* service, net_socket nd, char send_rest) { unsigned short index; struct net_session* session; if(!service) { return; } if(!nd) { return; } index = ffid_index(service->socket_ids, nd); net_lock(&service->session_lock[index]); session = service->sessions[index]; if(!session || session->id != nd) { net_unlock(&service->session_lock[index]); return; } if(send_rest) { post_write(service, session); } service->sessions[index] = 0; if(session->wsession && session->wsession->op == OP_NET_WRITE) { shutdown(session->fd, 0); session->wsession->fd = session->fd; session->wsession->send_rest = send_rest; } else { shutdown(session->fd, SD_BOTH); net_close_fd(session->fd); } release_net_session(session); net_unlock(&service->session_lock[index]); net_lock(&service->id_lock); ffid_del_id(service->socket_ids, nd); net_unlock(&service->id_lock); }
int post_listen(struct net_service* service, struct net_session* session, struct accept_session* asession) { NET_SOCKET accept_socket; int err; accept_socket = create_socket(); if(NET_INVALID_SOCKET == accept_socket) { return -1; } CreateIoCompletionPort((HANDLE)accept_socket, service->net_service_fd, (ULONG_PTR)accept_socket, sizeof(NET_SOCKET)); memset(asession, 0, sizeof(struct accept_session)); asession->id = session->id; asession->accept_socket = accept_socket; asession->op = OP_NET_ACCEPT; if(!AcceptEx( session->fd, accept_socket, asession->data_buf, 0, sizeof(struct sockaddr_in) + 32, sizeof(struct sockaddr_in) + 32, &asession->recv_bytes, &asession->overlapped )) { err = net_get_error(); if(ERROR_IO_PENDING != err) { net_close_fd(accept_socket); return err; } } return NO_ERROR; }
void release_listen_session(struct listen_session* lsession) { NET_SOCKET s[32]; int cnt, i; if(!lsession) { return; } if(lsession->socket_queue) { while((cnt = msg_buff_read(lsession->socket_queue, s, sizeof(s)/sizeof(s[0])))) { for(i = 0; i < cnt; ++i) { net_close_fd(s[i]); } } msg_buff_release(lsession->socket_queue); } free(lsession); }
NET_API net_socket net_connect(struct net_service* service, const char* ip, unsigned short port) { int connect_socket; struct sockaddr_in connect_addr; struct epoll_event ev; struct net_session* session; int ret; ffid_vtype id; connect_socket = create_socket(); if(connect_socket < 0) { return 0; } ctl_socket_async(connect_socket); session = create_net_session(); if(!session) { net_close_fd(connect_socket); return 0; } session->fd = connect_socket; session->connect_flag = 1; id = add_net_session(service, session); if(!id) { release_net_session(session); net_close_fd(connect_socket); return 0; } memset(&connect_addr, 0, sizeof(connect_addr)); connect_addr.sin_family = AF_INET; connect_addr.sin_addr.s_addr = inet_addr(ip); connect_addr.sin_port = htons(port); ret = connect(connect_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)); if(ret < 0) { ret = net_get_error(); if(ret != EINPROGRESS) { net_socket_close_print_error(); net_socket_close(service, id, 0); return 0; } } memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN | EPOLLOUT | EPOLLET; ev.data.u64 = session->id; if((ret = epoll_ctl(service->net_service_fd, EPOLL_CTL_ADD, connect_socket, &ev))) { ret = net_get_error(); net_socket_close_print_error(); net_socket_close(service, id, 0); return 0; } return id; }
NET_API net_socket net_listen(struct net_service* service, unsigned short port, unsigned short listen_cnt) { int listen_socket; int opt; struct sockaddr_in listen_addr; struct epoll_event ev; struct net_session* session; int ret; ffid_vtype id; listen_socket = create_socket(); if(listen_socket < 0) { // printf("listen error step 0 %d\n", ret); // perror("info:"); return 0; } opt = 1; // listen socket reuse setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); ctl_socket_async(listen_socket); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(port); listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); if((ret = bind(listen_socket, (struct sockaddr*)&listen_addr, sizeof(listen_addr)))) { ret = net_get_error(); // printf("listen error step 1 %d\n", ret); // perror("info:"); net_close_fd(listen_socket); return 0; } if((ret = listen(listen_socket, listen_cnt))) { ret = net_get_error(); // printf("listen error step 2 %d\n", ret); // perror("info:"); net_close_fd(listen_socket); return 0; } session = create_net_session(); if(!session) { // printf("listen error step 3\n"); net_close_fd(listen_socket); return 0; } session->fd = listen_socket; session->lsession = create_listen_session(service, port, listen_cnt); if(!session->lsession) { // printf("listen error step 4 \n"); release_net_session(session); net_close_fd(listen_socket); return 0; } id = add_net_session(service, session); if(!id) { // printf("listen error step 5 \n"); release_net_session(session); net_close_fd(listen_socket); return 0; } memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN | EPOLLOUT | EPOLLET; ev.data.u64 = session->id; if((ret = epoll_ctl(service->net_service_fd, EPOLL_CTL_ADD, listen_socket, &ev))) { ret = net_get_error(); // printf("listen error step 6 %d\n", ret); // perror("info:"); net_socket_close_print_error(); net_socket_close(service, id, 0); return 0; } return id; }
NET_API net_socket net_connect(struct net_service* service, const char* ip, unsigned short port) { NET_SOCKET s; struct sockaddr_in connect_addr; struct net_session* session; struct connect_session* csession; ffid_vtype id; FUN_CONNECTEX connectExFun; int err; s = create_socket(); if(NET_INVALID_SOCKET == s) { return 0; } memset(&connect_addr, 0, sizeof(connect_addr)); connect_addr.sin_family = AF_INET; connect_addr.sin_addr.S_un.S_addr = INADDR_ANY; connect_addr.sin_port = 0; if(bind(s, (struct sockaddr*)&connect_addr, sizeof(connect_addr))) { net_close_fd(s); return 0; } connectExFun = 0; connectExFun = get_connect_ex_fun(s); if(!connectExFun) { net_close_fd(s); return 0; } CreateIoCompletionPort((HANDLE)s, service->net_service_fd, (ULONG_PTR)s, sizeof(NET_SOCKET)); csession = (struct connect_session*)malloc(sizeof(struct connect_session)); if(!csession) { net_close_fd(s); return 0; } memset(csession, 0, sizeof(struct connect_session)); csession->s = s; session = create_net_session(); if(!session) { net_close_fd(s); release_connect_session(csession); return 0; } id = add_net_session(service, session); if(!id) { net_close_fd(s); release_net_session(session); release_connect_session(csession); return 0; } memset(&connect_addr, 0, sizeof(connect_addr)); connect_addr.sin_family = AF_INET; connect_addr.sin_addr.S_un.S_addr = inet_addr(ip); connect_addr.sin_port = htons(port); csession->id = id; csession->op = OP_NET_CONNECT; session->connect_flag = 1; session->fd = s; session->data = 0; if(!connectExFun(s, (struct sockaddr*)&connect_addr, (int)sizeof(connect_addr), 0, 0, (LPDWORD)&csession->send_bytes, (LPOVERLAPPED)&csession->overlapped)) { err = net_get_error(); if(err != ERROR_IO_PENDING) { release_connect_session(csession); net_socket_close(service, id, 0); return 0; } } return id; }
NET_API net_socket net_listen(struct net_service* service, unsigned short port, unsigned short listen_cnt) { ffid_vtype id; NET_SOCKET listen_socket; struct net_session* session; struct sockaddr_in listen_addr; struct accept_session* asession; int i, ret; listen_socket = create_socket(); if(NET_INVALID_SOCKET == listen_socket) { return 0; } CreateIoCompletionPort((HANDLE)listen_socket, service->net_service_fd, (ULONG_PTR)listen_socket, sizeof(NET_SOCKET)); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(port); listen_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); if((ret = bind(listen_socket, (struct sockaddr*)&listen_addr, sizeof(listen_addr)))) { ret = net_get_error(); net_close_fd(listen_socket); return 0; } if(listen(listen_socket, listen_cnt)) { net_close_fd(listen_socket); return 0; } session = create_net_session(); if(!session) { net_close_fd(listen_socket); return 0; } session->fd = listen_socket; session->lsession = create_listen_session(service, port, listen_cnt); if(!session->lsession) { release_net_session(session); net_close_fd(listen_socket); return 0; } id = add_net_session(service, session); if(!id) { release_net_session(session); net_close_fd(listen_socket); return 0; } for(i = 0; i < listen_cnt; ++i) { asession = create_accept_session(); if(asession) { if(!post_listen(service, session, asession)) { asession->index = i; continue; } release_accept_session(asession); } net_socket_close(service, id, 0); return 0; } return id; }
static int _handleconn (int delay_time, int max_cost_time, int error) { if (error) { if (error == 1) { daemon_printf( "%d server temporarily unavailable\n", CODE_TEMPORARILY_UNAVAILABLE ); printf("daemon busy: temporarily unavailable\n"); } else { printf("daemon too busy: drop connection\n"); } net_close_fd(); return 0; } daemon_banner(); std::string buf; std::vector<std::string> *args; alarm(delay_time); while (true) { if (net_read_line(buf)) break; alarm(max_cost_time); printf("%s\n", buf.c_str()); args = args_new(buf.c_str()); if (args->size() == 0) { daemon_printf( "%d no command\n", CODE_SYNTAX_ERROR ); } else if ((*args)[0] == "client" && args->size()>=3) { daemon_client((*args)[1], (*args)[2]); } else if ((*args)[0] == "auth" && args->size()>=3) { daemon_auth((*args)[1], (*args)[2]); } else if ((*args)[0] == "lookup" && args->size()>=2) { if (args->size() >=3) { int wordcount = atoi((*args)[2].c_str()); if (wordcount < 1) { wordcount = 1; } else if (wordcount > 100) { wordcount = 100; } daemon_lookup((*args)[1], wordcount); } else { daemon_lookup((*args)[1], 30); } } else if ((*args)[0] == "query" && args->size()>=2) { daemon_query((*args)[1]); } else if ((*args)[0] == "selectquery" && args->size()>=2) { daemon_selectquery((*args)[1]); } else if ((*args)[0] == "smartquery" && args->size()>=3) { daemon_smartquery((*args)[1], (*args)[2]); } else if ((*args)[0] == "define" && args->size()>=2) { daemon_define((*args)[1]); } else if ((*args)[0] == "previous" && args->size()>=2) { if (args->size() >=3) { int wordcount = atoi((*args)[2].c_str()); if (wordcount < 1) { wordcount = 1; } else if (wordcount > 50) { wordcount = 50; } daemon_previous((*args)[1], wordcount); } else { daemon_previous((*args)[1], 15); } } else if ((*args)[0] == "next" && args->size()>=2) { if (args->size() >=3) { int wordcount = atoi((*args)[2].c_str()); if (wordcount < 1) { wordcount = 1; } else if (wordcount > 100) { wordcount = 100; } daemon_next((*args)[1], wordcount); } else { daemon_next((*args)[1], 30); } } else if ((*args)[0] == "quit" && args->size()>=1) { daemon_quit(); } else if ((*args)[0] == "register" && args->size()>=4) { daemon_register((*args)[1], (*args)[2], (*args)[3]); } else if ((*args)[0] == "change_password" && args->size()>=4) { daemon_change_password((*args)[1], (*args)[2], (*args)[3]); } else if ((*args)[0] == "setdictmask" && args->size()>=2) { daemon_setdictmask((*args)[1]); } else if ((*args)[0] == "getdictmask" && args->size()>=1) { daemon_getdictmask(); } else if ((*args)[0] == "setcollatefunc" && args->size()>=2) { daemon_setcollatefunc((*args)[1]); } else if ((*args)[0] == "getcollatefunc" && args->size()>=1) { daemon_getcollatefunc(); } else if ((*args)[0] == "setlanguage" && args->size()>=2) { daemon_setlanguage((*args)[1]); } else if ((*args)[0] == "getlanguage" && args->size()>=1) { daemon_getlanguage(); } else if ((*args)[0] == "setemail" && args->size()>=2) { daemon_setemail((*args)[1]); } else if ((*args)[0] == "getemail" && args->size()>=1) { daemon_getemail(); } else if ((*args)[0] == "getuserlevel" && args->size()>=1) { daemon_getuserlevel(); } else if ((*args)[0] == "maxdictcount" && args->size()>=1) { daemon_maxdictcount(); } else if ((*args)[0] == "dirinfo" && args->size()>=2) { daemon_dirinfo((*args)[1]); } else if ((*args)[0] == "dictinfo" && args->size()>=2) { daemon_dictinfo((*args)[1]); } else if ((*args)[0] == "userlevel" && args->size()>=4) { daemon_userlevel((*args)[1], (*args)[2], (*args)[3]); } else if ((*args)[0] == "fromto" && args->size() >= 1) { daemon_fromto(); } else if ((*args)[0] == "dictslist" && args->size()>=2) { daemon_dictslist((*args)[1]); } else if ((*args)[0] == "tmpdictmask" && args->size() >= 2) { daemon_LookupinTmpdictmask((*args)[1]); } else if ((*args)[0] == "getadinfo" && args->size()>=1) { daemon_getadinfo(); } else { daemon_printf( "%d unknown command\n", CODE_SYNTAX_ERROR ); } delete args; alarm(delay_time); } daemon_terminate( 0, "close" ); return 0; }