1 /*************************************************
3 module for communication with client program (java/javascript)
5 Copyright (C) 1999 Opengate Project Team
6 Written by Yoshiaki Watanabe 1999-2006
7 Modified Katsuhiko Eguchi, 2005
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Email: watanaby@is.saga-u.ac.jp
24 **************************************************/
26 #include "opengatesrv.h"
28 void GetPeerAddr(int sockfd, char *peerAddr);
29 void SendTerminateReply(void);
30 void ReadHttpHeaders(void);
31 void SendReplyToGetHello(void);
32 void SendHttpKeepPage(char *userid, char *sessionId, char *language, int port);
33 int SelectAccept(void);
34 void AcceptHttpReConnect(void);
35 int MacAddrCheck(int ipStatus,char *clientAddr4, char *clientAddr6, char *macAddr4, char *macAddr6);
36 int IsRightKey(char *pNowKey, char *sessionId);
37 void SendHttpReply(char *reply);
38 void CheckAjaxAbility(char *buff, char *sessionId);
40 void OnUsageTimeLimitAlarm(int signo);
41 void OnCheckBasicAlarm(int signo);
42 void OnCheckJavaAlarm(int signo);
43 void OnCheckHttpAlarm(int signo);
44 void OnReadWaitAlarm(int signo);
45 void OnAjaxWaitAlarm(int signo);
47 extern char ruleNumber4[WORDMAXLN]; /* ipfw rule number in string form */
48 extern char ruleNumber6[WORDMAXLN]; /* ip6fw rule number in string form */
49 extern char language[WORDMAXLN]; /* message language */
51 int ipType=IPV4; /* using IP type */
52 int listenfd[2]; /* file descriptor for listen port */
53 int connfd; /* file descriptor for connection port */
54 int connectMode = NOCONNECT; /* the TCP connection mode */
56 struct AlarmArg{ /* arguments used in on-alarm functions */
57 struct clientAddr *pClientAddr;
64 int ipStatus; /* ipv4 ipv6 or dual */
69 int helloWait=FALSE; /* hello reply waiting mode */
70 int readHelloTime=0; /* the time of reading hello */
71 int sendHelloTime=0; /* the time of sending hello */
72 int noReplyCount=0; /* count up the no reply to hello message */
75 /***************************************/
76 /* get temp listen port of this server */
77 /***************************************/
78 int getListenPort(void)
80 struct sockaddr_in servaddr4;
81 struct sockaddr_in6 servaddr6;
82 extern const struct in6_addr in6addr_any;
88 bzero(&servaddr4, sizeof(servaddr4));
89 bzero(&servaddr6, sizeof(servaddr6));
91 servaddr4.sin_family=AF_INET;
92 servaddr4.sin_addr.s_addr=htonl(INADDR_ANY);
94 servaddr6.sin6_family=AF_INET6;
95 servaddr6.sin6_addr=in6addr_any;
97 /* get port range from config file */
98 portmin=atoi(GetConfValue("ListenPort/Min"));
99 portmax=atoi(GetConfValue("ListenPort/Max"));
101 /* search unused port between PORTMIN and PORTMAX */
102 for(portNo=portmin; portNo<=portmax; portNo++){
103 servaddr4.sin_port=htons(portNo);
104 servaddr6.sin6_port=htons(portNo);
106 listenfd[0]=Socket(AF_INET, SOCK_STREAM, 0);
107 listenfd[1]=Socket(AF_INET6, SOCK_STREAM, 0);
109 if(listenfd[0]<0 || listenfd[1]<0){ /* if error, return */
113 if(listenfd[0]>=FD_SETSIZE && listenfd[1]>=FD_SETSIZE){
117 if((bind(listenfd[0], (SA *)&servaddr4, sizeof(servaddr4))==0) &&
118 (bind(listenfd[1], (SA *)&servaddr6, sizeof(servaddr6))==0) ){
126 if(portNo>portmax) return -1; /* cannot get unused port */
128 if(Listen(listenfd[0], LISTENQ)<0) return -1; /* if error, return */
129 if(Listen(listenfd[1], LISTENQ)<0) return -1;
134 /************************************/
135 /* wait for connection of client side program */
136 /************************************/
137 int waitClientConnect(char *userid, char *userProperty, char *sessionId, char *clientAddr4, char *clientAddr6, int duration, char *macAddr4, char *macAddr6, int ipStatus, struct clientAddr *pClientAddr, char *language, int port, int pid)
139 char buff[BUFFMAXLN]; /* read in buffer */
140 char connectAddr[ADDRMAXLN]; /* connected client address */
141 char httpStr[BUFFMAXLN]; /* HTTP GET string at terminate */
142 char useridAndSessionId[BUFFMAXLN]; /* comcat userid and sessionid */
144 /* set alarm function arguments */
145 alarmArg.pClientAddr=pClientAddr;
146 alarmArg.clientAddr4=clientAddr4;
147 alarmArg.clientAddr6=clientAddr6;
148 alarmArg.macAddr4=macAddr4;
149 alarmArg.macAddr6=macAddr6;
150 alarmArg.userid=userid;
151 alarmArg.userProperty=userProperty;
152 alarmArg.ipStatus=ipStatus;
153 alarmArg.checkInterval=atoi(GetConfValue("ActiveCheckInterval"));
154 alarmArg.noPacketInterval=atoi(GetConfValue("NoPacketInterval"));
156 /* set no conection initially */
157 connectMode=NOCONNECT;
159 /* set the alarm for usage time limit */
160 AddAlarm("UsageTimeLimitAlarm",duration,FALSE,OnUsageTimeLimitAlarm);
162 /* set the alarm for periodic keep alive check */
163 AddAlarm("CheckBasicAlarm", alarmArg.checkInterval, FALSE, OnCheckBasicAlarm);
165 /* loop until accepting correct user */
166 while(connectMode == NOCONNECT){
171 /* connection wait */
172 connfd = SelectAccept();
174 /*at abnormal connect */
175 if(connfd < 0) continue;
177 /* at normal connection */
178 /* stop alarm interupt between checking */
181 /* is it from the correct client addr */
182 /* the check is skipped for IPv6 */
183 if(ipType==IPV4 && ipStatus!=IPV6ONLY){
184 GetPeerAddr(connfd, connectAddr);
185 if(isNull(connectAddr)||strcmp(connectAddr, clientAddr4)!=0){
186 connectMode=NOCONNECT;
192 /* set read wait alarm */
193 AddAlarm("ReadWaitAlarm",atoi(GetConfValue("CommWaitTimeout")),
194 TRUE, OnReadWaitAlarm);
196 /* get string from connection */
197 if(readln(connfd, buff, BUFFMAXLN) <0){
198 /* if abnormal, wait next request */
199 connectMode=NOCONNECT;
203 RemoveAlarm("ReadWaitAlarm");
205 /* is it the correct userid from java applet */
206 /* the request is [<userid>:<sessionId>] */
207 snprintf(useridAndSessionId, BUFFMAXLN, "%s-%s", userid,sessionId);
208 if(strcmp(buff, useridAndSessionId)==0){
210 /* enter to the Java watch mode on the connection */
211 connectMode=JAVACONNECT;
215 /* is it the httpkeep page download request */
216 /* the request is [GET /httpkeep.html ....] */
217 snprintf(httpStr, BUFFMAXLN, "GET /httpkeep-%s-%s", userid,sessionId);
219 if(strstr(buff, httpStr)==buff){
221 /* page download request found */
222 /* read out the remained headers and send the page */
224 SendHttpKeepPage(userid, sessionId, language, port);
226 /* to check ajax ability, wait XMLHttpRequest for a while */
227 CheckAjaxAbility(buff, sessionId);
232 /* is it the terminate request */
233 /* the request is [GET /terminate-<pid> ..] */
234 snprintf(httpStr, BUFFMAXLN, "GET /terminate-%d", pid);
235 if(strstr(buff, httpStr)==buff){
236 /* terminate request found */
237 SendTerminateReply();
238 connectMode=ENDCONNECT;
243 /* some other unknown request */
244 err_msg("ERR at %s#%d: unknown request [%s] sent from client",
245 __FILE__,__LINE__,buff);
246 connectMode=NOCONNECT;
252 /* stop all alarms */
258 /***************************************/
259 /* check ajax ability */
260 /* read hello sent by XMLhttpRequest */
261 /* (reply is delayed) */
262 /* check result is set in connectMode */
263 /***************************************/
264 void checkAjaxAbility(char *buff, char *sessionId)
267 /* to check the ajax ablility of the client, wait ajax request */
268 AddAlarm("AjaxWaitAlarm",atoi(GetConfValue("CommWaitTimeout")),
269 TRUE, OnAjaxWaitAlarm);
272 /* read wait for ajax request in the connection */
274 if(readln(connfd, buff, BUFFMAXLN) <0){
276 /* if timeout, no ajax ability */
277 /* java might be connected */
278 connectMode=NOCONNECT;
283 /* recieved normal request */
284 RemoveAlarm("AjaxWaitAlarm");
287 /* usually, hello request is recieve */
288 if(strstr(buff, "GET /hello-")==buff){
290 /* if received hello-key is incorrect, exit */
291 /* [GET /hello-key1-key2 ..] */
292 if( IsRightKey(buff+strlen("GET /hello-"), sessionId)==FALSE){
293 connectMode=ENDCONNECT;
298 /* enter to the Http watch mode on the connection */
299 connectMode=HTTPCONNECT;
302 /* or some request might be inserted. eg:[GET /favicon.ico] */
311 /****************************/
312 /* wait for TCP connection */
313 /****************************/
314 int selectAccept(void)
317 int smax; /* select max descliptor */
318 fd_set rfd0; /* fd_set for select */
320 struct sockaddr_storage cliaddr; /* client IP adddress */
321 socklen_t len = sizeof(cliaddr);
325 FD_SET(listenfd[0], &rfd0);
326 FD_SET(listenfd[1], &rfd0);
328 if(listenfd[0]>listenfd[1]) smax=listenfd[0]+1;
329 else smax=listenfd[1]+1;
331 if((n = select(smax, &rfd0, NULL, NULL, NULL)) > 0){
332 /* wait connection */
334 if(FD_ISSET(listenfd[0], &rfd0)){
336 if((connfd=accept(listenfd[0], (struct sockaddr *)&cliaddr, &len)) >= 0){
338 /* connect by ipv4 */
342 if(FD_ISSET(listenfd[1], &rfd0)){
344 if((connfd=accept(listenfd[1], (struct sockaddr *)&cliaddr, &len)) >= 0){
346 /* connect by ipv6 */
354 /***************************************/
355 /* called at usage time limit */
356 /***************************************/
357 void onUsageTimeLimitAlarm(int signo)
359 connectMode=ENDCONNECT;
360 err_msg("ERR at %s#%d: no connection from client",__FILE__,__LINE__);
363 /***************************************/
364 /* called at read wait time limit */
365 /***************************************/
366 void onReadWaitAlarm(int signo)
368 connectMode=ENDCONNECT;
371 /***************************************/
372 /* called at ajax request wait timeout */
373 /***************************************/
374 void onAjaxWaitAlarm(int signo)
376 connectMode=NOCONNECT;
379 /***************************************/
380 /* called at periodic alive basic check */
381 /***************************************/
382 void onCheckBasicAlarm(int signo)
384 static int packetCountPrev=0; /* packet count at previous check */
385 int packetCountNow=0; /* packet count at now */
386 static int noPacketPeriod=0; /* no packet period count in check loop */
388 /* search new IPv6 addresses */
389 ScanNdpEntry(alarmArg.pClientAddr, alarmArg.userid,
390 alarmArg.macAddr6, alarmArg.userProperty);
392 /* mac address check */
393 if(MacAddrCheck(alarmArg.ipStatus,
394 alarmArg.clientAddr4, alarmArg.clientAddr6,
395 alarmArg.macAddr4, alarmArg.macAddr6)==FALSE){
396 connectMode=ENDCONNECT;
400 /* packet flow check */
401 packetCountNow=GetPacketCount(alarmArg.pClientAddr);
402 if(packetCountNow==packetCountPrev){ /* no packet between checks */
406 packetCountPrev=packetCountNow;
409 if(noPacketPeriod*alarmArg.checkInterval
410 >= alarmArg.noPacketInterval){
411 err_msg("ERR at %s#%d: no packet passed for the client",
413 connectMode=ENDCONNECT;
416 /* set the alarm for next periodic keep alive check */
417 AddAlarm("CheckBasicAlarm", alarmArg.checkInterval, FALSE, OnCheckBasicAlarm); /* EnableAlarm is called automatically in alarm function */
420 /***************************************/
421 /* check mac address change */
422 /***************************************/
423 int macAddrCheck(int ipStatus, char *clientAddr4, char *clientAddr6, char *macAddr4, char *macAddr6)
425 char macAddrNow[ADDRMAXLN]; /* MAC address at now */
427 if(ipStatus!=IPV6ONLY){
428 /* check mac address from arp */
429 GetMacAddrFromArp(clientAddr4, macAddrNow);
430 if(*macAddrNow!='?' && strcmp(macAddr4, macAddrNow)!=0){
431 err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
432 connectMode=ENDCONNECT;
436 /* check mac address from ndp */
437 GetMacAddrFromNdp(clientAddr6, macAddrNow);
438 if(*macAddrNow!='?' && strcmp(macAddr6, macAddrNow)!=0){
439 err_msg("ERR at %s#%d: mac address is changed",__FILE__,__LINE__);
440 connectMode=ENDCONNECT;
447 /***************************************/
448 /* get addr of connected remote site */
449 /***************************************/
450 void getPeerAddr(int sockfd, char *peerAddr)
452 struct sockaddr *cliaddr;
456 *peerAddr='\0'; /* set null string */
458 if((cliaddr=Malloc(ADDRMAXLN))==NULL) return; /* if error, return */
461 if(Getpeername(sockfd, cliaddr, &len)<0) return; /* if error, return */
463 pAddr=Sock_ntop_host(cliaddr, len);
464 if(pAddr!=NULL) strncpy(peerAddr, pAddr, ADDRMAXLN);
471 /***************************************************/
472 /* wait for close connection of java */
473 /***************************************************/
474 void waitJavaClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus)
476 char buff[BUFFMAXLN];
479 /* set alarm function arguments */
480 alarmArg.pClientAddr=pClientAddr;
481 alarmArg.macAddr4=macAddr4;
482 alarmArg.macAddr6=macAddr6;
483 alarmArg.userid=userid;
484 alarmArg.userProperty=userProperty;
485 alarmArg.ipStatus=ipStatus;
487 Writefmt(connfd,"accept\r\n");
489 /* TCP read/write loop */
490 /* this loop implement following logic */
491 /* repeat until receiving 'quit' or EOF from client */
492 /* say 'hello' to client */
493 /* receive 'hello' from client. if no reply, then quit. */
494 /* get packet count for client after short delay. */
496 /* get packet count again. if no packet, then quit. */
498 /* set the alarm for periodic check */
499 AddAlarm("CheckJavaAlarm", alarmArg.checkInterval, FALSE, OnCheckJavaAlarm);
503 /* set default to terminate */
504 connectMode=ENDCONNECT;
505 ret=readln(connfd, buff, BUFFMAXLN);
512 connectMode=JAVACONNECT;
513 /* read quit, then quit */
514 if(strstr(buff,"quit") != NULL){
518 /* read hello reply to the hello message in periodic check */
519 /* see onCheckJavaAlarm for timeout alarm setting */
520 else if((helloWait)&&(strstr(buff,"hello") !=NULL)){
522 RemoveAlarm("ReplyTimeoutAlarm");
524 /* read other string */
529 /* connection terminated */
530 if(connectMode==ENDCONNECT) break;
545 /***************************************/
546 /* called at periodic java alive check */
547 /***************************************/
548 void onReplyTimeoutAlarm(int signo)
551 err_msg("ERR at %s#%d: no reply to hello",__FILE__,__LINE__);
552 connectMode=ENDCONNECT;
555 /***************************************/
556 /* called at periodic java alive check */
557 /***************************************/
558 void onCheckJavaAlarm(int signo)
560 /* search new IPv6 addresses */
561 ScanNdpEntry(alarmArg.pClientAddr, alarmArg.userid,
562 alarmArg.macAddr6, alarmArg.userProperty);
564 /* send hello and wait the reply */
565 Writefmt(connfd,"hello\r\n");
568 /* mac address check */
569 if(MacAddrCheck(alarmArg.ipStatus,
570 alarmArg.clientAddr4, alarmArg.clientAddr6,
571 alarmArg.macAddr4, alarmArg.macAddr6)==FALSE){
572 connectMode=ENDCONNECT;
576 /* set the alarm for next periodic check */
577 AddAlarm("CheckJavaAlarm", alarmArg.checkInterval, FALSE, OnCheckJavaAlarm);
578 /* EnableAlarm is called automatically in alarm function */
580 connectMode=JAVACONNECT;
584 /***************************************************/
585 /* send reply to terminate access via connfd(not stdout) */
586 /***************************************************/
587 void sendTerminateReply(void)
589 Writefmt(connfd,"<META HTTP-EQUIV=Pragma CONTENT=no-cache>");
590 Writefmt(connfd,"<HTML><BODY> Network is closed. </BODY></HTML> \r\n\r\n");
594 /***************************************************/
595 /* send quit to client and close connection */
596 /***************************************************/
597 void sendQuitClient(void)
599 Writefmt(connfd,"quit\r\n");
604 /***************************************************/
605 /* wait for close connection of HTTP connection */
606 /***************************************************/
607 void waitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus, char *sessionId, int port)
609 char buff[BUFFMAXLN];
612 /* set alarm function arguments */
613 alarmArg.pClientAddr=pClientAddr;
614 alarmArg.macAddr4=macAddr4;
615 alarmArg.macAddr6=macAddr6;
616 alarmArg.userid=userid;
617 alarmArg.userProperty=userProperty;
618 alarmArg.ipStatus=ipStatus;
620 /* save time to read hello */
621 readHelloTime = time(NULL);
623 /* send first reply to hello */
624 SendReplyToGetHello();
625 sendHelloTime = time(NULL);
627 /* set the hello wait mode ON */
630 /* TCP read/write loop */
631 /* this loop implement following logic */
632 /* repeat until receiving 'GET /terminate' or EOF from client */
633 /* wait request from client. */
634 /* if wait timeout, then quit */
635 /* if 'GET /hello' request, then send reply */
636 /* if 'GET /terminate' request, then quit */
637 /* if connection closed, then quit */
639 /* set the alarm for periodic client check */
640 AddAlarm("checkHttpAlarm", alarmArg.checkInterval, FALSE, OnCheckHttpAlarm);
645 /* set default to terminate */
646 connectMode=ENDCONNECT;
648 /* read in wait for client request */
649 ret=readln(connfd, buff, BUFFMAXLN);
651 /* at some request, stop alarm between readin check*/
656 connectMode=HTTPCONNECT;
658 /* read [GET /hello] */
659 if(strstr(buff,"GET /hello") == buff){
661 /* save time to read hello */
662 readHelloTime = time(NULL);
666 /* if received key is not match, exit */
667 if(IsRightKey(buff+strlen("GET /hello-"), sessionId)==FALSE){
668 connectMode=ENDCONNECT;
672 /* set the hello wait mode OFF */
676 /* read other string */
682 /* some alarm is ringed or connecion is closed */
683 /* connectionMode might be modified in onAlarm */
685 if(connectMode==ENDCONNECT){
687 /* wait short time to accept reconnection */
688 /* (to permit occasional disconnection at exchanging hello) */
689 if(helloWait==TRUE &&
690 (time(NULL)-sendHelloTime)<=atoi(GetConfValue("ReconnectTimeout"))){
691 AcceptHttpReConnect();
694 /* no reconnection, then terminate */
695 if(connectMode==ENDCONNECT){
713 /*************************/
714 /* accept http reconnect */
715 /*************************/
716 void acceptHttpReConnect(void){
720 startTime=time(NULL);
722 /* wait a short time */
723 AddAlarm("ReadWaitAlarm",atoi(GetConfValue("ReconnectTimeout")),
724 TRUE, OnReadWaitAlarm);
727 /* connection wait */
728 connfd = SelectAccept();
731 /* abnormal return from selectAccept */
732 if(errno==EINTR){ /* timeout interupt */
733 err_msg("ERR at %s#%d: http reconnect timeout",
735 connectMode=ENDCONNECT;
736 }else{ /* other errors */
737 err_msg("ERR: http reconnect error [%s]",strerror(errno));
738 connectMode=ENDCONNECT;
742 /* normal return from selectAccept */
743 if(debug>0)err_msg("INFO: http reconnect after %d seconds",
744 time(NULL)-startTime);
745 connectMode=HTTPCONNECT;
748 /* receive request */
749 RemoveAlarm("ReadWaitAlarm");
752 /*****************************************************************/
753 /* Is the sent client key correct */
754 /* request string is as follows */
755 /* GET /hello-11111111111111111111-2222222222222222222 HTTP... */
756 /* MD5digest(32chars) MD5digest(32chars) */
760 /* save sid <------------------- sid */
761 /* md5(sid)+md5(md5(rand1)+sid) ---------> check nowkey */
763 /* md5(rand1)+md5(md5(rand2)+sid)---------> check nowkey */
765 /* md5(rand2)+md5(md5(rand3)+sid)---------> check nowkey */
767 /*****************************************************************/
768 int isRightKey(char *arg, char *sessionId)
770 static char savedKey[33]=""; /* saved MD5 string */
771 char tempbuff[BUFFMAXLN]; /* work area */
772 char md5work[33] ; /* md5 work */
776 /* initial value of savedKey is md5(md5(sessionId)+sessionId) */
777 if(isNull(savedKey)){
778 md5hex(tempbuff, 33, sessionId);
779 strncat(tempbuff, sessionId, BUFFMAXLN);
780 md5hex(savedKey, 33, tempbuff);
783 /* split NowKey and NextKey in argument */
784 /* 32 is the length of MD5 result */
790 /* make string [nowKey+sessionId] */
791 strncpy(tempbuff, pNowKey, BUFFMAXLN);
792 strncat(tempbuff, sessionId, BUFFMAXLN);
794 /* compare savedKey and md5(nowKey+sessionId) */
795 if(strcmp(savedKey, md5hex(md5work, 33, tempbuff))==0){
797 /* save nextKey for next check */
798 strncpy(savedKey, pNextKey, 33);
802 err_msg("ERR at %s#%d: incorrect client key",
808 /***************************************/
809 /* called at periodic http alive check */
810 /***************************************/
811 void onCheckHttpAlarm(int signo)
813 /* at this timing, hello request might be received */
814 /* if in hello wait mode, it is abnormal */
816 connectMode=ENDCONNECT;
820 /* send delayed reply to hello request */
821 SendReplyToGetHello();
823 /* save time to send hello */
824 sendHelloTime = time(NULL);
826 /* set the hello wait mode ON */
829 /* search new IPv6 addresses */
830 ScanNdpEntry(alarmArg.pClientAddr, alarmArg.userid,
831 alarmArg.macAddr6, alarmArg.userProperty);
833 /* mac address check */
834 if(MacAddrCheck(alarmArg.ipStatus,
835 alarmArg.clientAddr4, alarmArg.clientAddr6,
836 alarmArg.macAddr4, alarmArg.macAddr6)==FALSE){
837 connectMode=ENDCONNECT;
841 /* set the alarm for next periodic check */
842 AddAlarm("CheckHttpAlarm", alarmArg.checkInterval, FALSE, OnCheckHttpAlarm);
843 /* EnableAlarm is called automatically in alarm function */
846 connectMode = HTTPCONNECT;
850 /***************************************************/
851 /* read skip Http headers ended by null line */
852 /***************************************************/
853 void readHttpHeaders(void)
855 char buff[BUFFMAXLN]; /* read in buffer */
858 /* read until null line (only CRLF code) */
859 while((n=readln(connfd, buff, BUFFMAXLN))>0){
864 /********************************************************/
865 /* send hello to client for replying GET /hello request */
866 /********************************************************/
867 void sendReplyToGetHello(void)
869 /* send HTTP headers */
870 Writefmt(connfd,"HTTP/1.1 200 OK\r\n");
871 Writefmt(connfd,"Transfer-Encoding: chunked\r\n");
872 Writefmt(connfd,"Keep-Alive: timeout=300\r\n");
873 Writefmt(connfd,"Connection: Keep-Alive\r\n");
874 Writefmt(connfd,"Content-Type: text/html\r\n");
875 Writefmt(connfd,"\r\n");
877 /* send reply to hello */
878 Writefmt(connfd,"5\r\n");
879 Writefmt(connfd,"hello\r\n");
881 /* send end of chunk */
882 Writefmt(connfd,"0\r\n");
883 Writefmt(connfd,"\r\n");
886 /***************************************************/
887 /* send httpkeep page to client via connfd */
888 /***************************************************/
889 void sendHttpKeepPage(char *userid, char *sessionId, char *language, int port)
891 char buff[BUFFMAXLN]; /* read in buffer */
893 char httpKeepDoc[BUFFMAXLN];
894 char httpHelloUrl[BUFFMAXLN];
895 char terminateUrl[BUFFMAXLN];
896 char acceptDoc2Url[BUFFMAXLN];
897 char httpkeepJsUrl[BUFFMAXLN];
898 char md5JsUrl[BUFFMAXLN];
899 char *startPageUrl=GetConfValue("StartPage/Url");
900 int startPageType=atoi(GetConfValue("StartPage/Type"));
901 char opengateDir[BUFFMAXLN];
902 char portStr[WORDMAXLN];
905 /* create path to accept2 doc */
906 snprintf(acceptDoc2Url, BUFFMAXLN,
907 "http://%s%s/%s/%s",GetConfValue("OpengateServerName"),
908 GetConfValue("OpengateDir"),language,GetConfValue("AcceptDoc2"));
910 /* create terminate url [http://<servaddr>:<port>/terminate-<pid>] */
911 snprintf(terminateUrl, BUFFMAXLN, "http://%s:%d/terminate-%d",
912 GetConfValue("OpengateServerName"), port, getpid());
914 /* create httphello url [http://<servaddr>:<port>/hello] */
915 snprintf(httpHelloUrl, BUFFMAXLN, "http://%s:%d/hello",
916 GetConfValue("OpengateServerName"), port);
918 /* create httpkeep.js url[http://<serveraddr>/opengate/httpkeep.js] */
919 snprintf(httpkeepJsUrl, BUFFMAXLN, "http://%s%s/%s",
920 GetConfValue("OpengateServerName"),
921 GetConfValue("OpengateDir"),GetConfValue("HttpKeepJS"));
923 /* create md5.js url[http://<serveraddr>/opengate/md5.js] */
924 snprintf(md5JsUrl, BUFFMAXLN, "http://%s%s/%s",
925 GetConfValue("OpengateServerName"),
926 GetConfValue("OpengateDir"),GetConfValue("Md5JS"));
928 /* create path to httpkeep doc */
929 snprintf(httpKeepDoc,BUFFMAXLN, "%s%s/%s/%s",GetConfValue("DocumentRoot"),
930 GetConfValue("OpengateDir"),language,GetConfValue("HttpKeepDoc"));
932 /* create port string */
933 snprintf(portStr, WORDMAXLN, "%d", port);
935 /* create absolute url to opengateDir[http://<serveraddr>/opengate] */
936 snprintf(opengateDir, BUFFMAXLN, "http://%s%s",
937 GetConfValue("OpengateServerName"), GetConfValue("OpengateDir"));
939 /* open httpkeepdoc */
940 if((fp=fopen(httpKeepDoc, "r"))==NULL){
941 err_msg("ERR at %s#%d: cannot open %s",__FILE__,__LINE__,httpKeepDoc);
942 PutClientMsg("Cannot find html document");
946 /* send HTTP headers */
947 Writefmt(connfd,"HTTP/1.1 200 OK\r\n");
948 Writefmt(connfd,"Transfer-Encoding: chunked\r\n");
949 Writefmt(connfd,"Keep-Alive: timeout=300\r\n");
950 Writefmt(connfd,"Connection: Keep-Alive\r\n");
951 Writefmt(connfd,"Content-Type: text/html\r\n");
952 Writefmt(connfd,"\r\n");
954 while(fgets(buff, BUFFMAXLN, fp)!=NULL){
957 if(strlen(buff)>=BUFFMAXLN-1){
958 err_msg("ERR at %s#%d: too long line in %s",__FILE__,__LINE__,httpKeepDoc);
962 htmlReplace(buff, "%%HTTPHELLOURL%%", httpHelloUrl);
963 htmlReplace(buff, "%%USERID%%", userid);
964 htmlReplace(buff, "%%SESSIONID%%", sessionId);
965 htmlReplace(buff, "%%TERMINATEURL%%", terminateUrl);
966 htmlReplace(buff, "%%HTTPKEEPJSURL%%", httpkeepJsUrl);
967 htmlReplace(buff, "%%MD5JSURL%%", md5JsUrl);
969 htmlReplace(buff, "%%OPENGATEDIR%%", opengateDir);
970 htmlReplace(buff, "%%OPENGATEPORT%%", portStr);
971 htmlReplace(buff, "%%LANGUAGE%%", language);
973 /* replace start url mark */
974 if( startPageType==1 ){
975 htmlReplace(buff, "%%STARTURL%%", startPageUrl);
977 htmlReplace(buff, "%%STARTURL%%", acceptDoc2Url);
980 /* length of chunk in hex */
981 Writefmt(connfd, "%x\r\n", strlen(buff));
982 /* the chunk content */
983 Writefmt(connfd, "%s\r\n", buff);
987 Writefmt(connfd,"0\r\n");
988 Writefmt(connfd,"\r\n");
994 /*************************************************************/
995 /* send reply to unknown http request eg:[GET /favico.ico..] */
996 /*************************************************************/
997 void sendHttpReply(char *reply)
999 /* send HTTP headers */
1000 Writefmt(connfd,"HTTP/1.1 200 OK\r\n");
1001 Writefmt(connfd,"Transfer-Encoding: chunked\r\n");
1002 Writefmt(connfd,"Keep-Alive: timeout=300\r\n");
1003 Writefmt(connfd,"Connection: Keep-Alive\r\n");
1004 Writefmt(connfd,"Content-Type: text/html\r\n");
1005 Writefmt(connfd,"\r\n");
1008 /* length of chunk in hex */
1009 Writefmt(connfd, "%x\r\n", strlen(reply));
1010 /* the chunk content */
1011 Writefmt(connfd, "%s\r\n", reply);
1015 Writefmt(connfd,"0\r\n");
1016 Writefmt(connfd,"\r\n");
1019 /***************************************************/
1020 /***************************************************/
1021 void GetPeerAddr(int sockfd, char *peerAddr)
1023 if(debug>1) err_msg("DEBUG:=>getPeerAddr( )");
1024 getPeerAddr(sockfd,peerAddr);
1025 if(debug>1) err_msg("DEBUG:<=getPeerAddr(,%s)",peerAddr);
1029 int GetListenPort(void)
1033 if(debug>1) err_msg("DEBUG:=>getListenPort( )");
1034 ret=getListenPort();
1035 if(debug>1) err_msg("DEBUG:(%d)<=getListenPort( )",ret);
1040 int WaitClientConnect(char *userid, char *userProperty, char *sessionId, char *clientAddr4, char *clientAddr6, int duration, char *macAddr4, char *macAddr6, int ipStatus, struct clientAddr *pClientAddr, char *language, int port, int pid)
1044 if(debug>1) err_msg("DEBUG:=>waitClientConnect(%s,%s,%s,%s,%s,%d,%s,%s,%d,%s,%d,%d)",userid,userProperty,sessionId,clientAddr4,clientAddr6,duration,macAddr4,macAddr6,ipStatus,language,port,pid);
1045 ret=waitClientConnect(userid,userProperty,sessionId,clientAddr4,clientAddr6,duration,macAddr4,macAddr6,ipStatus,pClientAddr,language,port,pid);
1046 if(debug>1) err_msg("DEBUG:(%d)<=waitClientConnect( )",ret);
1051 void WaitJavaClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus)
1053 if(debug>1) err_msg("DEBUG:=>waitJavaClose(%p,%s,userProperty,%s,%s,%d)",pClientAddr,userid,macAddr4,macAddr6,ipStatus);
1054 waitJavaClose(pClientAddr,userid,userProperty,macAddr4,macAddr6,ipStatus);
1055 if(debug>1) err_msg("DEBUG:<=waitJavaClose( )");
1058 void SendQuitClient(void)
1060 if(debug>1) err_msg("DEBUG:=>sendQuitClient( )");
1062 if(debug>1) err_msg("DEBUG:<=sendQuitClient( )");
1065 void SendTerminateReply(void)
1067 if(debug>1) err_msg("DEBUG:=>sendTerminateReply( )");
1068 sendTerminateReply();
1069 if(debug>1) err_msg("DEBUG:<=sendTerminateReply( )");
1072 void WaitHttpClose(struct clientAddr *pClientAddr, char *userid, char *userProperty, char *macAddr4, char *macAddr6, int ipStatus, char *sessionid, int port)
1074 if(debug>1) err_msg("DEBUG:=>waitHttpClose(%p,%s,userProperty,%s,%s,%d,%s,%d)",pClientAddr,userid,macAddr4,macAddr6,ipStatus, sessionid, port);
1075 waitHttpClose(pClientAddr,userid,userProperty,macAddr4,macAddr6,ipStatus, sessionid, port);
1076 if(debug>1) err_msg("DEBUG:<=waitHttpClose( )");
1080 void ReadHttpHeaders(void)
1082 if(debug>1) err_msg("DEBUG:=>readHttpHeaders( )");
1084 if(debug>1) err_msg("DEBUG:<=readHttpHeaders( )");
1087 void SendReplyToGetHello(void)
1089 if(debug>1) err_msg("DEBUG:=>sendReplyToGetHello( )");
1090 sendReplyToGetHello();
1091 if(debug>1) err_msg("DEBUG:<=sendReplyToGetHello( )");
1094 void SendHttpKeepPage(char *userid, char *sessionId, char *language, int port)
1096 if(debug>1) err_msg("DEBUG:=>sendHttpKeepPage(%s,%s,%s,%d)", userid, sessionId, language, port);
1097 sendHttpKeepPage(userid, sessionId, language, port);
1098 if(debug>1) err_msg("DEBUG:<=sendHttpKeepPage( )");
1102 void OnUsageTimeLimitAlarm(int signo){
1104 if(debug>1) err_msg("DEBUG:=>onUsageTimeLimitAlarm()");
1105 onUsageTimeLimitAlarm(signo);
1106 if(debug>1) err_msg("DEBUG:<=onUsageTimeLimitAlarm()");
1109 void OnCheckBasicAlarm(int signo){
1111 if(debug>1) err_msg("DEBUG:=>onCheckBasicAlarm()");
1112 onCheckBasicAlarm(signo);
1113 if(debug>1) err_msg("DEBUG:<=onCheckBasicAlarm()");
1116 void OnCheckJavaAlarm(int signo){
1118 if(debug>1) err_msg("DEBUG:=>onCheckJavaAlarm()");
1119 onCheckJavaAlarm(signo);
1120 if(debug>1) err_msg("DEBUG:<=onCheckJavaAlarm()");
1123 void OnCheckHttpAlarm(int signo){
1125 if(debug>1) err_msg("DEBUG:=>onCheckHttpAlarm()");
1126 onCheckHttpAlarm(signo);
1127 if(debug>1) err_msg("DEBUG:<=onCheckHttpAlarm()");
1130 void OnReadWaitAlarm(int signo){
1132 if(debug>1) err_msg("DEBUG:=>onReadWaitAlarm()");
1133 onReadWaitAlarm(signo);
1134 if(debug>1) err_msg("DEBUG:<=onReadWaitAlarm()");
1137 void OnAjaxWaitAlarm(int signo){
1139 if(debug>1) err_msg("DEBUG:=>onAjaxWaitAlarm()");
1140 onAjaxWaitAlarm(signo);
1141 if(debug>1) err_msg("DEBUG:<=onAjaxWaitAlarm()");
1144 int SelectAccept(void){
1147 if(debug>1) err_msg("DEBUG:=>selectAccept()");
1149 if(debug>1) err_msg("DEBUG:(%d)<=selectAccept()",ret);
1154 void AcceptHttpReConnect(void){
1155 if(debug>1) err_msg("DEBUG:=>acceptHttpReConnect()");
1156 acceptHttpReConnect();
1157 if(debug>1) err_msg("DEBUG:<=acceptHttpReConnect()");
1160 int MacAddrCheck(int ipStatus, char *clientAddr4, char *clientAddr6, char *macAddr4, char *macAddr6) {
1163 if(debug>1) err_msg("DEBUG:=>macAddrCheck(%d,%s,%s,%s,%s)",
1164 ipStatus, clientAddr4, clientAddr6, macAddr4, macAddr6);
1165 ret=macAddrCheck(ipStatus, clientAddr4, clientAddr6, macAddr4, macAddr6);
1166 if(debug>1) err_msg("DEBUG:(%d)<=macAddrCheck()",ret);
1171 int IsRightKey(char *pNowKey, char *sessionId){
1174 if(debug>1) err_msg("DEBUG:=>isRightKey(%s,%s)", pNowKey, sessionId);
1175 ret=isRightKey(pNowKey, sessionId);
1176 if(debug>1) err_msg("DEBUG:(%d)<=isRightKey()",ret);
1181 void SendHttpReply(char *reply){
1182 if(debug>1) err_msg("DEBUG:=>sendHttpRepy(%s)", reply);
1183 sendHttpReply(reply);
1184 if(debug>1) err_msg("DEBUG:<=sendHttpReply()");
1187 void CheckAjaxAbility(char *buff, char *sessionId){
1188 if(debug>1) err_msg("DEBUG:=>checkAjaxAbility(%s,%s)",buff,sessionId);
1189 checkAjaxAbility(buff,sessionId);
1190 if(debug>1) err_msg("DEBUG:<=checkAjaxAbility()");