?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * Dynamic DNS Client Module
4 * Reference: DNS Update API Version 2.0.3 (www.dyndns.com)
5 *
6 *********************************************************************
7 * FileName: DynDNS.c
8 * Dependencies: TCP, Tick
9 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
10 * Compiler: Microchip C32 v1.05 or higher
11 * Microchip C30 v3.12 or higher
12 * Microchip C18 v3.30 or higher
13 * HI-TECH PICC-18 PRO 9.63PL2 or higher
14 * Company: Microchip Technology, Inc.
15 *
16 * Software License Agreement
17 *
18 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
19 * reserved.
20 *
21 * Microchip licenses to you the right to use, modify, copy, and
22 * distribute:
23 * (i) the Software when embedded on a Microchip microcontroller or
24 * digital signal controller product ("Device") which is
25 * integrated into Licensee's product; or
26 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
27 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
28 * used in conjunction with a Microchip ethernet controller for
29 * the sole purpose of interfacing with the ethernet controller.
30 *
31 * You should refer to the license agreement accompanying this
32 * Software for additional information regarding your rights and
33 * obligations.
34 *
35 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
36 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
37 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
38 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
39 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
40 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
41 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
42 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
43 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
44 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
45 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
46 *
47 *
48 * Author Date Comment
49 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50 * Amit Shirbhate 3/24/08 Original
51 ********************************************************************/
52 #ifndef __DYNDNSCLIENT_C
53 #define __DYNDNSCLIENT_C
54  
55 #include "TCPIPConfig.h"
56  
57 #if defined STACK_USE_DYNAMICDNS_CLIENT
58  
59 #include "TCPIP Stack/TCPIP.h"
60  
61 // Delimiter to locate IP address from CheckIP server
62 static ROM BYTE _checkIpSrvrResponse[] = "Address:";
63  
64 // Response codes from DynDNS Update Server
65 static ROM char* _updateIpSrvrResponse[] =
66 {
67 /* 0 */ "good", // Update was successful
68 /* 1 */ "nochg", // No change was made; request is considered abusive
69 /* 2 */ "abuse", // Account has been blocked for abuse
70 /* 3 */ "badsys", // System is not supported
71 /* 4 */ "badagent", // Agent has been blocked for abuse
72 /* 5 */ "badauth", // Authentication failed
73 /* 6 */ "!donator", // A paid account feature was requested on a free account
74 /* 7 */ "notfqdn", // Hostname was not a fully-qualified domain name
75 /* 8 */ "nohost", // Host name was not found in the system
76 /* 9 */ "!yours", // The specified hostname does not belong to this account
77 /* 10 */ "numhost", // Number of hosts does not match / serious error
78 /* 11 */ "dnserr", // System error was encountered, try again soon
79 /* 12 */ "911", // System error was encountered, try again later
80 };
81  
82 /****************************************************************************
83 Section:
84 Dynamic DNS Services
85 These services must support the DynDNS API, and correspond to
86 DDNS_SERVICES enumeration
87 ***************************************************************************/
88  
89 // Host names for various Dynamic DNS services
90 ROM char * ROM ddnsServiceHosts[] =
91 {
92 "members.dyndns.org", // DYNDNS_ORG
93 "dynupdate.no-ip.com", // NO_IP_COM
94 "updates.dnsomatic.com", // DNSOMATIC_COM
95 };
96  
97 // Port numbers for various Dynamic DNS services
98 static ROM WORD ddnsServicePorts[] =
99 {
100 80, // DYNDNS_ORG
101 80, // NO_IP_COM
102 80, // DNSOMATIC_COM
103 };
104  
105 /****************************************************************************
106 Section:
107 Global Variables
108 ***************************************************************************/
109 static IP_ADDR lastKnownIP; // Last known IP address of this device
110 static DDNS_STATUS lastStatus; // Status response from last update
111  
112 DDNS_POINTERS DDNSClient; // Configuration parameters for the module
113  
114 static DWORD dwUpdateAt; // Indicates when the next CheckIP should be done
115 static BOOL bForceUpdate; // Indicates that the update should be done regardless
116 // of whether or not the IP changed. Use this flag
117 // when the user/pass/hostname have changed.
118  
119 /****************************************************************************
120 Function:
121 void DDNSInit(void)
122  
123 Summary:
124 Initializes the Dynamic DNS module.
125  
126 Description:
127 This function initializes the Dynamic DNS client. It clears the
128 DDNSClient pointers structure, and tells the module to attempt the
129 first update after 15 seconds have elapsed (so as to allow the DHCP
130 configuration to stabalize).
131  
132 Precondition:
133 None
134  
135 Parameters:
136 None
137  
138 Returns:
139 None
140  
141 Remarks:
142 This function is called only one during lifetime of the application.
143 ***************************************************************************/
144 void DDNSInit(void)
145 {
146 // Clear the Dynamic DNS Client to start
147 memset((void*)&DDNSClient, 0x00, sizeof(DDNSClient));
148  
149 // Use the default Check IP server
150 DDNSClient.ROMPointers.CheckIPServer = 1;
151 DDNSClient.CheckIPServer.szROM = DDNS_CHECKIP_SERVER;
152 DDNSClient.CheckIPPort = DDNS_DEFAULT_PORT;
153  
154 // First update is 15 seconds after boot, allowing DHCP to stabilize
155 dwUpdateAt = TickGet() + 15*TICK_SECOND;
156 bForceUpdate = TRUE;
157 lastStatus = DDNS_STATUS_UNKNOWN;
158 }
159  
160 /****************************************************************************
161 Function:
162 void DDNSTask(void)
163  
164 Summary:
165 Dynamic DNS client task/state machine.
166  
167 Description:
168 This function performs the background tasks of the Dynamic DNS Client.
169 Once the DDNSPointers structure is configured, this task attempt to
170 update the Dynamic DNS hostname on a periodic schedule.
171  
172 The task first accesses the CheckIP server to determine the device's
173 current external IP address. If the IP address has changed, it
174 issues an update command to the dynamic DNS service to propagate the
175 change. This sequence executes whenever dwUpdateAt elapses, which by
176 default is every 10 minutes, or when an update is forced.
177  
178 Precondition:
179 DDNSInit() has been called.
180  
181 Parameters:
182 None
183  
184 Returns:
185 None
186  
187 Remarks:
188 This function acts as a task (similar to one in an RTOS). It
189 performs its task in a co-operative manner, and the main application
190 must call this function periodically to ensure that its tasks get
191 executed in a timely fashion.
192 ***************************************************************************/
193 void DDNSTask(void)
194 {
195 BYTE i;
196 static DWORD Timer;
197 static TCP_SOCKET MySocket = INVALID_SOCKET;
198 static char ROM * ROMStrPtr;
199 static char * RAMStrPtr;
200  
201 static BYTE vBuffer[16];
202 WORD wPos;
203 static IP_ADDR ipParsed;
204  
205 static enum
206 {
207 SM_IDLE = 0u,
208 SM_BEGIN_CHECKIP, //0x1
209 SM_CHECKIP_SKT_OBTAINED, //0x2
210 SM_CHECKIP_FIND_DELIMITER, //0x3
211 SM_CHECKIP_FIND_ADDRESS, //0x4
212 SM_CHECKIP_DISCONNECT, //0x5
213 SM_IP_UPDATE_HOME, //0x6
214 SM_IP_UPDATE_SKT_OBTAINED, //0x7
215  
216 /*
217 HTTP request msg is divided into 6 parts
218 SM_IP_UPDATE_REQ_A,B,C,D,E,F as the tcp ip tx
219 buffer is only able to carry 200 bytes at a time.
220 */
221  
222 SM_IP_UPDATE_REQ_A, //0x8
223 SM_IP_UPDATE_REQ_B, //0x9
224 SM_IP_UPDATE_REQ_C, //0xa
225 SM_IP_UPDATE_REQ_D, //0xb
226 SM_IP_UPDATE_REQ_E, //0xc
227 SM_IP_UPDATE_REQ_F, //0xd
228  
229 SM_IPUPDATE_FIND_RESPONSE, //0xe
230 SM_IPUPDATE_PARSE_RESPONSE, //0xf
231 SM_IPUDATE_DISCONNECT, //0x10
232 SM_DONE, // Done, try again in 10 minutes
233 SM_SOFT_ERROR, // Soft error, try again in 30 seconds
234 SM_SYSTEM_ERROR // System error, try again in 30 minutes
235 } smDDNS = SM_IDLE;
236  
237 switch(smDDNS)
238 {
239 case SM_IDLE:
240  
241 // Wait for timeout to begin IP check
242 if((LONG)(TickGet() - dwUpdateAt) < 0)
243 break;
244  
245 // Otherwise, continue to next state
246 smDDNS = SM_BEGIN_CHECKIP;
247  
248 case SM_BEGIN_CHECKIP:
249  
250 // If a fatal error has occurred, abort to the SM_DONE state and keep
251 // the error message.
252 if(lastStatus >= DDNS_STATUS_ABUSE && lastStatus <= DDNS_STATUS_911)
253 {
254 smDDNS = SM_DONE;
255 break;
256 }
257  
258 // If DDNSClient is not properly configured, abort
259 if(
260 // Verify that each pointer is not null, and is not empty
261 (DDNSClient.ROMPointers.Host && (!DDNSClient.Host.szROM || *DDNSClient.Host.szROM == '\0') ) ||
262 (!DDNSClient.ROMPointers.Host && (!DDNSClient.Host.szRAM || *DDNSClient.Host.szRAM == '\0') ) ||
263 (DDNSClient.ROMPointers.Username && (!DDNSClient.Username.szROM || *DDNSClient.Username.szROM == '\0') ) ||
264 (!DDNSClient.ROMPointers.Username && (!DDNSClient.Username.szRAM || *DDNSClient.Username.szRAM == '\0') ) ||
265 (DDNSClient.ROMPointers.Password && (!DDNSClient.Password.szROM || *DDNSClient.Password.szROM == '\0') ) ||
266 (!DDNSClient.ROMPointers.Password && (!DDNSClient.Password.szRAM || *DDNSClient.Password.szRAM == '\0') ) ||
267 (DDNSClient.ROMPointers.CheckIPServer && (!DDNSClient.CheckIPServer.szROM || *DDNSClient.CheckIPServer.szROM == '\0') ) ||
268 (!DDNSClient.ROMPointers.CheckIPServer && (!DDNSClient.CheckIPServer.szRAM || *DDNSClient.CheckIPServer.szRAM == '\0') ) ||
269 (DDNSClient.ROMPointers.UpdateServer && (!DDNSClient.UpdateServer.szROM || *DDNSClient.UpdateServer.szROM == '\0') ) ||
270 (!DDNSClient.ROMPointers.UpdateServer && (!DDNSClient.UpdateServer.szRAM || *DDNSClient.UpdateServer.szRAM == '\0') )
271 )
272 {
273 smDDNS = SM_SOFT_ERROR;
274 lastStatus = DDNS_STATUS_INVALID;
275 break;
276 }
277  
278 // Start with an invalidated IP String
279 vBuffer[0] = '\0';
280  
281 // Connect a socket to the remote server
282 if(DDNSClient.ROMPointers.CheckIPServer)
283 {
284 MySocket = TCPOpen((DWORD)(ROM_PTR_BASE)DDNSClient.CheckIPServer.szROM, TCP_OPEN_ROM_HOST,
285 DDNSClient.CheckIPPort, TCP_PURPOSE_DEFAULT);
286 }
287 else
288 {
289 MySocket = TCPOpen((DWORD)(PTR_BASE)DDNSClient.CheckIPServer.szRAM, TCP_OPEN_RAM_HOST,
290 DDNSClient.CheckIPPort, TCP_PURPOSE_DEFAULT);
291 }
292  
293 // If no socket available, try again on next loop
294 if(MySocket == INVALID_SOCKET)
295 break;
296  
297 smDDNS++;
298 Timer = TickGet();
299 break;
300  
301 case SM_CHECKIP_SKT_OBTAINED:
302  
303 // Wait for the remote server to accept our connection request
304 if(!TCPIsConnected(MySocket))
305 {
306 // Time out if too much time is spent in this state
307 if(TickGet()-Timer > 6*TICK_SECOND)
308 {
309 // Close the socket so it can be used by other modules
310 // We will retry soon
311 TCPDisconnect(MySocket);
312 MySocket = INVALID_SOCKET;
313 lastStatus = DDNS_STATUS_CHECKIP_ERROR;
314 smDDNS = SM_SOFT_ERROR;
315 }
316 break;
317 }
318  
319 Timer = TickGet();
320  
321 // Make certain the socket can be written to
322 if(TCPIsPutReady(MySocket) < 125u)//125 = size of TCP Tx buffer
323 break;
324  
325 // Transmit the request to the server
326 TCPPutROMString(MySocket, (ROM BYTE*)"GET / HTTP/1.0\r\nHost: ");
327  
328 if(DDNSClient.ROMPointers.CheckIPServer)
329 {
330 TCPPutROMString(MySocket, DDNSClient.CheckIPServer.szROM);
331 }
332 else
333 {
334 TCPPutString(MySocket, DDNSClient.CheckIPServer.szRAM);
335 }
336  
337 TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n");
338  
339 // Send the packet
340 TCPFlush(MySocket);
341 smDDNS++;
342 break;
343  
344 case SM_CHECKIP_FIND_DELIMITER:
345  
346 // Check if remote node is still connected. If not, force to the disconnect state,
347 // but don't break because data may still be waiting.
348 if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND)
349 smDDNS = SM_CHECKIP_DISCONNECT;
350  
351 // Search out the "Address: " delimiter in the response
352 wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"Address: ", 9, 0, FALSE);
353  
354 // If not yet found, clear as much as possible and break
355 if(wPos == 0xffff)
356 {
357 wPos = TCPIsGetReady(MySocket);
358 if(wPos > 9u)
359 TCPGetArray(MySocket, NULL, wPos - 9);
360 break;
361 }
362  
363 // Clear up to and past that string
364 TCPGetArray(MySocket, NULL, wPos + 9);
365  
366 // Continue on to read the IP
367 Timer = TickGet();
368 smDDNS++;
369  
370 case SM_CHECKIP_FIND_ADDRESS:
371  
372 // Check if remote node is still connected. If not, force to the disconnect state,
373 // but don't break because data may still be waiting.
374 if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND)
375 smDDNS = SM_CHECKIP_DISCONNECT;
376  
377 // Search out the "</body>" delimiter in the response
378 wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"</body>", 7, 0, FALSE);
379  
380 // If not yet found, break
381 if(wPos == 0xffff)
382 break;
383  
384 // Read and terminate that string as the IP address (preventing buffer overflows)
385 if(wPos > 15u)
386 wPos = 15;
387 TCPGetArray(MySocket, vBuffer, wPos);
388 vBuffer[wPos] = '\0';
389  
390 // Parse the IP address that was read, invalidating on failure
391 if(!StringToIPAddress(vBuffer, &ipParsed))
392 vBuffer[0] = '\0';
393  
394 // Continue on to close the socket
395  
396 case SM_CHECKIP_DISCONNECT:
397  
398 // Close the socket
399 TCPDisconnect(MySocket);
400 MySocket = INVALID_SOCKET;
401  
402 // Determine if an update is necessary
403 if(vBuffer[0] == '\0')
404 {// CheckIP Failed
405 lastStatus = DDNS_STATUS_CHECKIP_ERROR;
406 smDDNS = SM_SOFT_ERROR;
407 break;
408 }
409  
410 if( (ipParsed.Val ==lastKnownIP.Val) && (!bForceUpdate))
411 {
412 // IP address has not changed and no update is forced
413 lastStatus = DDNS_STATUS_UNCHANGED;
414 smDDNS = SM_DONE;
415 break;
416 }
417  
418 // Need to perform an update
419 lastKnownIP = ipParsed;
420 bForceUpdate = FALSE;
421 smDDNS++;
422 break;
423  
424 case SM_IP_UPDATE_HOME:
425  
426 // Connect a socket to the remote server
427 if(DDNSClient.ROMPointers.UpdateServer)
428 {
429 MySocket = TCPOpen((DWORD)(ROM_PTR_BASE)DDNSClient.UpdateServer.szROM, TCP_OPEN_ROM_HOST,
430 DDNSClient.UpdatePort, TCP_PURPOSE_DEFAULT);
431 }
432 else
433 {
434 MySocket = TCPOpen((DWORD)(PTR_BASE)DDNSClient.UpdateServer.szRAM, TCP_OPEN_RAM_HOST,
435 DDNSClient.UpdatePort, TCP_PURPOSE_DEFAULT);
436 }
437  
438 // If no socket is available, try again on the next loop
439 if(MySocket == INVALID_SOCKET)
440 break;
441  
442 // Move on to the next state
443 smDDNS++;
444 Timer = TickGet();
445 break;
446  
447 case SM_IP_UPDATE_SKT_OBTAINED:
448  
449 // Wait for the remote server to accept our connection request
450 if(!TCPIsConnected(MySocket))
451 {
452 // Time out if too much time is spent in this state
453 if(TickGet() - Timer > 6*TICK_SECOND)
454 {
455 // Close the socket so it can be used by other modules
456 // We will try again immediately
457 TCPDisconnect(MySocket);
458 MySocket = INVALID_SOCKET;
459 lastStatus = DDNS_STATUS_UPDATE_ERROR;
460 smDDNS--;
461 }
462 break;
463 }
464  
465 // Reset timer and begin sending the request
466 Timer = TickGet();
467 smDDNS++;
468 // No break needed...try to send first bit immediately.
469  
470 case SM_IP_UPDATE_REQ_A:
471  
472 // Check for lost connections or timeouts
473 if(!TCPIsConnected(MySocket) || (TickGet() - Timer > 10*TICK_SECOND))
474 {
475 lastStatus = DDNS_STATUS_UPDATE_ERROR;
476 smDDNS = SM_IPUDATE_DISCONNECT;
477 break;
478 }
479  
480 if(TCPIsPutReady(MySocket) < 25u) // 25 =~ 16+9
481 break;
482  
483 TCPPutROMString(MySocket, (ROM BYTE*)"GET /nic/update?hostname=");
484 smDDNS++;
485 // No break needed...try to send next bit immediately.
486  
487 case SM_IP_UPDATE_REQ_B:
488  
489 // Check for lost connections or timeouts
490 if(!TCPIsConnected(MySocket) || (TickGet() - Timer > 10*TICK_SECOND))
491 {
492 lastStatus = DDNS_STATUS_UPDATE_ERROR;
493 smDDNS = SM_IPUDATE_DISCONNECT;
494 break;
495 }
496  
497 // Try to write, verifying that space is available first
498 if(DDNSClient.ROMPointers.Host)
499 {
500 if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)DDNSClient.Host.szROM))
501 break;
502 TCPPutROMString(MySocket,DDNSClient.Host.szROM);
503 }
504 else
505 {
506 if(TCPIsPutReady(MySocket) < strlen((char*)DDNSClient.Host.szRAM))
507 break;
508 TCPPutString(MySocket,DDNSClient.Host.szRAM);
509 }
510  
511 smDDNS++;
512 // No break needed...try to send next bit immediately.
513  
514 case SM_IP_UPDATE_REQ_C:
515  
516 // Check for lost connections or timeouts
517 if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND)
518 {
519 lastStatus = DDNS_STATUS_UPDATE_ERROR;
520 smDDNS = SM_IPUDATE_DISCONNECT;
521 break;
522 }
523  
524 if(TCPIsPutReady(MySocket) < 70u)
525 break;
526  
527 TCPPutROMString(MySocket, (ROM BYTE*)"&myip=");
528 TCPPutString(MySocket, vBuffer);
529 TCPPutROMString(MySocket, (ROM BYTE*)"&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG HTTP/1.0");
530  
531 TCPFlush(MySocket);
532 smDDNS++;
533 // No break needed...try to send next bit immediately.
534  
535 case SM_IP_UPDATE_REQ_D:
536  
537 // Check for lost connections or timeouts
538 if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND)
539 {
540 lastStatus = DDNS_STATUS_UPDATE_ERROR;
541 smDDNS = SM_IPUDATE_DISCONNECT;
542 break;
543 }
544  
545 if(TCPIsPutReady(MySocket) < 131u) // 131 =~ 8+23 + dynamic dns server hostname
546 break;
547  
548 TCPPutROMString(MySocket, (ROM BYTE*)"\r\nHost: ");//8
549  
550 if(DDNSClient.ROMPointers.UpdateServer)
551 TCPPutROMString(MySocket,DDNSClient.UpdateServer.szROM);
552 else
553 TCPPutString(MySocket,DDNSClient.UpdateServer.szRAM);
554  
555 TCPPutROMString(MySocket, (ROM BYTE*)"\r\nAuthorization: Basic ");//23
556  
557 TCPFlush(MySocket);
558 smDDNS++;
559 // No break needed...try to send the next bit immediately.
560  
561 case SM_IP_UPDATE_REQ_E:
562  
563 // Check for lost connections or timeouts
564 if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND)
565 {
566 lastStatus = DDNS_STATUS_UPDATE_ERROR;
567 smDDNS = SM_IPUDATE_DISCONNECT;
568 break;
569 }
570  
571 // User name and passwords for DynDNS.org can each be up to 24 characters
572 // Base64 encoded data is always at least 25% bigger than the original
573 if(TCPIsPutReady(MySocket) < 100u)
574 break;
575  
576 if(DDNSClient.ROMPointers.Username)
577 {
578 ROMStrPtr = (ROM char*)DDNSClient.Username.szROM;
579 wPos = strlenpgm(ROMStrPtr);
580 }
581 else
582 {
583 RAMStrPtr = (char*)DDNSClient.Username.szRAM;
584 wPos = strlen((char*)RAMStrPtr);
585 }
586  
587 i = 0;
588 while(wPos)
589 {
590 while(i < wPos && i < 3u)
591 {
592 if(DDNSClient.ROMPointers.Username)
593 vBuffer[i] = *ROMStrPtr++;
594 else
595 vBuffer[i] = *RAMStrPtr++;
596 i++;
597 }
598 wPos -= i;
599  
600 if(i == 3u)
601 {
602 Base64Encode(vBuffer, i, vBuffer, 4);
603 TCPPutArray(MySocket, vBuffer, 4);
604 i = 0;
605 }
606 }
607  
608 if(DDNSClient.ROMPointers.Password)
609 {
610 ROMStrPtr = (ROM char*)DDNSClient.Password.szROM;
611 wPos = strlenpgm(ROMStrPtr);
612 }
613 else
614 {
615 RAMStrPtr = (char*)DDNSClient.Password.szRAM;
616 wPos = strlen((char*)RAMStrPtr);
617 }
618  
619 // Increment for the ':' separator and i for bytes left in username
620 wPos += i + 1;
621  
622 vBuffer[i++] = ':';
623  
624 while(wPos)
625 {
626 while(i < wPos && i < 3u)
627 {
628 if(DDNSClient.ROMPointers.Password)
629 vBuffer[i] = *ROMStrPtr++;
630 else
631 vBuffer[i] = *RAMStrPtr++;
632 i++;
633 }
634 wPos -= i;
635 Base64Encode(vBuffer, i, vBuffer, 4);
636 TCPPutArray(MySocket, vBuffer, 4);
637 i = 0;
638 }
639  
640 TCPFlush(MySocket);
641 smDDNS++;
642 break;
643  
644  
645 case SM_IP_UPDATE_REQ_F:
646  
647 // Check for lost connections or timeouts
648 if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND)
649 {
650 lastStatus = DDNS_STATUS_UPDATE_ERROR;
651 smDDNS = SM_IPUDATE_DISCONNECT;
652 break;
653 }
654  
655 if(TCPIsPutReady(MySocket) < 50u)
656 break;
657  
658 TCPPutROMString(MySocket, (ROM BYTE*)"\r\nUser-Agent: Microchip - TCPIPSTACK - "TCPIP_STACK_VERSION"\r\n\r\n");
659 TCPFlush(MySocket);
660 smDDNS++;
661  
662 // Reset the timer to wait for a response
663 Timer = TickGet();
664 break;
665  
666 case SM_IPUPDATE_FIND_RESPONSE:
667 // Locate the response string
668  
669 // Wait up to 10 seconds for a response
670 if(TickGet() - Timer > 10*TICK_SECOND)
671 {
672 lastStatus = DDNS_STATUS_UPDATE_ERROR;
673 smDDNS = SM_IPUDATE_DISCONNECT;
674 break;
675 }
676  
677 // According to HTTP, the response will start after the two CRLFs
678 wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"\r\n\r\n", 4, 0, FALSE);
679  
680 // If not yet found, eliminate everything up to
681 if(wPos == 0xffff)
682 {
683 wPos = TCPIsGetReady(MySocket);
684 if(wPos > 4u)
685 TCPGetArray(MySocket, NULL, wPos - 4);
686 break;
687 }
688  
689 TCPGetArray(MySocket, NULL, wPos+4);
690 smDDNS++;
691 // No break...continue to next state immediately
692  
693 case SM_IPUPDATE_PARSE_RESPONSE:
694 // Try to parse the response text
695  
696 // Wait up to 10 seconds for the remote server to disconnect
697 // so we know all data has been received
698 if(TCPIsConnected(MySocket) && TickGet() - Timer < 10*TICK_SECOND)
699 break;
700  
701 // Read the response code
702 wPos = TCPIsGetReady(MySocket);
703 if(wPos > sizeof(vBuffer) - 1)
704 wPos = sizeof(vBuffer) - 1;
705  
706 wPos = TCPGetArray(MySocket, vBuffer, wPos);
707 vBuffer[wPos] = '\0';
708 for(i = 0; i < sizeof(vBuffer); i++)
709 if(vBuffer[i] == ' ')
710 vBuffer[i] = '\0';
711  
712 for(lastStatus = 0; lastStatus <= DDNS_STATUS_UPDATE_ERROR; lastStatus++)
713 if(!strcmppgm2ram((char*)vBuffer, (ROM char*)_updateIpSrvrResponse[lastStatus]))
714 break;
715  
716 smDDNS++;
717 // No break...continue to finalization
718  
719 case SM_IPUDATE_DISCONNECT:
720 // Close the socket so it can be used by other modules.
721 if(MySocket != INVALID_SOCKET)
722 {
723 TCPDisconnect(MySocket);
724 MySocket = INVALID_SOCKET;
725 }
726  
727 // Determine what to do based on status
728 if(lastStatus <= DDNS_STATUS_NUMHOST || lastStatus == DDNS_STATUS_UNCHANGED)
729 smDDNS = SM_DONE;
730 else if(lastStatus == DDNS_STATUS_911 || lastStatus == DDNS_STATUS_DNSERR)
731 smDDNS = SM_SYSTEM_ERROR;
732 else
733 smDDNS = SM_SOFT_ERROR;
734  
735 smDDNS++;
736 break;
737  
738 case SM_DONE:
739 dwUpdateAt = TickGet() + 10*60*TICK_SECOND; // 10 minutes
740 smDDNS = SM_IDLE;
741 break;
742  
743 case SM_SOFT_ERROR:
744 dwUpdateAt = TickGet() + 30*TICK_SECOND; // 30 seconds
745 smDDNS = SM_IDLE;
746 break;
747  
748 case SM_SYSTEM_ERROR:
749 dwUpdateAt = TickGet() + 30*60*TICK_SECOND; // 30 minutes
750 smDDNS = SM_IDLE;
751 break;
752 }
753 }
754  
755 /*****************************************************************************
756 Function:
757 void DDNSForceUpdate(void)
758  
759 Summary:
760 Forces an immediate DDNS update
761  
762 Description:
763 This function forces the DDNS Client to execute a full update
764 immediately. Any error message is cleared, and the update will be
765 executed whether the IP address has changed or not. Call this
766 function every time the DDNSClient parameters have been modified.
767  
768 Precondition:
769 DDNSInit must have been called.
770  
771 Parameters:
772 None
773  
774 Returns:
775 None
776 ***************************************************************************/
777 void DDNSForceUpdate(void)
778 {
779 // Force update on next DDNSClient call
780 dwUpdateAt = TickGet();
781 bForceUpdate = TRUE;
782 lastStatus = DDNS_STATUS_UNKNOWN;
783 }
784  
785 /*****************************************************************************
786 Function:
787 void DDNSSetService(DDNS_SERVICES svc)
788  
789 Summary:
790 Selects a pre-configured Dynamic DNS service
791  
792 Description:
793 This function selects a Dynamic DNS service based on parameters
794 configured in ddnsServiceHosts and ddnsServicePorts. These arrays
795 must match the DDNS_SERVICES enumeration.
796  
797 Precondition:
798 None
799  
800 Parameters:
801 svc - one of the DDNS_SERVICES elements to indicate the selected service
802  
803 Returns:
804 None
805 ***************************************************************************/
806 void DDNSSetService(DDNS_SERVICES svc)
807 {
808 DDNSClient.ROMPointers.UpdateServer = 1;
809 DDNSClient.UpdateServer.szROM = (ROM BYTE*)ddnsServiceHosts[svc];
810 DDNSClient.UpdatePort = ddnsServicePorts[svc];
811 }
812  
813  
814 /*****************************************************************************
815 Function:
816 IP_ADDR DDNSGetLastIP(void)
817  
818 Summary:
819 Returns the last known external IP address of the device.
820  
821 Description:
822 This function returns the last known external IP address of the device.
823  
824 Precondition:
825 None
826  
827 Parameters:
828 None
829  
830 Returns:
831 The last known external IP address of the device.
832 ***************************************************************************/
833 IP_ADDR DDNSGetLastIP(void)
834 {
835 return lastKnownIP;
836 }
837  
838  
839  
840 /*****************************************************************************
841 Function:
842 DDNS_STATUS DDNSGetLastStatus(void)
843  
844 Summary:
845 Returns the status of the most recent update.
846  
847 Description:
848 This function returns the status of the most recent update. See the
849 DDNS_STATUS enumeration for possible codes.
850  
851 Precondition:
852 None
853  
854 Parameters:
855 None
856  
857 Returns:
858 DDNS_STATUS indicating the status code for the most recent update.
859 ***************************************************************************/
860  
861 DDNS_STATUS DDNSGetLastStatus(void)
862 {
863 return lastStatus;
864 }
865  
866 #endif //STACK_USE_DYNAMICDNS_CLIENT
867 #endif //__DYNDNSCLIENT_C
868  
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3