// IDispatch implementation void CoAuthServiceCall::ReadyStateChange() { const DWORD dwRef = ExternalAddRef(); // lock protect your instance try { switch (m_spRequest->readyState) { case READYSTATE_LOADING: { TRACE2("CoAuthServiceCall(%ls)::IXMLDOMDocumentsEvent::OnReadyStateChange() logical state: %d, m_spRequest->readyState: READYSTATE_LOADING\n", (BSTR)m_bstrUrl, m_eState); /* * siehe auch: kommentar zu * CoAuthServiceCall::m_bstrAccessToken UND * IWorkflow::AuthorizeRequest */ oAuthLib::IAuthorizePtr spAuthorize; if (SUCCEEDED(GetTokenServer(&spAuthorize))) spAuthorize->AuthorizeRequest(m_spRequest, &m_bstrAccessToken); } break; case READYSTATE_COMPLETE: { TRACE2("CoAuthServiceCall(%ls)::IXMLDOMDocumentsEvent::OnReadyStateChange() logical state: %d, m_spRequest->readyState: READYSTATE_COMPLETE\n", (BSTR)m_bstrUrl, m_eState); /* * das wird erst noetig wenn wir den UseCase: Shutdown, Wait for pending requests implementieren * CComPtr < IWorkflow > spWorkflow; * pThis->GetWorkflow(&spWorkflow); * spWorkflow->FinalizeRequest(m_spRequest); */ if (200 == m_spRequest->status) { m_eState = Finish; #ifdef AUTHORIZATION_SERVER_SUPPORT_JSON /* * das ist natuerlich LUXUS pur bzw. schon zuviel spezialisierung. es gibt ja auch noch XML * https://casablanca.codeplex.com/wikipage?title=JSON&referringTitle=Documentation * * CAUTION: this is necessary to avoid false memory leaks reported by the MFC framework; * http://codexpert.ro/blog/2015/05/23/using-lambdas-in-mfc-applications-part-3-dealing-with-c-rest-sdk/ */ web::json::value result = web::json::value::parse(utility::string_t(m_spRequest->responseText)); onSucceeded(result); // wir setzen das onSucceeded NICHT in abhaengigkeit vom m_spRequest->status #else onSucceeded(); // wir setzen das onSucceeded NICHT in abhaengigkeit vom m_spRequest->status #endif // break reference cycle, Remove sink from xml http request // CAUTION: this wont work for this implementation MFC/DISPATCH (Heap corrupt) // entweder KEINEN code mehr ausfuehren ODER Lock/Unlock // m_spRequest->put_onreadystatechange(NULL); } else if (401 == m_spRequest->status && InitialRequest == m_eState) { oAuthLib::IAuthorizePtr spAuthorize; if (SUCCEEDED(GetTokenServer(&spAuthorize))) { const HRESULT _hr = spAuthorize->raw_CanRetryImmediately(m_spRequest, m_bstrAccessToken); _ASSERT(SUCCEEDED(_hr)); // per definition gibt es hier KEIN E_FAIL/E_NOTIMPL ... if (S_FALSE == _hr) { /* * der ERSTE request der ein 401 empfaengt bzw. ALLE folge requests, die beendet wurden OHNE das wir bereits ein NEUES GUELTIGES access_token haben, laufen hier rein. * werden vom client bzw. den clients die requests schneller abgesetzt als ein ExchangeToken() mit gueltigem access_token zurueckkommt muss der second try gequeued werden. */ ASSERT(NULL == m_pRenewTokenAsync); m_pRenewTokenAsync = DYNAMIC_DOWNCAST(CoAuthRenewTokenAsync, RUNTIME_CLASS(CoAuthRenewTokenAsync)->CreateObject()); ASSERT(1 == m_pRenewTokenAsync->m_dwRef); /* * dieses object kuemmert sich transparent und OHNE jegliches zutun des programmieres * darum das es einen pThis->onSucceeded() bzw. pThis->onFailed(); gibt * diese referenz MUSS VOR dem aufruf von ::Init() gelockt anschliessend freigegeben UND NICHT gespeichert werden! * Hinweis: ein per CRunntimeClass::CreateObject()) erzeugtes object hat initial 1 == CCmdTarget::m_dwRef */ { oAuthLib::IRenewCallbackPtr spCallback(GetInterface(&__uuidof(oAuthLib::IRenewCallback))); ASSERT(CCmdTarget::m_dwRef == dwRef + 1); m_pRenewTokenAsync->Init(spAuthorize, spCallback); ASSERT(CCmdTarget::m_dwRef == dwRef + 2); } } else { /* * wir haben bereits ein NEUES GUELTIGES access_token empfangen. * wir koennen diesen request SOFORT neu anstossen. MUSS NATUERLICH ASYNC sein. */ // wir loeschen das alte/unbrauchbare access_token aus dem initialen request m_bstrAccessToken.Empty(); // mit IRenewCallback::Continue() wird der m_spRequest NEU initialisiert und indirekt ueber IWorkflow::AuthorizeRequest() wieder authorisiert. oAuthLib::IRenewCallbackPtr spCallback(GetInterface(&__uuidof(oAuthLib::IRenewCallback))); spCallback->Continue(); // here we go: NEUES GUELTIGES access_token ASSERT(0 < m_bstrAccessToken.Length()); } } else { // saudummer zustand wir koennen den fehler NICHT an den aufrufer liefern // ohne Workflow object geht nix da machen wir ganz ALLGEMEIN schluss m_eState = Finish; onFailed(); // break reference cycle, Remove sink from xml http request // CAUTION: this wont work for this implementation MFC/DISPATCH (Heap corrupt) // entweder KEINEN code mehr ausfuehren ODER Lock/Unlock // m_spRequest->put_onreadystatechange(NULL); } } else { // IRGENDEIN (unbehandelter) http-status m_eState = Finish; onFailed(); // break reference cycle // Remove sink from xml http request, hie faellt evtl. die letzte referenz // entweder KEINEN code mehr ausfuehren ODER Lock/Unlock // m_spRequest->put_onreadystatechange(NULL); } } break; default: TRACE2(" logical state: %d, m_spRequest->readyState: %d\n", m_eState, m_spRequest->readyState); break; } } catch (const _com_error& e) { TRACE0("CoAuthServiceCall::ReadyStateChange(): ignore exception keep system stable!!!\n"); } ExternalRelease(); // unlock your instance }
/****************************************************************************** * @fn dispatchFrame * * @brief Received frame looks OK so far. Dispatch to either NWK app by * invoking the handler or the user's app by simply leaving the * frame in the queue and letting the app poll the port. * * input parameters * @param fiPtr - frameInfo_t pointer to received frame * * output parameters * * @return void */ static void dispatchFrame(frameInfo_t *fiPtr) { uint8_t port = GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_PORT_OS); uint8_t nwkAppSize = sizeof(func)/sizeof(func[0]); fhStatus_t rc; linkID_t lid; #if defined(ACCESS_POINT) uint8_t loc; #endif #if !defined(END_DEVICE) uint8_t isForMe; #endif /* be sure it's not an echo... */ if (!memcmp(MRFI_P_SRC_ADDR(&fiPtr->mrfiPkt), sMyAddr, NET_ADDR_SIZE)) { fiPtr->fi_usage = FI_AVAILABLE; return; } /* Make sure encyrption bit conforms to our security support context. */ #if defined(SMPL_SECURE) if (!(GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_ENCRYPT_OS))) { /* Encyrption bit is not on when when it should be */ fiPtr->fi_usage = FI_AVAILABLE; return; } #else if (GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_ENCRYPT_OS)) { /* Encyrption bit is on when when it should not be */ fiPtr->fi_usage = FI_AVAILABLE; return; } #endif /* SMPL_SECURE */ /* If it's a network application port dispatch to service routine. Dispose * of frame depending on return code. */ if (port && (port <= nwkAppSize)) { #if defined(SMPL_SECURE) /* Non-connection-based frame. We can decode here if it was encrypted */ if (!nwk_getSecureFrame(&fiPtr->mrfiPkt, MRFI_GET_PAYLOAD_LEN(&fiPtr->mrfiPkt) - F_SEC_CTR_OS, 0)) { fiPtr->fi_usage = FI_AVAILABLE; return; } #endif rc = func[port-1](&fiPtr->mrfiPkt); if (FHS_KEEP == rc) { fiPtr->fi_usage = FI_INUSE_UNTIL_DEL; } #if !defined(END_DEVICE) else if (FHS_REPLAY == rc) { /* an AP or an RE could be relaying a NWK application frame... */ nwk_replayFrame(fiPtr); } #endif else /* rc == FHS_RELEASE (default...) */ { fiPtr->fi_usage = FI_AVAILABLE; } return; } /* sanity check */ else if ((port != SMPL_PORT_USER_BCAST) && ((port < PORT_BASE_NUMBER) || (port > SMPL_PORT_STATIC_MAX))) { /* bogus port. drop frame */ fiPtr->fi_usage = FI_AVAILABLE; return; } /* At this point we know the target is a user app. If this is an end device * and we got this far save the frame and we're done. If we're an AP there * are 3 cases: it's for us, it's for s store-and-forward client, or we need * to replay the frame. If we're and RE and the frame didn't come from an RE * and it's not for us, replay the frame. */ #if defined(END_DEVICE) /* If we're s polling end device we only accept application frames from * the AP. This prevents duplicate reception if we happen to be on when * a linked peer sends. */ #if defined(RX_POLLS) if (F_TX_DEVICE_ED != GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_TX_DEVICE)) { if (nwk_isConnectionValid(&fiPtr->mrfiPkt, &lid)) { fiPtr->fi_usage = FI_INUSE_UNTIL_DEL; } else { fiPtr->fi_usage = FI_AVAILABLE; } } else { fiPtr->fi_usage = FI_AVAILABLE; } #else /* it's destined for a user app. */ if (nwk_isConnectionValid(&fiPtr->mrfiPkt, &lid)) { fiPtr->fi_usage = FI_INUSE_UNTIL_DEL; if (spCallback && spCallback(lid)) { fiPtr->fi_usage = FI_AVAILABLE; return; } } else { fiPtr->fi_usage = FI_AVAILABLE; } #endif /* RX_POLLS */ #else /* END_DEVICE */ /* We have an issue if the frame is broadcast to the UUD port. The AP (or RE) must * handle this frame as if it were the target in case there is an application * running that is listening on that port. But if it's a broadcast it must also be * replayed. It isn't enough just to test for the UUD port because it could be a * directed frame to another device. We must check explicitly for broadcast * destination address. */ isForMe = !memcmp(sMyAddr, MRFI_P_DST_ADDR(&fiPtr->mrfiPkt), NET_ADDR_SIZE); if (isForMe || ((port == SMPL_PORT_USER_BCAST) && !memcmp(nwk_getBCastAddress(), MRFI_P_DST_ADDR(&fiPtr->mrfiPkt), NET_ADDR_SIZE))) { /* The folllowing test will succeed for the UUD port regardless of the * source address. */ if (nwk_isConnectionValid(&fiPtr->mrfiPkt, &lid)) { /* If this is for the UUD port and we are here then the device is either * an AP or an RE. In either case it must replay the UUD port frame if the * frame is not "for me". But it also must handle it since it could have a * UUD-listening application. Do the reply first and let the subsequent code * correctly set the frame usage state. Note that the routine return can be * from this code block. If not it will drop through to the bottom without * doing a replay. */ /* Do I need to replay it? */ if (!isForMe) { /* must be a broadcast for the UUD port */ nwk_replayFrame(fiPtr); } /* OK. Now I handle it... */ fiPtr->fi_usage = FI_INUSE_UNTIL_DEL; if (spCallback && spCallback(lid)) { fiPtr->fi_usage = FI_AVAILABLE; return; } } else { fiPtr->fi_usage = FI_AVAILABLE; } } #if defined( ACCESS_POINT ) /* Check to see if we need to save this for a S and F client. Otherwise, * if it's not for us, get rid of it. */ else if (nwk_isSandFClient(MRFI_P_DST_ADDR(&fiPtr->mrfiPkt), &loc)) { /* Don't bother if it is a duplicate frame or if it's a forwarded frame * echoed back from an RE. */ if (!isDupSandFFrame(&fiPtr->mrfiPkt) && !(GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_FWD_FRAME)) ) { #if defined(APP_AUTO_ACK) /* Make sure ack request bit is off. Sender will have gone away. */ PUT_INTO_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_ACK_REQ, 0); #endif fiPtr->fi_usage = FI_INUSE_UNTIL_FWD; } else { fiPtr->fi_usage = FI_AVAILABLE; } } else if (GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_TX_DEVICE) == F_TX_DEVICE_AP) { /* I'm an AP and this frame came from an AP. Don't replay. */ fiPtr->fi_usage = FI_AVAILABLE; } #elif defined( RANGE_EXTENDER ) else if (GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_TX_DEVICE) == F_TX_DEVICE_RE) { /* I'm an RE and this frame came from an RE. Don't replay. */ fiPtr->fi_usage = FI_AVAILABLE;//////ojooooo descomentar!!! //nwk_replayFrame(fiPtr);//ojoooooooooo borrar!!! } #endif else { /* It's not for me and I'm either an AP or I'm an RE and the frame * didn't come from an RE. Replay the frame. */ nwk_replayFrame(fiPtr); } #endif /* !END_DEVICE */ return; }
/****************************************************************************** * @fn smpl_send_join_reply * * @brief Send the Join reply. Include the Link token. If the device is * a polling sleeper put it into the list of store-and-forward * clients. * * input parameters * @param frame - join frame for which a reply is needed...maybe * * output parameters * * @return void */ static void smpl_send_join_reply(mrfiPacket_t *frame) { frameInfo_t *pOutFrame; uint8_t msg[JOIN_REPLY_FRAME_SIZE]; /* Is this a legacy frame? If so continue. Otherwise check verion.*/ if ((MRFI_GET_PAYLOAD_LEN(frame) - F_APP_PAYLOAD_OS) > JOIN_LEGACY_MSG_LENGTH) { /* see if protocol version is correct... */ if (*(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+J_PROTOCOL_VERSION_OS) != nwk_getProtocolVersion()) { /* Accommodation of protocol version differences can be noted or accomplished here. * Otherwise, no match and the board goes back */ return; } } /* see if join token is correct */ { uint32_t jt; nwk_getNumObjectFromMsg(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+J_JOIN_TOKEN_OS, &jt, sizeof(jt)); if (jt != sJoinToken) { return; } } /* send reply with tid, the link token, and the encryption context */ { uint32_t linkToken; nwk_getLinkToken(&linkToken); nwk_putNumObjectIntoMsg((void *)&linkToken, msg+JR_LINK_TOKEN_OS, sizeof(linkToken)); } msg[JR_CRYPTKEY_SIZE_OS] = SEC_CRYPT_KEY_SIZE; msg[JB_REQ_OS] = JOIN_REQ_JOIN | NWK_APP_REPLY_BIT; /* sender's tid... */ msg[JB_TID_OS] = *(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+JB_TID_OS); if (pOutFrame = nwk_buildFrame(SMPL_PORT_JOIN, msg, sizeof(msg), MAX_HOPS_FROM_AP)) { /* destination address is the source adddress of the received frame. */ memcpy(MRFI_P_DST_ADDR(&pOutFrame->mrfiPkt), MRFI_P_SRC_ADDR(frame), NET_ADDR_SIZE); #ifdef AP_IS_DATA_HUB /* if source device supports ED objects save source address to detect duplicate joins */ if (*(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+J_NUMCONN_OS)) { if (nwk_saveJoinedDevice(frame) && spCallback) { spCallback(0); } } #endif } else { /* oops -- no room left for Tx frame. Don't send reply. */ return; } /* If this device polls we need to provide store-and-forward support */ if (GET_FROM_FRAME(MRFI_P_PAYLOAD(frame),F_RX_TYPE) == F_RX_TYPE_POLLS) { uint8_t loc; /* Check duplicate status */ if (!nwk_isSandFClient(MRFI_P_SRC_ADDR(frame), &loc)) { uint8_t *pNumc = &spSandFContext->curNumSFClients; sfClientInfo_t *pClient = &spSandFContext->sfClients[*pNumc]; /* It's not a duplicate. Save it if there's room */ if (*pNumc < NUM_STORE_AND_FWD_CLIENTS) { memcpy(pClient->clientAddr.addr, MRFI_P_SRC_ADDR(frame), NET_ADDR_SIZE); *pNumc = *pNumc + 1; } else { /* No room left. Just return and don't send reply. */ return; } } else { /* We get here if it's a duplicate. We drop through and send reply. * Reset the S&F marker in the Management application -- we should * assume that the Client reset so the TID will be random. If this is * simply a duplicate frame it causes no harm. */ nwk_resetSFMarker(loc); } } #ifdef SMPL_SECURE nwk_setSecureFrame(&pOutFrame->mrfiPkt, sizeof(msg), 0); #endif /* SMPL_SECURE */ /* It's not S&F or it is but we're OK to send reply. */ nwk_sendFrame(pOutFrame, MRFI_TX_TYPE_FORCED); return; }