no-ip and Arduino Ethernet Shield

I would like to have my Arduino update my no-ip host. I have created this code based on the API published by no-ip: http://www.no-ip.com/integrate/request/

Below is my code and the output on the serial monitor. According to the no-ip API documentation, the server should provide a response, but I have been unable to get one. I believe my mistake must be somewhere in the http get request or in reading the response. Any help is appreciated. I would just like to be able to get a response, even if it is an error response.

Code:

#include <SPI.h>
#include <Ethernet.h>

byte mac = { 0x90, 0xA2, 0xDA, 0x00, 0x04, 0x16 };
char noipServer = “https://dynupdate.no-ip.com”;

EthernetClient client;

void setup() {
Serial.begin(9600);
if (Ethernet.begin(mac) == 0) {
Serial.println(“Failed to configure Ethernet using DHCP”);
// no point in carrying on, so do nothing forevermore:
while(true);
}

//Give time to initilize:
delay(2000);

if(client.connect(noipServer, 80)){
Serial.println(“Connected to noip”);

client.println(“GET /nic/update?hostname=johndoe.no-ip.org HTTP/1.0”);
client.println(“Host: dynupdate.no-ip.com”);
client.println(“Authorization: john.doe@gmail.com:mypassword”);
client.println(“User-Agent: Johns Arduino Client/0.0 john.doe@gmail.com”);
client.println();

//Wait for response
delay(5000);
Serial.print("Characters available: ");
Serial.println(client.available());

while(client.available() > 0)
{
char read_char = client.read();
Serial.print(read_char);
}
}
}

void loop() {

}

Output:

Connected to noip
Characters available: 0

You are not waiting for the server to respond correctly. Try this.

//Wait for response

   while(client.connected())
   {    
      // stay in this loop until the server closes the connection

       while(client.available())
       {
         // The server will not close the connection until it has sent the last packet
         // and this buffer is empty

         char read_char = client.read(); 
         Serial.write(read_char);
       }
   }
   // close your end after the server closes its end
   client.stop();

interesting - bookmarked!

I'm testing the no-ip update protocol, but have not received a status reply from the no-ip server.

I don't have an ethernet shield so forgive me if my info is redundant or irrelevant. If your ultimate goal is just making your dynamic IP behave as static by using a dynamic DNS service then you can also use dnsexit.com.

This url has to be accessed by the device whose current IP you want to reflect on the DNS. The user just has to open the following url

http://www.dnsexit.com/RemoteUpdate.sv?login=youUsername&password=yourPassword&host=rourHostName&myip=

I changed my code to reflect SuferTim's suggestion, but it still did not work. The server terminated the connection without sending anything back. I might have to contact no-ip support and figure out what is going on.

I tried putting this into the URL bar on my browser: https://dynupdate.no-ip.com/nic/update?hostname=johndoe.no-ip.org HTTP/1.0

(With my actual host name of course) And I was presented with a prompt for a user name and password. After entering that I was given a blank webpage with one of their response codes on it. The code was "nohost" which I thought was odd because I provided the proper info. But at least I got a response.

I am not an HTTP expert though, zoomkat, maybe you could try this? Maybe you will see something that I overlooked because I don't really know what I am doing.

EDIT: braindamage posted while I was writing this post. Thanks for the link. I will check it out. That sounds a lot easier.

Here is a link to the developer's doc of dnsexit http://downloads.dnsexit.com/ipUpdate.doc. Maybe you can find some more info here

I did not notice at first, but you will not get a response because the web client/server code does not support SSL (port 443) connections. https://dynupdate.no-ip.com/nic/update?hostname=johndoe.no-ip.org

first, noipServer should just be dynupdate.no-ip.com, you don’t need the https part.

second, from the protocol description, you need to send this

GET /nic/update?hostname=mytest.testdomain.com&myip=1.2.3.4 HTTP/1.0
Host: dynupdate.no-ip.com
Authorization: Basic base64-encoded-auth-string
User-Agent: Bobs Update Client WindowsXP/1.2 bob@somedomain.com

note the Authorization header MUST be base64 or UUencoded. You are sending in clear text. You need to search for code to do the encoding and add it to your program.

jerry

note the Authorization header MUST be base64 or UUencoded. You are sending in clear text.

Then why does the no-ip api page say the below? Also the "&myip=1.2.3.4" may cause a failure if an inappropriate IP address is used. Probably best left off.

"base64-encoded-auth-string should be the base64 encoding of username:password. Un-encoded strings are accepted as well."

That is exactly what I am saying, the authorization header string must be base64 or uu encoded.

http://www.w3.org/Protocols/HTTP/1.0/spec.html#BasicAA

myip is optional because the server can figure out your ip from the socket object.

That is exactly what I am saying, the authorization header string must be base64 or uu encoded.

Hmmm, in my world there is a distinct difference between "Un-encoded" and "uu encoded". In the real technical world assuming they are the same is why airplanes fall out of the sky and such.

ok. gotcha. I stand corrected.

Some of the stuff on the no-ip page just doesn't make scense, like the below statement.

An example update request string http://username:password@dynupdate.no-ip.com/nic/update? hostname=mytest.testdomain.com&myip=1.2.3.4

This is from another thread. Maybe that will help.

johnwasser:
Your authentication should look something like this:

client.write(

“GET /camera_control.cgi?user=user&password=password&command= HTTP/1.0\r\n”
“Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n”
“\r\n”);




You can use this website to encode your USERNAME:PASSWORD in base64:

http://www.opinionatedgeek.com/dotnet/tools/base64encode/

For this example, "Aladdin:open sesame" has been encoded as "QWxhZGRpbjpvcGVuIHNlc2FtZQ==".

zoomkat:
Some of the stuff on the no-ip page just doesn’t make scense, like the below statement.

An example update request string
http://username:password@dynupdate.no-ip.com/nic/update?
hostname=mytest.testdomain.com&myip=1.2.3.4

that means you enter that URL via a browser.

if you connect using your own program, then you need to break down that url to the components as per http protocol.
connect to host dynupdate.no-ip.com port 80
send the URI /nic/update?hostname=mytest…
send the rest of http protocol header, host, authorization, user-agent, etc.

the browser simply does all that in its program for you.

ok, I finally got a few minutes to do a quick test.

This code works (you need to replace the hostname and the encoded username:password with your values of course)

/*
  Web client
 
 This sketch connects to a website (http://www.google.com)
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 18 Dec 2009
 by David A. Mellis
 
modified for no-ip client example
by Jerry Sy aka doughboy
 */

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

void setup() {
  // start the serial library:
  Serial.begin(9600);
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect("dynupdate.no-ip.com", 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    //replace yourhost.no-ip.org with your no-ip hostname
    client.println("GET /nic/update?hostname=yourhhost.no-ip.org HTTP/1.0");
    client.println("Host: dynupdate.no-ip.com");
    //encode your username:password (make sure colon is between username and password) 
    //to base64 at http://www.opinionatedgeek.com/dotnet/tools/base64encode/
    //and replace the string below after Basic with your encoded string
    //clear text username:password is not accepted
    client.println("Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="); 
    client.println("User-Agent: Arduino Sketch/1.0 user@host.com");
    client.println();
  } 
  else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop()
{
  // if there are incoming bytes available 
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    for(;;)
      ;
  }
}

this is my serial monitor output (not my real ip address), result is nochg, meaning my ip address did not change

connecting...
connected
HTTP/1.1 200 OK
Date: Sat, 10 Mar 2012 01:37:40 GMT
Server: Apache/2
Content-Location: update.php
Vary: negotiate
TCN: choice
Content-Length: 20
Connection: close
Content-Type: text/plain; charset=UTF-8

nochg 50.131.456.123
disconnecting.

FWIW, un-encoded clear text password does not work.

Hope this helps.
Jerry

that means you enter that URL via a browser.

The example no-ip header code works, so I'll have to see what is different in what I tried that doesn't work. I'm still curous about the browser url method below. I can't get it to work with my data, as the "username:password@dynupdate" part seems to possibly cause a DNS lookup failure or confuses IE.

http://username:password@dynupdate.no-ip.com/nic/update?hostname=mytest.testdomain.com&myip=1.2.3.4

try this (I only tested on Chrome browser, I imagine this should work in firefox as well)

http://“username:password”@dynupdate.no-ip.com/nic/update?hostname=

that works for me, it returns
nochg

This is a fairly common URL format for ftp protocol, like when downloading files via ftp from a secured ftp server you can enter

ftp://username:password@<ftphost>/path to file

Actually, from the w3c spec, entering the username and password is part of ftp protocol url spec, but it is not mentioned for http protocol. So it may not work for all browsers.

http://www.w3.org/Addressing/URL/url-spec.txt

you can see that in page13-14 of the spec

I can get the url to work with an old version of firefox (it first gives a warning), But IE says it can't find the url somewhat like it is searching the hard drive or similar for the location. More head scratching.