⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aaa_route_msg_router.cxx

📁 Diameter协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
                /*          The Diameter protocol requires that agents maintain          transaction state, which is used for failover purposes.          Transaction state implies that upon forwarding a request,          the Hop-by-Hop identifier is saved; the field is replaced          with a locally unique identifier, which is restored to its          original value when the corresponding answer is received.          The request's state is released upon receipt of the answer.          A stateless agent is one that only maintains transaction          state.         */        int h2hIndex, rcode;        if (source) {            int localHH = AAA_HOPBYHOP_GEN()->Get();            h2hIndex = Add(localHH, msg, source, dest);            msg->hdr.hh = localHH;        }        else {            // locally generated            if (msg->hdr.hh == 0) {                msg->hdr.hh = AAA_HOPBYHOP_GEN()->Get();            }            if (msg->hdr.ee == 0) {                msg->hdr.ee = AAA_ENDTOEND_GEN()->Get();            }            h2hIndex = Add(msg->hdr.hh, msg, source, dest);        }                rcode = (dest->Send(msg) >= 0) ? 0 : (-1);            if (h2hIndex > 0) {            StoreRequestMessage(h2hIndex, msg);        }        return rcode;    }    return (0);}AAA_ROUTE_RESULT AAA_MsgRouter::DcReject::Process(std::auto_ptr<AAAMessage> msg,                                                  AAA_PeerEntry *source,                                                  AAA_PeerEntry *dest){    /*       6.2.1.  Processing received Answers        A Diameter client or proxy MUST match the Hop-by-Hop Identifier in an        answer received against the list of pending requests.  The        corresponding message should be removed from the list of pending        requests.  It SHOULD ignore answers received that do not match a        known Hop-by-Hop Identifier.    */    AAA_LOG(LM_INFO, "(%P|%t) *** Router rejected answer message ***\n");    AAA_MsgDump::Dump(*msg);    return (AAA_ROUTE_RESULT_SUCCESS);}int AAA_MsgRouter::DcReject::RequestMsg(std::auto_ptr<AAAMessage> msg,                                        AAA_PeerEntry *source,                                        AAA_PeerEntry *dest){    /*       6.1.  Diameter Request Routing Overview                     .                     .                     .         4. If none of the above is successful, an answer is returned with the            Result-Code set to AAA_UNABLE_TO_DELIVER, with the E-bit set.     */    AAA_LOG(LM_INFO, "(%P|%t) *** Router rejected request message ***\n");    AAA_MsgDump::Dump(*msg);    msg->hdr.flags.r = 0;    msg->hdr.flags.e = 1;    AAA_MsgResultCode rcode(*msg);    rcode.ResultCode(AAA_UNABLE_TO_DELIVER);    if (! source) {        // request must have been locally generated        m_Arg[AAA_MsgRouterHandlerTable::H_ERROR]->                Request(msg, source, dest);        return (0);    }    else {            return (source->Send(msg) == 0) ? 0 : (-1);    }}AAA_ROUTE_RESULT AAA_MsgRouter::DcReject::Lookup(std::auto_ptr<AAAMessage> &msg,                                                 AAA_PeerEntry *&dest){    /*       6.2.1.  Processing received Answers        A Diameter client or proxy MUST match the Hop-by-Hop Identifier in an        answer received against the list of pending requests.  The        corresponding message should be removed from the list of pending        requests.  It SHOULD ignore answers received that do not match a        known Hop-by-Hop Identifier.    */    return (AAA_ROUTE_RESULT_SUCCESS);}int AAA_MsgRouter::RedirectAgent::Request(std::auto_ptr<AAAMessage> &msg,                                          AAA_PeerEntry *source,                                          AAA_PeerEntry *dest){    /*      6.1.7.  Redirecting requests       When a redirect agent receives a request whose routing entry is set       to REDIRECT, it MUST reply with an answer message with the 'E' bit       set, while maintaining the Hop-by-Hop Identifier in the header, and       include the Result-Code AVP to AAA_REDIRECT_INDICATION.  Each of       the servers associated with the routing entry are added in separate       Redirect-Host AVP.                      +------------------+                      |     Diameter     |                      |  Redirect Agent  |                      +------------------+                       ^    |    2. command + 'E' bit        1. Request     |    |    Result-Code =       joe@example.com |    |    AAA_REDIRECT_INDICATION +                       |    |    Redirect-Host AVP(s)                       |    v                   +-------------+  3. Request  +-------------+                   | example.com |------------->| example.net |                   |    Relay    |              |   Diameter  |                   |    Agent    |<-------------|    Server   |                   +-------------+  4. Answer   +-------------+                             Figure 5: Diameter Redirect Agent       The receiver of the answer message with the 'E' bit set, and the       Result-Code AVP set to AAA_REDIRECT_INDICATION uses the hop-by-       hop field in the Diameter header to identify the request in the       pending message queue (see Section 5.3) that is to be redirected.  If       no transport connection exists with the new agent, one is created,       and the request is sent directly to it.       Multiple Redirect-Host AVPs are allowed.  The receiver of the answer       message with the 'E' bit set selects exactly one of these hosts as       the destination of the redirected message.    */    AAA_IdentityAvpContainerWidget destRealm(msg->acl);    diameter_identity_t *DestRealm = destRealm.GetAvp(AAA_AVPNAME_DESTREALM);    AAA_RouteEntry *route = AAA_ROUTE_TABLE()->Lookup(*DestRealm);    try {        diameter_unsigned32_t *idPtr;        char *avpNames[] = { AAA_AVPNAME_AUTHAPPID,                             AAA_AVPNAME_ACCTAPPID };        AAA_UInt32AvpContainerWidget id(msg->acl);        for (int i=0; i<sizeof(avpNames)/sizeof(char*); i++) {            if ((idPtr = id.GetAvp(avpNames[i]))) {                break;            }        }        AAA_RouteApplication *app = NULL;        if (idPtr) {            app = route->Lookup(*idPtr, 0); // base protocol only        }        else {            AAA_GroupedAvpContainerWidget vendorSpecificId(msg->acl);            diameter_grouped_t *grouped = vendorSpecificId.GetAvp                (AAA_AVPNAME_VENDORAPPID);            if (grouped) {                AAA_ApplicationIdLst vendorIdLst;                AAA_UInt32AvpContainerWidget gVendorId(*grouped);                diameter_unsigned32_t *value = gVendorId.GetAvp(AAA_AVPNAME_VENDORID);                for (int p=1; value; p++) {                    vendorIdLst.push_back(*value);                    value = gVendorId.GetAvp(AAA_AVPNAME_VENDORID, p);                }                          char *avpNames[] = { AAA_AVPNAME_AUTHAPPID,                                     AAA_AVPNAME_ACCTAPPID };                AAA_UInt32AvpContainerWidget gId(*grouped);                for (int i=0; i<sizeof(avpNames)/sizeof(char*); i++) {                    if ((value = gId.GetAvp(avpNames[i]))) {                       break;                    }                }                if (value) {                    AAA_ApplicationIdLst::iterator i = vendorIdLst.begin();                    for (; (app == NULL) && (i != vendorIdLst.end()); i++) {                        if ((app = route->Lookup(*value, *i))) {                            break;                        }                    }                }            }        }                if (app) {            AAA_DiamUriAvpWidget redirect(AAA_AVPNAME_REDIRECTHOST);            AAA_RouteServerEntry *server = app->Servers().First();            while (server) {                redirect.Get().fqdn = server->Server();                server = app->Servers().Next(*server);            }            if (! redirect.empty()) {                AAA_EnumAvpWidget redirectUsage(AAA_AVPNAME_REDIRECTHOSTUSAGE);                redirectUsage.Get() = route->RedirectUsage();                msg->acl.add(redirect());                msg->acl.add(redirectUsage());            }        }    }    catch (...) {        return (-1);    }    msg->hdr.flags.r = 0;    msg->hdr.flags.e = 1;    AAA_MsgResultCode rcode(*msg);    rcode.ResultCode(AAA_REDIRECT_INDICATION);    return (source->Send(msg) >= 0) ? 0 : (-1);}int AAA_MsgRouter::RedirectAgent::Answer(std::auto_ptr<AAAMessage> &msg,                                         AAA_PeerEntry *source,                                         AAA_PeerEntry *dest){    /*      2.8.3.  Redirect Agents       Redirect agents are useful in scenarios where the Diameter routing       configuration needs to be centralized.  An example is a redirect       agent that provides services to all members of a consortium, but does       not wish to be burdened with relaying all messages between realms.       This scenario is advantageous since it does not require that the       consortium provide routing updates to its members when changes are       made to a member's infrastructure.       Since redirect agents do not relay messages, and only return an       answer with the information necessary for Diameter agents to       communicate directly, they do not modify messages.  Since redirect       agents do not receive answer messages, they cannot maintain session       state.  Further, since redirect agents never relay requests, they are       not required to maintain transaction state.       The example provided in Figure 3 depicts a request issued from the       access device, NAS, for the user bob@example.com.  The message is       forwarded by the NAS to its relay, DRL, which does not have a routing       entry in its Diameter Routing Table for example.com.  DRL has a       default route configured to DRD, which is a redirect agent that       returns a redirect notification to DRL, as well as HMS' contact       information.  Upon receipt of the redirect notification, DRL       establishes a transport connection with HMS, if one doesn't already       exist, and forwards the request to it.                                   +------+                                   |      |                                   | DRD  |                                   |      |                                   +------+                                    ^    |                        2. Request  |    | 3. Redirection                                    |    |    Notification                                    |    v        +------+    --------->     +------+     --------->    +------+        |      |    1. Request     |      |     4. Request    |      |        | NAS  |                   | DRL  |                   | HMS  |        |      |    6. Answer      |      |     5. Answer     |      |        +------+    <---------     +------+     <---------    +------+       example.net                example.net               example.com                     Figure 3: Redirecting a Diameter Message       Since redirect agents do not perform any application level       processing, they provide relaying services for all Diameter       applications, and therefore MUST advertise the Relay Application       Identifier.    */        msg->hdr.flags.r = 1;    msg->hdr.flags.e = 0;    AAA_UInt32AvpContainerWidget resultCode(msg->acl);    resultCode.DelAvp(AAA_AVPNAME_RESULTCODE);    AAA_DiamUriAvpContainerWidget redirect(msg->acl);    diameter_uri_t *RedirectHost = redirect.GetAvp(AAA_AVPNAME_REDIRECTHOST);    for (int p=1; RedirectHost; p++) {        AAA_PeerEntry *peer = AAA_PEER_TABLE()->Lookup(RedirectHost->fqdn);        if (peer) {            if (peer->IsOpen()) {                AAA_IdentityAvpWidget destHost(AAA_AVPNAME_DESTHOST);                        destHost.Get() = RedirectHost->fqdn;                msg->acl.add(destHost());                redirect.DelAvp(AAA_AVPNAME_REDIRECTHOST);                return (peer->Send(msg) >= 0) ? 0 : (-1);            }            else {                // try opening it [TBD]            }        }        else {            // try to make connection to it [TBD]        }                RedirectHost = redirect.GetAvp(AAA_AVPNAME_REDIRECTHOST, p);    }    return (0);}bool AAA_MsgRouter::RedirectAgent::IsRedirected(std::auto_ptr<AAAMessage> &msg){    /*       The receiver of the answer message with the 'E' bit set, and the       Result-Code AVP set to AAA_REDIRECT_INDICATION uses the hop-by-       hop field in the Diameter header to identify the request in the       pending message queue (see Section 5.3) that is to be redirected.  If       no transport connection exists with the new agent, one is created,       and the request is sent directly to it.       Multiple Redirect-Host AVPs are allowed.  The receiver of the answer       message with the 'E' bit set selects exactly one of these hosts as       the destination of the redirected message.    */    AAA_MsgResultCode rcode(*msg);    return ((msg->hdr.flags.r == 0) &&            (msg->hdr.flags.e) &&            (rcode.ResultCode() == AAA_REDIRECT_INDICATION));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -