bool CDataQueue::ReadData(char* buffer,int wantread,int* readed) { *readed=0; while(wantread) { char* buf; int canread; if(!WantRead(&buf,wantread,&canread)) { return true; } if(canread!=wantread) { int ss=0; } memcpy(buffer,buf,canread); *readed+=canread; wantread-=canread; buffer+=canread; ReadMoveNext(canread); } return true; }
//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 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; }
PRStatus nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, int16_t oflags) { LOGDEBUG(("socks: DoHandshake(), state = %d", mState)); switch (mState) { case SOCKS_INITIAL: return StartDNS(fd); case SOCKS_DNS_IN_PROGRESS: PR_SetError(PR_IN_PROGRESS_ERROR, 0); return PR_FAILURE; case SOCKS_DNS_COMPLETE: return ConnectToProxy(fd); case SOCKS_CONNECTING_TO_PROXY: return ContinueConnectingToProxy(fd, oflags); case SOCKS4_WRITE_CONNECT_REQUEST: if (WriteToSocket(fd) != PR_SUCCESS) return PR_FAILURE; WantRead(8); mState = SOCKS4_READ_CONNECT_RESPONSE; return PR_SUCCESS; case SOCKS4_READ_CONNECT_RESPONSE: if (ReadFromSocket(fd) != PR_SUCCESS) return PR_FAILURE; return ReadV4ConnectResponse(); case SOCKS5_WRITE_AUTH_REQUEST: if (WriteToSocket(fd) != PR_SUCCESS) return PR_FAILURE; WantRead(2); mState = SOCKS5_READ_AUTH_RESPONSE; return PR_SUCCESS; case SOCKS5_READ_AUTH_RESPONSE: if (ReadFromSocket(fd) != PR_SUCCESS) return PR_FAILURE; return ReadV5AuthResponse(); case SOCKS5_WRITE_CONNECT_REQUEST: if (WriteToSocket(fd) != PR_SUCCESS) return PR_FAILURE; // The SOCKS 5 response to the connection request is variable // length. First, we'll read enough to tell how long the response // is, and will read the rest later. WantRead(5); mState = SOCKS5_READ_CONNECT_RESPONSE_TOP; return PR_SUCCESS; case SOCKS5_READ_CONNECT_RESPONSE_TOP: if (ReadFromSocket(fd) != PR_SUCCESS) return PR_FAILURE; return ReadV5ConnectResponseTop(); case SOCKS5_READ_CONNECT_RESPONSE_BOTTOM: if (ReadFromSocket(fd) != PR_SUCCESS) return PR_FAILURE; return ReadV5ConnectResponseBottom(); case SOCKS_CONNECTED: LOGERROR(("socks: already connected")); HandshakeFinished(PR_IS_CONNECTED_ERROR); return PR_FAILURE; case SOCKS_FAILED: LOGERROR(("socks: already failed")); return PR_FAILURE; } LOGERROR(("socks: executing handshake in invalid state, %d", mState)); HandshakeFinished(PR_INVALID_STATE_ERROR); return PR_FAILURE; }
PRStatus nsSOCKSSocketInfo::ReadV5ConnectResponseTop() { uint8_t res; uint32_t len; NS_ABORT_IF_FALSE(mState == SOCKS5_READ_CONNECT_RESPONSE_TOP, "Invalid state!"); NS_ABORT_IF_FALSE(mDataLength == 5, "SOCKS 5 connection reply must be exactly 5 bytes!"); LOGDEBUG(("socks5: checking connection reply")); // Check version number if (ReadUint8() != 0x05) { LOGERROR(("socks5: unexpected version in the reply")); HandshakeFinished(PR_CONNECT_REFUSED_ERROR); return PR_FAILURE; } // Check response res = ReadUint8(); if (res != 0x00) { PRErrorCode c = PR_CONNECT_REFUSED_ERROR; switch (res) { case 0x01: LOGERROR(("socks5: connect failed: " "01, General SOCKS server failure.")); break; case 0x02: LOGERROR(("socks5: connect failed: " "02, Connection not allowed by ruleset.")); break; case 0x03: LOGERROR(("socks5: connect failed: 03, Network unreachable.")); c = PR_NETWORK_UNREACHABLE_ERROR; break; case 0x04: LOGERROR(("socks5: connect failed: 04, Host unreachable.")); break; case 0x05: LOGERROR(("socks5: connect failed: 05, Connection refused.")); break; case 0x06: LOGERROR(("socks5: connect failed: 06, TTL expired.")); c = PR_CONNECT_TIMEOUT_ERROR; break; case 0x07: LOGERROR(("socks5: connect failed: " "07, Command not supported.")); break; case 0x08: LOGERROR(("socks5: connect failed: " "08, Address type not supported.")); c = PR_BAD_ADDRESS_ERROR; break; default: LOGERROR(("socks5: connect failed.")); break; } HandshakeFinished(c); return PR_FAILURE; } if (ReadV5AddrTypeAndLength(&res, &len) != PR_SUCCESS) { HandshakeFinished(PR_BAD_ADDRESS_ERROR); return PR_FAILURE; } mState = SOCKS5_READ_CONNECT_RESPONSE_BOTTOM; WantRead(len + 2); return PR_SUCCESS; }