diff options
author | Jose <jose@zeroc.com> | 2017-01-10 14:34:05 +0100 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2017-01-10 14:34:05 +0100 |
commit | 82f314a870b145e81553987100067558498a1be0 (patch) | |
tree | 2b94ca3464ee643c53237021bc7035394fecb4fd /cpp | |
parent | Fix for static initialization issue with VS 2013 (diff) | |
download | ice-82f314a870b145e81553987100067558498a1be0.tar.bz2 ice-82f314a870b145e81553987100067558498a1be0.tar.xz ice-82f314a870b145e81553987100067558498a1be0.zip |
UWP code simplifications
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/src/Ice/EndpointFactoryManager.cpp | 4 | ||||
-rwxr-xr-x | cpp/src/Ice/Network.cpp | 123 | ||||
-rwxr-xr-x | cpp/src/Ice/Network.h | 32 | ||||
-rw-r--r-- | cpp/src/Ice/ReferenceFactory.cpp | 2 | ||||
-rwxr-xr-x | cpp/src/IceSSL/Certificate.cpp | 47 | ||||
-rw-r--r-- | cpp/src/IceSSL/UWPTransceiverI.cpp | 33 | ||||
-rwxr-xr-x | cpp/src/IceSSL/Util.cpp | 255 |
7 files changed, 212 insertions, 284 deletions
diff --git a/cpp/src/Ice/EndpointFactoryManager.cpp b/cpp/src/Ice/EndpointFactoryManager.cpp index d69f5e2ff82..72fa5002aaa 100644 --- a/cpp/src/Ice/EndpointFactoryManager.cpp +++ b/cpp/src/Ice/EndpointFactoryManager.cpp @@ -62,7 +62,7 @@ IceInternal::EndpointFactoryManager::get(Short type) const return _factories[i]; } } - return 0; + return ICE_NULLPTR; } EndpointIPtr @@ -170,7 +170,7 @@ IceInternal::EndpointFactoryManager::create(const string& str, bool oaEndpoint) return ue; // Endpoint is opaque, but we don't have a factory for its type. } - return 0; + return ICE_NULLPTR; } EndpointIPtr diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index e53532c48d9..95e9a49249d 100755 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -32,7 +32,6 @@ #if defined(ICE_OS_UWP) # include <IceUtil/InputUtil.h> -# include <IceUtil/CountDownLatch.h> #elif defined(_WIN32) # include <winsock2.h> # include <ws2tcpip.h> @@ -2057,46 +2056,24 @@ IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string&) // message. We send a valiate connection message that the peers will ignore to workaround // the issue. // - promise<void> p; - create_task(safe_cast<DatagramSocket^>(fd)->GetOutputStreamAsync(group.host, group.port)) + auto out = IceInternal::runSync(safe_cast<DatagramSocket^>(fd)->GetOutputStreamAsync(group.host, group.port)); + auto writer = ref new DataWriter(out); - .then([](IOutputStream^ out) - { + OutputStream os; + os.write(magic[0]); + os.write(magic[1]); + os.write(magic[2]); + os.write(magic[3]); + os.write(currentProtocol); + os.write(currentProtocolEncoding); + os.write(validateConnectionMsg); + os.write(static_cast<Byte>(0)); // Compression status (always zero for validate connection). + os.write(headerSize); // Message size. + os.i = os.b.begin(); - OutputStream os; - os.write(magic[0]); - os.write(magic[1]); - os.write(magic[2]); - os.write(magic[3]); - os.write(currentProtocol); - os.write(currentProtocolEncoding); - os.write(validateConnectionMsg); - os.write(static_cast<Byte>(0)); // Compression status (always zero for validate connection). - os.write(headerSize); // Message size. - os.i = os.b.begin(); - - auto writer = ref new DataWriter(out); - writer->WriteBytes(ref new Array<unsigned char>(&*os.i, static_cast<unsigned int>(headerSize))); - - return writer->StoreAsync(); - }, - task_continuation_context::use_arbitrary()) - - .then([&p](task<unsigned int> t) - { - try - { - t.get(); - p.set_value(); - } - catch(...) - { - p.set_exception(current_exception()); - } - }, - task_continuation_context::use_arbitrary()); + writer->WriteBytes(ref new Array<unsigned char>(&*os.i, static_cast<unsigned int>(headerSize))); - p.get_future().get(); + IceInternal::runSync(writer->StoreAsync()); } catch(Platform::Exception^ pex) { @@ -2191,28 +2168,34 @@ namespace void checkResultAndWait(IAsyncAction^ action) { - if(action->Status == Windows::Foundation::AsyncStatus::Started) + auto status = action->Status; + switch(status) { - IceUtilInternal::CountDownLatch count(1); - HRESULT result = 0; - action->Completed = ref new AsyncActionCompletedHandler( - [&count, &result] (IAsyncAction^ action, Windows::Foundation::AsyncStatus status) - { - if(status != Windows::Foundation::AsyncStatus::Completed) + case Windows::Foundation::AsyncStatus::Started: + { + promise<HRESULT> p; + action->Completed = ref new AsyncActionCompletedHandler( + [&p] (IAsyncAction^ action, Windows::Foundation::AsyncStatus status) { - result = action->ErrorCode.Value; - } - count.countDown(); - }); - count.await(); - if(result) + p.set_value(status != Windows::Foundation::AsyncStatus::Completed ? action->ErrorCode.Value : 0); + }); + + HRESULT result = p.get_future().get(); + if(result) + { + checkErrorCode(__FILE__, __LINE__, result); + } + break; + } + case Windows::Foundation::AsyncStatus::Error: { - checkErrorCode(__FILE__, __LINE__, result); + checkErrorCode(__FILE__, __LINE__, action->ErrorCode.Value); + break; + } + default: + { + break; } - } - else if(action->Status == Windows::Foundation::AsyncStatus::Error) - { - checkErrorCode(__FILE__, __LINE__, action->ErrorCode.Value); } } @@ -2856,6 +2839,34 @@ IceInternal::checkErrorCode(const char* file, int line, HRESULT herr) } } +// +// UWP impose some restriction on operations that block when run from +// STA thread and throws concurrency::invalid_operation. We cannot +// directly call task::get or task::way, this helper method is used to +// workaround this limitation. +// +void +IceInternal::runSync(Windows::Foundation::IAsyncAction^ action) +{ + std::promise<void> p; + + concurrency::create_task(action).then( + [&p](concurrency::task<void> t) + { + try + { + t.get(); + p.set_value(); + } + catch(...) + { + p.set_exception(std::current_exception()); + } + }, + concurrency::task_continuation_context::use_arbitrary()); + + return p.get_future().get(); +} #endif diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index f558cff3e13..3f0c8cf2da7 100755 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -25,7 +25,7 @@ #include <Ice/EndpointTypes.h> #if defined(ICE_OS_UWP) -// Nothing to include +# include <ppltasks.h> #elif defined(_WIN32) # include <winsock2.h> # include <ws2tcpip.h> @@ -331,6 +331,36 @@ ICE_API Address getNumericAddress(const std::string&); #else ICE_API void checkConnectErrorCode(const char*, int, HRESULT); ICE_API void checkErrorCode(const char*, int, HRESULT); + +// +// UWP impose some restriction on operations that block when run from +// STA thread and throws concurrency::invalid_operation. We cannot +// directly call task::get or task::way, this helper method is used to +// workaround this limitation. +// +template<typename T> +T runSync(Windows::Foundation::IAsyncOperation<T>^ operation) +{ + std::promise<T> p; + concurrency::create_task(operation).then( + [&p](concurrency::task<T> t) + { + try + { + p.set_value(t.get()); + } + catch(...) + { + p.set_exception(std::current_exception()); + } + }, + concurrency::task_continuation_context::use_arbitrary()); + + return p.get_future().get(); +} + +ICE_API void runSync(Windows::Foundation::IAsyncAction^ action); + #endif #if defined(ICE_USE_IOCP) diff --git a/cpp/src/Ice/ReferenceFactory.cpp b/cpp/src/Ice/ReferenceFactory.cpp index 099cb147b4f..d4198699609 100644 --- a/cpp/src/Ice/ReferenceFactory.cpp +++ b/cpp/src/Ice/ReferenceFactory.cpp @@ -479,7 +479,7 @@ IceInternal::ReferenceFactory::create(const string& str, const string& propertyP string es = s.substr(beg, end - beg); EndpointIPtr endp = _instance->endpointFactoryManager()->create(es, false); - if(endp != 0) + if(endp != ICE_NULLPTR) { endpoints.push_back(endp); } diff --git a/cpp/src/IceSSL/Certificate.cpp b/cpp/src/IceSSL/Certificate.cpp index 97f2bd63365..fe0e85aef94 100755 --- a/cpp/src/IceSSL/Certificate.cpp +++ b/cpp/src/IceSSL/Certificate.cpp @@ -1138,39 +1138,24 @@ Certificate::load(const string& file) BIO_free(cert); return ICE_MAKE_SHARED(Certificate, x); #elif defined(ICE_OS_UWP) - promise<shared_ptr<Certificate>> result; - create_task(StorageFile::GetFileFromApplicationUriAsync( - ref new Uri(ref new String(stringToWstring(file).c_str())))).then([](StorageFile^ file) + try + { + auto uri = ref new Uri(ref new String(stringToWstring(file).c_str())); + auto file = create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).get(); + auto buffer = create_task(FileIO::ReadTextAsync(file)).get(); + return Certificate::decode(wstringToString(buffer->Data())); + } + catch(Platform::Exception^ ex) + { + if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND) { - return FileIO::ReadTextAsync(file); - }, - task_continuation_context::use_arbitrary()).then([&result, &file](task<String^> previous) + throw CertificateReadException(__FILE__, __LINE__, "certificate file not found:\n" + file); + } + else { - try - { - result.set_value(Certificate::decode(wstringToString(previous.get()->Data()))); - } - catch(Platform::Exception^ ex) - { - try - { - if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND) - { - throw CertificateReadException(__FILE__, __LINE__, "certificate file not found:\n" + file); - } - else - { - throw Ice::SyscallException(__FILE__, __LINE__, ex->HResult); - } - } - catch(...) - { - result.set_exception(current_exception()); - } - } - }, - task_continuation_context::use_arbitrary()); - return result.get_future().get(); + throw Ice::SyscallException(__FILE__, __LINE__, ex->HResult); + } + } #else # error "Unknown platform" #endif diff --git a/cpp/src/IceSSL/UWPTransceiverI.cpp b/cpp/src/IceSSL/UWPTransceiverI.cpp index bef7d0769b5..50f82800897 100644 --- a/cpp/src/IceSSL/UWPTransceiverI.cpp +++ b/cpp/src/IceSSL/UWPTransceiverI.cpp @@ -152,30 +152,15 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B //{ // params->ExclusiveTrustRoots->Append(_engine->ca()->getCert()); //} - - promise<CertificateChain^> p; - create_task(fd->Information->ServerCertificate->BuildChainAsync( - fd->Information->ServerIntermediateCertificates, params)).then( - [&](task<CertificateChain^> previous) - { - try - { - p.set_value(previous.get()); - } - catch(Platform::Exception^ ex) - { - try - { - throw SyscallException(__FILE__, __LINE__, ex->HResult); - } - catch(...) - { - p.set_exception(current_exception()); - } - } - }); - - _chain = p.get_future().get(); + try + { + _chain = create_task(fd->Information->ServerCertificate->BuildChainAsync( + fd->Information->ServerIntermediateCertificates, params)).get(); + } + catch(Platform::Exception^ ex) + { + throw SyscallException(__FILE__, __LINE__, ex->HResult); + } ChainValidationResult result = _chain->Validate(); // diff --git a/cpp/src/IceSSL/Util.cpp b/cpp/src/IceSSL/Util.cpp index f262d09979f..5a0f815b12d 100755 --- a/cpp/src/IceSSL/Util.cpp +++ b/cpp/src/IceSSL/Util.cpp @@ -23,10 +23,6 @@ #include <Ice/StringConverter.h> #include <fstream> -#ifdef ICE_OS_UWP -# include <ppltasks.h> -#endif - #ifdef ICE_USE_OPENSSL # include <openssl/err.h> // @@ -1705,45 +1701,22 @@ namespace Certificates::Certificate^ findPersonalCertificate(String^ friendlyName) { - std::promise<Certificates::Certificate^> p; - CertificateQuery^ query = ref new CertificateQuery(); query->IncludeDuplicates = true; query->IncludeExpiredCertificates = true; query->FriendlyName = friendlyName; query->StoreName = StandardCertificateStoreNames::Personal; - create_task(CertificateStores::FindAllAsync(query)) - - .then([&p](IVectorView<Certificates::Certificate^>^ certificates) - { - if(certificates->Size > 0) - { - p.set_value(certificates->GetAt(0)); - } - else - { - p.set_value(nullptr); - } - }, - task_continuation_context::use_arbitrary()) - - .then([&](task<void> t) - { - try - { - t.get(); - } - catch(Platform::Exception^ ex) - { - p.set_exception(make_exception_ptr( - PluginInitializationException(__FILE__, __LINE__, "IceSSL: certificate error:\n" + - wstringToString(ex->Message->Data())))); - } - }, - task_continuation_context::use_arbitrary()); - - return p.get_future().get(); + try + { + auto certificates = IceInternal::runSync(CertificateStores::FindAllAsync(query)); + return certificates->Size > 0 ? certificates->GetAt(0) : nullptr; + } + catch(Platform::Exception^ ex) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); + } } // @@ -1755,45 +1728,29 @@ findPersonalCertificate(String^ friendlyName) bool importPfxData(String^ friendlyName, String^ data, String^ password) { - promise<bool> p; - - create_task(CertificateEnrollmentManager::ImportPfxDataAsync( - data, - password, - ExportOption::NotExportable, - KeyProtectionLevel::NoConsent, - InstallOptions::None, - friendlyName)) - - .then([&p]() + try + { + IceInternal::runSync(CertificateEnrollmentManager::ImportPfxDataAsync( + data, + password, + ExportOption::NotExportable, + KeyProtectionLevel::NoConsent, + InstallOptions::None, + friendlyName)); + return false; // The import succcess + } + catch(Platform::Exception^ ex) + { + if(HRESULT_CODE(ex->HResult) == ERROR_DECRYPTION_FAILED) { - p.set_value(false); // The import succcess - }, - task_continuation_context::use_arbitrary()) - - .then([&p](task<void> t) + return true; // Password error + } + else { - try - { - t.get(); - } - catch(Platform::Exception^ ex) - { - if(HRESULT_CODE(ex->HResult) == ERROR_DECRYPTION_FAILED) - { - p.set_value(true); // Password error - } - else - { - p.set_exception(make_exception_ptr( - PluginInitializationException(__FILE__, __LINE__, "IceSSL: certificate error:\n" + - wstringToString(ex->Message->Data())))); - } - } - }, - task_continuation_context::use_arbitrary()); - - return p.get_future().get(); + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); + } + } } } @@ -1802,84 +1759,60 @@ Certificates::Certificate^ IceSSL::importPersonalCertificate(const string& file, function<string ()> password, bool passwordPrompt, int passwordRetryMax) { - std::promise<Certificates::Certificate^> p; auto uri = ref new Uri(ref new String(stringToWstring(file).c_str())); - create_task(StorageFile::GetFileFromApplicationUriAsync(uri)) - - .then([](StorageFile^ file) - { - return FileIO::ReadBufferAsync(file); - }, - task_continuation_context::use_arbitrary()) + try + { + auto file = IceInternal::runSync(StorageFile::GetFileFromApplicationUriAsync(uri)); + auto buffer = IceInternal::runSync(FileIO::ReadBufferAsync(file)); - .then([&file, &password, &p, passwordPrompt, passwordRetryMax](IBuffer^ buffer) + // + // Create a hash of the certificate to use as a friendly name, this will allow us + // to uniquely identify the certificate in the store. + // + auto hasher = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha1); + auto hash = hasher->CreateHash(); + + hash->Append(buffer); + String^ friendlyName = CryptographicBuffer::EncodeToBase64String(hash->GetValueAndReset()); + + // + // If the certificate is already in the store we avoid importing it. + // + Certificates::Certificate^ cert = findPersonalCertificate(friendlyName); + if(cert) { - // - // Create a hash of the certificate to use as a friendly name, this will allow us - // to uniquely identify the certificate in the store. - // - auto hasher = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha1); - auto hash = hasher->CreateHash(); - - hash->Append(buffer); - String^ friendlyName = CryptographicBuffer::EncodeToBase64String(hash->GetValueAndReset()); - - // - // If the certificate is already in the store we avoid importing it. - // - Certificates::Certificate^ cert = findPersonalCertificate(friendlyName); - if(cert) - { - p.set_value(cert); - } - else - { - String^ data = CryptographicBuffer::EncodeToBase64String(buffer); - int count = 0; - bool passwordErr = false; - do - { - passwordErr = importPfxData(friendlyName, data, - ref new String(stringToWstring(password()).c_str())); - } - while(passwordPrompt && passwordErr && ++count < passwordRetryMax); - if(passwordErr) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: error decoding certificate"); - } - p.set_value(findPersonalCertificate(friendlyName)); - } - }, - task_continuation_context::use_arbitrary()) - - .then([&p, &file](task<void> t) + return cert; + } + else { - try + String^ data = CryptographicBuffer::EncodeToBase64String(buffer); + int count = 0; + bool passwordErr = false; + do { - t.get(); - } - catch(Platform::Exception^ ex) - { - if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND) - { - p.set_exception(make_exception_ptr( - PluginInitializationException(__FILE__, __LINE__, "certificate file not found:\n" + file))); - } - else - { - p.set_exception(make_exception_ptr( - PluginInitializationException(__FILE__, __LINE__, "IceSSL: certificate error:\n" + - wstringToString(ex->Message->Data())))); - } + passwordErr = importPfxData(friendlyName, data, + ref new String(stringToWstring(password()).c_str())); } - catch(...) + while(passwordPrompt && passwordErr && ++count < passwordRetryMax); + if(passwordErr) { - p.set_exception(current_exception()); + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: error decoding certificate"); } - }, - task_continuation_context::use_arbitrary()); - - return p.get_future().get(); + return findPersonalCertificate(friendlyName); + } + } + catch(Platform::Exception^ ex) + { + if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND) + { + throw PluginInitializationException(__FILE__, __LINE__, "certificate file not found:\n" + file); + } + else + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); + } + } } IVectorView<Certificates::Certificate^>^ @@ -1974,31 +1907,15 @@ IceSSL::findCertificates(const string& name, const string& value) } } - std::promise<IVectorView<Certificates::Certificate^>^> p; - create_task(CertificateStores::FindAllAsync(query)) - - .then([&p](IVectorView<Certificates::Certificate^>^ certificates) - { - p.set_value(certificates); - }, - task_continuation_context::use_arbitrary()) - - .then([&p](task<void> t) - { - try - { - t.get(); - } - catch(Platform::Exception^ ex) - { - p.set_exception( - make_exception_ptr(PluginInitializationException(__FILE__, __LINE__, "IceSSL: certificate error:\n" + - wstringToString(ex->Message->Data())))); - } - }, - task_continuation_context::use_arbitrary()); - - return p.get_future().get(); + try + { + return IceInternal::runSync(CertificateStores::FindAllAsync(query)); + } + catch(Platform::Exception^ ex) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data())); + } } #endif |