Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for DNS name resolution #590

Closed
nkolban opened this issue Sep 28, 2015 · 13 comments
Closed

Add support for DNS name resolution #590

nkolban opened this issue Sep 28, 2015 · 13 comments
Labels
bug ESP8266 This is only a problem on ESP8266 devices implemented

Comments

@nkolban
Copy link
Contributor

nkolban commented Sep 28, 2015

The ESP8266 port does not yet have working support for DNS name resolution (i.e. taking a hostname and retrieving the IP address associated with it). This work items is being created to track the resolution of that omission.

@nkolban nkolban added bug ESP8266 This is only a problem on ESP8266 devices labels Sep 28, 2015
@nkolban
Copy link
Contributor Author

nkolban commented Sep 28, 2015

The ESP8266 has an API called espconn_gethostbyname(). See the ESP8266 SDK for details. At a logical level, when this API is called, it is not blocking. Instead, it takes a callback function that is invoked when the hostname has been resolved.

When we look at the Espruino board specific interface to DNS resolution, we find the following in libs/network/esp8266/network_esp8266.c:

void net_ESP8266_BOARD_gethostbyname(
   JsNetwork *net,
   char *hostName,
   uint32_t *outIp)

As we see, we have a non obvious mapping between the two capabilities.

This function is an indirection from the JsNetwork logical function called gethostbyname (see libs/network/network.h).

Gordon gave some excellent design guidance in this forum post.

Following this, some of the basic DNS mapping was added such that the ESP8266 gethostbyname now calls the ESP API ... however ... I am having trouble.

A call to JsNetwork gethostbyname is not passed the context of any sockets. What this means is that when a user JS app asks for a connect() API call and passes in a string hostname, the callback that will happen when the ESP8266 sdk gethostbyname() completes will not know which socket should have its state modified.

Action: Kolban to talk to Gordon. I believe that the correct story will be to either pass in a callback function to JSNetwork gethostbyname or else pass in context data to gethostbyname that can be used as a key.

@gfwilliams
Copy link
Member

gfwilliams commented Sep 29, 2015

I think you could rely on the fact that gethostbyname is always called from the same function as connect, just before - so you could actually kick the DNS off from connect itself and you'd be fine.


dns_name = ""
gethostbyname(name) {
  dns_name = name;
  return -1;
}

connect(address) {
  if (address==-1) dns_then_connect(dns_name)
  else connect(address);
}

it's pretty evil though. Ideally there would be a better way of handling this, but it's probably better to get it working for now and to then worry about fixing the API later on.

@nkolban
Copy link
Contributor Author

nkolban commented Sep 29, 2015

If I can make the assumption that gethostbyname is always linked to connect ... then yes ... I see that will work great ... however, that then removes the current hope to expose a gethostbyname API to the JS user.

User @HyGy seems to have run into this as an issue ... see:

http://www.esp8266.com/viewtopic.php?f=44&t=6056&p=31667

@HyGy
Copy link

HyGy commented Oct 19, 2015

I'll try it. But with virtual hosts it will not work...

thx,
HyGy

@nkolban
Copy link
Contributor Author

nkolban commented Oct 20, 2015

Implemented a simple ESP8266WiFi.getHostByName() function. Documented in the user guide. Submitted a Pull Request. Uploaded firmware build that contains the code.

@HyGy
Copy link

HyGy commented Nov 3, 2015

What is the state of this in the esp8266 binaries? When will be included?

And when it will incuded how can we use it?

http.get({
host: "thingspeak.com",

or stg command, what can resolv the name?

like
ESP8266WiFi.getHostByName('thingspeak.com');

thanks,
HyGy

@nkolban
Copy link
Contributor Author

nkolban commented Nov 3, 2015

Howdy HyGy ... the latest binaries have a class called "ESP8266".

You can code:

var ESP8266 = require("ESP8266");
ESP8266.getHostByName("thingspeak.com", function(address) {
   http.get({
      host: ESP8266.getAddressAsString(address),
      ...
   ...
});

I don't know when (if ever) we will be able to resolve hostnames by string without doing an explicit lookup. Our problem is that the Espruino internal architecture expects a "gethostbyname" function to be synchronous while on an ESP8266, the "gethostbyname" function is asynchronous. To change the logic would require a sign-off and participation by @gfwilliams as it will impact core and existing Espruino architecture rather than just implementation in the ESP8266 port.

I am happy to partner with others on working on the implementation, but am nervous about attempting such radical surgery in the heart of Espruino without explicit agreement from all parties concerned ... and even then, ideally with their cooperation.

@HyGy
Copy link

HyGy commented Nov 3, 2015

Thanks!!!!

Okay, that is good for me like this. I think it is usable, and not difficult.

What if if the same ip address uses multiple host names (virtual hosts for 1 ip address)? How can I add the host name? Somehow in the header?

@nkolban
Copy link
Contributor Author

nkolban commented Nov 3, 2015

The ESP8266 supplies an SDK that programmers can code against in C. This is what we are using inside the Espruino port. There is an API provided that takes a String as input (representing a hostname) and does a DNS lookup and asynchronously calls us back when an IP address is found. The callback supplied by the SDK returns only a single IP address. This seems to tell me that a hostname (at least as far as the SDK is concerned) can map to only a single IP address.

@HyGy
Copy link

HyGy commented Nov 3, 2015

So!

here is the solution. (maybe I asked wrong)

need to add a header "host", it is works for me my own apache server, i can get all the sites from the same address chainging the Host header in the request header.

var http = require("http");
        http.get({
            host: ipAddress,
            port: 80,
            headers: { 'Host' : 'tingspeak.com', },
            path: '/update?key=' + ApiKey + '&field1=' + press + '&field2=' + temp
        }

@nkolban
Copy link
Contributor Author

nkolban commented Nov 3, 2015

Ahhh ... now I see. Sorry ... I mis-understood the question. If that ever happens again, please be patient with me and keep asking using different words. I'll get it eventually :-)

@HyGy
Copy link

HyGy commented Nov 3, 2015

All my respect to you, you helpd me a lot, and U make a very great job about porting!!!! I think this can change the iot devices, couse js is easy, its close to real world events.

I used c with arduino before, and other things but I think this is the fastest coding env, with js. And esp8266 is very cheap, so I can connect things together. Like a air quality mesurement, a power flow meter, gas meter, etc!

So you are great! Please keep going!!!

@nkolban
Copy link
Contributor Author

nkolban commented Nov 11, 2015

There appears to be problems when users specify a string hostname on TCP/IP based functions. We need to do better than just document not doing this ... even if it is to throw an exception. See the following thread.

http://forum.espruino.com/conversations/277402/#comment12620455

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug ESP8266 This is only a problem on ESP8266 devices implemented
Projects
None yet
Development

No branches or pull requests

4 participants