support call duration limits on inbound OSP calls (issue #5346)
authorKevin P. Fleming <kpfleming@digium.com>
Tue, 4 Oct 2005 23:28:57 +0000 (23:28 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Tue, 4 Oct 2005 23:28:57 +0000 (23:28 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6721 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channel.c
channels/chan_sip.c
include/asterisk/channel.h
res/res_osp.c

index 9296ed1..3ffeeba 100755 (executable)
--- a/channel.c
+++ b/channel.c
@@ -273,6 +273,31 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
        return;
 }
 
+/*--- ast_channel_cmpwhentohangup: Compare a offset with when to hangup channel */
+int ast_channel_cmpwhentohangup(struct ast_channel *chan, time_t offset)
+{
+       time_t whentohangup;
+
+       if (chan->whentohangup == 0) {
+               if (offset == 0)
+                       return (0);
+               else
+                       return (-1);
+       } else { 
+               if (offset == 0)
+                       return (1);
+               else {
+                       whentohangup = offset + time (NULL);
+                       if (chan->whentohangup < whentohangup)
+                               return (1);
+                       else if (chan->whentohangup == whentohangup)
+                               return (0);
+                       else
+                               return (-1);
+               }
+       }
+}
+
 /*--- ast_channel_register: Register a new telephony channel in Asterisk */
 int ast_channel_register(const struct ast_channel_tech *tech)
 {
index 5505a84..2b449c5 100755 (executable)
@@ -637,6 +637,7 @@ static struct sip_pvt {
 #ifdef OSP_SUPPORT
        int osphandle;                          /* OSP Handle for call */
        time_t ospstart;                        /* OSP Start time */
+       unsigned int osptimelimit;              /* OSP call duration limit */
 #endif
        struct sip_request initreq;             /* Initial request */
        
@@ -2666,6 +2667,10 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
        struct ast_channel *tmp;
        struct ast_variable *v = NULL;
        int fmt;
+#ifdef OSP_SUPPORT
+       char iabuf[INET_ADDRSTRLEN];
+       char peer[MAXHOSTNAMELEN];
+#endif 
        
        ast_mutex_unlock(&i->lock);
        /* Don't hold a sip pvt lock while we allocate a channel */
@@ -2757,6 +2762,10 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
        if (!ast_strlen_zero(i->callid)) {
                pbx_builtin_setvar_helper(tmp, "SIPCALLID", i->callid);
        }
+#ifdef OSP_SUPPORT
+       snprintf(peer, sizeof(peer), "[%s]:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), i->sa.sin_addr), ntohs(i->sa.sin_port));
+       pbx_builtin_setvar_helper(tmp, "OSPPEER", peer);
+#endif
        ast_setstate(tmp, state);
        if (state != AST_STATE_DOWN) {
                if (ast_pbx_start(tmp)) {
@@ -2975,6 +2984,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
                p->timer_t1 = 500;      /* Default SIP retransmission timer T1 (RFC 3261) */
 #ifdef OSP_SUPPORT
        p->osphandle = -1;
+       p->osptimelimit = 0;
 #endif 
        if (sin) {
                memcpy(&p->sa, sin, sizeof(p->sa));
@@ -5957,6 +5967,22 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward
                list_route(p->route);
 }
 
+#ifdef OSP_SUPPORT
+/*--- check_osptoken: Validate OSP token for user authrroization ---*/
+static int check_osptoken (struct sip_pvt *p, char *token)
+{
+       char tmp[80];
+
+       if (ast_osp_validate (NULL, token, &p->osphandle, &p->osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
+               return (-1);
+       } else {
+               snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
+               pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
+               return (0);
+       }
+}
+#endif
+
 /*--- check_auth: Check user authorization from peer definition ---*/
 /*      Some actions, like REGISTER and INVITEs from peers require
         authentication (if peer have secret set) */
@@ -5968,9 +5994,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
        char *respheader = "Proxy-Authenticate";
        char *authtoken;
 #ifdef OSP_SUPPORT
-       char tmp[80];
        char *osptoken;
-       unsigned int osptimelimit;
 #endif
        /* Always OK if no secret */
        if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)
@@ -6002,14 +6026,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
                                        }
                                }
                                else {
-                                       if (ast_osp_validate (NULL, osptoken, &p->osphandle, &osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
-                                               return (-1);
-                                       } 
-                                       else {
-                                               snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
-                                               pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
-                                               return (0);
-                                       }
+                                       return (check_osptoken (p, osptoken));
                                }
                                break;
                        case SIP_OSPAUTH_PROXY:
@@ -6017,14 +6034,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
                                        return (0);
                                } 
                                else {
-                                       if (ast_osp_validate (NULL, osptoken, &p->osphandle, &osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
-                                               return (-1);
-                                       } 
-                                       else {
-                                               snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
-                                               pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
-                                               return (0);
-                                       }
+                                       return (check_osptoken (p, osptoken));
                                }
                                break;
                        case SIP_OSPAUTH_EXCLUSIVE:
@@ -6032,14 +6042,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
                                        return (-1);
                                }
                                else {
-                                       if (ast_osp_validate (NULL, osptoken, &p->osphandle, &osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
-                                               return (-1);
-                                       } 
-                                       else {
-                                               snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
-                                               pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
-                                               return (0);
-                                       }
+                                       return (check_osptoken (p, osptoken));
                                }
                                break;
                        default:
@@ -10243,6 +10246,9 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
        if (!ignore && p)
                p->lastinvite = seqno;
        if (c) {
+#ifdef OSP_SUPPORT
+               ast_channel_setwhentohangup (c, p->osptimelimit);
+#endif
                switch(c->_state) {
                case AST_STATE_DOWN:
                        transmit_response(p, "100 Trying", req);
index 67b32b1..0d7cb6b 100755 (executable)
@@ -562,6 +562,18 @@ int ast_softhangup_nolock(struct ast_channel *chan, int cause);
  */
 int ast_check_hangup(struct ast_channel *chan);
 
+/*! Compare a offset with the settings of when to hang a channel up */
+/*! 
+ * \param chan channel on which to check for hang up
+ * \param offset offset in seconds from current time
+ * \return 1, 0, or -1
+ * This function compares a offset from current time with the absolute time 
+ * out on a channel (when to hang up). If the absolute time out on a channel
+ * is earlier than current time plus the offset, it returns 1, if the two
+ * time values are equal, it return 0, otherwise, it retturn -1.
+ */
+int ast_channel_cmpwhentohangup(struct ast_channel *chan, time_t offset);
+
 /*! Set when to hang a channel up */
 /*! 
  * \param chan channel on which to check for hang up
index 128befb..dca948c 100755 (executable)
@@ -521,7 +521,6 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
        int tokenlen;
        unsigned int dummy=0;
        unsigned int timelimit;
-       char* sipcallid;
        unsigned int callidlen;
        char callidstr[OSPC_CALLID_MAXSIZE] = "";
        struct osp_provider *osp;
@@ -531,9 +530,9 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
        char destination[2048]="";
        char token[2000];
        char tmp[256]="", *l, *n;
-       OSPTCALLID *callid;
        OSPE_DEST_PROT prot;
        OSPE_DEST_OSP_ENABLED ospenabled;
+       char *devinfo = NULL;
 
        result->handle = -1;
        result->numresults = 0;
@@ -558,8 +557,6 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
        callerid = l;
 
        if (chan) {
-               sipcallid = pbx_builtin_getvar_helper (chan, "SIPCALLID");
-               ast_copy_string(callidstr, sipcallid, sizeof(callidstr));
                cres = ast_autoservice_start(chan);
                if (cres < 0)
                        return cres;
@@ -581,67 +578,71 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
        ast_mutex_unlock(&osplock);
        if (res) {
                res = 0;
-               callid = OSPPCallIdNew(strlen(callidstr), callidstr);
-               if (callid) {
-                       /* No more than 10 back */
-                       counts = 10;
-                       dummy = 0;
-                       callidlen = sizeof(callidstr);
-                       if (!OSPPTransactionRequestAuthorisation(result->handle, source, "", 
-                                 callerid,OSPC_E164, extension, OSPC_E164, NULL, 1, &callid, NULL, &counts, &dummy, NULL)) {
-                               if (counts) {
-                                       tokenlen = sizeof(token);
-                                       result->numresults = counts - 1;
-                                       if (!OSPPTransactionGetFirstDestination(result->handle, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
-                                               sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
-                                               ast_log(LOG_DEBUG, "Got destination '%s' and called: '%s' calling: '%s' for '%s' (provider '%s')\n",
-                                                       destination, callednum, callingnum, extension, provider);
-                                               ast_channel_setwhentohangup (chan, timelimit);  /* Only support OSP server with only one duration limit */
-                                               do {
-                                                       if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
-                                                               result->token[0] = 0;
-                                                       }
-                                                       else {
-                                                               ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
+               /* No more than 10 back */
+               counts = 10;
+               dummy = 0;
+               devinfo = pbx_builtin_getvar_helper (chan, "OSPPEER");
+               if (!devinfo) {
+                       devinfo = "";
+               }
+               if (!OSPPTransactionRequestAuthorisation(result->handle, source, devinfo, 
+                         callerid,OSPC_E164, extension, OSPC_E164, NULL, 0, NULL, NULL, &counts, &dummy, NULL)) {
+                       if (counts) {
+                               tokenlen = sizeof(token);
+                               result->numresults = counts - 1;
+                               callidlen = sizeof(callidstr);
+                               if (!OSPPTransactionGetFirstDestination(result->handle, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
+                                       sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
+                                       ast_log(LOG_DEBUG, "Got destination '%s' and called: '%s' calling: '%s' for '%s' (provider '%s')\n",
+                                               destination, callednum, callingnum, extension, provider);
+                                       /* Only support OSP server with only one duration limit */
+                                       if (ast_channel_cmpwhentohangup (chan, timelimit) < 0) {
+                                               ast_channel_setwhentohangup (chan, timelimit);  
+                                       }
+                                       do {
+                                               if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
+                                                       result->token[0] = 0;
+                                               }
+                                               else {
+                                                       ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
+                                               }
+                                               if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
+                                                       res = 1;
+                                                       /* Strip leading and trailing brackets */
+                                                       destination[strlen(destination) - 1] = '\0';
+                                                       switch(prot) {
+                                                       case OSPE_DEST_PROT_H323_SETUP:
+                                                               ast_copy_string(result->tech, "H323", sizeof(result->tech));
+                                                               snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+                                                               break;
+                                                       case OSPE_DEST_PROT_SIP:
+                                                               ast_copy_string(result->tech, "SIP", sizeof(result->tech));
+                                                               snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+                                                               break;
+                                                       case OSPE_DEST_PROT_IAX:
+                                                               ast_copy_string(result->tech, "IAX", sizeof(result->tech));
+                                                               snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+                                                               break;
+                                                       default:
+                                                               ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
+                                                               res = 0;
                                                        }
-                                                       if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
-                                                               res = 1;
-                                                               /* Strip leading and trailing brackets */
-                                                               destination[strlen(destination) - 1] = '\0';
-                                                               switch(prot) {
-                                                               case OSPE_DEST_PROT_H323_SETUP:
-                                                                       ast_copy_string(result->tech, "H323", sizeof(result->tech));
-                                                                       snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
-                                                                       break;
-                                                               case OSPE_DEST_PROT_SIP:
-                                                                       ast_copy_string(result->tech, "SIP", sizeof(result->tech));
-                                                                       snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
-                                                                       break;
-                                                               case OSPE_DEST_PROT_IAX:
-                                                                       ast_copy_string(result->tech, "IAX", sizeof(result->tech));
-                                                                       snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
-                                                                       break;
-                                                               default:
-                                                                       ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
-                                                                       res = 0;
-                                                               }
-                                                               if (!res && result->numresults) {
-                                                                       result->numresults--;
-                                                                       if (OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
-                                                                                       sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
-                                                                                       break;
-                                                                       }
+                                                       if (!res && result->numresults) {
+                                                               result->numresults--;
+                                                               callidlen = sizeof(callidstr);
+                                                               if (OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
+                                                                               sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
+                                                                               break;
                                                                }
-                                                       } else {
-                                                               ast_log(LOG_DEBUG, "Missing destination protocol\n");
-                                                               break;
                                                        }
-                                               } while(!res && result->numresults);
-                                       }
+                                               } else {
+                                                       ast_log(LOG_DEBUG, "Missing destination protocol\n");
+                                                       break;
+                                               }
+                                       } while(!res && result->numresults);
                                }
-                               
                        }
-                       OSPPCallIdDelete(&callid);
+                       
                }
                if (!res) {
                        OSPPTransactionDelete(result->handle);
@@ -680,11 +681,11 @@ int ast_osp_next(struct ast_osp_result *result, int cause)
 
        if (result->handle > -1) {
                dummy = 0;
-               callidlen = sizeof(callidstr);
                if (result->numresults) {
                        tokenlen = sizeof(token);
                        while(!res && result->numresults) {
                                result->numresults--;
+                               callidlen = sizeof(callidstr);
                                if (!OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
                                                                        sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
                                        if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {