//%LICENSE//////////////////////////////////////////////////////////////// // // Licensed to The Open Group (TOG) under one or more contributor license // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with // this work for additional information regarding copyright ownership. // Each contributor licenses this file to you under the OpenPegasus Open // Source License; you may not use this file except in compliance with the // License. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ////////////////////////////////////////////////////////////////////////// // //%///////////////////////////////////////////////////////////////////////////// #ifndef Pegasus_HTTPConnection_h #define Pegasus_HTTPConnection_h #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include PEGASUS_NAMESPACE_BEGIN class Monitor; class HTTPAcceptor; class PEGASUS_COMMON_LINKAGE HTTPConnection : public MessageQueue { public: typedef MessageQueue Base; /** Constructor. */ HTTPConnection( Monitor* monitor, SharedPtr& socket, const String& ipAddress, HTTPAcceptor * owningAcceptor, MessageQueue * outputMessageQueue); /** Destructor. */ ~HTTPConnection(); virtual void enqueue(Message *); /** In this specialization of isActive a check is performed on the non-blocking socket to see if it is active by reading 1 byte. Since the current thread is processing the request, its safe to try to read 1 byte from the socket as there should be no data on the socket. If read returns a message of size zero, it is an indication that the client has closed the connection and the socket at the server end can be closed. */ virtual Boolean isActive(); /** This method is called whenever a SocketMessage is enqueued on the input queue of the HTTPConnection object. */ virtual void handleEnqueue(Message *); virtual void handleEnqueue(); /** Return socket this connection is using. */ SocketHandle getSocket() { return _socket->getSocket();} MP_Socket& getMPSocket() { return *_socket;} /** Indicates whether this connection has an outstanding response. */ Boolean isResponsePending(); Boolean run(); HTTPAcceptor& getOwningAcceptor() { PEGASUS_ASSERT(_owningAcceptor); return *_owningAcceptor; } // was the request for chunking ? Boolean isChunkRequested(); void setSocketWriteTimeout(Uint32 socketWriteTimeout); static void setIdleConnectionTimeout(Uint32 idleConnectionTimeout); static Uint32 getIdleConnectionTimeout(); Boolean closeConnectionOnTimeout(struct timeval* timeNow); // This method is called in Client code to decide reconnection with // the Server and can also be used in the server code to check if the // connection is still alive and take appropriate action. Boolean needsReconnect(); // This method is called in Server code when response encoders or // HTTPAuthenticatorDelegator runs out-of-memory. This method calls // _handleWriteEvent() with a dummy HTTPMessage to maintain response // chunk sequence properly. Once all responses are arrived, connection // is closed. Param "respMsgIndex" indicates the response index and // isComplete indicates whether the response is complete or not. void handleInternalServerError( Uint32 respMsgIndex, Boolean isComplete); // ATTN-RK-P1-20020521: This is a major hack, required to get the CIM // server and tests to run successfully. The problem is that the // HTTPAcceptor is deleting an HTTPConnection before all the threads // that are queued up to run in that HTTPConnection instance have had // a chance to finish. This hack makes the HTTPAcceptor spin until // the HTTPConnection event threads have completed, before deleting // the HTTPConnection. Note that this fix is not perfect, because // there is a window between when the HTTPConnection queue lookup is // done and when the refcount is incremented. If the HTTPAcceptor // deletes the HTTPConnection in that window, the soon-to-be-launched // HTTPConnection event thread will fail (hard). AtomicInt refcount; CIMException cimException; // list of content languages ContentLanguageList contentLanguages; private: void _clearIncoming(); /** @exception Exception Indicates an error occurred. */ void _getContentLengthAndContentOffset(); void _closeConnection(); void _handleReadEvent(); Boolean _handleWriteEvent(HTTPMessage& httpMessage); void _handleReadEventFailure(const String& httpStatusWithDetail, const String& cimError = String()); void _handleReadEventTransferEncoding(); Boolean _isClient(); Monitor* _monitor; SharedPtr _socket; String _ipAddress; HTTPAcceptor* _owningAcceptor; MessageQueue* _outputMessageQueue; Sint32 _contentOffset; Sint32 _contentLength; Buffer _incomingBuffer; Buffer _outgoingBuffer; SharedPtr _authInfo; // _connectionRequestCount contains the number of // requests that have been received on this connection. Uint32 _connectionRequestCount; /** The _responsePending flag indicates whether the a request has been received on the connection and is awaiting a response. It is set to true when a request is received on the connection and set to false when a response is sent. The connection object must not be destructed while a response is pending, because the CIM Server must route the response to the connection object when it becomes available. */ Boolean _responsePending; Mutex _connection_mut; // The _connectionClosePending flag will be set to true if // the connection receives a close connection socket message. // This flag is used to set the connection status to // either Monitor::IDLE (_connectionClosePending == false) // or Monitor::DYING (_connectionClosePending == true) when // returning control of the connection to the Monitor. Boolean _connectionClosePending; // The _acceptPending flag is set to true if a server-side // connection is accepted but an SSL handshake has not been // completed. Boolean _acceptPending; // The _httpMethodNotChecked flag is disabled after the first bytes of a // request were read and validated to be one of the supported HTTP methods // "POST" or "M-POST". Boolean _httpMethodNotChecked; // Holds time since the accept pending condition was detected. struct timeval _acceptPendingStartTime; int _entry_index; // When used by the client, it is an offset (from start of http message) // representing last NON completely parsed chunk of a transfer encoding. // When used by the server, it is the message index that comes down // from the providers/repository representing each message chunk. // WARNING: Due to the duel use of this member variable, modifying code // that uses this variable should be done very carefully. Accidental bugs // introduced could easily break interoperability with wbem // clients/servers that transfer and/or receive data via HTTP chunking. Uint32 _transferEncodingChunkOffset; // list of transfer encoding values from sender Array _transferEncodingValues; // list of TE values from client Array _transferEncodingTEValues; // 2 digit prefix on http header if mpost was used String _mpostPrefix; // Holds time since this connection is idle. struct timeval _idleStartTime; // Idle connection timeout in seconds specified by Config property // idleConnectionTimeout. static Uint32 _idleConnectionTimeoutSeconds; #ifndef PEGASUS_INTEGERS_BOUNDARY_ALIGNED static Mutex _idleConnectionTimeoutSecondsMutex; #endif // When this flag is set to true, it indicates that internal error on this // connection occured. Currently this flag is used by the Server code when // out-of-memory error is occurs and connection is closed by the server // once all responses are arrived. Boolean _internalError; friend class Monitor; friend class HTTPAcceptor; friend class HTTPConnector; }; PEGASUS_NAMESPACE_END #endif /* Pegasus_HTTPConnection_h */