void bgcc::SSLEventCallback::SSLAcceptCallback(EventLoop* el, SOCKET fd, void* arg) { int ret; Event e; SSLEventCallbackArg* newCallbackArg = (SSLEventCallbackArg*)arg; BGCC_TRACE("bgcc", "Enter SSL SSLAcceptCallback(fd=%d)", fd); ret = SSL_accept(newCallbackArg->ssl); switch(SSL_get_error(newCallbackArg->ssl, ret)) { case SSL_ERROR_NONE: BGCC_TRACE("bgcc", "ERROR NONE"); PrepareEvent(e, fd, newCallbackArg); if (el->del_event(&e) != 0 || el->add_event(&e) != 0) { SSL_shutdown(newCallbackArg->ssl); BGCC_DEBUG("bgcc", "Memory SSL free: %p", newCallbackArg->ssl); SSL_free(newCallbackArg->ssl); newCallbackArg->ssl = NULL; RemoveFD(el, fd, true); BGCC_TRACE("bgcc", "ssl add_event failed"); } break; case SSL_ERROR_WANT_ACCEPT: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: BGCC_TRACE("bgcc", "WANT ACCPET"); break; default: BGCC_TRACE("bgcc", "DEFAULT"); SSL_shutdown(newCallbackArg->ssl); BGCC_DEBUG("bgcc", "Memory SSL free: %p", newCallbackArg->ssl); SSL_free(newCallbackArg->ssl); newCallbackArg->ssl = NULL; RemoveFD(el, fd, true); break; } BGCC_TRACE("bgcc", "Leave SSL SSLAcceptCallback(fd=%d)", fd); }
/*! Removes the file descriptor from the specified slot. */ static struct file_descriptor* remove_fd(struct io_context* context, int fd) { struct file_descriptor* descriptor = NULL; if (fd < 0) return NULL; mutex_lock(&context->io_mutex); if ((uint32)fd < context->table_size) descriptor = context->fds[fd]; select_info* selectInfos = NULL; bool disconnected = false; if (descriptor != NULL) { // fd is valid TFD(RemoveFD(context, fd, descriptor)); context->fds[fd] = NULL; fd_set_close_on_exec(context, fd, false); context->num_used_fds--; selectInfos = context->select_infos[fd]; context->select_infos[fd] = NULL; disconnected = (descriptor->open_mode & O_DISCONNECTED); } mutex_unlock(&context->io_mutex); if (selectInfos != NULL) deselect_select_infos(descriptor, selectInfos, true); return disconnected ? NULL : descriptor; }
void bgcc::EventCallback::DataCallback(EventLoop* el, SOCKET fd, void* arg) { int32_t ret=0; char *p=NULL; bgcc::Mempool* mempool = bgcc::Mempool::get_instance(); bgcc::ReadItem *pItem=&(Items[fd]); reading_item_t& item = pItem->item; p = item.head_buf; if(S_SIZE_READING == item.state){ p = item.head_buf; } else if(S_DATA_READING == item.state){ p = item.data; } BGCC_TRACE("bgcc", "Enter DataCallback(fd=%d)", fd); while (true){ ret = recv(fd, p+item.nread, item.nexpected, 0); if(ret>0){ item.nread += ret; item.nexpected -= ret; if (0 == item.nexpected) { if (S_SIZE_READING == item.state) { if (item.head_buf[0] != 'b' || item.head_buf[1] != 'g' || item.head_buf[2] != 'c' || item.head_buf[3] != 'P') { BGCC_WARN("bgcc", "invalid bgcc header(fd=%d)", fd); pItem->err = -1; break; } item.state = S_DATA_READING; item.nexpected = BODY_LEN(p); if (item.nexpected < 0){ BGCC_WARN("bgcc", "Message body length=%d too short, remove from epoll", item.nexpected); break; } else if(0==item.nexpected){ BGCC_TRACE("bgcc", "Empty body Package"); break; } item.data = (char*)mempool->get_mem_block(item.nexpected); p = item.data; item.nread = 0; continue; } else if (S_DATA_READING == item.state) { pItem->err=0; break; } } } else if (ret<0) { if (SocketTool::is_interrupt()) { continue; } else if (SocketTool::is_wouldblock()) { return; } else { pItem->err=BgccSockGetLastError(); BGCC_WARN("bgcc", "Recv Failed. fd=%d errno=%d", fd, pItem->err); break; } } else{ pItem->err=-1; BGCC_TRACE("bgcc", "Recv Return 0. fd=%d ", fd); break; } } EpollServer *pArg=(EpollServer*)arg; TaskAsso *pT= (pArg?pArg->Tasks+fd:NULL); pT->pLoop=el; pT->pServer=(EpollServer*)arg; pT->pItem=pItem; PrepareEvent(pT->event, fd, arg); pItem->pTask=pT; int32_t todel=1; // save pItem->err and pItem->isEnroll // because pItem may be invalid after Process when err && isEnroll int32_t err = pItem->err; bool is_enroll = pItem->isEnroll; BusizProcessor::Process(pItem, pT, item.nread, &todel); if (err) { if (is_enroll) {//put_conn call RemoveFD, so here not to call RemoveFD if(todel){ BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); SharedPointer<BinaryProtocol> proto = SharedPointer<BinaryProtocol>( new BinaryProtocol( SharedPointer<ServerPeerSocket>( new ServerPeerSocket(fd) ))); SharedPointer<ConnInfo> info=SharedPointer<ConnInfo>( new ConnInfo(proto, pItem) ); if(proto.is_valid()&&info.is_valid()){ bgcc::ConnectionManager::get_instance()->put_connection(pItem->item.memo, info, true); } } } else{ BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); RemoveFD(el,fd); } } BGCC_TRACE("bgcc", "Leave DataCallback(fd=%d)", fd); }
void bgcc::SSLEventCallback::DataCallback(EventLoop* el, SOCKET fd, void* arg) { int32_t ret = 0; char* p = NULL; bgcc::Mempool* mempool = bgcc::Mempool::get_instance(); struct SSLEventCallbackArg* callbackArg = (struct SSLEventCallbackArg*)arg; bgcc::ReadItem* pItem = &(Items[fd]); reading_item_t& item = pItem->item; p = item.head_buf; if (S_SIZE_READING == item.state) { p = item.head_buf; } else if (S_DATA_READING == item.state) { p = item.data; } BGCC_TRACE("bgcc", "Enter SSL DataCallback(fd=%d)", fd); if (!callbackArg->ssl) { BGCC_TRACE("bgcc", "callbackArg->ssl is NULL, we should not be here."); TimeUtil::safe_sleep_ms(0); BGCC_TRACE("bgcc", "Leave SSL DataCallback(fd=%d)", fd); return; } bool do_while = true; while (true && do_while) { ret = SSL_read(callbackArg->ssl, p + item.nread, item.nexpected); switch(SSL_get_error(callbackArg->ssl, ret)) { case SSL_ERROR_NONE: item.nread += ret; item.nexpected -= ret; if (0 == item.nexpected) { if (S_SIZE_READING == item.state) { if (item.head_buf[0] != 'b' || item.head_buf[1] != 'g' || item.head_buf[2] != 'c' || item.head_buf[3] != 'P') { BGCC_WARN("bgcc", "invalid bgcc header(fd=%d)", fd); pItem->err = -1; do_while = false; break; } item.state = S_DATA_READING; item.nexpected = BODY_LEN(p); if (item.nexpected < 0) { BGCC_WARN("bgcc", "Message body length=%d too short, remove from epoll", item.nexpected); do_while = false; break; } else if (0 == item.nexpected) { BGCC_TRACE("bgcc", "Empty body Package"); do_while = false; break; } item.data = (char*)mempool->get_mem_block(item.nexpected); p = item.data; item.nread = 0; continue; } else if (S_DATA_READING == item.state) { pItem->err = 0; do_while = false; break; } } continue; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: return; default: pItem->err = -1; do_while = false; break; } } SSLEpollServer* pArg = (SSLEpollServer*)callbackArg->arg; TaskAsso* pT = pArg ? pArg->Tasks+fd : NULL; pT->pLoop = el; pT->pServer = pArg; pT->pItem = pItem; PrepareEvent(pT->event, fd, arg); pItem->pTask = pT; int32_t todel = 1; BusizProcessor::Process(pItem, pT, item.nread, &todel, true, arg); if (pItem->err) { SSL_shutdown(callbackArg->ssl); BGCC_DEBUG("bgcc", "Memory SSL free: %p", callbackArg->ssl); SSL_free(callbackArg->ssl); callbackArg->ssl = NULL; if (pItem->isEnroll) { if(todel){ BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); SharedPointer<BinaryProtocol> proto = SharedPointer<BinaryProtocol>( new BinaryProtocol( SharedPointer<ServerPeerSocket>( new ServerPeerSocket(fd) ))); SharedPointer<ConnInfo> info=SharedPointer<ConnInfo>( new ConnInfo(proto, pItem) ); if(proto.is_valid()&&info.is_valid()){ bgcc::ConnectionManager::get_instance()->put_connection(pItem->item.memo, info, true); } } } else { BGCC_WARN("bgcc", "Other Party is Closed Or Protocol Is Invalid, Force To Release fd=%d", fd); RemoveFD(el,fd); } } BGCC_TRACE("bgcc", "Leave SSL DataCallback(fd=%d)", fd); }