Add support change gatekeeper mode or ip per ooh323 reload command
[asterisk/asterisk.git] / addons / ooh323c / src / ooGkClient.c
index 3dce5eb..c91b9ed 100644 (file)
@@ -22,6 +22,7 @@
  */
 #include "asterisk.h"
 #include "asterisk/lock.h"
+#include "asterisk/netsock2.h"
 
 #include "ooGkClient.h"
 #include "ootypes.h"
@@ -169,23 +170,25 @@ void ooGkClientPrintConfig(ooGkClient *pGkClient)
 
 int ooGkClientDestroy(void)
 {
+   ooGkClient *pGkClient = gH323ep.gkClient;
+
    if(gH323ep.gkClient)
    {
-      if(gH323ep.gkClient->state == GkClientRegistered)
+      ast_mutex_lock(&pGkClient->Lock);
+      gH323ep.gkClient = NULL;
+      if(pGkClient->state == GkClientRegistered)
       {
          OOTRACEINFO1("Unregistering from Gatekeeper\n");
-         if(ooGkClientSendURQ(gH323ep.gkClient, NULL)!=OO_OK)
+         if(ooGkClientSendURQ(pGkClient, NULL)!=OO_OK)
             OOTRACEERR1("Error:Failed to send URQ to gatekeeper\n");
       }
       OOTRACEINFO1("Destroying Gatekeeper Client\n");
-      ooGkClientCloseChannel(gH323ep.gkClient);
-      freeContext(&gH323ep.gkClient->msgCtxt);
-      freeContext(&gH323ep.gkClient->ctxt);
-      ast_mutex_lock(&gH323ep.gkClient->Lock);
-      ast_mutex_unlock(&gH323ep.gkClient->Lock);
-      ast_mutex_destroy(&gH323ep.gkClient->Lock);
-      memFreePtr(&gH323ep.ctxt, gH323ep.gkClient);
-      gH323ep.gkClient = NULL;
+      ooGkClientCloseChannel(pGkClient);
+      freeContext(&pGkClient->msgCtxt);
+      freeContext(&pGkClient->ctxt);
+      ast_mutex_unlock(&pGkClient->Lock);
+      ast_mutex_destroy(&pGkClient->Lock);
+      memFreePtr(&gH323ep.ctxt, pGkClient);
    }
    return OO_OK;
 }
@@ -261,7 +264,7 @@ int ooGkClientCreateChannel(ooGkClient *pGkClient)
    int ret=0;
    OOIPADDR ipaddrs;
    /* Create socket */
-   if((ret=ooSocketCreateUDP(&pGkClient->rasSocket))!=ASN_OK)
+   if((ret=ooSocketCreateUDP(&pGkClient->rasSocket, 4))!=ASN_OK)
    {
       OOTRACEERR1("Failed to create RAS socket\n");
       pGkClient->state = GkClientFailed;
@@ -269,7 +272,7 @@ int ooGkClientCreateChannel(ooGkClient *pGkClient)
    }
    if(pGkClient->localRASPort)
    {
-      ret= ooSocketStrToAddr (pGkClient->localRASIP, &ipaddrs);
+      inet_pton(AF_INET, pGkClient->localRASIP, &ipaddrs);
       if( (ret=ooSocketBind( pGkClient->rasSocket, ipaddrs, 
            pGkClient->localRASPort))!=ASN_OK ) 
       {
@@ -295,7 +298,7 @@ int ooGkClientCreateChannel(ooGkClient *pGkClient)
       OOTRACEDBGA1("Determining ip address for RAS channel "
                    "multihomed mode. \n");
       ret = ooSocketGetIpAndPort(pGkClient->rasSocket, pGkClient->localRASIP, 
-                                 20, &pGkClient->localRASPort);
+                                 20, &pGkClient->localRASPort, NULL);
       if(ret != ASN_OK)
       {
          OOTRACEERR1("Error:Failed to retrieve local ip and port from "
@@ -364,7 +367,7 @@ void ooGkClientFillVendor
 
 int ooGkClientReceive(ooGkClient *pGkClient)
 {
-   ASN1OCTET recvBuf[1024];
+   ASN1OCTET recvBuf[ASN_K_ENCBUFSIZ];
    int recvLen;
    char remoteHost[32];
    int iFromPort=0;
@@ -375,7 +378,7 @@ int ooGkClientReceive(ooGkClient *pGkClient)
    ast_mutex_lock(&pGkClient->Lock);
    pctxt = &pGkClient->msgCtxt;
 
-   recvLen = ooSocketRecvFrom(pGkClient->rasSocket, recvBuf, 1024, remoteHost,
+   recvLen = ooSocketRecvFrom(pGkClient->rasSocket, recvBuf, 2048, remoteHost,
                               32, &iFromPort);
    if(recvLen <0)
    {
@@ -430,7 +433,7 @@ int ooGkClientReceive(ooGkClient *pGkClient)
       if(iRet != OO_OK)
       {
          OOTRACEERR1("Error: Failed to handle received RAS message\n");
-         //pGkClient->state = GkClientFailed;
+         pGkClient->state = GkClientFailed;
       }
       memReset(pctxt);
    }
@@ -666,7 +669,7 @@ int ooGkClientSendGRQ(ooGkClient *pGkClient)
    }
 
  
-   ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pRasAddress->ip.data);
+   inet_pton(AF_INET, pGkClient->localRASIP, pRasAddress->ip.data);
 
    pRasAddress->ip.numocts = 4;
    pRasAddress->port = pGkClient->localRASPort;
@@ -858,7 +861,6 @@ int ooGkClientHandleGatekeeperConfirm
          memFreePtr(&pGkClient->ctxt, pTimer->cbData);
          ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer);
          OOTRACEDBGA1("Deleted GRQ Timer.\n");
-         break;
       }
    }
 
@@ -932,7 +934,7 @@ int ooGkClientSendRRQ(ooGkClient *pGkClient, ASN1BOOL keepAlive)
    }
    pTransportAddress->t = T_H225TransportAddress_ipAddress;
    pTransportAddress->u.ipAddress = pIpAddress;
-   ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpAddress->ip.data);
+   inet_pton(AF_INET, pGkClient->localRASIP, pIpAddress->ip.data);
    pIpAddress->ip.numocts = 4;
    pIpAddress->port = gH323ep.listenPort;
    
@@ -960,7 +962,7 @@ int ooGkClientSendRRQ(ooGkClient *pGkClient, ASN1BOOL keepAlive)
    pTransportAddress->t = T_H225TransportAddress_ipAddress;
    pTransportAddress->u.ipAddress = pIpAddress;
    
-   ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpAddress->ip.data);
+   inet_pton(AF_INET, pGkClient->localRASIP, pIpAddress->ip.data);
 
    pIpAddress->ip.numocts = 4;
    pIpAddress->port = pGkClient->localRASPort;
@@ -1063,7 +1065,7 @@ int ooGkClientSendRRQ(ooGkClient *pGkClient, ASN1BOOL keepAlive)
          allocate storage for endpoint-identifier, and populate it from what the
          GK told us from the previous RCF. Only allocate on the first pass thru here */
       pRegReq->endpointIdentifier.data = 
-           (ASN116BITCHAR*)memAlloc(pctxt, pGkClient->gkId.nchars*sizeof(ASN116BITCHAR));
+           (ASN116BITCHAR*)memAlloc(pctxt, pGkClient->endpointId.nchars*sizeof(ASN116BITCHAR));
       if (pRegReq->endpointIdentifier.data) {
          pRegReq->endpointIdentifier.nchars = pGkClient->endpointId.nchars;
          pRegReq->m.endpointIdentifierPresent = TRUE;
@@ -1136,6 +1138,8 @@ int ooGkClientHandleRegistrationConfirm
    ooGkClientTimerCb *cbData;
    ASN1UINT regTTL=0;
    /* Extract Endpoint Id */
+   if (pGkClient->endpointId.data)
+       memFreePtr(&pGkClient->ctxt, pGkClient->endpointId.data);
    pGkClient->endpointId.nchars = 
                               pRegistrationConfirm->endpointIdentifier.nchars;
    pGkClient->endpointId.data = (ASN116BITCHAR*)memAlloc(&pGkClient->ctxt,
@@ -1210,8 +1214,11 @@ int ooGkClientHandleRegistrationConfirm
 
       if(pGkClient->regTimeout > DEFAULT_TTL_OFFSET)
          regTTL = pGkClient->regTimeout - DEFAULT_TTL_OFFSET;
-      else
-         regTTL = pGkClient->regTimeout;
+      else {
+         regTTL = pGkClient->regTimeout - 1; /* -1 due to some ops expire us few earlier */
+        if (regTTL <= 0)
+               regTTL = 1;
+      }
 
       cbData = (ooGkClientTimerCb*) memAlloc
                                 (&pGkClient->ctxt, sizeof(ooGkClientTimerCb));
@@ -1259,7 +1266,6 @@ int ooGkClientHandleRegistrationConfirm
          memFreePtr(&pGkClient->ctxt, pTimer->cbData);
          ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer);
          OOTRACEDBGA1("Deleted RRQ Timer.\n");
-         break;
       }
    }
    pGkClient->state = GkClientRegistered;
@@ -1286,7 +1292,6 @@ int ooGkClientHandleRegistrationReject
          memFreePtr(&pGkClient->ctxt, pTimer->cbData);
          ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer);
          OOTRACEDBGA1("Deleted RRQ Timer.\n");
-         break;
       }
    }
 
@@ -1430,7 +1435,7 @@ int ooGkClientSendURQ(ooGkClient *pGkClient, ooAliases *aliases)
    }
    pTransportAddress->t = T_H225TransportAddress_ipAddress;
    pTransportAddress->u.ipAddress = pIpAddress;
-   ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpAddress->ip.data);
+   inet_pton(AF_INET, pGkClient->localRASIP, pIpAddress->ip.data);
    pIpAddress->ip.numocts = 4;
    pIpAddress->port = gH323ep.listenPort;
    
@@ -1504,8 +1509,10 @@ int ooGkClientSendURQ(ooGkClient *pGkClient, ooAliases *aliases)
 int ooGkClientHandleUnregistrationRequest
    (ooGkClient *pGkClient, H225UnregistrationRequest * punregistrationRequest)
 {
-   int iRet=0;
-
+   int iRet=0, x;
+   OOTimer *pTimer = NULL;
+   DListNode *pNode = NULL;
    /* Lets first send unregistration confirm message back to gatekeeper*/
    ooGkClientSendUnregistrationConfirm(pGkClient, 
                                       punregistrationRequest->requestSeqNum);
@@ -1527,6 +1534,24 @@ int ooGkClientHandleUnregistrationRequest
       pGkClient->rrqRetries = 0;
       pGkClient->state = GkClientDiscovered;
 
+
+      /* delete the corresponding RRQ & REG timers */
+       pNode = NULL;
+       for(x=0; x<pGkClient->timerList.count; x++) {
+               pNode =  dListFindByIndex(&pGkClient->timerList, x);
+               pTimer = (OOTimer*)pNode->data;
+               if(((ooGkClientTimerCb*)pTimer->cbData)->timerType & OO_RRQ_TIMER) {
+                       memFreePtr(&pGkClient->ctxt, pTimer->cbData);
+                       ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer);
+                       OOTRACEDBGA1("Deleted RRQ Timer.\n");
+               }
+               if(((ooGkClientTimerCb*)pTimer->cbData)->timerType & OO_REG_TIMER) {
+                       memFreePtr(&pGkClient->ctxt, pTimer->cbData);
+                       ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer);
+                       OOTRACEDBGA1("Deleted REG Timer.\n");
+               }
+       }
+
       iRet = ooGkClientSendRRQ(pGkClient, 0); 
       if(iRet != OO_OK)
       {
@@ -1645,14 +1670,14 @@ int ooGkClientSendAdmissionRequest
       ast_mutex_unlock(&pGkClient->Lock);
       return OO_FAILED;
    }
-   ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpAddressLocal->ip.data);
+   inet_pton(AF_INET, pGkClient->localRASIP, pIpAddressLocal->ip.data);
 
    pIpAddressLocal->ip.numocts = 4;
    pIpAddressLocal->port = gH323ep.listenPort;
 
    if(!ooUtilsIsStrEmpty(call->remoteIP))
    {
-      ooSocketConvertIpToNwAddr(call->remoteIP, pIpAddressRemote->ip.data);
+      inet_pton(AF_INET, call->remoteIP, pIpAddressRemote->ip.data);
       pIpAddressRemote->ip.numocts = 4;
       pIpAddressRemote->port = call->remotePort;
    }
@@ -1898,6 +1923,8 @@ int ooGkClientHandleAdmissionConfirm
    OOTimer *pTimer = NULL;
    char ip[20];
 
+   ast_mutex_lock(&pGkClient->Lock);
+
    /* Search call in pending calls list */
    for(x=0 ; x<pGkClient->callsPendingList.count; x++)
    {
@@ -1908,6 +1935,9 @@ int ooGkClientHandleAdmissionConfirm
          OOTRACEDBGC3("Found Pending call(%s, %s)\n", 
                       pCallAdmInfo->call->callType, 
                       pCallAdmInfo->call->callToken);
+
+         ast_mutex_lock(&pCallAdmInfo->call->GkLock);
+
          /* Populate Remote IP */
          if(pAdmissionConfirm->destCallSignalAddress.t != 
                                       T_H225TransportAddress_ipAddress)
@@ -1916,6 +1946,9 @@ int ooGkClientHandleAdmissionConfirm
                         "Gatekeeper is not an IPv4 address\n");
             OOTRACEINFO1("Ignoring ACF, will wait for timeout and retransmit "
                          "ARQ\n");
+            ast_mutex_unlock(&pCallAdmInfo->call->GkLock);
+            ast_mutex_unlock(&pGkClient->Lock);
+            ast_cond_signal(&pCallAdmInfo->call->gkWait);
             return OO_FAILED;
          }
          ipAddress = pAdmissionConfirm->destCallSignalAddress.u.ipAddress;
@@ -1924,8 +1957,11 @@ int ooGkClientHandleAdmissionConfirm
                                     ipAddress->ip.data[1],
                                     ipAddress->ip.data[2],
                                     ipAddress->ip.data[3]);
-         if(strcmp(ip, "0.0.0.0"))
+         if(strcmp(ip, "0.0.0.0")) {
+/* fix this when gk client will adopt to work with IPv6 */
+           pCallAdmInfo->call->versionIP = 4;
             strcpy(pCallAdmInfo->call->remoteIP, ip);
+        }
          pCallAdmInfo->call->remotePort = ipAddress->port;
          /* Update call model */
          if(pAdmissionConfirm->callModel.t == T_H225CallModel_direct)
@@ -1974,15 +2010,15 @@ int ooGkClientHandleAdmissionConfirm
                        pCallAdmInfo->call->callToken);
 
         pCallAdmInfo->call->callState = OO_CALL_CONNECTING;
-        ast_cond_signal(&pCallAdmInfo->call->gkWait);
-         /* ooH323CallAdmitted( pCallAdmInfo->call); */
 
          dListRemove(&pGkClient->callsPendingList, pNode);
          dListAppend(&pGkClient->ctxt, &pGkClient->callsAdmittedList, 
                                                         pNode->data);
          memFreePtr(&pGkClient->ctxt, pNode);
+         ast_mutex_unlock(&pCallAdmInfo->call->GkLock);
+        ast_mutex_unlock(&pGkClient->Lock);
+        ast_cond_signal(&pCallAdmInfo->call->gkWait);
          return OO_OK;
-         break;
       }
       else
       {
@@ -1991,6 +2027,7 @@ int ooGkClientHandleAdmissionConfirm
    }
    OOTRACEERR1("Error: Failed to process ACF as there is no corresponding "
                "pending call\n");
+   ast_mutex_unlock(&pGkClient->Lock);
    return OO_OK;
 }
 
@@ -2004,6 +2041,8 @@ int ooGkClientHandleAdmissionReject
    OOH323CallData *call=NULL;
    OOTimer *pTimer = NULL;
 
+   ast_mutex_lock(&pGkClient->Lock);
+
    /* Search call in pending calls list */
    for(x=0 ; x<pGkClient->callsPendingList.count; x++)
    {
@@ -2020,6 +2059,7 @@ int ooGkClientHandleAdmissionReject
       OOTRACEWARN2("Received admission reject with request number %d can not"
                    " be matched with any pending call.\n", 
                    pAdmissionReject->requestSeqNum);
+      ast_mutex_unlock(&pGkClient->Lock);
       return OO_OK;
    }
    else{
@@ -2028,6 +2068,7 @@ int ooGkClientHandleAdmissionReject
       memFreePtr(&pGkClient->ctxt, pCallAdmInfo);
       memFreePtr(&pGkClient->ctxt, pNode);
    }
+   ast_mutex_lock(&pCallAdmInfo->call->GkLock);
 
    /* Delete ARQ timer */
    for(y=0; y<pGkClient->timerList.count; y++)
@@ -2092,6 +2133,8 @@ int ooGkClientHandleAdmissionReject
          break;
    }
 
+   ast_mutex_unlock(&pCallAdmInfo->call->GkLock);
+   ast_mutex_unlock(&pGkClient->Lock);
    ast_cond_signal(&pCallAdmInfo->call->gkWait);
    return OO_OK;   
 }
@@ -2153,7 +2196,7 @@ int ooGkClientSendIRR
       ast_mutex_unlock(&pGkClient->Lock);
       return OO_FAILED;
    }
-   ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpAddressLocal->ip.data);
+   inet_pton(AF_INET, pGkClient->localRASIP, pIpAddressLocal->ip.data);
 
    pIpAddressLocal->ip.numocts = 4;
    pIpAddressLocal->port = gH323ep.listenPort;
@@ -2184,7 +2227,7 @@ int ooGkClientSendIRR
 
    pIpRasAddress->ip.numocts = 4;
    pIpRasAddress->port = pGkClient->localRASPort;
-   ooSocketConvertIpToNwAddr(pGkClient->localRASIP, pIpRasAddress->ip.data);
+   inet_pton(AF_INET, pGkClient->localRASIP, pIpRasAddress->ip.data);
 
    pIRR->rasAddress.u.ipAddress = pIpRasAddress;
    pIRR->rasAddress.t=T_H225TransportAddress_ipAddress; /* IPv4 address */
@@ -2283,11 +2326,11 @@ int ooGkClientSendIRR
       return OO_FAILED;
    }
    pLocalAddr->ip.numocts = 4;
-   ooSocketConvertIpToNwAddr(call->localIP, pLocalAddr->ip.data);
+   inet_pton(AF_INET, call->localIP, pLocalAddr->ip.data);
    pLocalAddr->port = (call->pH225Channel->port) ? call->pH225Channel->port : gH323ep.listenPort;
 
    pRemoteAddr->ip.numocts = 4;
-   ooSocketConvertIpToNwAddr(call->remoteIP, pRemoteAddr->ip.data);
+   inet_pton(AF_INET, call->remoteIP, pRemoteAddr->ip.data);
    pRemoteAddr->port = call->remotePort;
 
    perCallInfo->callSignaling.m.sendAddressPresent = TRUE;
@@ -2547,7 +2590,43 @@ int ooGkClientRRQTimerExpired(void*pdata)
    }
    memFreePtr(&pGkClient->ctxt, cbData);
    OOTRACEERR1("Error:Failed to register with gatekeeper\n");
-   pGkClient->state = GkClientGkErr;
+   pGkClient->state = GkClientUnregistered;
+
+
+/* Create timer to re-register after default timeout */
+/* network failure is one of cases here */
+
+   ast_mutex_lock(&pGkClient->Lock);
+
+   cbData = (ooGkClientTimerCb*) memAlloc
+                               (&pGkClient->ctxt, sizeof(ooGkClientTimerCb));
+   if(!cbData)
+   {
+      OOTRACEERR1("Error:Failed to allocate memory to RRQ timer callback\n");
+      pGkClient->state = GkClientFailed;
+      ast_mutex_unlock(&pGkClient->Lock);
+      return OO_FAILED;
+   }
+
+
+   cbData->timerType = OO_RRQ_TIMER;
+   cbData->pGkClient = pGkClient;
+   if(!ooTimerCreate(&pGkClient->ctxt, &pGkClient->timerList,
+                     &ooGkClientRRQTimerExpired, pGkClient->regTimeout,
+                     cbData, FALSE))
+   {
+      OOTRACEERR1("Error:Unable to create GRQ timer.\n ");
+      memFreePtr(&pGkClient->ctxt, cbData);
+      pGkClient->state = GkClientFailed;
+      ast_mutex_unlock(&pGkClient->Lock);
+      return OO_FAILED;
+   }
+
+/* clear rrq count for re-register after regTimeout */
+   pGkClient->rrqRetries = 0;
+
+   ast_mutex_unlock(&pGkClient->Lock);
+
    return OO_FAILED;
 }
 
@@ -2575,7 +2654,37 @@ int ooGkClientGRQTimerExpired(void* pdata)
    }
 
    OOTRACEERR1("Error:Gatekeeper could not be found\n");
-   pGkClient->state = GkClientGkErr;
+   pGkClient->state = GkClientUnregistered;
+/* setup timer to re-send grq after timeout */
+
+   ast_mutex_lock(&pGkClient->Lock);
+   cbData = (ooGkClientTimerCb*) memAlloc
+                               (&pGkClient->ctxt, sizeof(ooGkClientTimerCb));
+   if(!cbData)
+   {
+      OOTRACEERR1("Error:Failed to allocate memory to GRQ timer callback\n");
+      pGkClient->state = GkClientFailed;
+      ast_mutex_unlock(&pGkClient->Lock);
+      return OO_FAILED;
+   }
+   cbData->timerType = OO_GRQ_TIMER;
+   cbData->pGkClient = pGkClient;
+   if(!ooTimerCreate(&pGkClient->ctxt, &pGkClient->timerList,
+                     &ooGkClientGRQTimerExpired, pGkClient->grqTimeout,
+                     cbData, FALSE))
+   {
+      OOTRACEERR1("Error:Unable to create GRQ timer.\n ");
+      memFreePtr(&pGkClient->ctxt, cbData);
+      pGkClient->state = GkClientFailed;
+      ast_mutex_unlock(&pGkClient->Lock);
+      return OO_FAILED;
+   }
+/* clear grq counter */
+
+   pGkClient->grqRetries = 0;
+   ast_mutex_unlock(&pGkClient->Lock);
+
    return OO_FAILED;
 }