-
Notifications
You must be signed in to change notification settings - Fork 3k
Add non-blocking DNS functionality to network interface #6751
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
Conversation
@kjbracey-arm @SeppoTakalo Please review |
Please review jenkins CI (undefined functions that are being added here?) |
|
||
bool sys_tcpip_thread_check(void) | ||
{ | ||
osThreadId_t thread_id = osThreadGetId(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm very anti-verbosity, so I would have written this as one line:
return osThreadGetId() == lwip_tcpip_thread_id;
Maybe not to your taste.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected.
@@ -484,6 +484,24 @@ void sys_msleep(u32_t ms) { | |||
osDelay(ms); | |||
} | |||
|
|||
osThreadId_t lwip_tcpip_thread_id = 0; | |||
|
|||
bool sys_tcpip_thread_set(void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
void
return
features/netsocket/nsapi_dns.cpp
Outdated
return NSAPI_ERROR_OK ; | ||
} | ||
|
||
static nsapi_error_t nsapi_dns_call_in_default(int delay, mbed::Callback<void()> func) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion - these become the base implementation of NetworkStack::call
, and then the logic below becomes if (dns_call) { custom} else { stack->call }
.
/** Call a callback | ||
* | ||
* Call a callback from the network stack context. If returns error | ||
* callback will not be called. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a bit of text about what you can/can't do from here. Don't take significant time, and specify that of the network calls, only non-blocking UDP/datagram calls can be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a strange API for a network stack.
Why not expose an event queue by pointer and return NULL if there isn't one used.
Then the user could choose a timer or eventqueue based on their needs.
But also +1 for mentioning that long functions could mess with the network stack.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually thinking about it more this just seems like the wrong direction?
See below
features/netsocket/nsapi_dns.cpp
Outdated
|
||
// Allocates in case entry is free, otherwise reuses | ||
if (!dns_cache[index]) { | ||
dns_cache[index] = new DNS_CACHE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will explode on allocation failure - probably want new (nothrow) DNS_CACHE
here with a null check.
features/netsocket/nsapi_dns.h
Outdated
* NSAPI_ERROR_DNS_FAILURE indicates the host could not be found | ||
*/ | ||
nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host, | ||
NetworkStack::hostbyname_cb_t callback, void *data, nsapi_version_t version = NSAPI_IPv4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a Callback
- that's slightly more flexible.
See https://os.mbed.com/docs/v5.7/reference/platform.html#callbacks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep in mind this layer also supports C. But it would be useful to have a C++ overload. The callback class has a thunk member function that can be used when passing to C layer:
void hi(void (*cb)(void *data, int arg), void *data);
Callback<void(int)> cb = function_here;
hi(&Callback<void(int)>::thunk, &cb);
features/netsocket/nsapi_dns.cpp
Outdated
return; | ||
} | ||
|
||
nsapi_addr_t *addrs = new nsapi_addr_t[query->addr_count]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mixing C/C++ allocator types is a bit odd. Not going to rule it out, but these C++ ones should probably be nothrow
with null checks.
features/netsocket/nsapi_dns.cpp
Outdated
nsapi_addr_t *addrs = new nsapi_addr_t[query->addr_count]; | ||
|
||
uint32_t ttl; | ||
int count = dns_scan_response((const uint8_t *) packet, id, &ttl, addrs, query->addr_count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary cast?
features/netsocket/nsapi_dns.cpp
Outdated
} | ||
|
||
// gets id from response to associate with correct query | ||
uint16_t id = (*packet << 8) | *(packet + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style nit - I think (packet[0] << 8) | packet[1]
is nicer.
* @return 0 on success, negative error code on failure | ||
*/ | ||
virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, void *data, | ||
nsapi_version_t version = NSAPI_UNSPEC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, drop the data
as callback object can already encapsulate it for you.
Other than that +1 for the API.
features/netsocket/NetworkStack.cpp
Outdated
return NSAPI_ERROR_DNS_FAILURE; | ||
} | ||
|
||
return NSAPI_ERROR_OK; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did I miss something?
SocketAddress address
is local object.
And you return with NSAPI_ERROR_OK
but where do you actually call the callback with this new address, if it was in fact numeric and conversion was OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected.
features/netsocket/NetworkStack.h
Outdated
* @return 0 on success, negative error code on failure | ||
*/ | ||
virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, void *data, | ||
nsapi_version_t version = NSAPI_UNSPEC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API is identical with NetworkInterface and NetworkStack so can you move these both to one pure virtual class that both can inherit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If/when the callback can be called synchronously during the gethostbyname_async(), could it be documented here too? Just to avoid surprises.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add note about that.
@kjbracey-arm, be careful what you ask for : ) |
I'm confident @mikaleppanen's work can withstand the scrutiny. Pretty happy that this is good, just want to make sure it's perfect. Pretty important bit of API. |
* @param address On success, destination for the host SocketAddress | ||
* @param data Caller defined data | ||
*/ | ||
typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address, void *data)> hostbyname_cb_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think callback already handles data for you?
nsapi_error_t NetworkStack::add_dns_server(const SocketAddress &address) | ||
{ | ||
return nsapi_dns_add_server(address); | ||
} | ||
|
||
nsapi_error_t NetworkStack::get_dns_server(int index, SocketAddress *address) | ||
{ | ||
return NSAPI_ERROR_UNSUPPORTED; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't the default list of dns servers go here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only to return stack specific addresses from DHCP/PPP for network stacks that support those (only LWIP at the moment).
* | ||
* @return Null-terminated representation of the local IP address | ||
* or null if not yet connected | ||
*/ | ||
MBED_DEPRECATED_SINCE("mbed-os-5.7", | ||
"Use NetworkInterface::get_ip_address()") | ||
virtual const char *get_ip_address(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this being undeprecated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It actually never has been - that's a proposed deprecation on the feature-emac branch.
On reflection we've decided this is too useful as "get primary network address for this stack", which is what the DNS code among other wants to do to get hints for IPv6-ness, so we've decided not to deprecate.
Note that DNS is definitely a stack thing, but there's an issue that we've no way to get from stack to interface(s). If we were to add NetworkInterface *NetworkStack::get_default_interface()
or NetworkInterface *NetworkStack::get_interface(int)
, we would be able to use those, rather than have these funny network stack calls that implicitly map to default interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see 👍
/** Call a callback | ||
* | ||
* Call a callback from the network stack context. If returns error | ||
* callback will not be called. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a strange API for a network stack.
Why not expose an event queue by pointer and return NULL if there isn't one used.
Then the user could choose a timer or eventqueue based on their needs.
But also +1 for mentioning that long functions could mess with the network stack.
features/netsocket/nsapi_dns.h
Outdated
* NSAPI_ERROR_DNS_FAILURE indicates the host could not be found | ||
*/ | ||
nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host, | ||
NetworkStack::hostbyname_cb_t callback, void *data, nsapi_version_t version = NSAPI_IPv4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep in mind this layer also supports C. But it would be useful to have a C++ overload. The callback class has a thunk member function that can be used when passing to C layer:
void hi(void (*cb)(void *data, int arg), void *data);
Callback<void(int)> cb = function_here;
hi(&Callback<void(int)>::thunk, &cb);
features/netsocket/nsapi_dns.h
Outdated
* NSAPI_ERROR_DNS_FAILURE indicates the host could not be found | ||
*/ | ||
nsapi_size_or_error_t nsapi_dns_query_multiple_async(NetworkStack *stack, const char *host, | ||
NetworkStack::hostbyname_cb_t callback, void *data, nsapi_size_t addr_count, nsapi_version_t version = NSAPI_IPv4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a C verions of nsapi_dns_query_multiple_async
? If so it'd need the extern "C" and stuff.
features/netsocket/nsapi_dns.cpp
Outdated
{ | ||
if (stack->onboardNetworkStack()) { | ||
OnboardNetworkStack *onboard_stack = reinterpret_cast<OnboardNetworkStack *>(stack); | ||
return onboard_stack->call(func); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it more, I think this is just a bit too upside down. We're poking all these APIs through the network stack because we need them from an API that's called internally?
Why not just pass the necessary things to the more-or-less internal API?
If the dns_query_async API needs an event loop, just make that a necessary argument to the function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here is that we've hit a repeating requirement for network-related stuff to do little tasks. Things like PHY status monitoring in Ethernet drivers. Previously lwip/Nanostack drivers would use lwip/Nanostack event APIs to schedule those. In the EMAC world that's out, and they've been tending to switch to mbed global EventQueue
s.
Which isn't bad, but it is possible they end up being the only user of the global event queue. It will be the case in the smallest mini client.
So the thought is that we know any onboard network stack must have some sort of event-like mechanism, so this genericises the "run in stack context" drivers have historically used, and it remains the case that it will never spawn an extra thread. We were thinking of Ethernet drivers as much as DNS.
The need for this special API would be eliminated if we required OnboardNetworkStack
s to be using EventQueue
for their processing, but that's not the case for either LWIP
or Nanostack
at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But these all seem like things that are called from the network stack, so if the network stack has an event queue couldn't it just be passed to the ethernet drivers at call/init time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it effectively would be for drivers - we're not doing that yet. But it's not necessarily an mbed OS EventQueue
.
For DNS API purposes the callback context for DNS completion can be API-user specified if they have special requirements for their own event system, or they can say "don't care", in which case they end up getting called in the network stack's context, or the global EventQueue
which acts as the default for NetworkStack
.
(The whole DNS state machine runs in a single context, so that user-specified context setting has to be global, not per query. They can always use a trampoline to bounce per call if necessary).
Certainly simplest thing for DNS async API would be to require an EventQueue
to run on, and default to the global one. But that would mean an extra thread with LWIP and Nanostack, which is what we're trying to avoid. And we're not facing up to restructuring their respective event/thread model to use EventQueue
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, do you think we need an abstract EventQueue interface that could be backed by different event queue implementation? Then the DNS/EMAC apis could take in an "EventQueueHandle" that could be backed by the native nanostack event queue.
That may also be a good place to put all of the template madness for the event queue api.
(Name is a joke)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was thinking something like that might be in order, and was pondering suggesting it. Maybe if we start unambitiously with just the call/call_in API and we can flesh it out later.
(Only reason I was hesitating suggesting it was possible delivery time impact for this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it would probably take a while. Also not sure it's entirely possible to combine the virutal class with the templating inside the EventQueue.
Maybe you could just pass a pointer to the call_in function?
void emac_function(Callback<int(int ms, Callback<void()> cb)> call_in_cb);
(you could also use call_in(0, blah) for the call function without a timeout if you want one less argument)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change the API so that network stack provides private method to get the callback and that is passed to DNS resolver. That way there will be no public call/call_in interface. Also EMAC can in future can use same kind of interface (as described above).
/** Call a callback | ||
* | ||
* Call a callback from the network stack context. If returns error | ||
* callback will not be called. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually thinking about it more this just seems like the wrong direction?
See below
@@ -39,6 +39,8 @@ class OnboardNetworkStack : public NetworkStack { | |||
*/ | |||
static OnboardNetworkStack &get_default_instance(); | |||
|
|||
virtual OnboardNetworkStack *onboardNetworkStack() { return this; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See below (or above, depending on GitHub ordering). I don't think we need this on this pr
I left a few comments, but honestly I can't keep up with fully review these prs. So don't let me block anything, and feel free to do whatever you want as long as you take responsibility for the code >: ) |
features/netsocket/nsapi_dns.cpp
Outdated
} | ||
|
||
// Checks if already cached | ||
if (nsapi_dns_cache_find(host, address->get_ip_version(), NULL) == NSAPI_ERROR_OK) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be inside the lock so the state reflects the return value of nsapi_dns_cache_find?
features/netsocket/nsapi_dns.cpp
Outdated
} | ||
|
||
if (index < 0) { | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need an unlock here.
features/netsocket/nsapi_dns.h
Outdated
* @return 0 on success, negative error code on failure | ||
* NSAPI_ERROR_DNS_FAILURE indicates the host could not be found | ||
*/ | ||
nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should probably be an abort function to go along with each of these async starts. That way objects using the async APIs can properly cleanup in their destructor if they are destroyed before the async operation has been completed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. The cancel needs to be added to this API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add cancel to the interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, with a cancel this PR is a dream come true to us.
features/netsocket/nsapi_dns.cpp
Outdated
continue; | ||
} | ||
|
||
// recv the response | ||
err = socket.recvfrom(NULL, packet, DNS_BUFFER_SIZE); | ||
if (err == NSAPI_ERROR_WOULD_BLOCK) { | ||
if (!retry) { | ||
// retries once |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been experimenting with wifi on a bad connection and I often need to do multiple DNS lookups for it to go through. Would it be possible to make the retry number configurable and not fixed to one, please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add json configuration options about retries.
features/netsocket/NetworkStack.h
Outdated
* @param address On success, destination for the host SocketAddress | ||
* @param data Caller defined data | ||
*/ | ||
typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address, void *data)> hostbyname_cb_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As @kjbracey-arm mentioned elsewhere, the documentation of callback should state what can be done from it. I guess typical application would want to connect a socket on success case, or issue another DNS query on failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add a note about limitations. Since this is always running from thread it is possible to do more than e.g. for socket sigio(). But thread stack size limits what can be initiated.
If stack sizes are configured larger (lwip, nanostack or global event queue thread) or if application provides callback using nsapi_dns_call_in_set(), at least non-blocking UDP operations and asynchronous DNS query are possible from callback.
features/netsocket/NetworkStack.h
Outdated
* @param address On success, destination for the host SocketAddress | ||
* @param data Caller defined data | ||
*/ | ||
typedef mbed::Callback<void (nsapi_error_t result, SocketAddress *address, void *data)> hostbyname_cb_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the query returns multiple addresses, is there a way to iterate through all of them, just as with getaddrinfo() on POSIX?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like previous blocking interface, multiple addresses are not supported. That might be done later as a new extension to interface.
features/netsocket/nsapi_dns.cpp
Outdated
|
||
struct DNS_CACHE { | ||
SocketAddress address; | ||
char host[128]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If RFC 1035 states that full DNS name can be 255 bytes, could this non-standard limitation be specified by some configuration option. I have no objection for limiting this by default, but if the max length was exposed via a public define, the client application could use it for its own buffers too. And a space limited application might try to tune the max name length and cache size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add configuration options to json for both name length and number of entries in cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have hit problems with very long Amazon server names - not sure what limit was being breached there. Maybe 64 characters in the ESP8266?
I'd like the default to be the standard if it possibly fits. For a cache with your own internal structures, maybe claw some back by using the nsapi_addr_t, skipping the string literal representation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed limit to 255 and changed storage to use dynamic memory for host name.
} | ||
} else { | ||
if (eventOS_event_send(&event) < 0) { | ||
return NSAPI_ERROR_NO_MEMORY; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the cb be deleted on these error cases to avoid memory leaks?
Pushed a commit that contains fixes for review defects. Please review the corrections. |
features/netsocket/NetworkStack.h
Outdated
* @param callback Callback that is called for result | ||
* @param version IP version of address to resolve, NSAPI_UNSPEC indicates | ||
* version is chosen by the stack (defaults to NSAPI_UNSPEC) | ||
* @return 0 on success, negative error code on failure or an unique id that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To pin it down a little: "immediate success"? "immediate failure"? "positive unique id"? Kind of obvious, but just to be utterly clear.
And given it's a 3-way split, maybe put it as 3 separate @return
lines rather than 1 long run-on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected.
features/netsocket/NetworkStack.h
Outdated
* represents the hostname translation operation and can be passed to | ||
* cancel | ||
*/ | ||
virtual nsapi_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have nsapi_size_or_error_t
. Wondering if we should have something like that here rather than just using nsapi_error_t
. Or maybe make it return int
. Passing nsapi_error_t
to cancel is weird - I'd like that to take int
or some sort of nsapi_id_t
. (int
is probably fine)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added new definition: nsapi_value_or_error_t
features/netsocket/nsapi_dns.cpp
Outdated
#define DNS_SERVERS_SIZE 5 | ||
#define DNS_RESPONSE_MIN_SIZE 12 | ||
#define DNS_MAX_TTL 604800 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would help to have this as an expression and comment to clarify the derivation. I gather it's (7*24*60*60) \\ 7 days in seconds
.
Although, is there actually any requirement to have this clamp at the client end? Reference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed that.
features/netsocket/nsapi_dns.cpp
Outdated
|
||
if (dns_cache[index]) { | ||
dns_cache[index]->address = *address; | ||
dns_cache[index]->host = (char *) malloc(strlen(host) + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're being C++, new (nothrow) char[strlen(host) + 1]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to new
features/netsocket/nsapi_dns.cpp
Outdated
dns_cache[index]->host = (char *) malloc(strlen(host) + 1); | ||
strcpy(dns_cache[index]->host, host); | ||
uint64_t ms_count = rtos::Kernel::get_ms_count(); | ||
dns_cache[index]->expires = ms_count + ttl * 1000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically (if you weren't clamping ttl), you'd want to do something to make sure you don't overflow a 32-bit multiply - (uint64_t) ttt
or UINT64_C(1000)
. This is probably utterly pointless, of course.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added casting.
features/netsocket/mbed_lib.json
Outdated
"value": 3 | ||
}, | ||
"dns-retries": { | ||
"help": "Number of DNS query retries that the DNS translator makes per server", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whichever you decide for the previous, seems like it might be best to have the two settings phrased the same. I think this needs a bit more explanation - before moving on to the next server. Total retries/attempts is always limited by "dns-total-retries/attempts"
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the description.
features/netsocket/nsapi_dns.cpp
Outdated
static void nsapi_dns_cache_add(const char *host, nsapi_addr_t *address, uint32_t ttl) | ||
{ | ||
// RFC 1034: if TTL is zero, entry is not added to cache | ||
if (!ttl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is a number, not a boolean, I prefer if (ttl == 0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected.
features/netsocket/nsapi_dns.cpp
Outdated
dns_cache_mutex.lock(); | ||
|
||
int index = -1; | ||
uint64_t accessed = ~0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe UINT64_MAX
? Don't feel strongly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected.
features/netsocket/nsapi_dns.cpp
Outdated
#define DNS_HOST_NAME_MAX_LEN 255 | ||
|
||
#ifndef MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME | ||
#define MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME 5000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need these defaults? I just helped someone out who was confusing himself by trying to change lines like these, rather than the JSON file, to no effect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed those.
features/netsocket/nsapi_dns.cpp
Outdated
query->addrs = 0; | ||
} else { | ||
query->count = resp; | ||
nsapi_dns_call_in(query->call_in_cb, 0, mbed::callback(nsapi_dns_query_async_response, reinterpret_cast<void *>(query->unique_id))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this cast necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, seems that adding an int to callback is not possible.
- Added non-blocking DNS interface to network interface and network stack. - Added caching of DNS replies. - Added a network stack function to get DNS addresses from stack. - Added call and call_in hooks to onboard network stack to allow calling functions from onboard stack context. - Added support to call and call_in functions to LWIP and Nanostack. - Disabled LWIP DNS translator with the exception of DNS address storage used in DNS address get.
- Changed call_in/call methods of the stack to callback provided by the stack - Specified what are limitations for operations that are made in callback - Added pure virtual class DNS that defines DNS operations - Added cancel operation and unique ID to DNS request used in cancel - Added DNS configuration options to netsocket/mbed_lib.json for retries, response wait time and cache size - Changed host name to use dynamic memory in DNS query list and cache, set maximum length for the name to 255 bytes. - Added mutex to asynchronous DNS - Reworked retries: there is now total retry count and a server specific count - Ignores invalid incoming UDP socket messages (DNS header is not valid), and retries DNS query - Reworked DNS module asynchronous operation functions - Corrected other review issues (nothrow new, missing free, missing mutex unlock etc.)
- Serialized the sending of multiple async DNS queries since limits on event message box sizes - Added timer function that supervises the total time used to make DNS query and triggers socket timeouts - Changed nsapi_error_t to new nsapi_value_or_error_t on interface headers - Corrected wording of gethostbyname_async return values - Clarified .json options - Added a new data type for socket callback that can be used from interrupts - Corrected variable limits to use INT32_MAX etc. defines - Changed mallocs to new - Optimized variable sizes on DNS_QUERY definition
Corrected defects, please review. |
/morph build |
Build : SUCCESSBuild number : 2009 Triggering tests/morph test |
Test : FAILUREBuild number : 1819 |
features/netsocket/nsapi_dns.cpp
Outdated
// Protects cache shared between blocking and asynchronous calls | ||
static rtos::Mutex dns_cache_mutex; | ||
// Protects from several threads running asynchronous DNS | ||
static rtos::Mutex dns_mutex; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be PlatformMutex:es instead to support non-RTOS compilation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they can be. Changed them into PlatformMutex:es.
features/netsocket/nsapi_dns.cpp
Outdated
|
||
nsapi_dns_query_async_resp(query, status, addresses); | ||
|
||
if (addresses) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to check for NULL before calling operator delete.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+3
- Changed mutexes to platform mutexes - Removed not needed null check from delete - Changed nsapi_dns_call_in_set() to use call_in_callback_cb_t and added prototype to header
Exporter Build : FAILUREBuild number : 1661 |
/morph export-build |
@kjbracey-arm Echoing an earlier question. Why are you assigning release-version tags to PRs going into the feature-emac branch? |
Description
Pull request type