michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef _NSNSSCALLBACKS_H_ michael@0: #define _NSNSSCALLBACKS_H_ michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "pk11func.h" michael@0: #include "nspr.h" michael@0: #include "ocspt.h" michael@0: #include "nsIStreamLoader.h" michael@0: #include "mozilla/CondVar.h" michael@0: #include "mozilla/Mutex.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsString.h" michael@0: michael@0: class nsILoadGroup; michael@0: michael@0: char* michael@0: PK11PasswordPrompt(PK11SlotInfo *slot, PRBool retry, void* arg); michael@0: michael@0: void HandshakeCallback(PRFileDesc *fd, void *client_data); michael@0: SECStatus CanFalseStartCallback(PRFileDesc* fd, void* client_data, michael@0: PRBool *canFalseStart); michael@0: michael@0: class nsHTTPListener MOZ_FINAL : public nsIStreamLoaderObserver michael@0: { michael@0: private: michael@0: // For XPCOM implementations that are not a base class for some other michael@0: // class, it is good practice to make the destructor non-virtual and michael@0: // private. Then the only way to delete the object is via Release. michael@0: ~nsHTTPListener(); michael@0: michael@0: public: michael@0: nsHTTPListener(); michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSISTREAMLOADEROBSERVER michael@0: michael@0: nsCOMPtr mLoader; michael@0: michael@0: nsresult mResultCode; michael@0: michael@0: bool mHttpRequestSucceeded; michael@0: uint16_t mHttpResponseCode; michael@0: nsCString mHttpResponseContentType; michael@0: michael@0: const uint8_t* mResultData; // allocated in loader, but owned by listener michael@0: uint32_t mResultLen; michael@0: michael@0: mozilla::Mutex mLock; michael@0: mozilla::CondVar mCondition; michael@0: volatile bool mWaitFlag; michael@0: michael@0: bool mResponsibleForDoneSignal; michael@0: void send_done_signal(); michael@0: michael@0: // no nsCOMPtr. When I use it, I get assertions about michael@0: // loadgroup not being thread safe. michael@0: // So, let's use a raw pointer and ensure we only create and destroy michael@0: // it on the network thread ourselves. michael@0: nsILoadGroup *mLoadGroup; michael@0: PRThread *mLoadGroupOwnerThread; michael@0: void FreeLoadGroup(bool aCancelLoad); michael@0: }; michael@0: michael@0: class nsNSSHttpServerSession michael@0: { michael@0: public: michael@0: nsCString mHost; michael@0: uint16_t mPort; michael@0: michael@0: static SECStatus createSessionFcn(const char *host, michael@0: uint16_t portnum, michael@0: SEC_HTTP_SERVER_SESSION *pSession); michael@0: }; michael@0: michael@0: class nsNSSHttpRequestSession michael@0: { michael@0: protected: michael@0: mozilla::ThreadSafeAutoRefCnt mRefCount; michael@0: michael@0: public: michael@0: static SECStatus createFcn(SEC_HTTP_SERVER_SESSION session, michael@0: const char *http_protocol_variant, michael@0: const char *path_and_query_string, michael@0: const char *http_request_method, michael@0: const PRIntervalTime timeout, michael@0: SEC_HTTP_REQUEST_SESSION *pRequest); michael@0: michael@0: SECStatus setPostDataFcn(const char *http_data, michael@0: const uint32_t http_data_len, michael@0: const char *http_content_type); michael@0: michael@0: SECStatus addHeaderFcn(const char *http_header_name, michael@0: const char *http_header_value); michael@0: michael@0: SECStatus trySendAndReceiveFcn(PRPollDesc **pPollDesc, michael@0: uint16_t *http_response_code, michael@0: const char **http_response_content_type, michael@0: const char **http_response_headers, michael@0: const char **http_response_data, michael@0: uint32_t *http_response_data_len); michael@0: michael@0: SECStatus cancelFcn(); michael@0: SECStatus freeFcn(); michael@0: michael@0: void AddRef(); michael@0: void Release(); michael@0: michael@0: nsCString mURL; michael@0: nsCString mRequestMethod; michael@0: michael@0: bool mHasPostData; michael@0: nsCString mPostData; michael@0: nsCString mPostContentType; michael@0: michael@0: PRIntervalTime mTimeoutInterval; michael@0: michael@0: nsRefPtr mListener; michael@0: michael@0: protected: michael@0: nsNSSHttpRequestSession(); michael@0: ~nsNSSHttpRequestSession(); michael@0: michael@0: SECStatus internal_send_receive_attempt(bool &retryable_error, michael@0: PRPollDesc **pPollDesc, michael@0: uint16_t *http_response_code, michael@0: const char **http_response_content_type, michael@0: const char **http_response_headers, michael@0: const char **http_response_data, michael@0: uint32_t *http_response_data_len); michael@0: }; michael@0: michael@0: class nsNSSHttpInterface michael@0: { michael@0: public: michael@0: static SECStatus createSessionFcn(const char *host, michael@0: uint16_t portnum, michael@0: SEC_HTTP_SERVER_SESSION *pSession) michael@0: { michael@0: return nsNSSHttpServerSession::createSessionFcn(host, portnum, pSession); michael@0: } michael@0: michael@0: static SECStatus keepAliveFcn(SEC_HTTP_SERVER_SESSION session, michael@0: PRPollDesc **pPollDesc) michael@0: { michael@0: // Not yet implemented, however, Necko does transparent keep-alive michael@0: // anyway, when enabled in Necko's prefs. michael@0: return SECSuccess; michael@0: } michael@0: michael@0: static SECStatus freeSessionFcn(SEC_HTTP_SERVER_SESSION session) michael@0: { michael@0: delete static_cast(session); michael@0: return SECSuccess; michael@0: } michael@0: michael@0: static SECStatus createFcn(SEC_HTTP_SERVER_SESSION session, michael@0: const char *http_protocol_variant, michael@0: const char *path_and_query_string, michael@0: const char *http_request_method, michael@0: const PRIntervalTime timeout, michael@0: SEC_HTTP_REQUEST_SESSION *pRequest) michael@0: { michael@0: return nsNSSHttpRequestSession::createFcn(session, http_protocol_variant, michael@0: path_and_query_string, http_request_method, michael@0: timeout, pRequest); michael@0: } michael@0: michael@0: static SECStatus setPostDataFcn(SEC_HTTP_REQUEST_SESSION request, michael@0: const char *http_data, michael@0: const uint32_t http_data_len, michael@0: const char *http_content_type) michael@0: { michael@0: return static_cast(request) michael@0: ->setPostDataFcn(http_data, http_data_len, http_content_type); michael@0: } michael@0: michael@0: static SECStatus addHeaderFcn(SEC_HTTP_REQUEST_SESSION request, michael@0: const char *http_header_name, michael@0: const char *http_header_value) michael@0: { michael@0: return static_cast(request) michael@0: ->addHeaderFcn(http_header_name, http_header_value); michael@0: } michael@0: michael@0: static SECStatus trySendAndReceiveFcn(SEC_HTTP_REQUEST_SESSION request, michael@0: PRPollDesc **pPollDesc, michael@0: uint16_t *http_response_code, michael@0: const char **http_response_content_type, michael@0: const char **http_response_headers, michael@0: const char **http_response_data, michael@0: uint32_t *http_response_data_len) michael@0: { michael@0: return static_cast(request) michael@0: ->trySendAndReceiveFcn(pPollDesc, http_response_code, http_response_content_type, michael@0: http_response_headers, http_response_data, http_response_data_len); michael@0: } michael@0: michael@0: static SECStatus cancelFcn(SEC_HTTP_REQUEST_SESSION request) michael@0: { michael@0: return static_cast(request) michael@0: ->cancelFcn(); michael@0: } michael@0: michael@0: static SECStatus freeFcn(SEC_HTTP_REQUEST_SESSION request) michael@0: { michael@0: return static_cast(request) michael@0: ->freeFcn(); michael@0: } michael@0: michael@0: static void initTable(); michael@0: static SEC_HttpClientFcn sNSSInterfaceTable; michael@0: michael@0: void registerHttpClient(); michael@0: void unregisterHttpClient(); michael@0: }; michael@0: michael@0: #endif // _NSNSSCALLBACKS_H_