void ShutdownService::_sendShutdownRequestToService(const char* serviceName) { MessageQueueService* _mqs = static_cast<MessageQueueService*>(_controller); MessageQueue *queue = MessageQueue::lookup(serviceName); Uint32 _queueId; if (queue) { _queueId = queue->getQueueId(); } else { // service not found, just return return; } // send a Stop (this is a legacy message that in some of the MQS does // termination of its internal stuff. Then follow it with a Stop (to // open up its incoming queue), and then with a AsyncIoClose // which closes the incoming queue. // All of these messages MUST be sequential. Do not use SendForget or // SendAsync as those are asynchronous and their receipt is guaranteed // to be undeterministic and possibly out of sequence (which is something // we do not want). CimServiceStop stop_message( NULL, _queueId, _controller->getQueueId(), true); AutoPtr<AsyncReply> StopAsyncReply( _controller->ClientSendWait(_queueId, &stop_message)); CimServiceStart start_message( NULL, _queueId, _controller->getQueueId(), true); AutoPtr <AsyncReply> StartAsyncReply( _controller->ClientSendWait(_queueId, &start_message)); AsyncIoClose close_request( NULL, _queueId, _controller->getQueueId(), false); AutoPtr <AsyncReply> CloseAsyncReply( _controller->ClientSendWait(_queueId, &close_request)); }
void HTTPAuthenticatorDelegator::_sendResponse( Uint32 queueId, Buffer& message, Boolean closeConnect) { PEG_METHOD_ENTER(TRC_HTTP, "HTTPAuthenticatorDelegator::_sendResponse"); MessageQueue* queue = MessageQueue::lookup(queueId); if (queue) { AutoPtr<HTTPMessage> httpMessage(new HTTPMessage(message)); httpMessage->dest = queue->getQueueId(); queue->enqueue(httpMessage.release()); } PEG_METHOD_EXIT(); }
bool RebalanceImpl::updateProcessQueueTableInRebalance(const std::string& topic, std::set<MessageQueue>& mqSet) { bool changed = false; // 将多余的队列删除 std::map<MessageQueue, ProcessQueue*>::iterator it = m_processQueueTable.begin(); for ( ; it != m_processQueueTable.end();) { MessageQueue mq = it->first; if (mq.getTopic() == topic) { std::set<MessageQueue>::iterator its = mqSet.find(mq); if (its == mqSet.end()) { changed = true; ProcessQueue* pq = it->second; if (pq != NULL) { pq->setDroped(true); removeUnnecessaryMessageQueue(mq, *pq); //TODO log.info("doRebalance, {}, remove unnecessary mq, {}", // consumerGroup, mq); } std::map<MessageQueue, ProcessQueue*>::iterator ittmp = it; it++; m_processQueueTable.erase(ittmp); } else { it++; } } else { it++; } } // 增加新增的队列 std::list<PullRequest> pullRequestList; std::set<MessageQueue>::iterator its = mqSet.begin(); for (; its != mqSet.end(); its++) { MessageQueue mq = *its; std::map<MessageQueue, ProcessQueue*>::iterator itm = m_processQueueTable.find(mq); if (itm == m_processQueueTable.end()) { PullRequest pullRequest; pullRequest.setConsumerGroup(m_consumerGroup); pullRequest.setMessageQueue(new MessageQueue(mq.getTopic(),mq.getBrokerName(),mq.getQueueId())); pullRequest.setProcessQueue(new ProcessQueue()); // 这个需要根据策略来设置 long long nextOffset = computePullFromWhere(mq); if (nextOffset >= 0) { pullRequest.setNextOffset(nextOffset); pullRequestList.push_back(pullRequest); changed = true; m_processQueueTable[mq] = pullRequest.getProcessQueue(); //TODO log.info("doRebalance, {}, add a new mq, {}", consumerGroup, mq); } else { // 等待此次Rebalance做重试 //TODO log.warn("doRebalance, {}, add new mq failed, {}", consumerGroup, mq); } } } dispatchPullRequest(pullRequestList); return changed; }
void DefaultPropertyOwner::_requestIndicationServiceStateChange( const String& userName, Boolean enable, Uint32 timeoutSeconds) { MessageQueue *queue = MessageQueue::lookup( PEGASUS_QUEUENAME_INDICATIONSERVICE); // Return if indication service can not be found if (!queue) { return; } Uint32 queueId = queue->getQueueId(); const String METHOD_NAME = "RequestStateChange"; const String PARAMNAME_REQUESTEDSTATE = "RequestedState"; const String PARAMNAME_TIMEOUTPERIOD = "TimeoutPeriod"; const Uint16 STATE_ENABLED = 2; const Uint16 STATE_DISABLED = 3; String referenceStr("//", 2); referenceStr.append(System::getHostName()); referenceStr.append("/"); referenceStr.append(PEGASUS_NAMESPACENAME_INTEROP.getString()); referenceStr.append(":"); referenceStr.append( PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE.getString()); CIMObjectPath reference(referenceStr); Array<CIMParamValue> inParams; Array<CIMParamValue> outParams; inParams.append(CIMParamValue(PARAMNAME_REQUESTEDSTATE, CIMValue(enable ? STATE_ENABLED : STATE_DISABLED))); inParams.append(CIMParamValue(PARAMNAME_TIMEOUTPERIOD, CIMValue(CIMDateTime(timeoutSeconds * 1000000, true)))); MessageQueueService *controller = ModuleController::getModuleController(); try { CIMInvokeMethodRequestMessage* request = new CIMInvokeMethodRequestMessage( XmlWriter::getNextMessageId(), PEGASUS_NAMESPACENAME_INTEROP, referenceStr, CIMNameCast(METHOD_NAME), inParams, QueueIdStack(queueId)); request->operationContext.insert( IdentityContainer(userName)); AsyncLegacyOperationStart *asyncRequest = new AsyncLegacyOperationStart( 0, queueId, request); AsyncReply * asyncReply = controller->SendWait(asyncRequest); CIMInvokeMethodResponseMessage * response = reinterpret_cast<CIMInvokeMethodResponseMessage *>( (static_cast<AsyncLegacyOperationResult *>( asyncReply))->get_result()); CIMException e = response->cimException; delete response; delete asyncRequest; delete asyncReply; if (e.getCode() != CIM_ERR_SUCCESS) { throw e; } } catch(const Exception &e) { PEG_TRACE((TRC_CONFIG,Tracer::LEVEL1, "Exception caught while invoking CIM_IndicationService." "RequestStateChange() method: %s", (const char*)e.getMessage().getCString())); throw; } catch(...) { PEG_TRACE_CSTRING(TRC_CONFIG,Tracer::LEVEL1, "Unknown exception caught while invoking CIM_IndicationService." "RequestStateChange() method"); throw; } }
void HTTPAuthenticatorDelegator::handleHTTPMessage( HTTPMessage* httpMessage, Boolean & deleteMessage) { PEG_METHOD_ENTER(TRC_HTTP, "HTTPAuthenticatorDelegator::handleHTTPMessage"); Boolean authenticated = false; deleteMessage = true; // ATTN-RK-P3-20020408: This check probably shouldn't be necessary, but // we're getting an empty message when the client closes the connection if (httpMessage->message.size() == 0) { // The message is empty; just drop it PEG_METHOD_EXIT(); return; } // // get the configured authentication flag // // WMI MAPPER SPECIFIC: AUTHENTICATION ALWAYS ENABLED: Boolean enableAuthentication = true; /* NORMAL METHOD OF LOOKING UP AUTHENTICATION CONFIGURATION: Boolean enableAuthentication = ConfigManager::parseBooleanValue( ConfigManager::getInstance()->getCurrentValue("enableAuthentication")); */ // // Save queueId: // Uint32 queueId = httpMessage->queueId; // // Parse the HTTP message: // String startLine; Array<HTTPHeader> headers; Uint32 contentLength; httpMessage->parse(startLine, headers, contentLength); // // Parse the request line: // String methodName; String requestUri; String httpVersion; HttpMethod httpMethod = HTTP_METHOD__POST; HTTPMessage::parseRequestLine( startLine, methodName, requestUri, httpVersion); // // Set HTTP method for the request // if (methodName == "M-POST") { httpMethod = HTTP_METHOD_M_POST; } if (methodName != "M-POST" && methodName != "POST") { // Only POST and M-POST are implemented by this server _sendHttpError(queueId, HTTP_STATUS_NOTIMPLEMENTED); } else if ((httpMethod == HTTP_METHOD_M_POST) && (httpVersion == "HTTP/1.0")) { // // M-POST method is not valid with version 1.0 // _sendHttpError(queueId, HTTP_STATUS_BADREQUEST); } else { // // Process M-POST and POST messages: // PEG_TRACE_CSTRING( TRC_HTTP, Tracer::LEVEL3, "HTTPAuthenticatorDelegator - M-POST/POST processing start"); // // Search for Authorization header: // String authorization; // // Do not require authentication for indication delivery // String cimExport; if (enableAuthentication && HTTPMessage::lookupHeader( headers, "CIMExport", cimExport, true)) { enableAuthentication = false; } if ( HTTPMessage::lookupHeader( headers, "PegasusAuthorization", authorization, false) && enableAuthentication ) { try { // // Do pegasus/local authentication // authenticated = _authenticationManager->performPegasusAuthentication( authorization, httpMessage->authInfo); if (!authenticated) { String authChallenge; String authResp; authResp = _authenticationManager->getPegasusAuthResponseHeader( authorization, httpMessage->authInfo); if (!String::equal(authResp, String::EMPTY)) { _sendChallenge(queueId, authResp, false); } else { _sendHttpError(queueId, HTTP_STATUS_BADREQUEST, String::EMPTY, "Authorization header error"); } PEG_METHOD_EXIT(); return; } } catch (CannotOpenFile &cof) { _sendHttpError(queueId, HTTP_STATUS_INTERNALSERVERERROR); PEG_METHOD_EXIT(); return; } } if ( HTTPMessage::lookupHeader( headers, "Authorization", authorization, false) && enableAuthentication ) { #ifdef PEGASUS_KERBEROS_AUTHENTICATION // The presence of a Security Association indicates that Kerberos // is being used. CIMKerberosSecurityAssociation *sa = httpMessage->authInfo->getSecurityAssociation(); if (sa) { sa->setClientSentAuthorization(true); } #endif // // Do http authentication if not authenticated already // if (!authenticated) { authenticated = _authenticationManager->performHttpAuthentication( authorization, httpMessage->authInfo); if (!authenticated) { //ATTN: the number of challenges get sent for a // request on a connection can be pre-set. #ifdef PEGASUS_KERBEROS_AUTHENTICATION // Kerberos authentication needs access to the // AuthenticationInfo object for this session in order // to set up the reference to the // CIMKerberosSecurityAssociation object for this session. String authResp = _authenticationManager->getHttpAuthResponseHeader( httpMessage->authInfo); #else String authResp = _authenticationManager->getHttpAuthResponseHeader(); #endif if (!String::equal(authResp, String::EMPTY)) { _sendChallenge(queueId, authResp, false); } else { _sendHttpError(queueId, HTTP_STATUS_BADREQUEST, String::EMPTY, "Authorization header error"); } PEG_METHOD_EXIT(); return; } } // first not authenticated check } // "Authorization" header check #ifdef PEGASUS_KERBEROS_AUTHENTICATION // The presence of a Security Association indicates that Kerberos is // being used. CIMKerberosSecurityAssociation *sa = httpMessage->authInfo->getSecurityAssociation(); // This will process a request with no content. if (sa && authenticated) { if (sa->getServerToken().size()) { // This will handle the scenario where client did not send // data (content) but is authenticated. After the client // receives the success it should will send the request. // For mutual authentication the client may choose not to // send request data until the context is fully established. // Note: if mutual authentication wass not requested by the // client then no server token will be available. if (contentLength == 0) { String authResp = _authenticationManager->getHttpAuthResponseHeader( httpMessage->authInfo); if (!String::equal(authResp, String::EMPTY)) { _sendSuccess(queueId, authResp); } else { _sendHttpError(queueId, HTTP_STATUS_BADREQUEST, String::EMPTY, "Authorization header error"); } PEG_METHOD_EXIT(); return; } } } // This will process a request without an authorization record. if (sa && !authenticated) { // Not authenticated can result from the client not sending an // authorization record due to a previous authentication. In // this scenario the client was previous authenticated but // chose not to send an authorization record. The Security // Association maintains state so a request will not be // processed unless the Security association thinks the client // is authenticated. // This will handle the scenario where the client was // authenticated in the previous request but choose not to // send an authorization record. if (sa->getClientAuthenticated()) { authenticated = true; } } // The following is processing to unwrap (unencrypt) the message // received from the client when using kerberos authentication. // For Kerberos there should always be an "Authorization" record // sent with the request so the authenticated flag in the method // should always be checked to verify that the client is actually // authenticated. If no "Authoriztion" was sent then the client // can't be authenticated. The "Authorization" record was // processed above and if the "Authorization" record was // successfully processed then the client is authenticated. if (sa && authenticated) { Uint32 rc; // return code for the wrap Array<Sint8> final_buffer; final_buffer.clear(); Array<Sint8> header_buffer; header_buffer.clear(); Array<Sint8> inWrappedMessage; inWrappedMessage.clear(); Array<Sint8> outUnwrappedMessage; outUnwrappedMessage.clear(); // The message needs to be parsed in order to distinguish // between the headers and content. The message was parsed // earlier in this method so we can use the contentLength set // during that parse. 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. // Extract the unwrapped headers for (Uint32 i = 0; i < httpMessage->message.size() - contentLength; i++) { header_buffer.append(httpMessage->message[i]); } // Extract the wrapped content for (Uint32 i = httpMessage->message.size() - contentLength; i < httpMessage->message.size(); i++) { inWrappedMessage.append(httpMessage->message[i]); } rc = sa->unwrap_message(inWrappedMessage, outUnwrappedMessage); // ASCII if (rc) { // clear out the outUnwrappedMessage; if unwrapping is required // and it fails we need to send back a bad request. A message // left in an wrapped state will be a severe failue later. // Reason for unwrap failing may be due to a problem with the // credentials or context or some other failure may have // occurred. outUnwrappedMessage.clear(); // build a bad request. We do not want to risk sending back // data that can't be authenticated. final_buffer = XmlWriter::formatHttpErrorRspMessage(HTTP_STATUS_BADREQUEST); //remove the last separater; the authentication record still // needs to be added. final_buffer.remove(final_buffer.size()); // "\n" final_buffer.remove(final_buffer.size()); // "\r" // Build the WWW_Authenticate record with token. String authResp = _authenticationManager->getHttpAuthResponseHeader( httpMessage->authInfo); // error occurred on wrap so the final_buffer needs to be built // differently final_buffer << authResp; // add double separaters to end final_buffer << "\r\n"; final_buffer << "\r\n"; _sendResponse(queueId, final_buffer); PEG_METHOD_EXIT(); return; } // If outUnwrappedMessage does not have any content data this // is a result of no data available. This could be a result // of the client not sending any content data. This is not // unique to Kerberos so this will not be handled here but it // will be handled when the content is processed. Or, the // client did not wrap message...this is okay. If the unwrap // resulted in no data when there should have been data then // this should have been caught above when the unwrap returned // a bad return code if (final_buffer.size() == 0) { // if outUnwrappedMessage is empty that indicates client did // not wrap the message. The original message will be used. if (outUnwrappedMessage.size()) { final_buffer.appendArray(header_buffer); final_buffer.appendArray(outUnwrappedMessage); // add back char that was appended earlier final_buffer.append('\0'); // Note: if additional characters added // in future add back here } } else { // The final buffer should not have any data at this point. // If it does end the server because something bad happened. PEG_TRACE_CSTRING( TRC_HTTP, Tracer::LEVEL2, "HTTPAuthenticatorDelegator - the final buffer should " "not have data"); PEGASUS_ASSERT(0); } // replace the existing httpMessage with the headers and // unwrapped message // If the final buffer has not been set then the original // httpMessage will be used. if (final_buffer.size()) { httpMessage->message.clear(); httpMessage->message = final_buffer; } } // if not kerberos and client not authenticated #endif if ( authenticated || !enableAuthentication ) { // // Search for "CIMOperation" header: // String cimOperation; if (HTTPMessage::lookupHeader( headers, "CIMOperation", cimOperation, true)) { PEG_TRACE(( TRC_HTTP, Tracer::LEVEL3, "HTTPAuthenticatorDelegator - CIMOperation: %s ", (const char*) cimOperation.getCString())); MessageQueue* queue = MessageQueue::lookup(_cimOperationMessageQueueId); if (queue) { httpMessage->dest = queue->getQueueId(); try { queue->enqueue(httpMessage); } catch(exception & e) { delete httpMessage; _sendHttpError(queueId, HTTP_STATUS_REQUEST_TOO_LARGE); PEG_METHOD_EXIT(); deleteMessage = false; return; } deleteMessage = false; } } else if (HTTPMessage::lookupHeader( headers, "CIMExport", cimOperation, true)) { PEG_TRACE(( TRC_HTTP, Tracer::LEVEL3, "HTTPAuthenticatorDelegator - CIMExport: $0 ", (const char*) cimOperation.getCString())); MessageQueue* queue = MessageQueue::lookup(_cimExportMessageQueueId); if (queue) { httpMessage->dest = queue->getQueueId(); queue->enqueue(httpMessage); deleteMessage = false; } } else { // We don't recognize this request message type // The Specification for CIM Operations over HTTP reads: // // 3.3.4. CIMOperation // // If a CIM Server receives a CIM Operation request without // this [CIMOperation] header, it MUST NOT process it as if // it were a CIM Operation Request. The status code // returned by the CIM Server in response to such a request // is outside of the scope of this specification. // // 3.3.5. CIMExport // // If a CIM Listener receives a CIM Export request without // this [CIMExport] header, it MUST NOT process it. The // status code returned by the CIM Listener in response to // such a request is outside of the scope of this // specification. // // The author has chosen to send a 400 Bad Request error, but // without the CIMError header since this request must not be // processed as a CIM request. _sendHttpError(queueId, HTTP_STATUS_BADREQUEST); PEG_METHOD_EXIT(); return; } // bad request } // authenticated and enableAuthentication check else { // client not authenticated; send challenge #ifdef PEGASUS_KERBEROS_AUTHENTICATION String authResp = _authenticationManager->getHttpAuthResponseHeader( httpMessage->authInfo); #else String authResp = _authenticationManager->getHttpAuthResponseHeader(); #endif if (!String::equal(authResp, String::EMPTY)) { _sendChallenge(queueId, authResp, false); } else { _sendHttpError(queueId, HTTP_STATUS_BADREQUEST, String::EMPTY, "Authorization header error"); } } } // M-POST and POST processing PEG_METHOD_EXIT(); }
ThreadReturnType PEGASUS_THREAD_CDECL client_func (void *parm) { Thread *myself = reinterpret_cast < Thread * >(parm); test_async_queue *client = new test_async_queue (test_async_queue::CLIENT); // find the server MessageQueue *serverQueue = 0; while (serverQueue == 0) { serverQueue = MessageQueue::lookup("server"); // It is a good idea to yield to other threads. You should do this, // but this test-case stresses situations in which does not happen. //Threads::yield (); } if (verbose) { cout << "testing low-level async send " << endl; } Uint32 requestCount = 0; while (requestCount < 10000) { // The problem on multi-processor machines is that if we make it // continue on sending the messages, and the MessageQueueService // does not get to pick up the messages, the machine can crawl to // halt with about 300-400 threads and ever-continuing number of // them created. This is an evil stress test so lets leave it behind. try { Message *cim_rq = new Message (CIM_GET_INSTANCE_REQUEST_MESSAGE); AsyncOpNode *op = client->get_op(); AsyncOperationStart *async_rq = new AsyncOperationStart( op, serverQueue->getQueueId(), client->getQueueId(), false, cim_rq); client->SendAsync( op, serverQueue->getQueueId(), test_async_queue::async_handleEnqueue, client, (void *) 0); } catch (const PEGASUS_STD(bad_alloc) &) { cerr << "Out of memory! Continuing tests." << endl; continue; } requestCount++; // You really ought to allow other threads to their job (like picking // up all of these messages, but we want to stress test unfair // circumstances. //Threads::yield (); } if (verbose) { cout << "Waiting until all messages are flushed." << endl; } while (test_async_queue::msg_count.get() != requestCount) { if (verbose) { if (test_async_queue::msg_count.get() % (requestCount/10) == 0) { cout << test_async_queue::msg_count.get() / (requestCount/100) << "% complete" << endl; } } Threads::yield(); } if (verbose) { cout << "Waiting until all messages are flushed. " << endl; } while (test_async_queue::msg_count.get() != requestCount) { if (verbose) { if (test_async_queue::msg_count.get() % (requestCount/10) == 0) { cout << test_async_queue::msg_count.get() / (requestCount/100) << "% complete" << endl; } } Threads::yield(); } if (verbose) { cout << "sending stop to server " << endl; } try { CimServiceStop *stop = new CimServiceStop( 0, serverQueue->getQueueId(), client->getQueueId (), true); AsyncMessage *reply = client->SendWait (stop); delete stop; delete reply; } catch (const PEGASUS_STD(bad_alloc) &) { cerr <<" Out of memory! Continuing tests." << endl; } // wait for the server to shut down while (serverQueue) { serverQueue = MessageQueue::lookup("server"); Threads::yield (); } if (verbose) { cout << "shutting down client" << endl; } delete client; return ThreadReturnType(0); }