Add support change gatekeeper mode or ip per ooh323 reload command
[asterisk/asterisk.git] / addons / ooh323c / src / ooGkClient.c
index 33d7df0..c91b9ed 100644 (file)
@@ -170,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;
 }
@@ -365,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;
@@ -376,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)
    {
@@ -431,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);
    }
@@ -859,7 +861,6 @@ int ooGkClientHandleGatekeeperConfirm
          memFreePtr(&pGkClient->ctxt, pTimer->cbData);
          ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer);
          OOTRACEDBGA1("Deleted GRQ Timer.\n");
-         break;
       }
    }
 
@@ -1064,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;
@@ -1137,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,
@@ -1289,7 +1292,6 @@ int ooGkClientHandleRegistrationReject
          memFreePtr(&pGkClient->ctxt, pTimer->cbData);
          ooTimerDelete(&pGkClient->ctxt, &pGkClient->timerList, pTimer);
          OOTRACEDBGA1("Deleted RRQ Timer.\n");
-         break;
       }
    }
 
@@ -1921,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++)
    {
@@ -1931,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)
@@ -1939,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;
@@ -1947,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)
@@ -1997,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
       {
@@ -2014,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;
 }
 
@@ -2027,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++)
    {
@@ -2043,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{
@@ -2051,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++)
@@ -2115,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;   
 }
@@ -2570,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;
 }
 
@@ -2598,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;
 }