HTTPRequest HTTPRequest::post( const Str & body, const Str & uri, const Str & version) { return HTTPRequest(Str("POST"), uri, body, version); }
HTTPRequest HTTPRequest::get( const Str & uri, const Str & version) { (void)uri; (void)version; return HTTPRequest("GET", uri, "", version); }
HTTPServer::HTTPServer(const std::string &addr, const std::string &port, int maxClientsCount, std::function<HTTPResponse(HTTPRequest &request)> onGet, std::function<HTTPResponse(HTTPRequest &request)> onPost, EpollHandler &epoll) { std::function<void(TCPSocket &)> onAccept = [&onGet, &onPost, this](TCPSocket &sock) { const int BUF_MAX_SIZE = 4096; char buf[BUF_MAX_SIZE]; int len; while (true) { len = sock.recieveMsg(buf, BUF_MAX_SIZE); if (len <= 0) break; addBufToString(currentRequest[sock.sockfd], buf, len); } std::cerr << " ======\n" << currentRequest[sock.sockfd] << "\n===========\n"; HTTPRequest httpRequest; HTTPResponse httpResponse; try { //std::cout << currentRequest << "\n"; httpRequest = HTTPRequest(currentRequest[sock.sockfd]); //std::cout << "Request from soket " << sock.sockfd << ": " << currentRequest << "\n"; if (httpRequest.getMethod() == "GET") { httpResponse = onGet(httpRequest); } else if (httpRequest.getMethod() == "POST") { httpResponse = onPost(httpRequest); } std::cout << "Response for socket " << sock.sockfd << ": \n"; sock.sendMsg(httpResponse.buildResponse().c_str()); currentRequest[sock.sockfd] = ""; } catch (NotFullRequestException &e) { std::cerr << "Not full request: " << e.getMessage() << "\n"; } catch (HTTPException &e) { std::cerr << "Bad HTTP Request: " << e.getMessage() << "\n"; httpResponse.setHttpVersion("HTTP/1.1"); httpResponse.setStatusCode(400); httpResponse.setReasonPhrase("Bad Request"); httpResponse.addEntityHeader("Content-Type", "*/*"); std::cout << "Response for socket " << sock.sockfd << ": \n"; sock.sendMsg(httpResponse.buildResponse().c_str()); currentRequest[sock.sockfd] = ""; } }; tcpServer = new TCPServer(addr.c_str(), port.c_str(), maxClientsCount * 2, onAccept, epoll); }
//Request Process(HTTP part) bool __fastcall HTTPRequestProcess( const DNS_PACKET_DATA &Packet, char *OriginalRecv, const size_t RecvSize, const SOCKET_DATA &LocalSocketData) { size_t DataLength = 0; memset(OriginalRecv, 0, RecvSize); //EDNS switching(Part 1) size_t EDNS_SwitchLength = Packet.Length; uint16_t EDNS_Packet_Flags = ((dns_hdr *)(Packet.Buffer))->Flags; if (Parameter.EDNS_Label && !Parameter.EDNS_Switch.EDNS_HTTP) { //Reset EDNS flags, resource record counts and packet length. ((dns_hdr *)(Packet.Buffer))->Flags = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Flags) & (~DNS_GET_BIT_AD)); ((dns_hdr *)(Packet.Buffer))->Flags = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Flags) & (~DNS_GET_BIT_CD)); if (((dns_hdr *)(Packet.Buffer))->Additional > 0) ((dns_hdr *)(Packet.Buffer))->Additional = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Additional) - 1U); EDNS_SwitchLength -= Packet.EDNS_Record; } //HTTP request DataLength = HTTPRequest(Packet.Buffer, EDNS_SwitchLength, OriginalRecv, RecvSize); //Send response. if (DataLength >= DNS_PACKET_MINSIZE && DataLength < RecvSize) { SendToRequester(OriginalRecv, DataLength, RecvSize, Packet.Protocol, LocalSocketData); return true; } //EDNS switching(Part 2) if (Parameter.EDNS_Label && !Parameter.EDNS_Switch.EDNS_HTTP) { ((dns_hdr *)(Packet.Buffer))->Flags = EDNS_Packet_Flags; ((dns_hdr *)(Packet.Buffer))->Additional = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Additional) + 1U); } return false; }
bool HTTPParser::parse(HTTPRequest &request) { static const string delim = "\r\n\r\n"; int pos = m_buf.find(delim); if (pos == string::npos) return false; string data = m_buf.substr(0, pos); m_buf.erase(0, pos + delim.length()); vector<string> lines = move(Utils::Strings::split(data, "\r\n")); vector<string> parts = move(Utils::Strings::split(lines[0])); if (parts.size() != 3) throw HTTPIncompleteRequest(Utils::Strings::format("Invalid HTTP request \"%s\"", lines[0].c_str())); string method = parts[0]; if (!isMethod(method)) throw HTTPInvalidMethod(Utils::Strings::format("Invalid HTTP method \"%s\"", method.c_str())); string uri = parts[1]; map<string, string> params; parseURI(uri, params); string version = parts[2]; if (version != "HTTP/1.1") throw HTTPUnsupportedVersion(Utils::Strings::format("Unsupported HTTP version \"%s\"", version.c_str())); request = HTTPRequest(method, uri, version, params); return true; }
QByteArray SSLConnect::getUrl( RequestType type, const QString &value ) { if( !d->ssl ) return QByteArray(); if( !SSL_check_private_key( d->ssl ) ) { d->setError(); return QByteArray(); } QString label; HTTPRequest req; switch( type ) { case AccessCert: { label = tr("Loading server access certificate. Please wait."); SOAPDocument s( "GetAccessToken", "urn:GetAccessToken" ); s.writeParameter( "Language", Settings::language().toUpper() ); s.writeParameter( "RequestTime", "" ); s.writeParameter( "SoftwareName", "DigiDoc3" ); s.writeParameter( "SoftwareVersion", qApp->applicationVersion() ); s.finalize(); req = HTTPRequest( "POST", "1.1", "https://id.sk.ee/GetAccessTokenWS/" ); req.setRawHeader( "Content-Type", "text/xml" ); req.setRawHeader( "SOAPAction", QByteArray() ); req.setRawHeader( "Connection", "close" ); req.setContent( s.document() ); break; } case MobileInfo: { label = tr("Loading Mobile info"); SOAPDocument s( "GetMIDTokens", "urn:GetMIDTokens" ); s.finalize(); req = HTTPRequest( "POST", "1.1", "https://id.sk.ee/MIDInfoWS/" ); req.setRawHeader( "Content-Type", "text/xml" ); req.setRawHeader( "SOAPAction", QByteArray() ); req.setRawHeader( "Connection", "close" ); req.setContent( s.document() ); break; } case EmailInfo: label = tr("Loading Email info"); req = HTTPRequest( "GET", "1.0", "https://sisene.www.eesti.ee/idportaal/postisysteem.naita_suunamised" ); break; case ActivateEmails: label = tr("Loading Email info"); req = HTTPRequest( "GET", "1.0", QString("https://www.eesti.ee/portaal/!postisysteem.suunamised?%1").arg( value ) ); break; case PictureInfo: label = tr("Downloading picture"); req = HTTPRequest( "GET", "1.0", "https://sisene.www.eesti.ee/idportaal/portaal.idpilt" ); break; default: return QByteArray(); } QByteArray url = req.url().host().toUtf8(); BIO *sock = BIO_new_connect( (char*)url.constData() ); BIO_set_conn_port( sock, "https" ); if( BIO_do_connect( sock ) <= 0 ) { d->setError( tr( "Failed to connect to host. Are you connected to the internet?" ) ); return QByteArray(); } SSL_set_bio( d->ssl, sock, sock ); if( !SSL_connect( d->ssl ) ) { d->setError(); return QByteArray(); } QByteArray header = req.request(); if( !SSL_write( d->ssl, header.constData(), header.size() ) ) { d->setError(); return QByteArray(); } QProgressDialog p( label, QString(), 0, 0, qApp->activeWindow() ); p.setWindowFlags( (p.windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowCloseButtonHint ); if( QProgressBar *bar = p.findChild<QProgressBar*>() ) bar->setTextVisible( false ); p.open(); return SSLReadThread( d ).waitForDone(); }
SInt64 EasyCMSSession::Run() { OS_Error theErr = OS_NoErr; EventFlags events = this->GetEvents(); if(events & Task::kKillEvent) { qtss_printf("kill event but not handle it!\n"); } while(1) { switch (fState) { case kIdle://空闲 { qtss_printf("kIdle state \n"); if(!IsConnected()) { // TCPSocket未连接的情况,首先进行登录连接 Login(); } else { // TCPSocket已连接的情况下区分具体事件类型 if(events & Task::kStartEvent) { // CMSSession掉线,重新进行上线动作 if(kSessionOffline == fSessionStatus) Login(); } if(events & Task::kReadEvent) { // 对已连接的TCP进行消息读取 fState = kReadingRequest; } if(events & Task::kTimeoutEvent) { // 保活时间到,需要发送保活报文 Login(); } } // 如果有消息需要发送则进入发送流程 if (fOutputStream.GetBytesWritten() > 0) { fState = kSendingResponse; } if(kIdle == fState) return 0; break; } case kReadingRequest: { qtss_printf("kReadingRequest state \n"); // 读取锁,已经在处理一个报文包时,不进行新网络报文的读取和处理 OSMutexLocker readMutexLocker(&fReadMutex); // 网络请求报文存储在fInputStream中 if ((theErr = fInputStream.ReadRequest()) == QTSS_NoErr) { //如果RequestStream返回QTSS_NoErr,就表示已经读取了目前所到达的网络数据 //但,还不能构成一个整体报文,还要继续等待读取... fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(EV_RE); return 0; } if ((theErr != QTSS_RequestArrived) && (theErr != E2BIG) && (theErr != QTSS_BadArgument)) { //Any other error implies that the input connection has gone away. // We should only kill the whole session if we aren't doing HTTP. // (If we are doing HTTP, the POST connection can go away) Assert(theErr > 0); // If we've gotten here, this must be an HTTP session with // a dead input connection. If that's the case, we should // clean up immediately so as to not have an open socket // needlessly lingering around, taking up space. Assert(!fSocket->GetSocket()->IsConnected()); this->ResetClientSocket(); return 0; } fState = kProcessingRequest; break; } case kProcessingRequest: { qtss_printf("kProcessingRequest state \n"); // 处理网络报文 Assert( fInputStream.GetRequestBuffer() ); Assert(fRequest == NULL); // 根据具体请求报文构造HTTPRequest请求类 fRequest = NEW HTTPRequest(&sServiceStr, fInputStream.GetRequestBuffer()); // 在这里,我们已经读取了一个完整的Request,并准备进行请求的处理,直到响应报文发出 // 在此过程中,此Session的Socket不进行任何网络数据的读/写; fReadMutex.Lock(); fSessionMutex.Lock(); // 清空发送缓冲区 fOutputStream.ResetBytesWritten(); // 网络请求超过了缓冲区,返回Bad Request if (theErr == E2BIG) { // 返回HTTP报文,错误码408 //(void)QTSSModuleUtils::SendErrorResponse(fRequest, qtssClientBadRequest, qtssMsgRequestTooLong); fState = kSendingResponse; break; } // Check for a corrupt base64 error, return an error if (theErr == QTSS_BadArgument) { //返回HTTP报文,错误码408 //(void)QTSSModuleUtils::SendErrorResponse(fRequest, qtssClientBadRequest, qtssMsgBadBase64); fState = kSendingResponse; break; } Assert(theErr == QTSS_RequestArrived); ProcessRequest(); // 每一步都检测响应报文是否已完成,完成则直接进行回复响应 if (fOutputStream.GetBytesWritten() > 0) { fState = kSendingResponse; } else { fState = kCleaningUp; } break; } case kSendingResponse: { qtss_printf("kSendingResponse state \n"); // 响应报文发送,确保完全发送 // Assert(fRequest != NULL); //发送响应报文 theErr = fOutputStream.Flush(); if (theErr == EAGAIN || theErr == EINPROGRESS) { // If we get this error, we are currently flow-controlled and should // wait for the socket to become writeable again // 如果收到Socket EAGAIN错误,那么我们需要等Socket再次可写的时候再调用发送 fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(fSocket->GetEventMask()); this->ForceSameThread(); // We are holding mutexes, so we need to force // the same thread to be used for next Run() return 0; } else if (theErr != QTSS_NoErr) { // Any other error means that the client has disconnected, right? Assert(!this->IsConnected()); ResetClientSocket(); return 0; } fState = kCleaningUp; break; } case kCleaningUp: { qtss_printf("kCleaningUp state \n"); // 清理已经处理的请求或者已经发送的报文缓存 // Cleaning up consists of making sure we've read all the incoming Request Body // data off of the socket ////if (this->GetRemainingReqBodyLen() > 0) ////{ //// err = this->DumpRequestData(); //// if (err == EAGAIN) //// { //// fInputSocketP->RequestEvent(EV_RE); //// this->ForceSameThread(); // We are holding mutexes, so we need to force //// // the same thread to be used for next Run() //// return 0; //// } ////} // 一次请求的读取、处理、响应过程完整,等待下一次网络报文! this->CleanupRequest(); fState = kIdle; if(IsConnected()) { fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(fSocket->GetEventMask()); } return 0; } } } return 0; }
SInt64 EasyCMSSession::Run() { OSMutexLocker locker(&fMutex); OS_Error theErr = OS_NoErr; EventFlags events = this->GetEvents(); if ((events & Task::kTimeoutEvent) || (events & Task::kKillEvent)) fLiveSession = false; while(fLiveSession) { switch (fState) { case kIdle: { //根据事件类型执行不同的动作 if(events & Task::kStartEvent) { switch(fEasyMsgType) { case MSG_CS_FREE_STREAM_REQ: { CSFreeStream(); break; } default: break; } } if(events & Task::kReadEvent) { // 已连接,有新消息需要读取(数据或者断开) fState = kReadingMessage; } // 如果有消息需要发送则进入发送流程 if (fOutputStream.GetBytesWritten() > 0) { fState = kSendingMessage; } //当前状态没有进行数据发送,则等待下一次事件触发 if(kIdle == fState) { return 0; } break; } case kReadingMessage: { // 网络请求报文存储在fInputStream中 if ((theErr = fInputStream.ReadRequest()) == QTSS_NoErr) { //如果RequestStream返回QTSS_NoErr,就表示已经读取了目前所到达的网络数据 //但!还不能构成一个整体报文Header部分,还要继续等待读取... fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(EV_RE); fState = kIdle; return 0; } if ((theErr != QTSS_RequestArrived) && (theErr != E2BIG) && (theErr != QTSS_BadArgument)) { //Any other error implies that the input connection has gone away. // We should only kill the whole session if we aren't doing HTTP. // (If we are doing HTTP, the POST connection can go away) Assert(theErr > 0); // If we've gotten here, this must be an HTTP session with // a dead input connection. If that's the case, we should // clean up immediately so as to not have an open socket // needlessly lingering around, taking up space. Assert(!fSocket->GetSocket()->IsConnected()); //this->ResetClientSocket(); //return 0; //读取数据失败,直接进入析构 } // 网络请求超过了缓冲区,返回Bad Request if ( (theErr == E2BIG) || (theErr == QTSS_BadArgument) ) { //返回HTTP报文,错误码408 //(void)QTSSModuleUtils::SendErrorResponse(fRequest, qtssClientBadRequest, qtssMsgBadBase64); fState = kCleaningUp; } else { fState = kProcessingMessage; } break; } case kProcessingMessage: { // 处理网络报文 Assert( fInputStream.GetRequestBuffer() ); Assert(fRequest == NULL); // 根据具体请求报文构造HTTPRequest请求类 fRequest = NEW HTTPRequest(&QTSServerInterface::GetServerHeader(), fInputStream.GetRequestBuffer()); // 清空发送缓冲区 fOutputStream.ResetBytesWritten(); Assert(theErr == QTSS_RequestArrived); // 处理收到的具体报文 ProcessMessage(); // 每一步都检测响应报文是否已完成,完成则直接进行回复响应 if (fOutputStream.GetBytesWritten() > 0) { fState = kSendingMessage; } else { fState = kCleaningUp; } break; } case kSendingMessage: { //发送响应报文 theErr = fOutputStream.Flush(); if(theErr == 115) { fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(EV_WR); this->ForceSameThread(); return 0; } if (theErr == EAGAIN || theErr == EINPROGRESS) { // If we get this error, we are currently flow-controlled and should // wait for the socket to become writeable again // 如果收到Socket EAGAIN错误,那么我们需要等Socket再次可写的时候再调用发送 fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(fSocket->GetEventMask()); this->ForceSameThread(); // We are holding mutexes, so we need to force // the same thread to be used for next Run() return 0; } else if (theErr != QTSS_NoErr) { // Any other error means that the client has disconnected, right? Assert(!this->IsConnected()); //向服务器发送数据失败,直接进入析构 //ResetClientSocket(); return -1; } fState = kCleaningUp; break; } case kCleaningUp: { // 一次请求的读取、处理、响应过程完整,等待下一次网络报文! this->CleanupRequest(); fState = kIdle; if(IsConnected()) { fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(EV_RE | EV_WR);//网络事件监听 } return 0; } } } return -1; }
/*! \brief 事件由ServiceSession Task进行处理,大多数为网络报文处理事件 \param \return 处理完成返回0,断开Session返回-1 \ingroup \see */ SInt64 CServiceSession::Run() { //获取事件类型 EventFlags events = this->GetEvents(); QTSS_Error err = QTSS_NoErr; QTSSModule* theModule = NULL; UInt32 numModules = 0; // Some callbacks look for this struct in the thread object OSThreadDataSetter theSetter(&fModuleState, NULL); //超时事件或者Kill事件,进入释放流程:清理 & 返回-1 if (events & Task::kKillEvent) fLiveSession = false; if(events & Task::kTimeoutEvent) { //客户端Session超时,暂时不处理 char msgStr[512]; qtss_snprintf(msgStr, sizeof(msgStr), "session timeout,release session\n"); QTSServerInterface::LogError(qtssMessageVerbosity, msgStr); return -1; } //正常事件处理流程 while (this->IsLiveSession()) { //报文处理以状态机的形式,可以方便多次处理同一个消息 switch (fState) { case kReadingFirstRequest://首次对Socket进行读取 { if ((err = fInputStream.ReadRequest()) == QTSS_NoErr) { //如果RequestStream返回QTSS_NoErr,就表示已经读取了目前所到达的网络数据 //但,还不能构成一个整体报文,还要继续等待读取... fInputSocketP->RequestEvent(EV_RE); return 0; } if ((err != QTSS_RequestArrived) && (err != E2BIG)) { // Any other error implies that the client has gone away. At this point, // we can't have 2 sockets, so we don't need to do the "half closed" check // we do below Assert(err > 0); Assert(!this->IsLiveSession()); break; } if ((err == QTSS_RequestArrived) || (err == E2BIG)) fState = kHaveCompleteMessage; } continue; case kReadingRequest://读取请求报文 { //读取锁,已经在处理一个报文包时,不进行新网络报文的读取和处理 OSMutexLocker readMutexLocker(&fReadMutex); //网络请求报文存储在fInputStream中 if ((err = fInputStream.ReadRequest()) == QTSS_NoErr) { //如果RequestStream返回QTSS_NoErr,就表示已经读取了目前所到达的网络数据 //但,还不能构成一个整体报文,还要继续等待读取... fInputSocketP->RequestEvent(EV_RE); return 0; } if ((err != QTSS_RequestArrived) && (err != E2BIG) && (err != QTSS_BadArgument)) { //Any other error implies that the input connection has gone away. // We should only kill the whole session if we aren't doing HTTP. // (If we are doing HTTP, the POST connection can go away) Assert(err > 0); if (fOutputSocketP->IsConnected()) { // If we've gotten here, this must be an HTTP session with // a dead input connection. If that's the case, we should // clean up immediately so as to not have an open socket // needlessly lingering around, taking up space. Assert(fOutputSocketP != fInputSocketP); Assert(!fInputSocketP->IsConnected()); fInputSocketP->Cleanup(); return 0; } else { Assert(!this->IsLiveSession()); break; } } fState = kHaveCompleteMessage; } case kHaveCompleteMessage://读取到完整的请求报文 { Assert( fInputStream.GetRequestBuffer() ); Assert(fRequest == NULL); //根据具体请求报文构造HTTPRequest请求类 fRequest = NEW HTTPRequest(&sServiceStr, fInputStream.GetRequestBuffer()); //在这里,我们已经读取了一个完整的Request,并准备进行请求的处理,直到响应报文发出 //在此过程中,此Session的Socket不进行任何网络数据的读/写; fReadMutex.Lock(); fSessionMutex.Lock(); //清空发送缓冲区 fOutputStream.ResetBytesWritten(); //网络请求超过了缓冲区,返回Bad Request if (err == E2BIG) { //返回HTTP报文,错误码408 //(void)QTSSModuleUtils::SendErrorResponse(fRequest, qtssClientBadRequest, qtssMsgRequestTooLong); fState = kSendingResponse; break; } // Check for a corrupt base64 error, return an error if (err == QTSS_BadArgument) { //返回HTTP报文,错误码408 //(void)QTSSModuleUtils::SendErrorResponse(fRequest, qtssClientBadRequest, qtssMsgBadBase64); fState = kSendingResponse; break; } Assert(err == QTSS_RequestArrived); fState = kFilteringRequest; } case kFilteringRequest: { //刷新Session保活时间 fTimeoutTask.RefreshTimeout(); //对请求报文进行解析 QTSS_Error theErr = SetupRequest(); //当SetupRequest步骤未读取到完整的网络报文,需要进行等待 if(theErr == QTSS_WouldBlock) { this->ForceSameThread(); fInputSocketP->RequestEvent(EV_RE); // We are holding mutexes, so we need to force // the same thread to be used for next Run() return 0;//返回0表示有事件才进行通知,返回>0表示规定事件后调用Run } //每一步都检测响应报文是否已完成,完成则直接进行回复响应 if (/*fRequest->HasResponseBeenSent()*/fOutputStream.GetBytesWritten() > 0) { fState = kSendingResponse; break; } fState = kPreprocessingRequest; break; } case kPreprocessingRequest: { //请求预处理过程 //TODO:报文处理过程 fState = kCleaningUp; break; } case kProcessingRequest: { if (fOutputStream.GetBytesWritten() == 0) { //如果到这里,响应报文还没有形成,返回500 Server Internal Error ////QTSSModuleUtils::SendErrorResponse(fRequest, qtssServerInternal, qtssMsgNoModuleForRequest); } fState = kSendingResponse; } case kSendingResponse: { //响应报文发送,确保完全发送 Assert(fRequest != NULL); //发送响应报文 err = fOutputStream.Flush(); if (err == EAGAIN) { // If we get this error, we are currently flow-controlled and should // wait for the socket to become writeable again //如果收到Socket EAGAIN错误,那么我们需要等Socket再次可写的时候再调用发送 fSocket.RequestEvent(EV_WR); this->ForceSameThread(); // We are holding mutexes, so we need to force // the same thread to be used for next Run() return 0; } else if (err != QTSS_NoErr) { // Any other error means that the client has disconnected, right? Assert(!this->IsLiveSession()); break; } fState = kCleaningUp; } case kCleaningUp: { // Cleaning up consists of making sure we've read all the incoming Request Body // data off of the socket if (this->GetRemainingReqBodyLen() > 0) { err = this->DumpRequestData(); if (err == EAGAIN) { fInputSocketP->RequestEvent(EV_RE); this->ForceSameThread(); // We are holding mutexes, so we need to force // the same thread to be used for next Run() return 0; } } //一次请求的读取、处理、响应过程完整,等待下一次网络报文! this->CleanupRequest(); fState = kReadingRequest; } } } //清空Session占用的所有资源 this->CleanupRequest(); //Session引用数为0,返回-1后,系统会将此Session删除 if (fObjectHolders == 0) return -1; //如果流程走到这里,Session实际已经无效了,应该被删除,但没有,因为还有其他地方引用了Session对象 return 0; }
SInt64 EasyCMSSession::Run() { //OSMutexLocker locker(&fMutex); OS_Error theErr = OS_NoErr; EventFlags events = this->GetEvents(); while (true) { switch (fState) { case kIdle: { if (!isConnected()) { // TCPSocket未连接的情况,首先进行登录连接 doDSRegister(); } else { if (fNoneACKMsgCount > 3) { this->resetClientSocket(); return 0; } // TCPSocket已连接的情况下先区分具体事件类型 if (events & Task::kStartEvent) { // 已连接,但状态为离线,重新进行上线动作 if (kSessionOffline == fSessionStatus) doDSRegister(); } if (events & Task::kReadEvent) { // 已连接,有新消息需要读取(数据或者断开) fState = kReadingMessage; } if (events & Task::kTimeoutEvent) { // 已连接,保活时间到需要发送保活报文 if(fCSeq%3 == 1) doDSPostSnap(); else doDSRegister(); fTimeoutTask.RefreshTimeout(); } if (events & Task::kUpdateEvent) { //已连接,发送快照更新 doDSPostSnap(); } } // 如果有消息需要发送则进入发送流程 if (fOutputStream.GetBytesWritten() > 0) { fState = kSendingMessage; } // if (kIdle == fState) { return 0; } break; } case kReadingMessage: { // 网络请求报文存储在fInputStream中 if ((theErr = fInputStream.ReadRequest()) == QTSS_NoErr) { //如果RequestStream返回QTSS_NoErr,就表示已经读取了目前所到达的网络数据 //但!还不能构成一个整体报文Header部分,还要继续等待读取... fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(EV_RE); fState = kIdle; return 0; } if ((theErr != QTSS_RequestArrived) && (theErr != E2BIG) && (theErr != QTSS_BadArgument)) { //Any other error implies that the input connection has gone away. // We should only kill the whole session if we aren't doing HTTP. // (If we are doing HTTP, the POST connection can go away) Assert(theErr > 0); // If we've gotten here, this must be an HTTP session with // a dead input connection. If that's the case, we should // clean up immediately so as to not have an open socket // needlessly lingering around, taking up space. Assert(!fSocket->GetSocket()->IsConnected()); this->resetClientSocket(); return 0; } // 网络请求超过了缓冲区,返回Bad Request if ((theErr == E2BIG) || (theErr == QTSS_BadArgument)) { //返回HTTP报文,错误码408 //(void)QTSSModuleUtils::SendErrorResponse(fRequest, qtssClientBadRequest, qtssMsgBadBase64); fState = kCleaningUp; } else { fState = kProcessingMessage; } break; } case kProcessingMessage: { // 处理网络报文 Assert(fInputStream.GetRequestBuffer()); Assert(fRequest == NULL); // 根据具体请求报文构造HTTPRequest请求类 fRequest = NEW HTTPRequest(&QTSServerInterface::GetServerHeader(), fInputStream.GetRequestBuffer()); // 清空发送缓冲区 fOutputStream.ResetBytesWritten(); Assert(theErr == QTSS_RequestArrived); QTSS_Error theErr = processMessage(); // 每一步都检测响应报文是否已完成,完成则直接进行回复响应 if (fOutputStream.GetBytesWritten() > 0) { fState = kSendingMessage; } else { fState = kCleaningUp; } break; } case kSendingMessage: { theErr = fOutputStream.Flush(); if (theErr == EAGAIN || theErr == EINPROGRESS) { qtss_printf("EasyCMSSession::Run fOutputStream.Flush() theErr:%d \n", theErr); fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(fSocket->GetEventMask()); this->ForceSameThread(); return 0; } else if (theErr != QTSS_NoErr) { // Any other error means that the client has disconnected, right? Assert(!this->isConnected()); resetClientSocket(); return 0; } ++fNoneACKMsgCount; fState = kCleaningUp; break; } case kCleaningUp: { // Cleaning up consists of making sure we've read all the incoming Request Body // data off of the socket ////if (this->GetRemainingReqBodyLen() > 0) ////{ //// err = this->DumpRequestData(); //// if (err == EAGAIN) //// { //// fInputSocketP->RequestEvent(EV_RE); //// this->ForceSameThread(); // We are holding mutexes, so we need to force //// // the same thread to be used for next Run() //// return 0; //// } ////} // clean up and wait for next run cleanupRequest(); fState = kIdle; if (isConnected()) { fSocket->GetSocket()->SetTask(this); fSocket->GetSocket()->RequestEvent(EV_RE | EV_WR); } return 0; } } } return 0; }