void CDataQueue::WriteData(const char* buffer,int buffersize) { while(buffersize) { char* writepos; int towrite; WantWrite(&writepos,buffersize,&towrite); memcpy(writepos,buffer,towrite); buffer+=towrite; buffersize-=towrite; WriteMoveNext(towrite); } }
void epollEngine::MessageLoop() { const static int maxevents = 1024; struct epoll_event events[1024]; int nfds, i; BaseSocket * s; while(m_running) { nfds = epoll_wait(epoll_fd, events, maxevents, 1000); for(i = 0; i < nfds; ++i) { s = fds[events[i].data.fd]; if(s == 0) { printf("epoll returned invalid fd %u\n", events[i].data.fd); continue; } if(events[i].events & EPOLLHUP || events[i].events & EPOLLERR) { s->OnError(errno); } else if(events[i].events & EPOLLIN) { s->OnRead(0); if(s->Writable() && !s->m_writeLock) { ++s->m_writeLock; WantWrite(s); } } else if(events[i].events & EPOLLOUT) { s->OnWrite(0); if(!s->Writable()) { /* change back to read state */ struct epoll_event ev; memset(&ev, 0, sizeof(epoll_event)); ev.data.fd = s->GetFd(); ev.events = EPOLLIN | EPOLLET; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, s->GetFd(), &ev); --s->m_writeLock; } } } } }
//core algorithm !! bool Client::StatusMachine() { std::string::size_type newline; PluginStatus plugin_status; RequestStatus request_status; while (true) { switch (m_status) { case BEFORE_REQUEST: //transitional status if (!PluginBeforeRequest()) { return false; } WantRead(); SetStatus(ON_REQUEST); break; case ON_REQUEST: //lasting status if (!PluginOnRequest()) { return false; } request_status = GetHttpRequest(); if (request_status == REQ_ERROR) { return false; } else if (request_status == REQ_IS_COMPLETE) { SetStatus(AFTER_REQUEST); break; } else { return true; } case AFTER_REQUEST: //transitional status if (!PluginAfterRequest()) { return false; } NotWantRead(); SetStatus(BEFORE_RESPONSE); break; case BEFORE_RESPONSE: //transitional status if (!PluginBeforeResponse()) { return false; } WantWrite(); SetStatus(ON_RESPONSE); break; case ON_RESPONSE: //lasting status plugin_status = PluginOnResponse(); if (plugin_status == ERROR) { //need to send back 500(Server Internal Error) SetStatus(BEFORE_ERROR); continue; } else if (plugin_status == NOT_OK) { //Plugin isn't ready, we continue with other client return true; } //All Plugins have been finished, Send out the response. m_outbuf += m_response.SerializeResponse(); SetStatus(AFTER_RESPONSE); break; case AFTER_RESPONSE: //transitional status if (!PluginAfterResponse()) { return false; } delete m_request; m_request = NULL; m_response.ResetResponse(); NotWantWrite(); SetStatus(BEFORE_REQUEST); break; case BEFORE_ERROR: m_response.ResetResponse(); m_response.m_code = 500; m_response.m_explain = "Server Error"; m_response.m_headers["Date"] = "Fri, 27 October 2012 15:45:00 GMT"; m_outbuf += m_response.SerializeResponse(); SetStatus(ON_ERROR); break; case ON_ERROR: if (!m_outbuf.size()) //keep write event to check if 500 response has been sent away { return false; //let the client leave, error 500 has been sent away. } return true; } } return true; }
bool IOCPEngine::AddFd(EventHandler* eh) { /* Does it at least look valid? */ if (!eh) return false; int* fake_fd = new int(GenerateFd(eh->GetFd())); int is_accept = 0; int opt_len = sizeof(int); /* In range? */ if ((*fake_fd < 0) || (*fake_fd > MAX_DESCRIPTORS)) { delete fake_fd; return false; } /* Already an entry here */ if (ref[*fake_fd]) { delete fake_fd; return false; } /* are we a listen socket? */ getsockopt(eh->GetFd(), SOL_SOCKET, SO_ACCEPTCONN, (char*)&is_accept, &opt_len); /* set up the read event so the socket can actually receive data :P */ eh->Extend("internal_fd", fake_fd); unsigned long completion_key = (ULONG_PTR)*fake_fd; /* assign the socket to the completion port */ if (!CreateIoCompletionPort((HANDLE)eh->GetFd(), m_completionPort, completion_key, 0)) return false; /* setup initial events */ if(is_accept) PostAcceptEvent(eh); else PostReadEvent(eh); /* log message */ ServerInstance->Logs->Log("SOCKET",DEBUG, "New fake fd: %u, real fd: %u, address 0x%p", *fake_fd, eh->GetFd(), eh); /* post a write event if there is data to be written */ if(eh->Writeable()) WantWrite(eh); /* we're all good =) */ try { m_binding.insert( std::map<int, EventHandler*>::value_type( eh->GetFd(), eh ) ); } catch (...) { /* Ohshi-, map::insert failed :/ */ return false; } ++CurrentSetSize; ref[*fake_fd] = eh; return true; }
bool TcpServer::_StartUpLin() { #ifndef WIN32 int loop_times = 0; const int timer_check_point = 10; //达到指定循环次数即开始timer检查 while(m_bRun) { int res = epoll_wait(m_epoll_fd, m_epev_arr, EVENT_TOTAL_COUNT, 100); if ( res < 0) { //及时退出,否则会导致 CPU 100% if (EINTR == errno) continue; log_debug("epoll_wait return false, errno = %d\n", errno); break; } else if (0 == res) { //timeout loop_times = 0; run_timer(); } else { //间隔一定次数即开始检查定时器的超时事件 if (++loop_times >= timer_check_point) { loop_times = 0; //驱动定时器处理 run_timer(); } } for(int i=0; i<res; i++) { if(m_epev_arr[i].data.fd == m_listen_fd) { handle_accept(); continue; } int fd = (uint32_t)m_epev_arr[i].data.u64; /* mask out the lower 32 bits */ uint32 index = (uint32_t)(m_epev_arr[i].data.u64 >> 32); TcpHandler* s = fds[fd]; if( s == 0 || s->get_fd_index() != index ) { continue; // epoll returned invalid fd } if( m_epev_arr[i].events & ( EPOLLHUP | EPOLLERR )) { handle_close(s); continue; } else if(m_epev_arr[i].events & EPOLLIN ) { if(s->handle_read() == -1) { handle_close(s); continue; } if( s->Writable() ) WantWrite(s); } else if(m_epev_arr[i].events&EPOLLOUT) { if(s->handle_output() == -1) { handle_close(s); continue; } if(!s->Writable()) WantRead(s); } } } #endif return true; }
void kqueueEngine::MessageLoop() { const static int maxevents = MAX_DESCRIPTORS; timespec timeout; timeout.tv_sec = 1; timeout.tv_nsec = 0; struct kevent events[MAX_DESCRIPTORS]; struct kevent ev; int nfds, i; BaseSocket * s; while(m_running) { nfds = kevent(kq, 0, 0, events, maxevents, &timeout); for(i = 0; i < nfds; ++i) { s = fds[events[i].ident]; if(s == 0) { printf("kqueue returned invalid fd %u\n", events[i].ident); continue; } if(events[i].flags & EV_EOF || events[i].flags & EV_ERROR) { s->OnError(events[i].fflags); continue; } if(events[i].filter == EVFILT_READ) { s->OnRead(0); if(s->Writable() && !s->m_writeLock) { ++s->m_writeLock; WantWrite(s); } } else if(events[i].filter == EVFILT_WRITE) { s->OnWrite(0); if(!s->Writable()) { --s->m_writeLock; EV_SET(&ev, s->GetFd(), EVFILT_READ, EV_ADD, 0, 0, NULL); if(kevent(kq, &ev, 1, NULL, 0, NULL) < 0) printf("!! could not modify kevent (to read) for fd %u\n", s->GetFd()); } else { EV_SET(&ev, s->GetFd(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, NULL); if(kevent(kq, &ev, 1, NULL, 0, NULL) < 0) printf("!! could not modify kevent (to write) for fd %u\n", s->GetFd()); } } else { printf("Unknwon filter: %u Fflags: %u, fd: %u, flags: %u\n", events[i].filter, events[i].fflags, events[i].ident, events[i].flags); } } } }