BINLINE PProtocol BTransport::negotiateProtocolServer(const BTargetId& targetId, PBytes& buf, PAsyncResult asyncResult) { try { bool succ = BNegotiate::isNegotiateMessage(buf); if (succ) { BNegotiate nego; nego.read(buf); { byps_unique_lock lock(mtx); protocol = createNegotiatedProtocol(nego); this->targetId = targetId; this->sessionId = targetId.toSessionId(); } PBytes bytes = BBytes::create(NEGOTIATE_MAX_SIZE); nego.targetId = targetId; nego.sessionId = sessionId; nego.write(bytes); asyncResult->setAsyncResult(BVariant(bytes)); } } catch (const exception& ex) { asyncResult->setAsyncResult(BVariant(ex)); } return protocol; }
virtual void setAsyncResult(const BVariant& result) { try { if (result.isException()) { innerResult->setAsyncResult(result); } else { POBJECT obj; result.get(obj); PMessage msg = byps_static_ptr_cast<BMessage>(obj); BNegotiate nego; nego.read(msg->buf); { byps_unique_lock lock(transport->mtx); transport->protocol = transport->createNegotiatedProtocol(nego); transport->targetId = nego.targetId; transport->connectedServerId = nego.targetId.getServerId(); transport->sessionId = nego.sessionId; } transport->internalAuthenticate(innerResult); } } catch (const exception& ex) { innerResult->setAsyncResult(BVariant(ex)); } delete this; }
virtual void setAsyncResult(const BVariant& result) { try { if (result.isException()) { innerResult->setAsyncResult(result); } else { transport->assignSessionThenSendMethod(requestObject, innerResult); } } catch (const exception& ex) { innerResult->setAsyncResult(BVariant(ex)); } delete this; }
BINLINE void BTransport::negotiateProtocolClient(PAsyncResult asyncResult) { PTransport pthis = shared_from_this(); if (!pthis) return; // Check that we do not run into recursive authentication requests. bool expectedActive = false; if (negotiateActive.compare_exchange_strong(expectedActive, true) == false) { BException ex(BExceptionC::FORBIDDEN, L"Authentication procedure failed. Server returned 401 for every request. " L"A common reason for this error is slow authentication handling."); // ... or calling a function that requires authentication in BAuthentication.authenticate() - see. TestRemoteWithAuthentication.testAuthenticateBlocksRecursion asyncResult->setAsyncResult(BVariant(ex)); return; } PBytes bytes = BBytes::create(NEGOTIATE_MAX_SIZE); BNegotiate nego(apiDesc); nego.version = apiDesc->version; nego.write(bytes); PAsyncResult outerResult = new BTransport_MyNegoAsyncResult(pthis, asyncResult); BMessageHeader header; header.messageId = wire->makeMessageId(); vector<PContentStream> streams; PMessage msg(new BMessage(header, bytes, streams)); wire->send(msg, outerResult); }
BINLINE void BTransport::internalAuthenticate(PAsyncResult innerResult) { if (authentication) { authentication->authenticate(PClient(), innerResult); } else { innerResult->setAsyncResult(BVariant(true)); } }
virtual void setAsyncResult(const BVariant& result) { bool relogin = false; try { if (result.isException()) { relogin = internalIsReloginException(result.getException()); if (!relogin) { innerResult->setAsyncResult(BVariant(result.getException())); } } else { try { POBJECT obj; result.get(obj); if (obj) { PMessage msg = byps_static_ptr_cast<BMessage>(obj); PInput inp = transport->getInput(msg->header, msg->buf); PSerializable sobj = inp->load(); innerResult->setAsyncResult(BVariant(sobj)); } else { BException ex(BExceptionC::CORRUPT, L"Missing message object in result."); innerResult->setAsyncResult(BVariant(ex)); } } catch (const BException& e) { relogin = internalIsReloginException(e); if (!relogin) { innerResult->setAsyncResult(BVariant(e)); } } } if (relogin) { transport->loginAndRetrySend(requestObject, innerResult); } } catch (const exception& ex) { innerResult->setAsyncResult(BVariant(ex)); } delete this; }
virtual void setAsyncResult(const BVariant& var) { try { if (var.isException()) { outp->setException(var.getException()); } else { PSerializable obj; var.get(obj); outp->store(obj); } PMessage msg = outp->toMessage(); innerResult->setAsyncResult(BVariant(msg)); } catch (const exception& ex) { innerResult->setAsyncResult(BVariant(ex)); } delete this; }
BINLINE void BTransport::internalAuthenticate(PAsyncResult innerResult) { if (authentication) { bool first = false; bool assumeAuthenticationIsValid = false; { byps_unique_lock lock(mtx); system_clock::time_point now = system_clock::now(); milliseconds diff = duration_cast<milliseconds>(now - lastAuthenticationTime); assumeAuthenticationIsValid = RETRY_AUTHENTICATION_AFTER_MILLIS >= diff.count(); if (!assumeAuthenticationIsValid) { first = asyncResultsWaitingForAuthentication.size() == 0; asyncResultsWaitingForAuthentication.push_back(innerResult); } } if (first) { PAsyncResult authResult(new BTransport_InternalAuthenticate_BAsyncResult(shared_from_this())); authentication->authenticate(PClient(), authResult); } else if (assumeAuthenticationIsValid) { innerResult->setAsyncResult(BVariant(lastAuthenticationException)); } else { // innerResult has been added to asyncResultsWaitingForAuthentication // and will be called in InternalAuthenticate_BAsyncResult } } else { innerResult->setAsyncResult(BVariant(true)); } }
BINLINE void BTransport::assignSessionThenSendMethod(const PSerializable& requestObject, const PAsyncResult& asyncResult) { if (this->authentication) { try { BTYPEID typeId = getObjectTypeId(requestObject); PAsyncResult sessionResult(new BTransport_AssingSessionThenSendMethod(shared_from_this(), requestObject, asyncResult)); this->authentication->getSession(PClient(), typeId, sessionResult); } catch (const BException& ex) { asyncResult->setAsyncResult(BVariant(ex)); } } else { this->send(requestObject, asyncResult); } }
virtual void setAsyncResult(const BVariant& result) { if (result.isException()) { asyncResult->setAsyncResult(result); } else { PMethodRequest methodRequest = byps_ptr_cast<BMethodRequest>(requestObject); if (methodRequest) { PSerializable session; result.get(session); methodRequest->setSession(session); } pTransport->send(methodRequest, asyncResult); } delete this; }
BINLINE void BTransport::send(const PSerializable& obj, PAsyncResult asyncResult) { PTransport pthis = shared_from_this(); if (!pthis) throw BException(BExceptionC::CANCELLED); try { POutput outp = getOutput(); outp->store(obj); PAsyncResult outerResult = new BTransport_DeserlializeMethodResultMaybeRelogin(pthis, obj, asyncResult); PMessage msg = outp->toMessage(); wire->send(msg, outerResult); } catch (const exception& ex) { asyncResult->setAsyncResult(BVariant(ex)); } }