📄 httpconnection.cpp
字号:
messageStart = (char *)contentLanguagesString.getData(); // insert the content language line before end // of header // note: this can be expensive on large payloads buffer.insert( insertOffset, messageStart, messageLength); messageLength = buffer.size(); // null terminate messageStart = (char *) buffer.getData(); messageStart[messageLength] = 0; bytesRemaining = messageLength; } // if there were any content languages#ifdef PEGASUS_KERBEROS_AUTHENTICATION // The following is processing to wrap (encrypt) the // response from the server when using kerberos // authentications. // If the security association does not exist then // kerberos authentication is not being used. CIMKerberosSecurityAssociation *sa = _authInfo->getSecurityAssociation(); if (sa) { // The message needs to be parsed in order to // distinguish between the headers and content. // When parsing, the code breaks out of the loop // as soon as it finds the double separator that // terminates the headers so the headers and // content can be easily separated. Boolean authrecExists = false; String authorization = String::EMPTY; if (HTTPMessage::lookupHeader( headers, "WWW-Authenticate", authorization, false)) { authrecExists = true; } // The following is processing to wrap (encrypt) // the response from the server when using // kerberos authentications. sa->wrapResponseMessage( buffer, contentLength, authrecExists); messageLength = buffer.size(); // null terminate messageStart = (char *) buffer.getData(); messageStart[messageLength] = 0; bytesRemaining = messageLength; } // endif kerberos security assoc exists#endif } // if this is the last chunk else bytesRemaining = 0; } // if chunk request is false } // if this is the first chunk containing the header else { // if chunking was requested, then subsequent messages that are // received need to turn response chunking on if (isChunkRequest == true && messageIndex > 0) { isChunkResponse = true; bytesToWrite = messageLength; } } // the data is sitting in buffer, but we want to cache it in // _incomingBuffer because there may be more chunks to append if (isChunkRequest == false) _incomingBuffer.swap(buffer); } // if not a client SignalHandler::ignore(PEGASUS_SIGPIPE); // use the next four lines to test the SIGABRT handler //getSigHandle()->registerHandler(PEGASUS_SIGABRT, sig_act); //getSigHandle()->activate(PEGASUS_SIGABRT); //Thread t(sigabrt_generator, NULL, false); //t.run(); char *sendStart = messageStart; Sint32 bytesWritten = 0; if (isFirst == true && isChunkResponse == true && bytesToWrite > 0) { // send the header first for chunked reponses. // dont include header terminator yet Uint32 headerLength = bytesToWrite; bytesToWrite -= headerLineTerminatorLength; bytesWritten = _socket->write(sendStart, bytesToWrite); if (bytesWritten < 0) _socketWriteError(); totalBytesWritten += bytesWritten; bytesRemaining -= bytesWritten; // put in trailer header. Buffer trailer; trailer << headerNameTrailer << headerNameTerminator << _mpostPrefix << headerNameCode << headerValueSeparator << _mpostPrefix << headerNameDescription << headerValueSeparator << headerNameContentLanguage << headerLineTerminator; sendStart = (char *) trailer.getData(); bytesToWrite = trailer.size(); bytesWritten = _socket->write(sendStart, bytesToWrite); if (bytesWritten < 0) _socketWriteError(); totalBytesWritten += bytesWritten; // the trailer is outside the header buffer, so dont include in // tracking variables // now send header terminator bytesToWrite = headerLineTerminatorLength; sendStart = messageStart + headerLength - bytesToWrite; bytesWritten = _socket->write(sendStart, bytesToWrite); if (bytesWritten < 0) _socketWriteError(); totalBytesWritten += bytesWritten; bytesRemaining -= bytesWritten; messageStart += headerLength; messageLength -= headerLength; sendStart = messageStart; bytesWritten = 0; bytesToWrite = bytesRemaining; } // if first chunk of chunked response // room enough for hex string representing chunk length and terminator char chunkLine[sizeof(Uint32)*2 + chunkLineTerminatorLength+1]; for (; bytesRemaining > 0; ) { if (isChunkResponse == true) { // send chunk line containing hex string and chunk line // terminator sprintf(chunkLine, "%x%s", bytesToWrite, chunkLineTerminator); sendStart = chunkLine; Sint32 chunkBytesToWrite = strlen(sendStart); bytesWritten = _socket->write(sendStart, chunkBytesToWrite); if (bytesWritten < 0) _socketWriteError(); totalBytesWritten += bytesWritten; } // for chunking, we will send the entire chunk data in one send, but // for non-chunking, we will send incrementally else bytesToWrite = _Min(bytesRemaining, bytesToWrite); // send non-chunked data // // Socket writes larger than 64K cause some platforms to return // errors. When the socket write can't send the full buffer at // one time, subtract the bytes sent and loop until the whole // buffer has gone. Use httpTcpBufferSize for maximum send size. // for (; bytesRemaining > 0; ) { sendStart = messageStart + messageLength - bytesRemaining; bytesToWrite = _Min(httpTcpBufferSize, bytesRemaining); bytesWritten = _socket->write(sendStart, bytesToWrite); if (bytesWritten < 0) _socketWriteError(); totalBytesWritten += bytesWritten; bytesRemaining -= bytesWritten; } if (isChunkResponse == true) { // send chunk terminator, on the last chunk, it is the chunk // body terminator Buffer trailer; Boolean traceTrailer = false; trailer << chunkLineTerminator; // on the last chunk, attach the last chunk termination // sequence: 0 + last chunk terminator + optional trailer + // chunkBodyTerminator if (isLast == true) { if (bytesRemaining > 0) _throwEventFailure(httpStatusInternal, "more bytes after indicated last chunk"); trailer << "0" << chunkLineTerminator; Uint32 httpStatus = cimException.getCode(); if (httpStatus != 0) { char httpStatusP[11]; sprintf(httpStatusP, "%u",httpStatus); traceTrailer = true; trailer << _mpostPrefix << headerNameCode << headerNameTerminator << httpStatusP << headerLineTerminator; const String& httpDescription = cimException.getMessage(); if (httpDescription.size() != 0) trailer << _mpostPrefix << headerNameDescription << headerNameTerminator << httpDescription << headerLineTerminator; } // Add Content-Language to the trailer if requested if (contentLanguages.size() != 0) { traceTrailer = true; trailer << _mpostPrefix << headerNameContentLanguage << headerNameTerminator << LanguageParser::buildContentLanguageHeader( contentLanguages) << headerLineTerminator; } // now add chunkBodyTerminator trailer << chunkBodyTerminator; } // if isLast if (traceTrailer) { Tracer::trace(TRC_XML_IO,Tracer::LEVEL2, "<!-- Trailer: queue id: %u -->\n%s \n", getQueueId(), trailer.getData()); } sendStart = (char *) trailer.getData(); Sint32 chunkBytesToWrite = (Sint32) trailer.size(); bytesWritten = _socket->write(sendStart, chunkBytesToWrite); if (bytesWritten < 0) _socketWriteError(); totalBytesWritten += bytesWritten; } // isChunkResponse == true } // for all bytes in message } // try catch (Exception &e) { httpStatus = e.getMessage(); } catch (...) { httpStatus = HTTP_STATUS_INTERNALSERVERERROR; String message("Unknown internal error"); Tracer::trace(__FILE__, __LINE__, TRC_HTTP, Tracer::LEVEL2, message); } if (isLast == true) { _incomingBuffer.clear(); _transferEncodingTEValues.clear(); // // decrement request count // _requestCount--; if (httpStatus.size() == 0) { static const char msg[] = "A response has been sent (%d of %d bytes have been written).\n" "There are %d requests pending within the CIM Server.\n" "A total of %d requests have been processed on this " "connection."; Tracer::trace(TRC_HTTP, Tracer::LEVEL4, msg, totalBytesWritten, messageLength, _requestCount.get(), _connectionRequestCount); } // // Since we are done writing, update the status of entry to IDLE // and notify the Monitor. // if (_isClient() == false) { // Check for message to close if (message.getCloseConnect()== true) { Tracer::trace( TRC_HTTP, Tracer::LEVEL3, "HTTPConnection::_handleWriteEvent - Connection: Close " "in client message."); _closeConnection(); } else { Tracer::trace (TRC_HTTP, Tracer::LEVEL2, "Now setting state to %d", _MonitorEntry::IDLE); _monitor->setState (_entry_index, _MonitorEntry::IDLE); _monitor->tickle(); } _responsePending = false; cimException = CIMException(); } } return httpStatus.size() == 0 ? false : true;}void HTTPConnection::handleEnqueue(){ Message* message = dequeue(); if (!message) return; handleEnqueue(message);}Boolean _IsBodylessMessage(const char* line){ //ATTN: Make sure this is the right place to check for HTTP/1.1 and // HTTP/1.0 that is part of the authentication challenge header. // ATTN-RK-P2-20020305: How do we make sure we have the complete list? // List of request methods which do not have message bodies const char* METHOD_NAMES[] = { "GET", "HEAD" }; // List of response codes which the client accepts and which should not
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -