OSDN Git Service

Ver.1.4.9: Change hello timing control from client side to server side.
[opengate/opengate.git] / opengate / opengatesrv / watch-client.c
index 242c837..7d6e237 100644 (file)
@@ -1,6 +1,6 @@
 /*************************************************
 Opengate server
-  module for communication with client prgram (java/javascript) 
+  module for communication with client program (java/javascript) 
 
 Copyright (C) 1999 Opengate Project Team
 Written by Yoshiaki Watanabe 1999-2006
@@ -31,6 +31,11 @@ void ReadHttpHeaders(void);
 void SendReplyToGetHello(void);
 void SendHttpKeepPage(char *userid, char *sessionId, char *language, int port);
 int SelectAccept(void);
+void AcceptHttpReConnect(void);
+int MacAddrCheck(int ipStatus,char *clientAddr4, char *clientAddr6, char *macAddr4, char *macAddr6);
+int IsRightKey(char *pNowKey, char *sessionId);
+void SendHttpReply(char *reply);
+void CheckAjaxAbility(char *buff, char *sessionId);
 
 void OnUsageTimeLimitAlarm(int signo);
 void OnCheckBasicAlarm(int signo);
@@ -63,6 +68,7 @@ struct AlarmArg{          /* arguments used in on-alarm functions */
 
 int helloWait=FALSE;  /* hello reply waiting mode */
 int readHelloTime=0;  /* the time of reading hello */
+int sendHelloTime=0;  /* the time of sending hello */
 int noReplyCount=0; /* count up the no reply to hello message */
 
 
@@ -184,7 +190,8 @@ int waitClientConnect(char *userid, char *userProperty, char *sessionId, char *c
     }
  
     /* set read wait alarm */
-    AddAlarm("ReadWaitAlarm",COMMWAITTIMEOUT, TRUE, OnReadWaitAlarm); 
+    AddAlarm("ReadWaitAlarm",atoi(GetConfValue("CommWaitTimeout")),
+            TRUE, OnReadWaitAlarm); 
     EnableAlarm();
     /* get string from connection */
     if(readln(connfd, buff, BUFFMAXLN) <0){
@@ -216,25 +223,12 @@ int waitClientConnect(char *userid, char *userProperty, char *sessionId, char *c
       ReadHttpHeaders();
       SendHttpKeepPage(userid, sessionId, language, port);
 
-      /* to check the ajax ablility of the client, wait ajax request */
-      AddAlarm("AjaxWaitAlarm",COMMWAITTIMEOUT, TRUE, OnAjaxWaitAlarm); 
-      EnableAlarm();
-      /* read wait for ajax request in the connection */
-      if(readln(connfd, buff, BUFFMAXLN) <0){
-        /* if timeout, no ajax ability */
-       connectMode=NOCONNECT;  
-       Close(connfd);
-       continue;
-      }
-      /* recieve request */
-      RemoveAlarm("AjaxWaitAlarm");
-      ReadHttpHeaders();
+      /* to check ajax ability, wait XMLHttpRequest for a while */
+      CheckAjaxAbility(buff, sessionId);
 
-      /* enter to the Http watch mode on the connection */
-      connectMode=HTTPCONNECT;
       break;
     }
-  
+
     /* is it the terminate request */
     /* the request is [GET /terminate-<pid> ..] */
     snprintf(httpStr, BUFFMAXLN, "GET /terminate-%d", pid);
@@ -248,21 +242,72 @@ int waitClientConnect(char *userid, char *userProperty, char *sessionId, char *c
 
     /* some other unknown request */    
     err_msg("ERR at %s#%d: unknown request [%s] sent from client",
-           __FILE__,__LINE__);
+           __FILE__,__LINE__,buff);
     connectMode=NOCONNECT;
     Close(connfd);
+    
     continue;
   }
 
   /* stop all alarms */
   RemoveAlarm(NULL);
-  
-  Close(listenfd[0]);
-  Close(listenfd[1]);
-  
+    
   return connectMode;
 }
 
+/***************************************/
+/* check ajax ability                  */
+/* read hello sent by XMLhttpRequest   */
+/*  (reply is delayed)                 */
+/* check result is set in connectMode  */ 
+/***************************************/ 
+void checkAjaxAbility(char *buff, char *sessionId)
+{
+
+  /* to check the ajax ablility of the client, wait ajax request */
+  AddAlarm("AjaxWaitAlarm",atoi(GetConfValue("CommWaitTimeout")), 
+          TRUE, OnAjaxWaitAlarm); 
+  EnableAlarm();
+
+  /* read wait for ajax request in the connection */
+  while(1){
+    if(readln(connfd, buff, BUFFMAXLN) <0){
+      
+      /* if timeout, no ajax ability */
+      /* java might be connected */
+      connectMode=NOCONNECT;   
+      Close(connfd);
+      break;
+    }
+    
+    /* recieved normal request */
+    RemoveAlarm("AjaxWaitAlarm");
+    ReadHttpHeaders();
+    
+    /* usually, hello request is recieve */
+    if(strstr(buff, "GET /hello-")==buff){
+      
+      /* if received hello-key is incorrect, exit */
+      /* [GET /hello-key1-key2 ..] */
+      if( IsRightKey(buff+strlen("GET /hello-"), sessionId)==FALSE){
+       connectMode=ENDCONNECT;
+       Close(connfd);
+       break;
+      }
+      
+      /* enter to the Http watch mode on the connection */
+      connectMode=HTTPCONNECT;
+      break;
+    }
+    /* or some request might be inserted. eg:[GET /favicon.ico] */
+    /* ignore it */
+    else{
+      SendHttpReply("");
+      continue;
+    }
+  }
+}
+
 /****************************/
 /* wait for TCP connection  */
 /****************************/
@@ -283,17 +328,21 @@ int selectAccept(void)
   if(listenfd[0]>listenfd[1]) smax=listenfd[0]+1;
   else smax=listenfd[1]+1;
 
-  //if((n = select(smax, &rfd0, NULL, NULL, &timeout)) > 0){
   if((n = select(smax, &rfd0, NULL, NULL, NULL)) > 0){
     /* wait connection */
+
     if(FD_ISSET(listenfd[0], &rfd0)){
+
       if((connfd=accept(listenfd[0], (struct sockaddr *)&cliaddr, &len)) >= 0){
+
        /* connect by ipv4 */
        ipType=IPV4;
       }
     }
     if(FD_ISSET(listenfd[1], &rfd0)){
+
       if((connfd=accept(listenfd[1], (struct sockaddr *)&cliaddr, &len)) >= 0){
+
        /* connect by ipv6 */
        ipType=IPV6;
       }
@@ -317,7 +366,6 @@ void onUsageTimeLimitAlarm(int signo)
 void onReadWaitAlarm(int signo)
 {
   connectMode=ENDCONNECT;
-  err_msg("ERR at %s#%d: read request timeout",__FILE__,__LINE__);
 }
 
 /***************************************/
@@ -336,12 +384,19 @@ void onCheckBasicAlarm(int signo)
   static int packetCountPrev=0;  /* packet count at previous check */
   int packetCountNow=0;   /* packet count at now */
   static   int noPacketPeriod=0; /* no packet period count in check loop */
-  char macAddrNow[ADDRMAXLN];       /* MAC address at now */
 
   /* search new IPv6 addresses */
   ScanNdpEntry(alarmArg.pClientAddr, alarmArg.userid,
             alarmArg.macAddr6, alarmArg.userProperty);
 
+  /* mac address check */
+  if(MacAddrCheck(alarmArg.ipStatus, 
+                 alarmArg.clientAddr4, alarmArg.clientAddr6, 
+                 alarmArg.macAddr4, alarmArg.macAddr6)==FALSE){
+    connectMode=ENDCONNECT;
+    return;
+  }  
+
   /* packet flow check */
   packetCountNow=GetPacketCount(alarmArg.pClientAddr);
   if(packetCountNow==packetCountPrev){  /* no packet between checks */
@@ -358,26 +413,35 @@ void onCheckBasicAlarm(int signo)
     connectMode=ENDCONNECT;
     return;
   }
-  
-  /* mac address check */
-  if(alarmArg.ipStatus!=IPV6ONLY){
-    GetMacAddrFromArp(alarmArg.clientAddr4, macAddrNow);
-    if(strcmp(alarmArg.macAddr4, macAddrNow)!=0){
+  /* set the alarm for next periodic keep alive check */
+  AddAlarm("CheckBasicAlarm", alarmArg.checkInterval, FALSE, OnCheckBasicAlarm);  /* EnableAlarm is called automatically in alarm function */
+}
+
+/***************************************/
+/* check mac address change            */
+/***************************************/
+int macAddrCheck(int ipStatus, char *clientAddr4, char *clientAddr6, char *macAddr4, char *macAddr6) 
+{ 
+  char macAddrNow[ADDRMAXLN];       /* MAC address at now */
+
+  if(ipStatus!=IPV6ONLY){
+    /* check mac address from arp */
+    GetMacAddrFromArp(clientAddr4, macAddrNow);
+    if(*macAddrNow!='?' && strcmp(macAddr4, macAddrNow)!=0){
       err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
       connectMode=ENDCONNECT;
-      return;
+      return FALSE;
     }
   }else{
-    GetMacAddrFromNdp(alarmArg.clientAddr6, macAddrNow);
-    if(strcmp(alarmArg.macAddr6, macAddrNow)!=0){
+    /* check mac address from ndp */
+    GetMacAddrFromNdp(clientAddr6, macAddrNow);
+    if(*macAddrNow!='?' && strcmp(macAddr6, macAddrNow)!=0){
       err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
       connectMode=ENDCONNECT;
-      return;
+      return FALSE;
     }
   }
-
-  /* set the alarm for next periodic keep alive check */
-  AddAlarm("CheckBasicAlarm", alarmArg.checkInterval, FALSE, OnCheckBasicAlarm);  /* EnableAlarm is called automatically in alarm function */
+  return TRUE;
 }
 
 /***************************************/
@@ -493,8 +557,6 @@ void onReplyTimeoutAlarm(int signo)
 /***************************************/
 void onCheckJavaAlarm(int signo)
 {
-  char macAddrNow[ADDRMAXLN];       /* MAC address at now */
-
   /* search new IPv6 addresses */
   ScanNdpEntry(alarmArg.pClientAddr, alarmArg.userid,
             alarmArg.macAddr6, alarmArg.userProperty);
@@ -504,20 +566,11 @@ void onCheckJavaAlarm(int signo)
   helloWait=TRUE;
 
   /* mac address check */
-  if(alarmArg.ipStatus!=IPV6ONLY){
-    GetMacAddrFromArp(alarmArg.clientAddr4, macAddrNow);
-    if(strcmp(alarmArg.macAddr4, macAddrNow)!=0){
-      err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
-      connectMode=ENDCONNECT;
-      return;
-    }
-  }else{
-    GetMacAddrFromNdp(alarmArg.clientAddr6, macAddrNow);
-    if(strcmp(alarmArg.macAddr6, macAddrNow)!=0){
-      err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
-      connectMode=ENDCONNECT;
-      return;
-    }
+  if(MacAddrCheck(alarmArg.ipStatus, 
+                 alarmArg.clientAddr4, alarmArg.clientAddr6, 
+                 alarmArg.macAddr4, alarmArg.macAddr6)==FALSE){
+    connectMode=ENDCONNECT;
+    return;
   }
 
   /* set the alarm for next periodic check */
@@ -551,7 +604,7 @@ void sendQuitClient(void)
 /***************************************************/
 /* wait for close connection of HTTP connection    */
 /***************************************************/
-void waitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus)
+void waitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus, char *sessionId, int port)
 {
   char buff[BUFFMAXLN];
   int ret;
@@ -567,7 +620,12 @@ void waitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userPrope
   /* save time to read hello */
   readHelloTime = time(NULL);
 
+  /* send first reply to hello */
   SendReplyToGetHello();
+  sendHelloTime = time(NULL);
+
+  /* set the hello wait mode ON */
+  helloWait=TRUE;
   
   /* TCP read/write loop */
   /* this loop implement following logic */
@@ -583,6 +641,7 @@ void waitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userPrope
   EnableAlarm();
   
   while(1){
+
     /* set default to terminate */
     connectMode=ENDCONNECT;
 
@@ -596,22 +655,24 @@ void waitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userPrope
       /* normal read */
       connectMode=HTTPCONNECT;
 
-      /* read [GET /terminate], then quit */
-      if(strstr(buff,"GET /terminate") == buff){
-       connectMode=ENDCONNECT;
-       break;
-      }
-      
-      /* read [GET /hello], then reply */
-      else if(strstr(buff,"GET /hello") == buff){
+      /* read [GET /hello] */
+      if(strstr(buff,"GET /hello") == buff){
        
        /* save time to read hello */
        readHelloTime = time(NULL);
 
        ReadHttpHeaders();
-       SendReplyToGetHello();
-      }
 
+       /* if received key is not match, exit */
+       if(IsRightKey(buff+strlen("GET /hello-"), sessionId)==FALSE){
+         connectMode=ENDCONNECT;
+         break;
+       }
+       
+       /* set the hello wait mode OFF */
+       helloWait=FALSE;
+      }
+      
       /* read other string */
       else{
       }
@@ -620,63 +681,169 @@ void waitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userPrope
       /*abnormal read */
       /* some alarm is ringed or connecion is closed */
       /*  connectionMode might be modified in onAlarm */
-      if(connectMode==ENDCONNECT) break;
+
+      if(connectMode==ENDCONNECT){
+
+       /* wait short time to accept reconnection */
+       /* (to permit occasional disconnection at exchanging hello) */
+       if(helloWait==TRUE &&
+          (time(NULL)-sendHelloTime)<=atoi(GetConfValue("ReconnectTimeout"))){
+         AcceptHttpReConnect();
+       }
+
+       /* no reconnection, then terminate */
+       if(connectMode==ENDCONNECT){
+         break;
+       }
+      }
     }
-      
+
     /* restart alarm */
     EnableAlarm();
   }
 
   /* reset alarm */
-  RemoveAlarm(NULL);
-
-  /* send quit message to client */
-  SendQuitClient();
+   RemoveAlarm(NULL);
 
   Close(connfd);
   
   return;
 }
 
+/*************************/
+/* accept http reconnect */
+/*************************/
+void acceptHttpReConnect(void){
+
+  int startTime; 
+
+  startTime=time(NULL);
+
+  /* wait a short time */
+  AddAlarm("ReadWaitAlarm",atoi(GetConfValue("ReconnectTimeout")),
+          TRUE, OnReadWaitAlarm); 
+  EnableAlarm();
+
+  /* connection wait */
+  connfd = SelectAccept();
+
+  if(connfd<0){
+    /* abnormal return from selectAccept */
+    if(errno==EINTR){ /* timeout interupt */
+      err_msg("ERR at %s#%d: http reconnect timeout",
+             __FILE__,__LINE__);
+      connectMode=ENDCONNECT;
+    }else{           /* other errors */
+      err_msg("ERR: http reconnect error [%s]",strerror(errno)); 
+      connectMode=ENDCONNECT;
+    }
+
+  }else{
+    /* normal return from selectAccept */
+    if(debug>0)err_msg("INFO: http reconnect after %d seconds",
+                      time(NULL)-startTime); 
+    connectMode=HTTPCONNECT;
+  }
+
+  /* receive request */
+  RemoveAlarm("ReadWaitAlarm");
+}
+
+/*****************************************************************/
+/* Is the sent client key correct                                */
+/*  request string is as follows                                 */
+/*  GET /hello-11111111111111111111-2222222222222222222 HTTP...  */
+/*              MD5digest(32chars)   MD5digest(32chars)          */
+/*                nowKey               nextKey                   */
+/*                                                               */
+/*         client                            server              */
+/*       save sid     <-------------------     sid               */
+/* md5(sid)+md5(md5(rand1)+sid)  ---------> check nowkey         */
+/*                                          save nextKey         */
+/* md5(rand1)+md5(md5(rand2)+sid)---------> check nowkey         */
+/*                                          save nextKey         */
+/* md5(rand2)+md5(md5(rand3)+sid)---------> check nowkey         */
+/*                                          save nextKey         */
+/*****************************************************************/
+int isRightKey(char *arg, char *sessionId)
+{
+  static char savedKey[33]=""; /* saved MD5 string */
+  char tempbuff[BUFFMAXLN];    /* work area */
+  char md5work[33]      ;      /* md5 work */
+  char *pNowKey;
+  char *pNextKey;
+
+  /* initial value of savedKey is md5(md5(sessionId)+sessionId) */
+  if(isNull(savedKey)){
+    md5hex(tempbuff, 33, sessionId);
+    strncat(tempbuff, sessionId, BUFFMAXLN);
+    md5hex(savedKey, 33, tempbuff);
+  }
+
+  /* split NowKey and NextKey in argument */
+  /* 32 is the length of MD5 result */
+  pNowKey=arg;
+  *(pNowKey+32)='\0';
+  pNextKey=pNowKey+33;
+  *(pNextKey+32)='\0';
+
+  /* make string [nowKey+sessionId] */
+  strncpy(tempbuff, pNowKey, BUFFMAXLN);
+  strncat(tempbuff, sessionId, BUFFMAXLN);
+
+  /* compare savedKey and md5(nowKey+sessionId) */
+  if(strcmp(savedKey, md5hex(md5work, 33, tempbuff))==0){
+
+    /* save nextKey for next check */
+    strncpy(savedKey, pNextKey, 33);
+    return TRUE;
+  }
+  else{
+    err_msg("ERR at %s#%d: incorrect client key",
+           __FILE__,__LINE__);
+    return FALSE;
+  }
+}
+
 /***************************************/
 /* called at periodic http alive check */
 /***************************************/
 void onCheckHttpAlarm(int signo)
 {
-  char macAddrNow[ADDRMAXLN];       /* MAC address at now */
+  /* at this timing, hello request might be received */
+  /* if in hello wait mode, it is abnormal */
+  if(helloWait==TRUE){
+    connectMode=ENDCONNECT;
+    return;
+  }
+
+  /* send delayed reply to hello request */
+  SendReplyToGetHello();
+
+  /* save time to send hello */
+  sendHelloTime = time(NULL);  
+
+  /* set the hello wait mode ON */
+  helloWait=TRUE;
 
   /* search new IPv6 addresses */
   ScanNdpEntry(alarmArg.pClientAddr, alarmArg.userid,
             alarmArg.macAddr6, alarmArg.userProperty);
 
-  /* if long HTTP read waiting, then quit */ 
-  if( (time(NULL)-readHelloTime) > alarmArg.checkInterval ){
-    connectMode = ENDCONNECT;
-  }else{
-    connectMode = HTTPCONNECT;
-  }
-  
   /* mac address check */
-  if(alarmArg.ipStatus!=IPV6ONLY){
-    GetMacAddrFromArp(alarmArg.clientAddr4, macAddrNow);
-    if(strcmp(alarmArg.macAddr4, macAddrNow)!=0){
-      err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
-      connectMode=ENDCONNECT;
-      return;
-    }
-  }else{
-    GetMacAddrFromNdp(alarmArg.clientAddr6, macAddrNow);
-    if(strcmp(alarmArg.macAddr6, macAddrNow)!=0){
-      err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
-      connectMode=ENDCONNECT;
-      return;
-    }
+  if(MacAddrCheck(alarmArg.ipStatus, 
+                 alarmArg.clientAddr4, alarmArg.clientAddr6, 
+                 alarmArg.macAddr4, alarmArg.macAddr6)==FALSE){
+    connectMode=ENDCONNECT;
+    return;
   }
 
   /* set the alarm for next periodic check */
   AddAlarm("CheckHttpAlarm", alarmArg.checkInterval, FALSE, OnCheckHttpAlarm);
   /* EnableAlarm is called automatically in alarm function */
 
+  /* normal return */
+  connectMode = HTTPCONNECT;
   return;
 }
 
@@ -724,11 +891,11 @@ void sendHttpKeepPage(char *userid, char *sessionId, char *language, int port)
   char buff[BUFFMAXLN];             /* read in buffer */
   FILE *fp;
   char httpKeepDoc[BUFFMAXLN];
-  char httpHelloInterval[WORDMAXLN];
   char httpHelloUrl[BUFFMAXLN];
   char terminateUrl[BUFFMAXLN];
   char acceptDoc2Url[BUFFMAXLN];
   char httpkeepJsUrl[BUFFMAXLN];
+  char md5JsUrl[BUFFMAXLN];
   char *startPageUrl=GetConfValue("StartPage/Url");
   int startPageType=atoi(GetConfValue("StartPage/Type"));
   char opengateDir[BUFFMAXLN];
@@ -748,14 +915,16 @@ void sendHttpKeepPage(char *userid, char *sessionId, char *language, int port)
   snprintf(httpHelloUrl, BUFFMAXLN, "http://%s:%d/hello", 
          GetConfValue("OpengateServerName"), port);
 
-  /* create httphello interval [50] */
-  snprintf(httpHelloInterval, WORDMAXLN, "%s", GetConfValue("HttpWatch/HelloInterval"));
-
   /* create httpkeep.js url[http://<serveraddr>/opengate/httpkeep.js] */
   snprintf(httpkeepJsUrl, BUFFMAXLN, "http://%s%s/%s", 
           GetConfValue("OpengateServerName"),
           GetConfValue("OpengateDir"),GetConfValue("HttpKeepJS"));
 
+  /* create md5.js url[http://<serveraddr>/opengate/md5.js] */
+  snprintf(md5JsUrl, BUFFMAXLN, "http://%s%s/%s", 
+          GetConfValue("OpengateServerName"),
+          GetConfValue("OpengateDir"),GetConfValue("Md5JS"));
+
   /* create path to httpkeep doc */
   snprintf(httpKeepDoc,BUFFMAXLN, "%s%s/%s/%s",GetConfValue("DocumentRoot"),
          GetConfValue("OpengateDir"),language,GetConfValue("HttpKeepDoc"));
@@ -790,12 +959,12 @@ void sendHttpKeepPage(char *userid, char *sessionId, char *language, int port)
     }
 
     /* replace mark */
-    htmlReplace(buff, "%%HTTPHELLOINTERVAL%%", httpHelloInterval);
     htmlReplace(buff, "%%HTTPHELLOURL%%", httpHelloUrl);
     htmlReplace(buff, "%%USERID%%", userid);
     htmlReplace(buff, "%%SESSIONID%%", sessionId);
     htmlReplace(buff, "%%TERMINATEURL%%", terminateUrl);
     htmlReplace(buff, "%%HTTPKEEPJSURL%%", httpkeepJsUrl);
+    htmlReplace(buff, "%%MD5JSURL%%", md5JsUrl);
 
     htmlReplace(buff, "%%OPENGATEDIR%%", opengateDir);
     htmlReplace(buff, "%%OPENGATEPORT%%", portStr);
@@ -817,9 +986,36 @@ void sendHttpKeepPage(char *userid, char *sessionId, char *language, int port)
   /* chunk end */
   Writefmt(connfd,"0\r\n");
   Writefmt(connfd,"\r\n");
+
   fclose(fp);
 }
 
+
+/*************************************************************/
+/* send reply to unknown http request eg:[GET /favico.ico..] */
+/*************************************************************/
+void sendHttpReply(char *reply)
+{
+  /* send HTTP headers */
+  Writefmt(connfd,"HTTP/1.1 200 OK\r\n");
+  Writefmt(connfd,"Transfer-Encoding: chunked\r\n");
+  Writefmt(connfd,"Keep-Alive: timeout=300\r\n");
+  Writefmt(connfd,"Connection: Keep-Alive\r\n");
+  Writefmt(connfd,"Content-Type: text/html\r\n");
+  Writefmt(connfd,"\r\n");
+  
+  if(!isNull(reply)){
+    /* length of chunk in hex */
+    Writefmt(connfd, "%x\r\n", strlen(reply));
+    /* the chunk content */
+    Writefmt(connfd, "%s\r\n", reply);
+  }
+
+  /* chunk end */
+  Writefmt(connfd,"0\r\n");
+  Writefmt(connfd,"\r\n");
+}
+
 /***************************************************/
 /***************************************************/
 void GetPeerAddr(int sockfd, char *peerAddr)
@@ -873,10 +1069,10 @@ void SendTerminateReply(void)
   if(debug>1) err_msg("DEBUG:<=sendTerminateReply( )");
 }
 
-void WaitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus)
+void WaitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus, char *sessionid, int port)
 {
-  if(debug>1) err_msg("DEBUG:=>waitHttpClose(%p,%s,userProperty,%s,%s,%d)",pClientAddr,userid,macAddr4,macAddr6,ipStatus);
-  waitHttpClose(pClientAddr,userid,userProperty,macAddr4,macAddr6,ipStatus);
+  if(debug>1) err_msg("DEBUG:=>waitHttpClose(%p,%s,userProperty,%s,%s,%d,%s,%d)",pClientAddr,userid,macAddr4,macAddr6,ipStatus, sessionid, port);
+  waitHttpClose(pClientAddr,userid,userProperty,macAddr4,macAddr6,ipStatus, sessionid, port);
   if(debug>1) err_msg("DEBUG:<=waitHttpClose( )");
 
 }
@@ -893,7 +1089,6 @@ void SendReplyToGetHello(void)
   if(debug>1) err_msg("DEBUG:=>sendReplyToGetHello( )");
   sendReplyToGetHello();
   if(debug>1) err_msg("DEBUG:<=sendReplyToGetHello( )");
-
 }
 
 void SendHttpKeepPage(char *userid, char *sessionId, char *language, int port)
@@ -955,3 +1150,42 @@ int SelectAccept(void){
 
   return ret;
 }
+
+void AcceptHttpReConnect(void){
+  if(debug>1) err_msg("DEBUG:=>acceptHttpReConnect()");
+  acceptHttpReConnect();
+  if(debug>1) err_msg("DEBUG:<=acceptHttpReConnect()");
+}
+
+int MacAddrCheck(int ipStatus, char *clientAddr4, char *clientAddr6, char *macAddr4, char *macAddr6) {
+  int ret;
+
+  if(debug>1) err_msg("DEBUG:=>macAddrCheck(%d,%s,%s,%s,%s)", 
+                     ipStatus, clientAddr4, clientAddr6, macAddr4, macAddr6);
+  ret=macAddrCheck(ipStatus, clientAddr4, clientAddr6, macAddr4, macAddr6);
+  if(debug>1) err_msg("DEBUG:(%d)<=macAddrCheck()",ret);
+
+  return ret;
+}
+
+int IsRightKey(char *pNowKey, char *sessionId){
+  int ret;
+
+  if(debug>1) err_msg("DEBUG:=>isRightKey(%s,%s)", pNowKey, sessionId);
+  ret=isRightKey(pNowKey, sessionId);
+  if(debug>1) err_msg("DEBUG:(%d)<=isRightKey()",ret);
+
+  return ret;
+}
+
+void SendHttpReply(char *reply){
+  if(debug>1) err_msg("DEBUG:=>sendHttpRepy(%s)", reply);
+  sendHttpReply(reply);
+  if(debug>1) err_msg("DEBUG:<=sendHttpReply()");
+}
+
+void CheckAjaxAbility(char *buff, char *sessionId){
+  if(debug>1) err_msg("DEBUG:=>checkAjaxAbility(%s,%s)",buff,sessionId);
+  checkAjaxAbility(buff,sessionId);
+  if(debug>1) err_msg("DEBUG:<=checkAjaxAbility()");
+}