Skip to content

Introduce the network-socket API to mbed #2216

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

Merged
merged 41 commits into from
Jul 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
9f668f1
Preparing new layout - added net/NetworkSocketAPI
Apr 5, 2016
4c7992c
Matched changes NetworkSocketAPI
geky Apr 6, 2016
d38ccb7
Add open call as alternative to passing NetworkInterface at construction
geky Mar 13, 2016
a7e6c10
Remove shutdown parameter from close call
geky Mar 13, 2016
dfc1ca4
Move to single state-change interrupt
geky Mar 13, 2016
1b368cf
Renamed NetworkInterface create/destroy methods to match Socket methods
geky Mar 13, 2016
3f08f39
Added support for storing bytes directly in SocketAddress
geky Mar 13, 2016
bd8cbf0
Move to SocketAddress in gethostbyname
geky Mar 13, 2016
56e11d6
Added better support for SocketAddress/string addresses/ports
geky Mar 13, 2016
aea45c8
Fix ipv6 addr in SocketAddress
c1728p9 Apr 19, 2016
63725d6
Move bind to Socket
geky Mar 13, 2016
3fa1bb6
Revised stack specific configurations
geky Mar 13, 2016
d84f4be
Added support for shortened form ipv6 addresses
geky Mar 14, 2016
b9d9842
Revisited documentation for NetworkInterface specific methods
geky Apr 19, 2016
0ae11b4
Removed is_connected function
geky Apr 19, 2016
aa2357a
Revisited documentation for Socket API
geky Apr 19, 2016
d36a0b6
Revised documentation for Interface classes
geky Apr 19, 2016
fc71bad
Rename Interface -> Stack
geky Apr 19, 2016
cd4a521
Fix race condition in socket close
geky Apr 20, 2016
abd25f9
Added workaround for bug in newlib sscanf
geky Apr 20, 2016
a4f1071
Add standardized stack options
geky Apr 20, 2016
bd5e913
Separate Stack/Interface concept into two distinct classes
geky Apr 20, 2016
f2715b7
Consolidate set_timeout/set_blocking behaviour
geky Apr 21, 2016
943dd71
Added WFI to save power in temporary polling implementation
geky Apr 21, 2016
710fab5
Add NSAPI_ERROR_PARAMETER
geky May 10, 2016
3d310c2
Small bug fixes
geky May 10, 2016
8f33c0f
Add synchronization to the network socket API
c1728p9 May 3, 2016
1c0a7c2
Adopt Callback class in NetworkSocketAPI
geky May 16, 2016
c3baf27
Fix SocketAddress constructor to support ipv6
c1728p9 May 17, 2016
a6edc26
Coalesce redundant events to reduce cpu usage in lazy implementations
geky Jun 6, 2016
3ee8e30
Added NSAPI_KEEPINTVL/NSAPI_KEEPIDLE options to the socket API
geky Jun 8, 2016
90cd978
Separate interface from stack in NSAPI
c1728p9 May 27, 2016
04e4d9f
Fix async NSAPI race condition
c1728p9 Jul 19, 2016
97380a7
Restructured nsapi headers
geky Jul 19, 2016
d985d70
Added primitive nsapi_addr_t type
geky Jul 20, 2016
7ab9f4c
Added opaque nsapi_socket_t type
geky Jul 20, 2016
5b63cbb
Added primitive nsapi_stack_t and nsapi_stack_api_t structures
geky Jul 20, 2016
01f38cc
Added better support for NetworkInterface/NetworkStack
geky Jul 20, 2016
8561209
Standardized documentation of the NetworkInterface class
geky Jul 20, 2016
e095654
Fixed ambiguity/protected access issue in Socket::open
geky Jul 20, 2016
03c5855
Add 'features/net/network-socket/' from commit 'e09565474188b905cada2…
geky Jul 21, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions features/net/network-socket/CellularInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* CellularInterface
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef CELLULAR_INTERFACE_H
#define CELLULAR_INTERFACE_H

#include "network-socket/NetworkInterface.h"


/** CellularInterface class
*
* Common interface that is shared between ethernet hardware
*/
class CellularInterface : public NetworkInterface
{
public:
/** Start the interface
*
* @param apn Optional name of the network to connect to
* @param username Optional username for your APN
* @param password Optional password for your APN
* @return 0 on success, negative error code on failure
*/
virtual int connect(const char *apn = 0, const char *username = 0, const char *password = 0) = 0;

/** Stop the interface
*
* @return 0 on success, negative error code on failure
*/
virtual int disconnect() = 0;

/** Get the local MAC address
*
* @return Null-terminated representation of the local MAC address
*/
virtual const char *get_mac_address() = 0;
};


#endif
216 changes: 216 additions & 0 deletions features/net/network-socket/DnsQuery/DnsQuery.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
*
* 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.
*/
#include "DnsQuery.h"
#include <stdio.h>
#include <string.h>


#define DNS_COUNT (sizeof DNS_IPS / sizeof DNS_IPS[0])
const char *DNS_IPS[] = {
"8.8.8.8",
"209.244.0.3",
"84.200.69.80",
"8.26.56.26",
"208.67.222.222"
};

static bool isIP(const char *host)
{
int i;

for (i = 0; host[i]; i++) {
if (!(host[i] >= '0' && host[i] <= '9') && host[i] != '.') {
return false;
}
}

// Ending with '.' garuntees host
if (i > 0 && host[i-1] == '.') {
return false;
}

return true;
}


static bool parseRR(uint8_t *resp, int &c, char *adr)
{
int n = 0;
while((n=resp[c++]) != 0) {
if ((n & 0xc0) != 0) {
// This is a link
c++;
break;
} else {
// skip this segment, not interested in string domain names
c+= n;
}
}

int TYPE = (((int)resp[c])<<8) + resp[c+1];
int CLASS = (((int)resp[c+2])<<8) + resp[c+3];
int RDLENGTH = (((int)resp[c+8])<<8) + resp[c+9];

c+= 10;
if ((CLASS == 1) && (TYPE == 1)) {
sprintf(adr,"%d.%d.%d.%d", resp[c], resp[c+1], resp[c+2], resp[c+3]);
c+= RDLENGTH;
return true;
}
c+= RDLENGTH;

return false;
}


static bool resolve(unsigned char *resp, char *ipaddress)
{

int ID = (((int)resp[0]) <<8) + resp[1];
int QR = resp[2] >>7;
int Opcode = (resp[2]>>3) & 0x0F;
int RCODE = (resp[3] & 0x0F);
int ANCOUNT = (((int)resp[6])<<8)+ resp[7];

if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) {
return false;
}

int c = 12;
int d;
// Skip domain question
while( (d=resp[c++]) != 0) {
c+=d;
}
c+= 4; // skip QTYPE and QCLASS

// Here comes the resource record
for (int ans = 0 ; ans < ANCOUNT; ans++) {
if (parseRR(resp, c, ipaddress)) {
return true;
}
}

return false;
}

static int32_t query(UDPSocket *socket, const SocketAddress &addr, const char *hostname, char *ipaddress)
{
int len = 0;
if (hostname == NULL) {
return false;
}
len = strlen(hostname);
if ((len > 128) || (len == 0)) {
return false;
}

int packetlen = /* size of HEADER structure */ 12 + /* size of QUESTION Structure */5 + len + 1;
uint8_t *packet = new uint8_t[packetlen]; /* this is the UDP packet to send to the DNS */
if (packet == NULL) {
return false;
}

// Fill the header
memset(packet, 0, packetlen);
packet[1] = 1; // ID = 1
packet[5] = 1; // QDCOUNT = 1 (contains one question)
packet[2] = 1; // recursion requested

int c = 13; // point to NAME element in question section or request
int cnt = 12; // points to the counter of
packet[cnt] = 0;
for (int i = 0 ; i < len ; i++) {
if (hostname[i] != '.') {
// Copy the character and increment the character counter
packet[cnt]++;
packet[c++] = hostname[i];
} else {
// Finished with this part, so go to the next
cnt = c++;
packet[cnt] = 0;
}
}

// Terminate this domain name with a zero entry
packet[c++] = 0;

// Set QTYPE
packet[c++] = 0;
packet[c++] = 1;
// Set QCLASS
packet[c++] = 0;
packet[c++] = 1;


if (socket->sendto(addr, packet, packetlen) < 0) {
delete packet;
return false;
}
delete packet;

packet = new uint8_t [1024];

// Receive the answer from DNS
int response_length = 0;
response_length = socket->recvfrom(NULL, packet, 1024);

if (response_length > 0 ) {
if (!resolve(packet, ipaddress)) {
delete packet;
return NSAPI_ERROR_DNS_FAILURE;
}

// cleanup and return
delete packet;
return 0;
}

delete packet;
return NSAPI_ERROR_DNS_FAILURE;
}

int32_t dnsQuery(NetworkStack *iface, const char *host, char *ip)
{
if (isIP(host)) {
strcpy(ip, host);
return 0;
}

UDPSocket sock(iface);

for (unsigned i = 0; i < DNS_COUNT; i++) {
return query(&sock, SocketAddress(DNS_IPS[0], 53), host, ip);
}

return NSAPI_ERROR_DNS_FAILURE;
}

int32_t dnsQuery(UDPSocket *socket, const char *host, char *ip)
{
if (isIP(host)) {
strcpy(ip, host);
return 0;
}

for (unsigned i = 0; i < DNS_COUNT; i++) {
return query(socket, SocketAddress(DNS_IPS[0], 53), host, ip);
}

return NSAPI_ERROR_DNS_FAILURE;
}
41 changes: 41 additions & 0 deletions features/net/network-socket/DnsQuery/DnsQuery.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
*
* 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.
*/
#ifndef __DNSQUERY_H__
#define __DNSQUERY_H__

#include "NetworkStack.h"
#include "UDPSocket.h"


/** Function dnsQuery implements the functionality to query a domain name
* server for an IP-Address of a given hostname.
* @param iface : Network interface to use for DNS resolution.
* @param sock : Previously opened socket to use for DNS resolution.
* @param hostname : The hostname of interest as a string.
* Format must be without http:// or www. IE google.com, mbed.org, etc.
* If a standard IP Address is passed, it will be copied into ip unmodified.
* @param ipaddress : A reference to a IPADDRESS_t object which will receive
* the resolved IP Address of the host in question.
* @returns 0 on succes, NS_DNS_FAILURE if host is not found,
* or a negative value for other errors.
*/
int32_t dnsQuery(NetworkStack *iface, const char *host, char *ip);
int32_t dnsQuery(UDPSocket *sock, const char *host, char *ip);


#endif // __DNSQUERY_H__
50 changes: 50 additions & 0 deletions features/net/network-socket/EthInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* EthInterface
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef ETH_INTERFACE_H
#define ETH_INTERFACE_H

#include "network-socket/NetworkInterface.h"


/** EthInterface class
*
* Common interface that is shared between ethernet hardware.
*/
class EthInterface : public NetworkInterface
{
public:
/** Start the interface
*
* @return 0 on success, negative error code on failure
*/
virtual int connect() = 0;

/** Stop the interface
*
* @return 0 on success, negative error code on failure
*/
virtual int disconnect() = 0;

/** Get the local MAC address
*
* @return Null-terminated representation of the local MAC address
*/
virtual const char *get_mac_address() = 0;
};


#endif
Loading