Object subclass: #DynDNSClient instanceVariableNames: 'hostName ipAddress accountName accountPassword result' classVariableNames: '' poolDictionaries: '' category: 'DynDNS-Client'! !DynDNSClient commentStamp: 'cc 2/14/2009 20:16' prior: 0! DynDNSClient - I provide mechanisms for a) getting the pubic IP address of my host or PC and b) for setting a DynDNS Dynaimc IP address based on my current WAN or DHCP address, in order to deploy services in hosts without having a fixed IP. This object implements the methods to obtain the currrent IP address and setting it into a hostname inside the DynDNS pre-registered domain names. Your hostname will look like "mysqueak.dynalias.net". As an example, provided you register the name "seaside" in a public-available domain, your web app's URL may be written as "http://seaside.dynalias.org:8080/app"! !DynDNSClient methodsFor: 'initialize-release' stamp: 'cc 6/11/2008 21:33'! initialize super initialize. hostName := 'localhost'. ipAddress := ''. accountName := 'none'. accountPassword := ''. result := nil. ^ self ! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/8/2008 15:51'! accountName ^ accountName! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/8/2008 15:53'! accountName: aString accountName := aString! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/8/2008 15:51'! accountPassword ^ accountPassword! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/8/2008 15:53'! accountPassword: aString accountPassword := aString! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/8/2008 15:50'! hostName ^ hostName! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/8/2008 15:50'! hostName: aString hostName := aString! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/8/2008 21:06'! ipAddress ^ ipAddress! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/22/2008 01:09'! ipAddress: aString ipAddress := aString. self changed: #ipAddress! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 7/27/2008 18:32'! result ^result ! ! !DynDNSClient methodsFor: 'accessors' stamp: 'cc 6/9/2008 21:08'! result: anObject result := anObject! ! !DynDNSClient methodsFor: 'update' stamp: 'cc 2/14/2009 20:14'! synchronize "Determine if the current IP address got from checkip is obsoleting the DNS resolution" | ipByDns | ipByDns := self dnsResolve: self ipAdsress.! ! !DynDNSClient methodsFor: 'update' stamp: 'cc 2/14/2009 20:12'! updateIP | myIp request | myIp := self class getPublicIP. "store myIP into the object for future reference and debugging" self ipAddress: myIp. "build the GET request - as per DynDNS, the Raw Request" request := self class membersHostName , '/nic/update?hostname=', self hostName, '&myip=', self ipAddress, '&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG'. "pefrom the request over a HTTP socket, and store the result" self result: (HTTPSocket httpGet: request args: #() user: (self accountName) passwd: (self accountPassword)). "use accessors to obtain the result, otherwise an exception is raised" ^self! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 6/22/2008 01:38'! badAuth "wrong username or password" | token | token := self result contents. (token findString: 'badauth') == 1 ifTrue: [^true]. ^false! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 6/22/2008 01:39'! badHost "badhost in result" | token | token := self result contents. (token findString: 'nohost') == 1 ifTrue: [^true]. ^false! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 6/22/2008 01:47'! dnsIsDelayed ^ self inSyncWithDNS not ! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 7/27/2008 18:34'! goodOrNoChange "The update was done or the address was not changed" | token | token := self result contents. (token findString: 'good') == 1 ifTrue: [^true]. (token findString: 'nochg') == 1 ifTrue: [^true]. ^false! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 7/27/2008 18:35'! inSyncWithDNS "resolve the hostname and compare against my current IP address" | myIP ipFromDNS | myIP := self ipAddress. ipFromDNS := NetNameResolver addressForName: (self hostName). "to remove later" Transcript show: 'My IP is ', self ipAddress, ' and '; cr; show: 'DNS for ', self hostName, ' is ', ipFromDNS; cr. ! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 6/22/2008 01:42'! ipChanged "good in result" | token | token := self result contents. (token findString: 'good') == 1 ifTrue: [^true]. ^false! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 6/22/2008 01:40'! noChange "nochg in result" | token | token := self result contents. (token findString: 'nochg') == 1 ifTrue: [^true]. ^false! ! !DynDNSClient methodsFor: 'comparing' stamp: 'cc 6/22/2008 01:41'! noHost ^self badHost! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DynDNSClient class instanceVariableNames: ''! !DynDNSClient class methodsFor: 'get IP' stamp: 'cc 6/22/2008 01:22'! getMyIPAsHTML "Return my current dynamic IP address from DynDNS check IP service" ^ self checkIPHostUrl asUrl retrieveContents contents "If you are behind a broadband, DSL, or dial-up connection, evaluate the following expression to retrieve your current IP address. When you are behind a NAT firewall-router, the public IP aqcuired bu the router (by DHCP) is returned. If you are going to deploy a service in a computer that is behind NAT, you must enable IP forwarding in your router to your application listener port and protocol. Most Windows XP users have firewall enabled by default. DynDNSClient getMyIPAsHTML The output will be as follows: Current IP Check Current IP Address: "! ! !DynDNSClient class methodsFor: 'get IP' stamp: 'cc 2/14/2009 19:09'! getPublicIP | stream | stream := HTTPSocket httpGet: self checkIPHostUrl. stream upToAll: 'IP Address: '. ^ stream upTo: $< ! ! !DynDNSClient class methodsFor: 'definitions' stamp: 'cc 6/18/2008 20:26'! checkIPHostUrl "DynDNS check IP service's web server URL" ^ 'http://checkip.dyndns.org/' ! ! !DynDNSClient class methodsFor: 'definitions' stamp: 'cc 2/23/2009 21:34'! membersHostName "DynDNS members host name, all updates go through this host" ^ 'members.dyndns.com' ! ! !DynDNSClient class methodsFor: 'instance creation' stamp: 'cc 6/11/2008 22:04'! onHost: ahostName user: userName password: password "Create a DynDNSClient instance" ^ (self new initialize) hostName: ahostName; accountName: userName; accountPassword: password; yourself ! ! !DynDNSClient class methodsFor: 'documentation' stamp: 'cc 2/24/2009 21:32'! changeLog " 2/23/2009 Changed the members host name from .org to .com 2/24/2009 Decoupled from Regex package "! ! !DynDNSClient class methodsFor: 'documentation' stamp: 'cc 2/24/2009 21:33'! howTo " To learn about Dynamic DNS: www.dyndns.com (formerly www.dyndns.org) DynDNS Updater background and update method at: http://www.dyndns.com/developers/specs/syntax.html This class works with the Dynamic DNS service only, it was tested both using the provided test accounts, as well as with an account owned by the author of this class. To get your actual public IP address, point your web brwoser to http://checkip.dynnds.org Omce you loaded this class into your Squeak image, you may evaluate to retrieve your current public IP address. DynDNSClient getPublicIP You may want to just retrieve your public IP address. Later on, you may want to use the DNS to publish your web-based services, using a FQDN rather than a dynamic IP address- for that you need to register for a DynDNS account and update the DNS record with your actual IP, that may change every time you connect to your ISP. The expected output is something like '' Now, try updating a test hostname into DynDNS.org using your current IP | dns | dns := DynDNSClient onHost: 'test.dyndns.net' user: 'test' password: 'test'. dns updateIP ipAddress Try resolvinh thhat DynDNS host with ping test.dyndns.net Once you pass this test, register for a new Dynamic DNS account and retry the test using your acquired host name, and replacing the account name and password. Prerequisities: - Squeak 3.10.2, Any comments and suggestions are welcome, please contact Carlos Crosetti (carlos@mostar.com.ar) "! ! !DynDNSClient class methodsFor: 'documentation' stamp: 'cc 2/14/2009 20:12'! license " The MIT License http://www.opensource.org/licenses/mit-license.php Copyright (c) 2008 Carlos Crosetti, released under the MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. "! !