1#include <time.h>
2#include "phupdate.h"
3#include "log.h"
4#include "blowfish.h"
5
6#include "generate.h"
7#include "lutil.h"
8#include <stdlib.h>
9#include <bcmnvram.h>
10
11BOOL InitializeSockets(PHGlobal *phglobal)
12{
13	DestroySockets(phglobal);
14	if (!phCreate(&(phglobal->m_tcpsocket),0,SOCK_STREAM,phglobal->szBindAddress))
15	{
16		return FALSE;
17	}
18
19	if (!phCreate(&(phglobal->m_udpsocket),0,SOCK_DGRAM,phglobal->szBindAddress))
20	{
21		return FALSE;
22	}
23	return TRUE;
24}
25
26BOOL DestroySockets(PHGlobal *phglobal)
27{
28	phClose(&phglobal->m_tcpsocket);
29	phClose(&phglobal->m_udpsocket);
30	return TRUE;
31}
32
33BOOL BeginKeepAlive(PHGlobal *phglobal)
34{
35	if (!phConnect(phglobal->m_udpsocket, phglobal->szTcpConnectAddress,phglobal->nPort,&phglobal->nAddressIndex, NULL)) return FALSE;
36	phglobal->nLastResponseID = time(0);
37	return TRUE;
38}
39
40BOOL SendKeepAlive(PHGlobal *phglobal, int opCode)
41{
42	DATA_KEEPALIVE data;
43	blf_ctx blf;
44	char p1[KEEPALIVE_PACKET_LEN],p2[KEEPALIVE_PACKET_LEN];
45
46	memset(&data,0,sizeof(data));
47	data.lChatID = phglobal->nChatID;
48	data.lID = phglobal->nStartID;
49	data.lOpCode = opCode;
50	data.lSum = 0 - (data.lID + data.lOpCode);
51	data.lReserved = 0;
52
53	if (!phglobal->bTcpUpdateSuccessed) return FALSE;
54
55	LOG(1) ("SendKeepAlive() %d\n",opCode);
56
57
58	InitBlowfish(&blf, (unsigned char*)phglobal->szChallenge,phglobal->nChallengeLen);
59	memcpy(p1,&data,KEEPALIVE_PACKET_LEN);
60	memcpy(p2,&data,KEEPALIVE_PACKET_LEN);
61	Blowfish_EnCode(&blf, p1+4,p2+4,KEEPALIVE_PACKET_LEN-4);
62
63	if (phglobal->bBigEndian)
64    {
65                reverse_byte_order((int*)p2, 5);
66                //printf("debug-- reversed byte order\n");
67     }
68
69	phSend(phglobal->m_udpsocket, p2, KEEPALIVE_PACKET_LEN,0);
70	//RecvKeepaliveResponse();
71	return TRUE;
72}
73
74int RecvKeepaliveResponse(PHGlobal *phglobal)
75{
76	char temp[100];
77	DATA_KEEPALIVE_EXT rdata;
78	DATA_KEEPALIVE data;
79	blf_ctx blf;
80	char p1[KEEPALIVE_PACKET_LEN],p2[KEEPALIVE_PACKET_LEN];
81
82	if (!phglobal->bTcpUpdateSuccessed) return errorOccupyReconnect;
83
84	//prevent the thread to be suspended while waiting for data
85	if (phDataReadable(phglobal->m_udpsocket, 0)<=0)
86	{
87		return okNoData;
88	}
89	//DATA_KEEPALIVE data;
90	//if (m_udpsocket.Receive(&data,sizeof(DATA_KEEPALIVE),0)<=0) return FALSE;
91	if (phReceive(phglobal->m_udpsocket, temp,sizeof(temp),0)<=0) return okNoData;
92	//printf("debug-- received some udp data\n");
93	memcpy(&rdata, temp, sizeof(DATA_KEEPALIVE_EXT));
94	//if (phglobal->bBigEndian) reverse_byte_order((int*)&rdata.ip, 1);
95
96	data = rdata.keepalive;
97
98	InitBlowfish(&blf, (unsigned char*)phglobal->szChallenge,phglobal->nChallengeLen);
99
100	memcpy(p1,&data,KEEPALIVE_PACKET_LEN);
101	if (phglobal->bBigEndian) reverse_byte_order((int*)p1, 5);
102	memcpy(p2,&data,KEEPALIVE_PACKET_LEN);
103	Blowfish_DeCode(&blf, p1+4,p2+4,KEEPALIVE_PACKET_LEN-4);
104	memcpy(&data,p2,KEEPALIVE_PACKET_LEN);
105
106	phglobal->nStartID = data.lID + 1;
107
108	LOG(1) (("RecvKeepaliveResponse() Data comes, OPCODE:%d\n"),data.lOpCode);
109	if (data.lID - phglobal->nLastResponseID > 3 && phglobal->nLastResponseID != -1)
110	{
111		return errorOccupyReconnect;
112	}
113
114	phglobal->nLastResponseID = data.lID;
115	phglobal->tmLastResponse = time(0);
116
117	phglobal->ip = rdata.ip;
118
119	if (data.lOpCode == UDP_OPCODE_UPDATE_ERROR) return okServerER;
120	//if (data.lOpCode == UDP_OPCODE_LOGOUT) return okNormal;
121
122	return okKeepAliveRecved;
123}
124
125int ExecuteUpdate(PHGlobal *phglobal)
126{
127	char buffer[1024];
128
129    char username[128] = "";
130	char key[128] = "";
131	char sendbuffer[256];
132
133    char domains[255][255];
134    char regicommand[255];
135	int i,len, totaldomains;
136	long challengetime = 0;
137
138	char *chatid = NULL;
139	char *startid = NULL;
140	char *xmldata = NULL;
141	int buflen = 0;
142
143	LOG(1) ("ExecuteUpdate Connecting %s.\n",phglobal->szHost);
144
145	if (!phConnect(phglobal->m_tcpsocket, phglobal->szHost,phglobal->nPort,&phglobal->nAddressIndex,phglobal->szTcpConnectAddress))
146	{
147		LOG(1) ("ExecuteUpdate errorConnectFailed.\n");
148		phglobal->nAddressIndex++;
149nvram_set("ddns_return_code", "connect_fail");
150nvram_set("ddns_return_code_chk", "connect_fail");
151		return errorConnectFailed;
152	}
153	//////////////////////////////////////////////////////////////////////////
154	//Recv server hello string
155	memset(buffer, 0, 128);
156	len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
157	if (len <=0 )
158	{
159		LOG(1) ("ExecuteUpdate Recv server hello string failed.\n");
160		phClose(&phglobal->m_tcpsocket);
161		phglobal->nAddressIndex++;
162nvram_set("ddns_return_code", "connect_fail");
163nvram_set("ddns_return_code_chk", "connect_fail");
164		return errorConnectFailed;
165	}
166
167	LOG(1) (("SEND AUTH REQUEST COMMAND..."));
168	phSend(phglobal->m_tcpsocket, (char*)COMMAND_AUTH,sizeof(COMMAND_AUTH),0);
169    LOG(1) (("OK.\n"));
170
171	//////////////////////////////////////////////////////////////////////////
172	//Recv server key string
173	memset(buffer, 0, 128);
174	len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
175	if (len <=0 )
176	{
177		LOG(1) (("ExecuteUpdate Recv server key string failed.\n"));
178		phClose(&phglobal->m_tcpsocket);
179nvram_set("ddns_return_code", "connect_fail");
180nvram_set("ddns_return_code_chk", "connect_fail");
181		return errorConnectFailed;
182	}
183    LOG(1) (("SERVER SIDE KEY \"%s\" RECEIVED.\n"),buffer);
184
185	phglobal->nChallengeLen =  lutil_b64_pton(buffer+4, (unsigned char *)phglobal->szChallenge, 256);
186
187
188	//////////////////////////////////////////////////////////////////////////
189	//////////////////////////////////////////////////////////////////////////
190	//////////////////////////////////////////////////////////////////////////
191	//Generate encoded auth string
192	len = GenerateCrypt(phglobal->szUserID, phglobal->szUserPWD, buffer+4, phglobal->clientinfo, phglobal->challengekey, sendbuffer);
193	strcat(sendbuffer, "\r\n");
194    //Generate ok.
195	//////////////////////////////////////////////////////////////////////////
196	//////////////////////////////////////////////////////////////////////////
197	//////////////////////////////////////////////////////////////////////////
198
199	//////////////////////////////////////////////////////////////////////////
200	//send auth data
201	LOG(1) (("SEND AUTH DATA..."));
202	phSend(phglobal->m_tcpsocket, sendbuffer,strlen(sendbuffer),0);
203    LOG(1) (("OK\n"));
204
205	memset(buffer, 0, 128);
206	len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
207	buffer[3] = 0;
208
209	if (len <=0 )
210	{
211		LOG(1) (("ExecuteUpdate Recv server auth response failed.\n"));
212		phClose(&phglobal->m_tcpsocket);
213		//modified skyvense 2005/10/08, for server db conn lost bug
214		//return errorAuthFailed;
215nvram_set("ddns_return_code", "connect_fail");
216nvram_set("ddns_return_code_chk", "connect_fail");
217		return errorConnectFailed;
218	}
219	if (strcmp(buffer,"250")!=0 && strcmp(buffer,"536")!=0)
220	{
221		LOG(1) ("CTcpThread::ExecuteUpdate auth failed.\n");
222		phClose(&phglobal->m_tcpsocket);
223
224nvram_set("ddns_return_code", "auth_fail");
225nvram_set("ddns_return_code_chk", "auth_fail");
226		if (strstr(buffer + 4, "Busy.") != NULL) return errorAuthBusy;
227		return errorAuthFailed;
228	}
229	if (strcmp(buffer,"536") == 0) //find redirected server address, and let us connect again to new server
230	{
231		char *pos0 = strchr(buffer + 4, '<');
232		if (pos0)
233		{
234			char *pos1 = strchr(pos0 + 1, '>');
235			if (pos1)
236			{
237				*pos1 = '\0';
238				strcpy(phglobal->szHost, pos0 + 1);
239
240				phClose(&phglobal->m_tcpsocket);
241				return okRedirecting;
242			}
243		}
244nvram_set("ddns_return_code", "auth_fail");
245nvram_set("ddns_return_code_chk", "auth_fail");
246		return errorAuthFailed;
247	}
248	if (strcmp(buffer,"250") == 0) //get user type level, 0(free),1(pro),2(biz)
249	{
250		char *pos0 = strchr(buffer + 4, '<');
251		if (pos0)
252		{
253			char *pos1 = strchr(pos0 + 1, '>');
254			if (pos1)
255			{
256				*pos1 = '\0';
257				phglobal->nUserType = atoi(pos0 + 1);
258			}
259		}
260	}
261
262	//////////////////////////////////////////////////////////////////////////
263	//list domains
264	for (i=0,totaldomains=0;i<255;i++)
265    {
266        memset(domains[i], 0, 255);
267        phReadOneLine(phglobal->m_tcpsocket, domains[i],255);
268        LOG(1) (("ExecuteUpdate domain \"%s\"\n"),domains[i]);
269        totaldomains++;
270		strcpy(phglobal->szActiveDomains[i],domains[i]);
271        if (domains[i][0] == '.') break;
272    }
273	if (totaldomains<=0)
274	{
275		LOG(1) (("ExecuteUpdate Domain List Failed.\n"));
276		phClose(&phglobal->m_tcpsocket);
277		return errorDomainListFailed;
278	}
279
280	phglobal->cLastResult = okDomainListed;
281	if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, phglobal->cLastResult, 0);
282	//::SendMessage(theApp.m_hWndController,WM_DOMAIN_UPDATEMSG,okDomainListed,(long)domains);
283	//////////////////////////////////////////////////////////////////////////
284	//send domain regi commands list
285	for (i=0;;i++)
286    {
287        if (domains[i][0] == '.') break;
288		memset(regicommand, 0, 128);
289        strcpy(regicommand, COMMAND_REGI);
290        strcat(regicommand, " ");
291        strcat(regicommand, domains[i]);
292        strcat(regicommand, "\r\n");
293        //printf("%s",regicommand);
294        phSend(phglobal->m_tcpsocket,regicommand,strlen(regicommand),0);
295    }
296
297	//////////////////////////////////////////////////////////////////////////
298	//send confirm
299	LOG(1) (("SEND CNFM DATA..."));
300    phSend(phglobal->m_tcpsocket,(char*)COMMAND_CNFM,strlen(COMMAND_CNFM),0);
301    LOG(1) (("OK\n"));
302
303	for (i=0;i<totaldomains-1;i++)
304    {
305		memset(buffer, 0, 128);
306		len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
307		if (len <= 0)
308		{
309			LOG(1) (("ExecuteUpdate Recv server confirm response failed.\n"));
310			phClose(&phglobal->m_tcpsocket);
311			return errorDomainRegisterFailed;
312		}
313		LOG(1) (("ExecuteUpdate %s\n"),buffer);
314		if (phglobal->cbOnDomainRegistered) phglobal->cbOnDomainRegistered(phglobal, domains[i]);
315    }
316
317	memset(buffer, 0, 128);
318	len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
319	if (len <= 0)
320	{
321		LOG(1) (("ExecuteUpdate Recv server confirmed chatID response failed.\n"));
322		phClose(&phglobal->m_tcpsocket);
323		return errorDomainRegisterFailed;
324	}
325	LOG(1) (("%s\n"),buffer);
326
327	//////////////////////////////////////////////////////////////////////////
328	//find chatid & startid
329	buffer[3] = 0;
330	if (strcmp(buffer,"250")!=0)
331	{
332		phglobal->nChatID = phglobal->nStartID = 0;
333		LOG(1) (("ExecuteUpdate register failed %s\n"),buffer);
334	}
335	else
336	{
337		chatid = buffer + 4;
338		startid = NULL;
339
340		for (i=0;i<strlen(chatid);i++)
341		{
342			if (buffer[i] == ' ')
343			{
344				buffer[i] = 0;
345				startid = buffer + i + 1;
346				break;
347			}
348		}
349		phglobal->nChatID = atoi(chatid);
350		if (startid) phglobal->nStartID = atoi(startid);
351		LOG(1) (("ExecuteUpdate nChatID:%d, nStartID:%d\n"),phglobal->nChatID,phglobal->nStartID);
352	}
353
354
355	//////////////////////////////////////////////////////////////////////////
356	//////////////////////////////////////////////////////////////////////////
357	//after confirm domain register, we begin to get user information
358	phSend(phglobal->m_tcpsocket,(void *)COMMAND_STAT_USER,sizeof(COMMAND_STAT_USER),0);
359	memset(buffer, 0, 1024);
360	len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
361	buffer[3] = 0;
362	if (len <= 0 || strcmp(buffer,"250")!=0)
363	{
364		LOG(1) ("CTcpThread::ExecuteUpdate Recv server confirmed stat user response failed.\n");
365		phClose(&phglobal->m_tcpsocket);
366		return errorStatDetailInfoFailed;
367	}
368
369	buflen = MAX_PATH;
370	xmldata = (char *)malloc(buflen);
371	memset(xmldata, 0, buflen);
372
373	for (;;)
374	{
375		memset(buffer, 0, 1024);
376        len = phReadOneLine(phglobal->m_tcpsocket, buffer,1024);
377        if (buffer[0] == '.' || len <= 0) break;
378		if (buflen < strlen(xmldata) + len)
379		{
380			buflen += MAX_PATH;
381			xmldata = realloc(xmldata, buflen);
382			memset((xmldata + buflen) - MAX_PATH, 0, MAX_PATH);
383		}
384		strncat(xmldata, buffer, len);
385	}
386	LOG(1) ("userinfo: \r\n%s\r\n", xmldata);
387	if (phglobal->cbOnUserInfo) phglobal->cbOnUserInfo(phglobal, xmldata, strlen(xmldata));
388	free(xmldata);
389	buflen = 0;
390
391
392	phSend(phglobal->m_tcpsocket,(void *)COMMAND_STAT_DOM,sizeof(COMMAND_STAT_DOM),0);
393	memset(buffer, 0, 1024);
394	len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
395	buffer[3] = 0;
396	if (len <= 0 || strcmp(buffer,"250")!=0)
397	{
398		LOG(1) ("CTcpThread::ExecuteUpdate Recv server confirmed stat user response failed.\n");
399		phClose(&phglobal->m_tcpsocket);
400		return errorStatDetailInfoFailed;
401	}
402
403	buflen = MAX_PATH;
404	xmldata = (char *)malloc(buflen);
405	memset(xmldata, 0, buflen);
406
407	for (;;)
408	{
409		memset(buffer, 0, 1024);
410        len = phReadOneLine(phglobal->m_tcpsocket, buffer,1024);
411        if (buffer[0] == '.' || len <= 0) break;
412		if (buflen < strlen(xmldata) + len)
413		{
414			buflen += MAX_PATH;
415			xmldata = realloc(xmldata, buflen);
416			memset((xmldata + buflen) - MAX_PATH, 0, MAX_PATH);
417		}
418		strncat(xmldata, buffer, len);
419	}
420	LOG(1) ("domaininfo: \r\n%s\r\n", xmldata);
421	if (phglobal->cbOnAccountDomainInfo) phglobal->cbOnAccountDomainInfo(phglobal, xmldata, strlen(xmldata));
422	free(xmldata);
423	buflen = 0;
424
425	//////////////////////////////////////////////////////////////////////////
426	//good bye!
427    	LOG(1) (("SEND QUIT COMMAND..."));
428	phSend(phglobal->m_tcpsocket,(char*)COMMAND_QUIT,sizeof(COMMAND_QUIT),0);
429    	LOG(1) (("OK.\n"));
430
431	LOG(1) (("Update ddns_return_code!!!"));
432	nvram_set("ddns_updated", "1");
433	nvram_set("ddns_return_code", "200");
434	nvram_set("ddns_return_code_chk", "200");
435        for (i=0,totaldomains=0;i<255;i++)
436    	{
437                if(phglobal->szActiveDomains[i] && (phglobal->szActiveDomains[i][0] != '.') )
438			nvram_set("ddns_hostname_x", phglobal->szActiveDomains[i]);
439		LOG(1) (("Update Domain: %s\n", phglobal->szActiveDomains[i]));
440		if(phglobal->szActiveDomains[i][0] == '.')
441			break;
442    	}
443
444    	memset(buffer, 0, 128);
445	len = phReadOneLine(phglobal->m_tcpsocket, buffer,sizeof(buffer));
446	if (len <= 0)
447	{
448		LOG(1) (("ExecuteUpdate Recv server goodbye response failed.\n"));
449		phClose(&phglobal->m_tcpsocket);
450		return okDomainsRegistered;
451	}
452	LOG(1) (("%s\n"),buffer);
453	phClose(&phglobal->m_tcpsocket);
454	return okDomainsRegistered;
455}
456
457int phddns_getkeepalive(int user_type) {
458  return (user_type >= 3 ) ? 15 : ((user_type >= 1) ? 30 : 60);
459}
460
461int get_retry_seconds(int user_type) {
462	int nMaxRetrySeconds = 320; //5 * 60 + 20
463	switch (user_type)
464	{
465	case 1://pro
466	case 2://biz
467		nMaxRetrySeconds = 160; //5 * 30 + 10
468		break;
469	case 3://premium
470		nMaxRetrySeconds = 80; //5 * 15 + 5
471		break;
472	case 0://free
473	default:
474		nMaxRetrySeconds = 320; //5 * 60 + 20
475		break;
476	}
477	return nMaxRetrySeconds;
478}
479
480int get_keepalive_warn_seconds(int user_type) {
481	int nMaxKeepaliveWarnSeconds = 130; // 2 * 60 + 10
482	switch (user_type)
483	{
484	case 1://pro
485	case 2://biz
486		nMaxKeepaliveWarnSeconds = 65; // 2 * 30 + 5
487		break;
488	case 3://premium
489		nMaxKeepaliveWarnSeconds = 35; // 2 * 15 + 5
490		break;
491	case 0://free
492	default:
493		nMaxKeepaliveWarnSeconds = 130; // 2 * 60 + 10
494		break;
495	}
496	return nMaxKeepaliveWarnSeconds;
497}
498
499int phddns_step(PHGlobal *phglobal)
500{
501	int ret = 0;
502	if (phglobal->bNeed_connect)
503	{
504		strcpy(phglobal->szActiveDomains[0],".");
505
506		phglobal->cLastResult = okConnecting;
507
508		if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, phglobal->cLastResult, 0);
509
510		if (!InitializeSockets(phglobal))
511		{
512			LOG(1) ("InitializeSockets failed, waiting for 5 seconds to retry...\n");
513			phglobal->cLastResult = errorConnectFailed;
514			if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, phglobal->cLastResult, 0);
515			return 5;
516		}
517
518		ret = ExecuteUpdate(phglobal);
519//Yau
520LOG(1) ("  ===> ExecuteUpdate ret = %d\n\n", ret);
521		phglobal->cLastResult = ret;
522		if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, phglobal->cLastResult, ret == okDomainsRegistered ? phglobal->nUserType : 0);
523		if (ret == okDomainsRegistered)
524		{
525			//OnUserInfo(phglobal->szUserInfo);
526			//OnAccountDomainInfo(phglobal->szDomainInfo);
527			if (phglobal->nChatID == 0) //user has no domains, no need to begin keepalive
528			{
529				LOG(1) ("ExecuteUpdate OK, nChatID 0\n");
530			}
531			else
532			{
533				LOG(1) ("ExecuteUpdate OK, BeginKeepAlive!\n");
534
535				BeginKeepAlive(phglobal);
536
537			}
538			phglobal->bTcpUpdateSuccessed = TRUE;
539			phglobal->tmLastResponse = time(0);
540			phglobal->bNeed_connect = FALSE;
541			phglobal->lasttcptime = phglobal->tmLastSend = time(0);
542		}
543		else
544		{
545			if (ret == okRedirecting)
546			{
547				phglobal->bTcpUpdateSuccessed = FALSE;
548				phglobal->bNeed_connect = TRUE;
549				LOG(1) ("Need redirect, waiting for 5 seconds...\n");
550				return 5;
551			}
552			if (ret == errorAuthFailed)
553			{
554				LOG(1) ("ExecuteUpdate AuthFailed, waiting for 600 seconds to retry...\n");
555				return 600;
556			}
557
558			LOG(1) ("ExecuteUpdate failed, waiting for 30 seconds to retry...\n");
559			return 30;
560		}
561		phglobal->nLastResponseID = -1;
562	}
563	else
564	{
565		if (phglobal->nChatID == 0)//user has no domains, no need to begin keepalive
566		{
567			return 300;
568		}
569
570		if (time(0) - phglobal->tmLastSend > phddns_getkeepalive(phglobal->nUserType) )  // old code (phglobal->nUserType >= 1 ? 30 : 60)
571		{
572			SendKeepAlive(phglobal, UDP_OPCODE_UPDATE_VER2);
573			phglobal->tmLastSend = time(0);
574		}
575		ret = RecvKeepaliveResponse(phglobal);
576		if (ret != okNormal && ret != okNoData) phglobal->cLastResult = ret;
577		if (ret == errorOccupyReconnect)
578		{
579			LOG(1) ("RecvKeepaliveResponse failed, waiting for 30 seconds to reconnect...\n");
580			phglobal->bNeed_connect = TRUE;
581			phglobal->bTcpUpdateSuccessed = FALSE;
582
583			if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, phglobal->cLastResult, 0);
584			return 30;
585		}
586		else
587		{
588			if (ret == okKeepAliveRecved)
589			{
590				struct in_addr t;
591				t.s_addr = phglobal->ip;
592				LOG(1) ("Keepalive response received, client ip: %s\n",inet_ntoa(t));
593				if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, phglobal->cLastResult, phglobal->ip);
594			}
595		}
596
597		if (time(0) - phglobal->tmLastResponse > get_retry_seconds(phglobal->nUserType) && phglobal->tmLastResponse != -1)
598		{
599			LOG(1) ("No response from server for %d seconds, reconnect immediately...\n", get_retry_seconds(phglobal->nUserType));
600			phglobal->bTcpUpdateSuccessed = FALSE;
601			phglobal->bNeed_connect = TRUE;
602			if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, errorRetrying, 0);
603
604			return 1;
605		}
606		else if (((time(0) - phglobal->tmLastResponse) > get_keepalive_warn_seconds(phglobal->nUserType)) && phglobal->tmLastResponse != -1)
607		{
608			//LOG(1) ("No response from server for %d seconds, keepAlive error...\n", ret);
609			if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, errorKeepAliveError, 0);
610
611			return 1;
612		}
613
614		//if (time(0) - phglobal->tmLastResponse > (phglobal->nUserType >= 1 ? 130 : 320) && phglobal->tmLastResponse != -1)
615		//{
616		//	LOG(1) ("No response from server for %d seconds, reconnect immediately...\n", (phglobal->nUserType == 1 ? 160 : 320));
617		//	phglobal->bTcpUpdateSuccessed = FALSE;
618		//	phglobal->bNeed_connect = TRUE;
619
620		//	if (phglobal->cbOnStatusChanged) phglobal->cbOnStatusChanged(phglobal, errorOccupyReconnect, 0);
621		//	return 1;
622		//}
623	}
624	return 1;
625}
626
627void phddns_stop(PHGlobal *phglobal)
628{
629	SendKeepAlive(phglobal, UDP_OPCODE_LOGOUT);
630	phglobal->tmLastSend = time(0);
631	sleep(1); //ensure data sent
632	DestroySockets(phglobal);
633}
634