Work on precaching
authorMark Spencer <markster@digium.com>
Fri, 22 Oct 2004 14:19:11 +0000 (14:19 +0000)
committerMark Spencer <markster@digium.com>
Fri, 22 Oct 2004 14:19:11 +0000 (14:19 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4045 65c4cc65-6c06-0410-ace0-fbb531ad65f3

configs/dundi.conf.sample
include/asterisk/dundi.h
pbx/pbx_dundi.c

index e63b1df..c95d7fd 100755 (executable)
@@ -139,6 +139,9 @@ autokill=yes
 ; model - inbound, outbound, or symmetric for whether we receive 
 ;         requests only, transmit requests only, or do both.
 ;
+; canprecache - Permits this peer to provide answers (which are cached)
+;               for queries we did not make (a.k.a. pre-caching)
+;
 ; The '*' peer is special and matches an unspecified entity
 ;
 
index 5780c3d..0dc548c 100755 (executable)
@@ -101,6 +101,7 @@ struct dundi_cause {
 #define DUNDI_COMMAND_DPRESPONSE       (2 | 0x40)      /* Respond to a discovery request */
 #define DUNDI_COMMAND_EIDQUERY         3                       /* Request information for a peer */
 #define DUNDI_COMMAND_EIDRESPONSE      (4 | 0x40)      /* Response to a peer query */
+#define DUNDI_COMMAND_PRECACHE         5                       /* Unsolicited answer pre-cache */
 #define DUNDI_COMMAND_INVALID          (7 | 0x40)      /* Invalid dialog state (does not require ack) */
 #define DUNDI_COMMAND_UNKNOWN          (8 | 0x40)      /* Unknown command */
 #define DUNDI_COMMAND_NULL                     9                       /* No-op */
index f4847c5..b09c3de 100755 (executable)
@@ -203,6 +203,7 @@ static struct dundi_peer {
        int registerid;
        int qualifyid;
        int sentfullkey;
+       int canprecache;
        int order;
        unsigned char txenckey[256]; /* Transmitted encrypted key + sig */
        unsigned char rxenckey[256]; /* Cache received encrypted key + sig */
@@ -1240,6 +1241,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
        int x,y,z;
        int resp;
        int res;
+       int authpass=0;
        unsigned char *bufcpy;
        struct dundi_ie_data ied;
        struct dundi_ies ies;
@@ -1349,10 +1351,82 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                        }
                }
                break;
+       case DUNDI_COMMAND_PRECACHE:
+               /* Success of some sort */
+               ast_log(LOG_DEBUG, "Looks like a precache with %d answers\n", ies.anscount);
+               /* A dialplan or entity discover -- qualify by highest level entity */
+               peer = find_peer(ies.eids[0]);
+               if (peer && ies.called_number) {
+                       struct dundi_request dr;
+                       struct dundi_result dr2[1];
+                       memset(&dr, 0, sizeof(dr));
+                       memset(&dr2, 0, sizeof(dr2));
+                       /* Build placeholder Dundi Request */
+                       trans->us_eid = peer->us_eid;
+                       if (!ies.called_context)
+                               ies.called_context = "e164";
+                       strncpy(dr.dcontext, ies.called_context, sizeof(dr.dcontext) - 1);
+                       strncpy(dr.number, ies.called_number, sizeof(dr.number) - 1);
+                       dr.dr = dr2;
+                       trans->parent = &dr;
+                       
+                       /* Make sure we have all the proper auths */
+                       if (strlen(peer->inkey)) {
+                               authpass = encrypted;
+                       } else 
+                               authpass = 1;
+                       authpass &= has_permission(peer->include, ies.called_context);
+                       authpass &= peer->canprecache;
+                       if (authpass) {
+                               /* Okay we're authentiated and all, now we check if they're authorized */
+                               for (x=0;x<ies.anscount;x++) {
+                                       /* Copy into parent responses */
+                                       trans->parent->dr[0].flags = ntohs(ies.answers[x]->flags);
+                                       trans->parent->dr[0].techint = ies.answers[x]->protocol;
+                                       trans->parent->dr[0].weight = ntohs(ies.answers[x]->weight);
+                                       trans->parent->dr[0].eid = ies.answers[x]->eid;
+                                       if (ies.expiration > 0)
+                                               trans->parent->dr[0].expiration = ies.expiration;
+                                       else
+                                               trans->parent->dr[0].expiration = DUNDI_DEFAULT_CACHE_TIME;
+                                       dundi_eid_to_str(trans->parent->dr[0].eid_str, 
+                                               sizeof(trans->parent->dr[0].eid_str),
+                                               &ies.answers[x]->eid);
+                                       strncpy(trans->parent->dr[0].dest, ies.answers[x]->data,
+                                               sizeof(trans->parent->dr[0].dest));
+                                       strncpy(trans->parent->dr[0].tech, tech2str(ies.answers[x]->protocol),
+                                               sizeof(trans->parent->dr[0].tech));
+                                       trans->parent->respcount=1;
+                                       /* Save all the results (if any) we had.  Even if no results, still cache lookup.  Let
+                                          the cache know if this request was unaffected by our entity list. */
+                                       cache_save(&trans->them_eid, trans->parent, 0, 
+                                               ies.hint ? ntohs(ies.hint->flags) & DUNDI_HINT_UNAFFECTED : 0, ies.expiration);
+                               }
+                               if (ies.hint) {
+                                       cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration);
+                                       if (ntohs(ies.hint->flags) & DUNDI_HINT_TTL_EXPIRED)
+                                               trans->parent->hmd->flags |= DUNDI_HINT_TTL_EXPIRED;
+                                       if (ntohs(ies.hint->flags) & DUNDI_HINT_DONT_ASK) { 
+                                               if (strlen(ies.hint->data) > strlen(trans->parent->hmd->exten)) {
+                                                       strncpy(trans->parent->hmd->exten, ies.hint->data, 
+                                                               sizeof(trans->parent->hmd->exten) - 1);
+                                               }
+                                       } else {
+                                               trans->parent->hmd->flags &= ~DUNDI_HINT_DONT_ASK;
+                                       }
+                               }
+                       }
+               }
+               if (!authpass && ies.eids[0])
+                       ast_log(LOG_NOTICE, "Peer '%s' does not have permission to pre-cache!\n", 
+                               dundi_eid_to_str(eid_str, sizeof(eid_str), ies.eids[0]));
+               /* Close connection if not final */
+               if (!final) 
+                       dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
+               break;
        case DUNDI_COMMAND_DPRESPONSE:
                /* A dialplan response, lets see what we got... */
                if (ies.cause < 1) {
-                       int authpass=0;
                        /* Success of some sort */
                        ast_log(LOG_DEBUG, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
                        if (trans->flags & FLAG_ENCRYPT) {
@@ -1437,7 +1511,6 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
        case DUNDI_COMMAND_EIDRESPONSE:
                /* A dialplan response, lets see what we got... */
                if (ies.cause < 1) {
-                       int authpass=0;
                        /* Success of some sort */
                        ast_log(LOG_DEBUG, "Looks like success of some sort (%d)\n", ies.cause);
                        if (trans->flags & FLAG_ENCRYPT) {
@@ -3381,6 +3454,8 @@ static void build_peer(dundi_eid *eid, struct ast_variable *v)
                                strncpy(peer->inkey, v->value, sizeof(peer->inkey) - 1);
                        } else if (!strcasecmp(v->name, "outkey")) {
                                strncpy(peer->outkey, v->value, sizeof(peer->outkey) - 1);
+                       } else if (!strcasecmp(v->name, "canprecache")) {
+                               peer->canprecache = ast_true(v->value);
                        } else if (!strcasecmp(v->name, "host")) {
                                if (!strcasecmp(v->value, "dynamic")) {
                                        peer->dynamic = 1;