void httpconnection_on_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { HTTPConnection* c = static_cast<HTTPConnection*>(handle->data); if(nread < 0) { int r = uv_read_stop(handle); if(r) { RX_ERROR("> error uv_read_stop: %s", uv_strerror(uv_last_error(handle->loop))); } if(buf.base) { delete buf.base; buf.base = NULL; } uv_err_t err = uv_last_error(handle->loop); if(err.code != UV_EOF) { RX_ERROR("> disconnected from server but not correctly: %s",uv_strerror(uv_last_error(handle->loop))) ; } r = uv_shutdown(&c->shutdown_req, handle, httpconnection_on_shutdown); if(r) { RX_ERROR("> error shutting down client: %s", uv_strerror(uv_last_error(handle->loop))); RX_ERROR("@ todo should be `delete` the connection here?"); } return; } c->addToInputBuffer(buf.base, nread); if(buf.base) { delete[] buf.base; buf.base = NULL; } }
int httpconnection_on_status_complete(http_parser* p) { HTTPConnection* c = static_cast<HTTPConnection*>(p->data); if(c->cb_event) { c->cb_event(c, HTTP_ON_STATUS, NULL, 0, c->cb_event_user); } return 0; }
void HTTPAcceptor::destroyConnections() { if (_rep) { // For each connection created by this object: AutoMutex autoMut(_rep->_connection_mut); for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) { HTTPConnection* connection = _rep->connections[i]; SocketHandle socket = connection->getSocket(); // Unsolicit SocketMessages: _monitor->unsolicitSocketMessages(socket); // Destroy the connection (causing it to close): while (connection->refcount.get()) { } delete connection; } _rep->connections.clear(); } }
void CIMOperationResponseEncoder::enqueue(Message* message) { try { handleEnqueue(message); } catch(PEGASUS_STD(bad_alloc)&) { MessageLoaderParms parms( "Server.CIMOperationResponseEncoder.OUT_OF_MEMORY", "A System error has occurred. Please retry the CIM Operation " "at a later time."); Logger::put_l( Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, parms); CIMResponseMessage* response = dynamic_cast<CIMResponseMessage*>(message); Uint32 queueId = response->queueIds.top(); MessageQueue* queue = MessageQueue::lookup(queueId); HTTPConnection* httpQueue = dynamic_cast<HTTPConnection*>(queue); PEGASUS_ASSERT(httpQueue); // Handle internal error on this connection. httpQueue->handleInternalServerError( response->getIndex(), response->isComplete()); delete message; } }
int httpconnection_on_message_complete(http_parser* p) { HTTPConnection* c = static_cast<HTTPConnection*>(p->data); if(c->cb_event) { c->cb_event(c, HTTP_ON_COMPLETE, NULL, 0, c->cb_event_user); } return 0; }
int httpconnection_on_body(http_parser* p, const char* at, size_t len) { HTTPConnection* c = static_cast<HTTPConnection*>(p->data); if(c->cb_event) { c->cb_event(c, HTTP_ON_BODY, at, len, c->cb_event_user); } return 0; }
IHTTPConnection* HTTPConnectionManager::initConnection(Chunk *chunk) { HTTPConnection *con = new HTTPConnection(this->stream); if ( con->init(chunk) == false ) return NULL; this->chunkMap[chunk] = con; this->chunkCount++; return con; }
HTTPConnection * HTTPConnectionManager::getConnection(const std::string &hostname, uint16_t port, int sockettype) { std::vector<HTTPConnection *>::const_iterator it; for(it = connectionPool.begin(); it != connectionPool.end(); ++it) { HTTPConnection *conn = *it; if(conn->isAvailable() && conn->compare(hostname, port, sockettype)) return conn; } return NULL; }
void HTTPAcceptor::handleEnqueue(Message *message) { if (!message) return; PEGASUS_ASSERT(_rep != 0); switch (message->getType()) { case SOCKET_MESSAGE: { SocketMessage* socketMessage = (SocketMessage*)message; // If this is a connection request: PEGASUS_ASSERT(socketMessage->socket == _rep->socket); PEGASUS_ASSERT(socketMessage->events & SocketMessage::READ); _acceptConnection(); break; } case CLOSE_CONNECTION_MESSAGE: { CloseConnectionMessage* closeConnectionMessage = (CloseConnectionMessage*)message; AutoMutex autoMut(_rep->_connection_mut); for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) { HTTPConnection* connection = _rep->connections[i]; SocketHandle socket = connection->getSocket(); if (socket == closeConnectionMessage->socket) { _monitor->unsolicitSocketMessages(socket); _rep->connections.remove(i); delete connection; break; } } break; } default: PEGASUS_ASSERT(false); break; } delete message; }
void httpconnection_on_close(uv_handle_t* handle) { HTTPConnection* c = static_cast<HTTPConnection*>(handle->data); delete handle; handle = NULL; if(c->cb_event) { c->cb_event(c, HTTP_ON_CLOSED, NULL, 0, c->cb_event_user); } if(c->cb_close) { c->cb_close(c, HTTP_ON_CLOSED, NULL, 0, c->cb_close_user); } }
/** getOutstandingRequestCount - returns the number of outstanding requests. */ Uint32 HTTPAcceptor::getOutstandingRequestCount() const { Uint32 count = 0; if (_rep) { AutoMutex autoMut(_rep->_connection_mut); for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) { HTTPConnection* connection = _rep->connections[i]; if (connection->isResponsePending()) { count++; } } } return count; }
bool HTTPChunkSource::prepare() { if(prepared) return true; if(!connManager) return false; ConnectionParams connparams = params; /* can be changed on 301 */ unsigned int i_redirects = 0; while(i_redirects++ < HTTPConnection::MAX_REDIRECTS) { if(!connection) { connection = connManager->getConnection(connparams); if(!connection) break; } requeststatus = connection->request(connparams.getPath(), bytesRange); if(requeststatus != RequestStatus::Success) { if(requeststatus == RequestStatus::Redirection) { HTTPConnection *httpconn = dynamic_cast<HTTPConnection *>(connection); if(httpconn) connparams = httpconn->getRedirection(); connection->setUsed(false); connection = NULL; if(httpconn) continue; } break; } /* Because we don't know Chunk size at start, we need to get size from content length */ contentLength = connection->getContentLength(); prepared = true; return true; } return false; }
HTTPConnection * HTTPConnectionManager::getConnection(const std::string &scheme, const std::string &hostname, uint16_t port) { if((scheme != "http" && scheme != "https") || hostname.empty()) return NULL; const int sockettype = (scheme == "https") ? TLSSocket::TLS : Socket::REGULAR; vlc_mutex_lock(&lock); HTTPConnection *conn = getConnection(hostname, port, sockettype); if(!conn) { Socket *socket = (sockettype == TLSSocket::TLS) ? new (std::nothrow) TLSSocket() : new (std::nothrow) Socket(); if(!socket) { vlc_mutex_unlock(&lock); return NULL; } /* disable pipelined tls until we have ticket/resume session support */ conn = new (std::nothrow) HTTPConnection(stream, socket, sockettype != TLSSocket::TLS); if(!conn) { delete socket; vlc_mutex_unlock(&lock); return NULL; } connectionPool.push_back(conn); if (!conn->connect(hostname, port)) { vlc_mutex_unlock(&lock); return NULL; } } conn->setUsed(true); vlc_mutex_unlock(&lock); return conn; }
HTTPConnection* HTTP::sendRequest(HTTPRequest& r, /* the request that we will sent */ httpconnection_event_callback eventCB, /* this function gets called when we receive data, see HTTPConnection.h */ void* user, /* the user pointer that gets passed into `eventCB` */ SSL* ssl) /* pass a SSL* when you want to make a secure connection */ { // create request string. std::string request_str; if(!r.toString(request_str)) { RX_ERROR("Cannot create request string"); return NULL; } // create connection HTTPConnection* c = new HTTPConnection(loop, r.getURL().getHost(), r.getURL().getPort(), ssl); c->cb_close = http_on_connection_event; c->cb_close_user = this; c->addToOutputBuffer(request_str); c->connect(eventCB, user); connections.push_back(c); return c; }
void httpconnection_on_flush_output_buffer(const char* data, size_t len, void* user) { HTTPConnection* c = static_cast<HTTPConnection*>(user); c->send((char*)data, len); }
/* Pull operation version of SendResponse. This adds one additional parameter (bodyParamsIn) that contains the parameters. This is because the parameters are added only on the the final segment of a chunk */ void CIMOperationResponseEncoder::sendResponsePull( CIMResponseMessage* response, const String& name, Boolean isImplicit, Buffer* bodyParams, Buffer* bodygiven) { PEG_METHOD_ENTER(TRC_DISPATCHER, "CIMOperationResponseEncoder::sendResponse"); PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, "name = %s", (const char*)name.getCString())); if (! response) { PEG_METHOD_EXIT(); return; } Uint32 queueId = response->queueIds.top(); Boolean closeConnect = response->getCloseConnect(); PEG_TRACE(( TRC_HTTP, Tracer::LEVEL4, "CIMOperationResponseEncoder::sendResponse()- " "response->getCloseConnect() returned %d", closeConnect)); MessageQueue* queue = MessageQueue::lookup(queueId); if (!queue) { PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1, "ERROR: non-existent queueId = %u, response not sent.", queueId)); PEG_METHOD_EXIT(); return; } HttpMethod httpMethod = response->getHttpMethod(); String& messageId = response->messageId; CIMException& cimException = response->cimException; Buffer message; // Note: the language is ALWAYS passed empty to the xml formatters because // it is HTTPConnection that needs to make the decision of whether to add // the languages to the HTTP message. ContentLanguageList contentLanguage; CIMName cimName(name); Uint32 messageIndex = response->getIndex(); Boolean isFirst = messageIndex == 0 ? true : false; Boolean isLast = response->isComplete(); Buffer bodylocal; Buffer& body = bodygiven ? *bodygiven : bodylocal; Buffer& bodyParamsBuf = bodyParams ? *bodyParams : bodylocal; // STAT_SERVEREND sets the getTotalServerTime() value in the message class STAT_SERVEREND #ifndef PEGASUS_DISABLE_PERFINST Uint64 serverTime = response->getTotalServerTime(); #else Uint64 serverTime = 0; #endif Buffer (*formatResponse)( const CIMName& iMethodName, const String& messageId, HttpMethod httpMethod, const ContentLanguageList& httpContentLanguages, const Buffer& bodyParams, const Buffer& body, Uint64 serverResponseTime, Boolean isFirst, Boolean isLast); Buffer (*formatError)( const CIMName& methodName, const String& messageId, HttpMethod httpMethod, const CIMException& cimException); if (isImplicit == false) { formatResponse = XmlWriter::formatSimpleMethodRspMessage; formatError = XmlWriter::formatSimpleMethodErrorRspMessage; } else { formatError = XmlWriter::formatSimpleIMethodErrorRspMessage; if (response->binaryResponse) { formatResponse = BinaryCodec::formatSimpleIMethodRspMessage; } else { formatResponse = XmlWriter::formatSimpleIMethodRspMessage; } } if (cimException.getCode() != CIM_ERR_SUCCESS) { HTTPConnection* httpQueue = dynamic_cast<HTTPConnection*>(queue); Boolean isChunkRequest = false; Boolean isFirstError = true; // Note: The WMI Mapper may use a non-HTTPConnection queue here. if (httpQueue) { isChunkRequest = httpQueue->isChunkRequested(); isFirstError = (httpQueue->cimException.getCode() == CIM_ERR_SUCCESS); } // only process the FIRST error if (isFirstError) { // NOTE: even if this error occurs in the middle, HTTPConnection // will flush the entire queued message and reformat. if (isChunkRequest == false) { message = formatError(name, messageId, httpMethod, cimException); } // uri encode the error (for the http header) only when it is // non-chunking or the first error with chunking if (isChunkRequest == false || (isChunkRequest == true && isFirst == true)) { String msg = TraceableCIMException(cimException).getDescription(); String uriEncodedMsg = XmlWriter::encodeURICharacters(msg); CIMException cimExceptionUri( cimException.getCode(), uriEncodedMsg); cimExceptionUri.setContentLanguages( cimException.getContentLanguages()); cimException = cimExceptionUri; } } // if first error in response stream // never put the error in chunked response (because it will end up in // the trailer), so just use the non-error response formatter to send // more data if (isChunkRequest == true) { message = formatResponse( cimName, messageId, httpMethod, contentLanguage, bodyParamsBuf, body, serverTime, isFirst, isLast); } } else { // else non-error condition try { message = formatResponse( cimName, messageId, httpMethod, contentLanguage, bodyParamsBuf, body, serverTime, isFirst, isLast); } catch (PEGASUS_STD(bad_alloc)&) { MessageLoaderParms parms( "Server.CIMOperationResponseEncoder.OUT_OF_MEMORY", "A System error has occurred. Please retry the CIM Operation " "at a later time."); Logger::put_l( Logger::ERROR_LOG, System::CIMSERVER, Logger::WARNING, parms); cimException = PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, parms); // try again with new error and no body body.clear(); sendResponse(response, name, isImplicit); PEG_METHOD_EXIT(); return; } STAT_BYTESSENT } AutoPtr<HTTPMessage> httpMessage( new HTTPMessage(message, 0, &cimException)); httpMessage->setComplete(isLast); httpMessage->setIndex(messageIndex); httpMessage->binaryResponse = response->binaryResponse; if (cimException.getCode() != CIM_ERR_SUCCESS) { httpMessage->contentLanguages = cimException.getContentLanguages(); } else { const OperationContext::Container& container = response->operationContext.get(ContentLanguageListContainer::NAME); const ContentLanguageListContainer& listContainer = *dynamic_cast<const ContentLanguageListContainer*>(&container); contentLanguage = listContainer.getLanguages(); httpMessage->contentLanguages = contentLanguage; } httpMessage->setCloseConnect(closeConnect); queue->enqueue(httpMessage.release()); PEG_METHOD_EXIT(); }
void WsmResponseEncoder::enqueue(WsmResponse* response) { PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmResponseEncoder::enqueue()"); PEGASUS_ASSERT(response); PEG_TRACE((TRC_WSMSERVER, Tracer::LEVEL4, "WsmResponseEncoder::enqueue()- " "response->getHttpCloseConnect() returned %d", response->getHttpCloseConnect())); try { switch (response->getType()) { case WS_TRANSFER_GET: _encodeWxfGetResponse((WxfGetResponse*) response); break; case WS_TRANSFER_PUT: _encodeWxfPutResponse((WxfPutResponse*) response); break; case WS_TRANSFER_CREATE: _encodeWxfCreateResponse((WxfCreateResponse*) response); break; case WS_TRANSFER_DELETE: _encodeWxfDeleteResponse((WxfDeleteResponse*) response); break; case WS_ENUMERATION_RELEASE: _encodeWsenReleaseResponse((WsenReleaseResponse*) response); break; case WSM_FAULT: _encodeWsmFaultResponse((WsmFaultResponse*) response); break; case SOAP_FAULT: _encodeSoapFaultResponse((SoapFaultResponse*) response); break; case WS_INVOKE: _encodeWsInvokeResponse((WsInvokeResponse*)response); break; case WS_ENUMERATION_ENUMERATE: case WS_ENUMERATION_PULL: // These cases are handled specially to allow for the message // contents to be tuned according to the MaxEnvelopeSize value. default: // Unexpected message type PEGASUS_ASSERT(0); break; } } catch (PEGASUS_STD(bad_alloc)&) { MessageLoaderParms parms( "WsmServer.WsmResponseEncoder.OUT_OF_MEMORY", "A System error has occurred. Please retry the " "WS-Management operation at a later time."); Logger::put_l( Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, parms); MessageQueue* queue = MessageQueue::lookup(response->getQueueId()); HTTPConnection* httpQueue = dynamic_cast<HTTPConnection*>(queue); PEGASUS_ASSERT(httpQueue); // Handle the internal server error on this connection. httpQueue->handleInternalServerError(0, true); } PEG_METHOD_EXIT(); }
HTTPMessageBodyChunk::HTTPMessageBodyChunk( HTTPConnection& connection, YO_NEW_REF Buffer* data ) : yield::http::HTTPMessageBodyChunk(data), connection(connection.inc_ref()) { }