mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Add 'features/net/network-socket/' from commit 'e09565474188b905cada21166118a82e66359217'
git-subtree-dir: features/net/network-socket git-subtree-mainline:pull/2216/headdb60d6a7f7git-subtree-split:e095654741
						commit
						03c5855496
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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__
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
/* MeshInterface
 | 
			
		||||
 * 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 MESH_INTERFACE_H
 | 
			
		||||
#define MESH_INTERFACE_H
 | 
			
		||||
 | 
			
		||||
#include "network-socket/NetworkInterface.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** MeshInterface class
 | 
			
		||||
 *
 | 
			
		||||
 *  Common interface that is shared between mesh hardware
 | 
			
		||||
 */
 | 
			
		||||
class MeshInterface : public NetworkInterface
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** Start the interface
 | 
			
		||||
     *
 | 
			
		||||
     *  @return     0 on success, negative on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int connect() = 0;
 | 
			
		||||
 | 
			
		||||
    /** Stop the interface
 | 
			
		||||
     *
 | 
			
		||||
     *  @return     0 on success, negative 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
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
/* NetworkStack
 | 
			
		||||
 * 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 NETWORK_INTERFACE_H
 | 
			
		||||
#define NETWORK_INTERFACE_H
 | 
			
		||||
 | 
			
		||||
// Predeclared class
 | 
			
		||||
class NetworkStack;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** NetworkInterface class
 | 
			
		||||
 *
 | 
			
		||||
 *  Common interface that is shared between network devices
 | 
			
		||||
 */
 | 
			
		||||
class NetworkInterface {
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~NetworkInterface() {};
 | 
			
		||||
 | 
			
		||||
    /** Get the local IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Null-terminated representation of the local IP address
 | 
			
		||||
     *                  or null if not yet connected
 | 
			
		||||
     */
 | 
			
		||||
    virtual const char *get_ip_address() = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    friend class Socket;
 | 
			
		||||
    friend class UDPSocket;
 | 
			
		||||
    friend class TCPSocket;
 | 
			
		||||
    friend class TCPServer;
 | 
			
		||||
    friend class SocketAddress;
 | 
			
		||||
    template <typename IF>
 | 
			
		||||
    friend NetworkStack *nsapi_create_stack(IF *iface);
 | 
			
		||||
 | 
			
		||||
    /** Provide access to the NetworkStack object
 | 
			
		||||
     *
 | 
			
		||||
     *  @return The underlying NetworkStack object
 | 
			
		||||
     */
 | 
			
		||||
    virtual NetworkStack *get_stack() = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,257 @@
 | 
			
		|||
/* Socket
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "NetworkStack.h"
 | 
			
		||||
#include "DnsQuery.h"
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "stddef.h"
 | 
			
		||||
#include <new>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Default NetworkStack operations
 | 
			
		||||
int NetworkStack::gethostbyname(SocketAddress *address, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    char buffer[NSAPI_IP_SIZE];
 | 
			
		||||
    int err = dnsQuery(this, name, buffer);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    address->set_ip_address(buffer);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int NetworkStack::setstackopt(int level, int optname, const void *optval, unsigned optlen)
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int NetworkStack::getstackopt(int level, int optname, void *optval, unsigned *optlen)
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int NetworkStack::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int NetworkStack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// NetworkStackWrapper class for encapsulating the raw nsapi_stack structure
 | 
			
		||||
class NetworkStackWrapper : public NetworkStack
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    inline nsapi_stack_t *_stack()
 | 
			
		||||
    {
 | 
			
		||||
        return reinterpret_cast<nsapi_stack_t *>(
 | 
			
		||||
                reinterpret_cast<uint8_t *>(this)
 | 
			
		||||
                - offsetof(nsapi_stack_t, _stack_buffer));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline const nsapi_stack_api_t *_stack_api()
 | 
			
		||||
    {
 | 
			
		||||
        return _stack()->stack_api;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    virtual const char *get_ip_address()
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->get_ip_address) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static uint8_t buffer[sizeof(SocketAddress)];
 | 
			
		||||
        SocketAddress *address = new (buffer) SocketAddress(_stack_api()->get_ip_address(_stack()));
 | 
			
		||||
        return address->get_ip_address();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int gethostbyname(SocketAddress *address, const char *name)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->gethostbyname) {
 | 
			
		||||
            return NetworkStack::gethostbyname(address, name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        nsapi_addr_t addr = {NSAPI_IPv4, 0};
 | 
			
		||||
        int err = _stack_api()->gethostbyname(_stack(), &addr, name);
 | 
			
		||||
        address->set_addr(addr);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int setstackopt(int level, int optname, const void *optval, unsigned optlen)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->setstackopt) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->setstackopt(_stack(), level, optname, optval, optlen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int getstackopt(int level, int optname, void *optval, unsigned *optlen)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->getstackopt) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->getstackopt(_stack(), level, optname, optval, optlen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual int socket_open(nsapi_socket_t *socket, nsapi_protocol_t proto)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_open) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_open(_stack(), socket, proto);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_close(nsapi_socket_t socket)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_close) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_close(_stack(), socket);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_bind(nsapi_socket_t socket, const SocketAddress &address)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_bind) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_bind(_stack(), socket, address.get_addr(), address.get_port());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_listen(nsapi_socket_t socket, int backlog)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_listen) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_listen(_stack(), socket, backlog);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_connect(nsapi_socket_t socket, const SocketAddress &address)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_connect) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_connect(_stack(), socket, address.get_addr(), address.get_port());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_accept(nsapi_socket_t *socket, nsapi_socket_t server)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_accept) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_accept(_stack(), socket, server);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_send(nsapi_socket_t socket, const void *data, unsigned size)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_send) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_send(_stack(), socket, data, size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_recv(nsapi_socket_t socket, void *data, unsigned size)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_recv) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_recv(_stack(), socket, data, size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_sendto(nsapi_socket_t socket, const SocketAddress &address, const void *data, unsigned size)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_sendto) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_sendto(_stack(), socket, address.get_addr(), address.get_port(), data, size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int socket_recvfrom(nsapi_socket_t socket, SocketAddress *address, void *data, unsigned size)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_recvfrom) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        nsapi_addr_t addr = {NSAPI_IPv4, 0};
 | 
			
		||||
        uint16_t port = 0;
 | 
			
		||||
 | 
			
		||||
        int err = _stack_api()->socket_recvfrom(_stack(), socket, &addr, &port, data, size);
 | 
			
		||||
 | 
			
		||||
        if (address) {
 | 
			
		||||
            address->set_addr(addr);
 | 
			
		||||
            address->set_port(port);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void socket_attach(nsapi_socket_t socket, void (*callback)(void *), void *data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->socket_attach) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->socket_attach(_stack(), socket, callback, data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int setsockopt(nsapi_socket_t socket, int level, int optname, const void *optval, unsigned optlen)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->setsockopt) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->setsockopt(_stack(), socket, level, optname, optval, optlen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int getsockopt(nsapi_socket_t socket, int level, int optname, void *optval, unsigned *optlen)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_stack_api()->getsockopt) {
 | 
			
		||||
            return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _stack_api()->getsockopt(_stack(), socket, level, optname, optval, optlen);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Conversion function for network stacks
 | 
			
		||||
NetworkStack *nsapi_create_stack(nsapi_stack_t *stack)
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(sizeof stack->_stack_buffer >= sizeof(NetworkStackWrapper));
 | 
			
		||||
    return new (stack->_stack_buffer) NetworkStackWrapper;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NetworkStack *nsapi_create_stack(NetworkStack *stack)
 | 
			
		||||
{
 | 
			
		||||
    return stack;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,300 @@
 | 
			
		|||
/* NetworkStack
 | 
			
		||||
 * 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 NETWORK_STACK_H
 | 
			
		||||
#define NETWORK_STACK_H
 | 
			
		||||
 | 
			
		||||
#include "nsapi_types.h"
 | 
			
		||||
#include "network-socket/SocketAddress.h"
 | 
			
		||||
#include "network-socket/NetworkInterface.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** NetworkStack class
 | 
			
		||||
 *
 | 
			
		||||
 *  Common interface that is shared between hardware that
 | 
			
		||||
 *  can connect to a network over IP. By implementing the
 | 
			
		||||
 *  NetworkStack, a network stack can be used as a target
 | 
			
		||||
 *  for instantiating network sockets.
 | 
			
		||||
 */
 | 
			
		||||
class NetworkStack
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~NetworkStack() {};
 | 
			
		||||
 | 
			
		||||
    /** Get the local IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Null-terminated representation of the local IP address
 | 
			
		||||
     *                  or null if not yet connected
 | 
			
		||||
     */
 | 
			
		||||
    virtual const char *get_ip_address() = 0;
 | 
			
		||||
 | 
			
		||||
    /** Translates a hostname to an IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  The hostname may be either a domain name or an IP address. If the
 | 
			
		||||
     *  hostname is an IP address, no network transactions will be performed.
 | 
			
		||||
     *  
 | 
			
		||||
     *  If no stack-specific DNS resolution is provided, the hostname
 | 
			
		||||
     *  will be resolve using a UDP socket on the stack. 
 | 
			
		||||
     *
 | 
			
		||||
     *  @param address  Destination for the host SocketAddress
 | 
			
		||||
     *  @param host     Hostname to resolve
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int gethostbyname(SocketAddress *address, const char *host);
 | 
			
		||||
 | 
			
		||||
    /*  Set stack-specific stack options
 | 
			
		||||
     *
 | 
			
		||||
     *  The setstackopt allow an application to pass stack-specific hints
 | 
			
		||||
     *  to the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and the stack is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    virtual int setstackopt(int level, int optname, const void *optval, unsigned optlen);
 | 
			
		||||
 | 
			
		||||
    /*  Get stack-specific stack options
 | 
			
		||||
     *
 | 
			
		||||
     *  The getstackopt allow an application to retrieve stack-specific hints
 | 
			
		||||
     *  from the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Destination for option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    virtual int getstackopt(int level, int optname, void *optval, unsigned *optlen);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    friend class Socket;
 | 
			
		||||
    friend class UDPSocket;
 | 
			
		||||
    friend class TCPSocket;
 | 
			
		||||
    friend class TCPServer;
 | 
			
		||||
 | 
			
		||||
    /** Opens a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates a network socket and stores it in the specified handle.
 | 
			
		||||
     *  The handle must be passed to following calls on the socket.
 | 
			
		||||
     *
 | 
			
		||||
     *  A stack may have a finite number of sockets, in this case
 | 
			
		||||
     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Destination for the handle to a newly created socket
 | 
			
		||||
     *  @param proto    Protocol of socket to open, NSAPI_TCP or NSAPI_UDP
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Close the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Closes any open connection and deallocates any memory associated
 | 
			
		||||
     *  with the socket.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_close(nsapi_socket_t handle) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Bind a specific address to a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Binding a socket specifies the address and port on which to recieve
 | 
			
		||||
     *  data. If the IP address is zeroed, only the port is bound.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param address  Local address to bind
 | 
			
		||||
     *  @return         0 on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_bind(nsapi_socket_t handle, const SocketAddress &address) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Listen for connections on a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Marks the socket as a passive socket that can be used to accept
 | 
			
		||||
     *  incoming connections.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param backlog  Number of pending connections that can be queued
 | 
			
		||||
     *                  simultaneously
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_listen(nsapi_socket_t handle, int backlog) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Connects TCP socket to a remote host
 | 
			
		||||
     *
 | 
			
		||||
     *  Initiates a connection to a remote server specified by the
 | 
			
		||||
     *  indicated address.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param address  The SocketAddress of the remote host
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_connect(nsapi_socket_t handle, const SocketAddress &address) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Accepts a connection on a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The server socket must be bound and set to listen for connections.
 | 
			
		||||
     *  On a new connection, creates a network socket and stores it in the
 | 
			
		||||
     *  specified handle. The handle must be passed to following calls on
 | 
			
		||||
     *  the socket.
 | 
			
		||||
     *
 | 
			
		||||
     *  A stack may have a finite number of sockets, in this case
 | 
			
		||||
     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If accept would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Destination for a handle to the newly created sockey
 | 
			
		||||
     *  @param server   Socket handle to server to accept from
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_accept(nsapi_socket_t *handle, nsapi_socket_t server) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Send data over a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The socket must be connected to a remote host. Returns the number of
 | 
			
		||||
     *  bytes sent from the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If send would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param data     Buffer of data to send to the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of sent bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_send(nsapi_socket_t handle, const void *data, unsigned size) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Receive data over a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The socket must be connected to a remote host. Returns the number of
 | 
			
		||||
     *  bytes received into the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If recv would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param data     Destination buffer for data received from the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of received bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_recv(nsapi_socket_t handle, void *data, unsigned size) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Send a packet over a UDP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Sends data to the specified address. Returns the number of bytes
 | 
			
		||||
     *  sent from the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If sendto would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param address  The SocketAddress of the remote host
 | 
			
		||||
     *  @param data     Buffer of data to send to the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of sent bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_sendto(nsapi_socket_t handle, const SocketAddress &address, const void *data, unsigned size) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Receive a packet over a UDP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Receives data and stores the source address in address if address
 | 
			
		||||
     *  is not NULL. Returns the number of bytes received into the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If recvfrom would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param address  Destination for the source address or NULL
 | 
			
		||||
     *  @param data     Destination buffer for data received from the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of received bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, unsigned size) = 0;
 | 
			
		||||
 | 
			
		||||
    /** Register a callback on state change of the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The specified callback will be called on state changes such as when
 | 
			
		||||
     *  the socket can recv/send/accept successfully and on when an error
 | 
			
		||||
     *  occurs. The callback may also be called spuriously without reason.
 | 
			
		||||
     *
 | 
			
		||||
     *  The callback may be called in an interrupt context and should not
 | 
			
		||||
     *  perform expensive operations such as recv/send calls.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param callback Function to call on state change
 | 
			
		||||
     *  @param data     Argument to pass to callback
 | 
			
		||||
     */
 | 
			
		||||
    virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) = 0;
 | 
			
		||||
 | 
			
		||||
    /*  Set stack-specific socket options
 | 
			
		||||
     *
 | 
			
		||||
     *  The setsockopt allow an application to pass stack-specific hints
 | 
			
		||||
     *  to the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    virtual int setsockopt(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen);
 | 
			
		||||
 | 
			
		||||
    /*  Get stack-specific socket options
 | 
			
		||||
     *
 | 
			
		||||
     *  The getstackopt allow an application to retrieve stack-specific hints
 | 
			
		||||
     *  from the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param handle   Socket handle
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Destination for option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    virtual int getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Convert a raw nsapi_stack_t object into a C++ NetworkStack object
 | 
			
		||||
 *
 | 
			
		||||
 *  @param stack    Reference to an object that can be converted to a stack
 | 
			
		||||
 *                  - A raw nsapi_stack_t object
 | 
			
		||||
 *                  - A reference to a network stack
 | 
			
		||||
 *                  - A reference to a network interface
 | 
			
		||||
 *  @return         Reference to the underlying network stack
 | 
			
		||||
 */
 | 
			
		||||
NetworkStack *nsapi_create_stack(nsapi_stack_t *stack);
 | 
			
		||||
NetworkStack *nsapi_create_stack(NetworkStack *stack);
 | 
			
		||||
 | 
			
		||||
template <typename IF>
 | 
			
		||||
NetworkStack *nsapi_create_stack(IF *iface)
 | 
			
		||||
{
 | 
			
		||||
    return nsapi_create_stack(static_cast<NetworkInterface *>(iface)->get_stack());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,157 @@
 | 
			
		|||
/* Socket
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "Socket.h"
 | 
			
		||||
 | 
			
		||||
Socket::Socket()
 | 
			
		||||
    : _stack(0)
 | 
			
		||||
    , _socket(0)
 | 
			
		||||
    , _timeout(osWaitForever)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Socket::open(NetworkStack *stack)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
 | 
			
		||||
    if (_stack != NULL || stack == NULL) {
 | 
			
		||||
        _lock.unlock();
 | 
			
		||||
        return NSAPI_ERROR_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
    _stack = stack;
 | 
			
		||||
 | 
			
		||||
    nsapi_socket_t socket;
 | 
			
		||||
    int err = _stack->socket_open(&socket, get_proto());
 | 
			
		||||
    if (err) {
 | 
			
		||||
        _lock.unlock();
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _socket = socket;
 | 
			
		||||
    _event.attach(this, &Socket::event);
 | 
			
		||||
    _stack->socket_attach(_socket, Callback<void()>::thunk, &_event);
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Socket::close()
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    if (_socket) {
 | 
			
		||||
        _stack->socket_attach(_socket, 0, 0);
 | 
			
		||||
        nsapi_socket_t socket = _socket;
 | 
			
		||||
        _socket = 0;
 | 
			
		||||
        ret = _stack->socket_close(socket);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Wakeup anything in a blocking operation
 | 
			
		||||
    // on this socket
 | 
			
		||||
    event();
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Socket::bind(uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    // Underlying bind is thread safe
 | 
			
		||||
    SocketAddress addr(0, port);
 | 
			
		||||
    return bind(addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Socket::bind(const char *address, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    // Underlying bind is thread safe
 | 
			
		||||
    SocketAddress addr(address, port);
 | 
			
		||||
    return bind(addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Socket::bind(const SocketAddress &address)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (!_socket) {
 | 
			
		||||
        ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = _stack->socket_bind(_socket, address);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::set_blocking(bool blocking)
 | 
			
		||||
{
 | 
			
		||||
    // Socket::set_timeout is thread safe
 | 
			
		||||
    set_timeout(blocking ? -1 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::set_timeout(int timeout)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
 | 
			
		||||
    if (timeout >= 0) {
 | 
			
		||||
        _timeout = (uint32_t)timeout;
 | 
			
		||||
    } else {
 | 
			
		||||
        _timeout = osWaitForever;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Socket::setsockopt(int level, int optname, const void *optval, unsigned optlen)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (!_socket) {
 | 
			
		||||
        ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = _stack->setsockopt(_socket, level, optname, optval, optlen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Socket::getsockopt(int level, int optname, void *optval, unsigned *optlen)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (!_socket) {
 | 
			
		||||
        ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = _stack->getsockopt(_socket, level, optname, optval, optlen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Socket::attach(Callback<void()> callback)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
 | 
			
		||||
    _callback = callback;
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,195 @@
 | 
			
		|||
/* Socket
 | 
			
		||||
 * 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 SOCKET_H
 | 
			
		||||
#define SOCKET_H
 | 
			
		||||
 | 
			
		||||
#include "network-socket/SocketAddress.h"
 | 
			
		||||
#include "network-socket/NetworkStack.h"
 | 
			
		||||
#include "rtos/Mutex.h"
 | 
			
		||||
#include "Callback.h"
 | 
			
		||||
 | 
			
		||||
#ifndef NSAPI_NO_INCLUDE_MBED
 | 
			
		||||
#include "mbed.h" // needed for backwards compatability
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Abstract socket class
 | 
			
		||||
 */
 | 
			
		||||
class Socket {
 | 
			
		||||
public:
 | 
			
		||||
    /** Destroy a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Closes socket if the socket is still open
 | 
			
		||||
     */
 | 
			
		||||
    virtual ~Socket() {}
 | 
			
		||||
 | 
			
		||||
    /** Opens a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates a network socket on the network stack of the given
 | 
			
		||||
     *  network interface. Not needed if stack is passed to the
 | 
			
		||||
     *  socket's constructor.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int open(NetworkStack *stack);
 | 
			
		||||
 | 
			
		||||
    template <typename S>
 | 
			
		||||
    int open(S *stack) {
 | 
			
		||||
        return open(nsapi_create_stack(stack));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /** Close the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Closes any open connection and deallocates any memory associated
 | 
			
		||||
     *  with the socket. Called from destructor if socket is not closed.
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int close();
 | 
			
		||||
    
 | 
			
		||||
    /** Bind a specific address to a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Binding a socket specifies the address and port on which to recieve
 | 
			
		||||
     *  data.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param port     Local port to bind
 | 
			
		||||
     *  @return         0 on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    int bind(uint16_t port);
 | 
			
		||||
 | 
			
		||||
    /** Bind a specific address to a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Binding a socket specifies the address and port on which to recieve
 | 
			
		||||
     *  data. If the IP address is zeroed, only the port is bound.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param address  Null-terminated local address to bind
 | 
			
		||||
     *  @param port     Local port to bind
 | 
			
		||||
     *  @return         0 on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    int bind(const char *address, uint16_t port);
 | 
			
		||||
 | 
			
		||||
    /** Bind a specific address to a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Binding a socket specifies the address and port on which to recieve
 | 
			
		||||
     *  data. If the IP address is zeroed, only the port is bound.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param address  Local address to bind
 | 
			
		||||
     *  @return         0 on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    int bind(const SocketAddress &address);
 | 
			
		||||
    
 | 
			
		||||
    /** Set blocking or non-blocking mode of the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Initially all sockets are in blocking mode. In non-blocking mode
 | 
			
		||||
     *  blocking operations such as send/recv/accept return
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK if they can not continue.
 | 
			
		||||
     *
 | 
			
		||||
     *  set_blocking(false) is equivalent to set_timeout(-1)
 | 
			
		||||
     *  set_blocking(true) is equivalent to set_timeout(0)
 | 
			
		||||
     *
 | 
			
		||||
     *  @param blocking true for blocking mode, false for non-blocking mode.
 | 
			
		||||
     */
 | 
			
		||||
    void set_blocking(bool blocking);
 | 
			
		||||
    
 | 
			
		||||
    /** Set timeout on blocking socket operations
 | 
			
		||||
     *
 | 
			
		||||
     *  Initially all sockets have unbounded timeouts. NSAPI_ERROR_WOULD_BLOCK
 | 
			
		||||
     *  is returned if a blocking operation takes longer than the specified
 | 
			
		||||
     *  timeout. A timeout of 0 removes the timeout from the socket. A negative
 | 
			
		||||
     *  value give the socket an unbounded timeout.
 | 
			
		||||
     *
 | 
			
		||||
     *  set_timeout(0) is equivalent to set_blocking(false)
 | 
			
		||||
     *  set_timeout(-1) is equivalent to set_blocking(true)
 | 
			
		||||
     *
 | 
			
		||||
     *  @param timeout  Timeout in milliseconds
 | 
			
		||||
     */
 | 
			
		||||
    void set_timeout(int timeout);
 | 
			
		||||
 | 
			
		||||
    /*  Set stack-specific socket options
 | 
			
		||||
     *
 | 
			
		||||
     *  The setsockopt allow an application to pass stack-specific hints
 | 
			
		||||
     *  to the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    int setsockopt(int level, int optname, const void *optval, unsigned optlen);
 | 
			
		||||
 | 
			
		||||
    /*  Get stack-specific socket options
 | 
			
		||||
     *
 | 
			
		||||
     *  The getstackopt allow an application to retrieve stack-specific hints
 | 
			
		||||
     *  from the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Destination for option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    int getsockopt(int level, int optname, void *optval, unsigned *optlen);
 | 
			
		||||
 | 
			
		||||
    /** Register a callback on state change of the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The specified callback will be called on state changes such as when
 | 
			
		||||
     *  the socket can recv/send/accept successfully and on when an error
 | 
			
		||||
     *  occurs. The callback may also be called spuriously without reason.
 | 
			
		||||
     *
 | 
			
		||||
     *  The callback may be called in an interrupt context and should not
 | 
			
		||||
     *  perform expensive operations such as recv/send calls.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param func     Function to call on state change
 | 
			
		||||
     */
 | 
			
		||||
    void attach(mbed::Callback<void()> func);
 | 
			
		||||
 | 
			
		||||
    /** Register a callback on state change of the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The specified callback will be called on state changes such as when
 | 
			
		||||
     *  the socket can recv/send/accept successfully and on when an error
 | 
			
		||||
     *  occurs. The callback may also be called spuriously without reason.
 | 
			
		||||
     *
 | 
			
		||||
     *  The callback may be called in an interrupt context and should not
 | 
			
		||||
     *  perform expensive operations such as recv/send calls.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param obj      Pointer to object to call method on
 | 
			
		||||
     *  @param method   Method to call on state change
 | 
			
		||||
     */
 | 
			
		||||
    template <typename T, typename M>
 | 
			
		||||
    void attach(T *obj, M method) {
 | 
			
		||||
        attach(mbed::Callback<void()>(obj, method));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    Socket();
 | 
			
		||||
    virtual nsapi_protocol_t get_proto() = 0;
 | 
			
		||||
    virtual void event() = 0;
 | 
			
		||||
 | 
			
		||||
    NetworkStack *_stack;
 | 
			
		||||
    nsapi_socket_t _socket;
 | 
			
		||||
    uint32_t _timeout;
 | 
			
		||||
    mbed::Callback<void()> _event;
 | 
			
		||||
    mbed::Callback<void()> _callback;
 | 
			
		||||
    rtos::Mutex _lock;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,282 @@
 | 
			
		|||
/* Socket
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "SocketAddress.h"
 | 
			
		||||
#include "NetworkInterface.h"
 | 
			
		||||
#include "NetworkStack.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static bool ipv4_is_valid(const char *addr)
 | 
			
		||||
{
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
    // Check each digit for [0-9.]
 | 
			
		||||
    for (; addr[i]; i++) {
 | 
			
		||||
        if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Ending with '.' garuntees host
 | 
			
		||||
    if (i > 0 && addr[i-1] == '.') {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool ipv6_is_valid(const char *addr)
 | 
			
		||||
{
 | 
			
		||||
    // Check each digit for [0-9a-fA-F:]
 | 
			
		||||
    for (int i = 0; addr[i]; i++) {
 | 
			
		||||
        if (!(addr[i] >= '0' && addr[i] <= '9') &&
 | 
			
		||||
            !(addr[i] >= 'a' && addr[i] <= 'f') &&
 | 
			
		||||
            !(addr[i] >= 'A' && addr[i] <= 'F') &&
 | 
			
		||||
            addr[i] != ':') {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipv4_from_address(uint8_t *bytes, const char *addr)
 | 
			
		||||
{
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
    for (; count < NSAPI_IPv4_BYTES; count++) {
 | 
			
		||||
        int scanned = sscanf(&addr[i], "%hhu", &bytes[count]);
 | 
			
		||||
        if (scanned < 1) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (; addr[i] != '.'; i++) {
 | 
			
		||||
            if (!addr[i]) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) {
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
    for (; count < NSAPI_IPv6_BYTES/2; count++) {
 | 
			
		||||
        int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
 | 
			
		||||
        if (scanned < 1) {
 | 
			
		||||
            return count;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (; chunk[i] != ':'; i++) {
 | 
			
		||||
            if (!chunk[i]) {
 | 
			
		||||
                return count+1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipv6_from_address(uint8_t *bytes, const char *addr)
 | 
			
		||||
{
 | 
			
		||||
    // Start with zeroed address
 | 
			
		||||
    uint16_t shorts[NSAPI_IPv6_BYTES/2];
 | 
			
		||||
    memset(shorts, 0, sizeof shorts);
 | 
			
		||||
 | 
			
		||||
    int suffix = 0;
 | 
			
		||||
 | 
			
		||||
    // Find double colons and scan suffix
 | 
			
		||||
    for (int i = 0; addr[i]; i++) {
 | 
			
		||||
        if (addr[i] == ':' && addr[i+1] == ':') {
 | 
			
		||||
            suffix = ipv6_scan_chunk(shorts, &addr[i+2]);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Move suffix to end
 | 
			
		||||
    memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
 | 
			
		||||
            suffix*sizeof(uint16_t));
 | 
			
		||||
 | 
			
		||||
    // Scan prefix
 | 
			
		||||
    ipv6_scan_chunk(shorts, &addr[0]);
 | 
			
		||||
 | 
			
		||||
    // Flip bytes
 | 
			
		||||
    for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
 | 
			
		||||
        bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
 | 
			
		||||
        bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipv4_to_address(char *addr, const uint8_t *bytes)
 | 
			
		||||
{
 | 
			
		||||
    sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipv6_to_address(char *addr, const uint8_t *bytes)
 | 
			
		||||
{
 | 
			
		||||
    for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
 | 
			
		||||
        sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]);
 | 
			
		||||
        addr[5*i+4] = ':';
 | 
			
		||||
    }
 | 
			
		||||
    addr[NSAPI_IPv6_SIZE-1] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SocketAddress::SocketAddress(nsapi_addr_t addr, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    _ip_address[0] = '\0';
 | 
			
		||||
    set_addr(addr);
 | 
			
		||||
    set_port(port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SocketAddress::SocketAddress(const char *addr, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    _ip_address[0] = '\0';
 | 
			
		||||
    set_ip_address(addr);
 | 
			
		||||
    set_port(port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    _ip_address[0] = '\0';
 | 
			
		||||
    set_ip_bytes(bytes, version);
 | 
			
		||||
    set_port(port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SocketAddress::SocketAddress(const SocketAddress &addr)
 | 
			
		||||
{
 | 
			
		||||
    _ip_address[0] = '\0';
 | 
			
		||||
    set_addr(addr.get_addr());
 | 
			
		||||
    set_port(addr.get_port());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketAddress::set_ip_address(const char *addr)
 | 
			
		||||
{
 | 
			
		||||
    _ip_address[0] = '\0';
 | 
			
		||||
 | 
			
		||||
    if (addr && ipv4_is_valid(addr)) {
 | 
			
		||||
        _addr.version = NSAPI_IPv4;
 | 
			
		||||
        ipv4_from_address(_addr.bytes, addr);
 | 
			
		||||
    } else if (addr && ipv6_is_valid(addr)) {
 | 
			
		||||
        _addr.version = NSAPI_IPv6;
 | 
			
		||||
        ipv6_from_address(_addr.bytes, addr);
 | 
			
		||||
    } else {
 | 
			
		||||
        _addr = (nsapi_addr_t){};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_addr_t addr;
 | 
			
		||||
    addr.version = version;
 | 
			
		||||
    memcpy(addr.bytes, bytes, NSAPI_IP_BYTES);
 | 
			
		||||
    set_addr(addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketAddress::set_addr(nsapi_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    _ip_address[0] = '\0';
 | 
			
		||||
    _addr = addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketAddress::set_port(uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    _port = port;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *SocketAddress::get_ip_address() const
 | 
			
		||||
{
 | 
			
		||||
    char *ip_address = (char *)_ip_address;
 | 
			
		||||
 | 
			
		||||
    if (!ip_address[0]) {
 | 
			
		||||
        if (_addr.version == NSAPI_IPv4) {
 | 
			
		||||
            ipv4_to_address(ip_address, _addr.bytes);
 | 
			
		||||
        } else if (_addr.version == NSAPI_IPv6) {
 | 
			
		||||
            ipv6_to_address(ip_address, _addr.bytes);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ip_address;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const void *SocketAddress::get_ip_bytes() const
 | 
			
		||||
{
 | 
			
		||||
    return _addr.bytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_version_t SocketAddress::get_ip_version() const
 | 
			
		||||
{
 | 
			
		||||
    return _addr.version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_addr_t SocketAddress::get_addr() const
 | 
			
		||||
{
 | 
			
		||||
    return _addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t SocketAddress::get_port() const
 | 
			
		||||
{
 | 
			
		||||
    return _port;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SocketAddress::operator bool() const
 | 
			
		||||
{
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    if (_addr.version == NSAPI_IPv4) {
 | 
			
		||||
        count = NSAPI_IPv4_BYTES;
 | 
			
		||||
    } else if (_addr.version == NSAPI_IPv6) {
 | 
			
		||||
        count = NSAPI_IPv6_BYTES;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < count; i++) {
 | 
			
		||||
        if (_addr.bytes[i]) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    _ip_address[0] = '\0';
 | 
			
		||||
 | 
			
		||||
    // Check for valid IP addresses
 | 
			
		||||
    if (host && ipv4_is_valid(host)) {
 | 
			
		||||
        _addr.version = NSAPI_IPv4;
 | 
			
		||||
        ipv4_from_address(_addr.bytes, host);
 | 
			
		||||
        _port = port;
 | 
			
		||||
    } else if (host && ipv6_is_valid(host)) {
 | 
			
		||||
        _addr.version = NSAPI_IPv6;
 | 
			
		||||
        ipv6_from_address(_addr.bytes, host);
 | 
			
		||||
        _port = port;
 | 
			
		||||
    } else {
 | 
			
		||||
        // DNS lookup
 | 
			
		||||
        int err = iface->gethostbyname(this, host);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            _addr = (nsapi_addr_t){};
 | 
			
		||||
            _port = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,149 @@
 | 
			
		|||
/* SocketAddress
 | 
			
		||||
 * 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 SOCKET_ADDRESS_H
 | 
			
		||||
#define SOCKET_ADDRESS_H
 | 
			
		||||
 | 
			
		||||
#include "nsapi_types.h"
 | 
			
		||||
#include "toolchain.h"
 | 
			
		||||
 | 
			
		||||
// Predeclared classes
 | 
			
		||||
class NetworkStack;
 | 
			
		||||
class NetworkInterface;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** SocketAddress class
 | 
			
		||||
 *
 | 
			
		||||
 *  Representation of an IP address and port pair. 
 | 
			
		||||
 */
 | 
			
		||||
class SocketAddress {
 | 
			
		||||
public:
 | 
			
		||||
    /** Create a SocketAddress from a hostname and port
 | 
			
		||||
     *
 | 
			
		||||
     *  The hostname may be either a domain name or an IP address. If the
 | 
			
		||||
     *  hostname is an IP address, no network transactions will be performed.
 | 
			
		||||
     *
 | 
			
		||||
     *  On failure, the IP address and port will be set to zero
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack to use for DNS resolution
 | 
			
		||||
     *  @param host     Hostname to resolve
 | 
			
		||||
     *  @param port     Optional 16-bit port
 | 
			
		||||
     */
 | 
			
		||||
    template <typename S>
 | 
			
		||||
    SocketAddress(S *stack, const char *host, uint16_t port = 0)
 | 
			
		||||
    {
 | 
			
		||||
        _SocketAddress(nsapi_create_stack(stack), host, port);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Create a SocketAddress from a raw IP address and port
 | 
			
		||||
     *
 | 
			
		||||
     *  @param addr     Raw IP address
 | 
			
		||||
     *  @param port     Optional 16-bit port
 | 
			
		||||
     */
 | 
			
		||||
    SocketAddress(nsapi_addr_t addr = (nsapi_addr_t){}, uint16_t port = 0);
 | 
			
		||||
 | 
			
		||||
    /** Create a SocketAddress from an IP address and port
 | 
			
		||||
     *
 | 
			
		||||
     *  @param host     Null-terminated representation of the IP address
 | 
			
		||||
     *  @param port     Optional 16-bit port
 | 
			
		||||
     */
 | 
			
		||||
    SocketAddress(const char *addr, uint16_t port = 0);
 | 
			
		||||
 | 
			
		||||
    /** Create a SocketAddress from raw IP bytes, IP version, and port
 | 
			
		||||
     *
 | 
			
		||||
     *  @param bytes    Raw IP address in big-endian order
 | 
			
		||||
     *  @param version  IP address version, NSAPI_IPv4 or NSAPI_IPv6
 | 
			
		||||
     *  @param port     Optional 16-bit port
 | 
			
		||||
     */
 | 
			
		||||
    SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port = 0);
 | 
			
		||||
 | 
			
		||||
    /** Create a SocketAddress from another SocketAddress
 | 
			
		||||
     *
 | 
			
		||||
     *  @param address  SocketAddress to copy
 | 
			
		||||
     */
 | 
			
		||||
    SocketAddress(const SocketAddress &addr);
 | 
			
		||||
   
 | 
			
		||||
    /** Set the IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  @param addr     Null-terminated represention of the IP address
 | 
			
		||||
     */
 | 
			
		||||
    void set_ip_address(const char *addr);
 | 
			
		||||
 | 
			
		||||
    /** Set the raw IP bytes and IP version
 | 
			
		||||
     *
 | 
			
		||||
     *  @param bytes    Raw IP address in big-endian order
 | 
			
		||||
     *  @param version  IP address version, NSAPI_IPv4 or NSAPI_IPv6
 | 
			
		||||
     */
 | 
			
		||||
    void set_ip_bytes(const void *bytes, nsapi_version_t version);
 | 
			
		||||
 | 
			
		||||
    /** Set the raw IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  @param addr     Raw IP address
 | 
			
		||||
     */
 | 
			
		||||
    void set_addr(nsapi_addr_t addr);
 | 
			
		||||
 | 
			
		||||
    /** Set the port
 | 
			
		||||
     *
 | 
			
		||||
     *  @param port     16-bit port
 | 
			
		||||
     */
 | 
			
		||||
    void set_port(uint16_t port);
 | 
			
		||||
    
 | 
			
		||||
    /** Get the IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Null-terminated representation of the IP Address
 | 
			
		||||
     */
 | 
			
		||||
    const char *get_ip_address() const;
 | 
			
		||||
 | 
			
		||||
    /*  Get the raw IP bytes
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Raw IP address in big-endian order
 | 
			
		||||
     */
 | 
			
		||||
    const void *get_ip_bytes() const;
 | 
			
		||||
 | 
			
		||||
    /** Get the IP address version
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         IP address version, NSAPI_IPv4 or NSAPI_IPv6
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_version_t get_ip_version() const;
 | 
			
		||||
 | 
			
		||||
    /** Get the raw IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Raw IP address
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_addr_t get_addr() const;
 | 
			
		||||
    
 | 
			
		||||
    /** Get the port
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         The 16-bit port
 | 
			
		||||
     */
 | 
			
		||||
    uint16_t get_port() const;
 | 
			
		||||
 | 
			
		||||
    /** Test if address is zero
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         True if address is not zero
 | 
			
		||||
     */
 | 
			
		||||
    operator bool() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void _SocketAddress(NetworkStack *iface, const char *host, uint16_t port);
 | 
			
		||||
 | 
			
		||||
    char _ip_address[NSAPI_IP_SIZE];
 | 
			
		||||
    nsapi_addr_t _addr;
 | 
			
		||||
    uint16_t _port;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,110 @@
 | 
			
		|||
/* Socket
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "TCPServer.h"
 | 
			
		||||
#include "Timer.h"
 | 
			
		||||
 | 
			
		||||
TCPServer::TCPServer()
 | 
			
		||||
    : _pending(0), _accept_sem(0)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TCPServer::~TCPServer()
 | 
			
		||||
{
 | 
			
		||||
    close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_protocol_t TCPServer::get_proto()
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_TCP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TCPServer::listen(int backlog)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (!_socket) {
 | 
			
		||||
        ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = _stack->socket_listen(_socket, backlog);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TCPServer::accept(TCPSocket *connection)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (!_socket) {
 | 
			
		||||
            ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
            break;
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        _pending = 0;
 | 
			
		||||
        void *socket;
 | 
			
		||||
        ret = _stack->socket_accept(&socket, _socket);
 | 
			
		||||
 | 
			
		||||
        if (0 == ret) {
 | 
			
		||||
            connection->_lock.lock();
 | 
			
		||||
 | 
			
		||||
            if (connection->_socket) {
 | 
			
		||||
                connection->close();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            connection->_stack = _stack;
 | 
			
		||||
            connection->_socket = socket;
 | 
			
		||||
            connection->_event = Callback<void()>(connection, &TCPSocket::event);
 | 
			
		||||
            _stack->socket_attach(socket, &Callback<void()>::thunk, &connection->_event);
 | 
			
		||||
 | 
			
		||||
            connection->_lock.unlock();
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (NSAPI_ERROR_WOULD_BLOCK == ret) {
 | 
			
		||||
            int32_t count;
 | 
			
		||||
 | 
			
		||||
            _lock.unlock();
 | 
			
		||||
            count = _accept_sem.wait(_timeout);
 | 
			
		||||
            _lock.lock();
 | 
			
		||||
 | 
			
		||||
            if (count < 1) {
 | 
			
		||||
                ret = NSAPI_ERROR_WOULD_BLOCK;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TCPServer::event()
 | 
			
		||||
{
 | 
			
		||||
    int32_t acount = _accept_sem.wait(0);
 | 
			
		||||
    if (acount <= 1) {
 | 
			
		||||
        _accept_sem.release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _pending += 1;
 | 
			
		||||
    if (_callback && _pending == 1) {
 | 
			
		||||
        _callback();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
/* TCPServer
 | 
			
		||||
 * 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 TCPSERVER_H
 | 
			
		||||
#define TCPSERVER_H
 | 
			
		||||
 | 
			
		||||
#include "network-socket/Socket.h"
 | 
			
		||||
#include "network-socket/TCPSocket.h"
 | 
			
		||||
#include "network-socket/NetworkStack.h"
 | 
			
		||||
#include "network-socket/NetworkInterface.h"
 | 
			
		||||
#include "rtos/Semaphore.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** TCP socket server
 | 
			
		||||
  */
 | 
			
		||||
class TCPServer : public Socket {
 | 
			
		||||
public:
 | 
			
		||||
    /** Create an uninitialized socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Must call open to initialize the socket on a network stack.
 | 
			
		||||
     */
 | 
			
		||||
    TCPServer();
 | 
			
		||||
 | 
			
		||||
    /** Create a socket on a network interface
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates and opens a socket on the network stack of the given
 | 
			
		||||
     *  network interface.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket
 | 
			
		||||
     */
 | 
			
		||||
    TCPServer(NetworkStack *stack);
 | 
			
		||||
 | 
			
		||||
    template <typename IF>
 | 
			
		||||
    TCPServer(IF *iface)
 | 
			
		||||
        : _pending(0), _accept_sem(0)
 | 
			
		||||
    {
 | 
			
		||||
        open(iface->get_stack());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Destroy a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Closes socket if the socket is still open
 | 
			
		||||
     */
 | 
			
		||||
    virtual ~TCPServer();
 | 
			
		||||
 | 
			
		||||
    /** Listen for connections on a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Marks the socket as a passive socket that can be used to accept
 | 
			
		||||
     *  incoming connections.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param backlog  Number of pending connections that can be queued
 | 
			
		||||
     *                  simultaneously, defaults to 1
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int listen(int backlog = 1);
 | 
			
		||||
    
 | 
			
		||||
    /** Accepts a connection on a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The server socket must be bound and set to listen for connections.
 | 
			
		||||
     *  On a new connection, creates a network socket using the specified
 | 
			
		||||
     *  socket instance.
 | 
			
		||||
     *
 | 
			
		||||
     *  By default, accept blocks until data is sent. If socket is set to
 | 
			
		||||
     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
 | 
			
		||||
     *  immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param socket   TCPSocket instance that will handle the incoming connection.
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int accept(TCPSocket *connection);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual nsapi_protocol_t get_proto();
 | 
			
		||||
    virtual void event();
 | 
			
		||||
 | 
			
		||||
    volatile unsigned _pending;
 | 
			
		||||
    rtos::Semaphore _accept_sem;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,166 @@
 | 
			
		|||
/* Socket
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "TCPSocket.h"
 | 
			
		||||
#include "Timer.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
 | 
			
		||||
TCPSocket::TCPSocket()
 | 
			
		||||
    : _pending(0), _read_sem(0), _write_sem(0),
 | 
			
		||||
      _read_in_progress(false), _write_in_progress(false)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TCPSocket::~TCPSocket()
 | 
			
		||||
{
 | 
			
		||||
    close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_protocol_t TCPSocket::get_proto()
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_TCP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TCPSocket::connect(const SocketAddress &address)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (!_socket) {
 | 
			
		||||
        ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = _stack->socket_connect(_socket, address);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TCPSocket::connect(const char *host, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress address(_stack, host, port);
 | 
			
		||||
    if (!address) {
 | 
			
		||||
        return NSAPI_ERROR_DNS_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // connect is thread safe
 | 
			
		||||
    return connect(address);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TCPSocket::send(const void *data, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    // If this assert is hit then there are two threads
 | 
			
		||||
    // performing a send at the same time which is undefined
 | 
			
		||||
    // behavior
 | 
			
		||||
    MBED_ASSERT(!_write_in_progress);
 | 
			
		||||
    _write_in_progress = true;
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (!_socket) {
 | 
			
		||||
            ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _pending = 0;
 | 
			
		||||
        int sent = _stack->socket_send(_socket, data, size);
 | 
			
		||||
        if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
 | 
			
		||||
            ret = sent;
 | 
			
		||||
            break;
 | 
			
		||||
        } else {
 | 
			
		||||
            int32_t count;
 | 
			
		||||
 | 
			
		||||
            // Release lock before blocking so other threads
 | 
			
		||||
            // accessing this object aren't blocked
 | 
			
		||||
            _lock.unlock();
 | 
			
		||||
            count = _write_sem.wait(_timeout);
 | 
			
		||||
            _lock.lock();
 | 
			
		||||
 | 
			
		||||
            if (count < 1) {
 | 
			
		||||
                // Semaphore wait timed out so break out and return
 | 
			
		||||
                ret = NSAPI_ERROR_WOULD_BLOCK;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _write_in_progress = false;
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TCPSocket::recv(void *data, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    // If this assert is hit then there are two threads
 | 
			
		||||
    // performing a recv at the same time which is undefined
 | 
			
		||||
    // behavior
 | 
			
		||||
    MBED_ASSERT(!_read_in_progress);
 | 
			
		||||
    _read_in_progress = true;
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (!_socket) {
 | 
			
		||||
            ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _pending = 0;
 | 
			
		||||
        int recv = _stack->socket_recv(_socket, data, size);
 | 
			
		||||
        if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
 | 
			
		||||
            ret = recv;
 | 
			
		||||
            break;
 | 
			
		||||
        } else {
 | 
			
		||||
            int32_t count;
 | 
			
		||||
 | 
			
		||||
            // Release lock before blocking so other threads
 | 
			
		||||
            // accessing this object aren't blocked
 | 
			
		||||
            _lock.unlock();
 | 
			
		||||
            count = _read_sem.wait(_timeout);
 | 
			
		||||
            _lock.lock();
 | 
			
		||||
 | 
			
		||||
            if (count < 1) {
 | 
			
		||||
                // Semaphore wait timed out so break out and return
 | 
			
		||||
                ret = NSAPI_ERROR_WOULD_BLOCK;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _read_in_progress = false;
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TCPSocket::event()
 | 
			
		||||
{
 | 
			
		||||
    int32_t wcount = _write_sem.wait(0);
 | 
			
		||||
    if (wcount <= 1) {
 | 
			
		||||
        _write_sem.release();
 | 
			
		||||
    }
 | 
			
		||||
    int32_t rcount = _read_sem.wait(0);
 | 
			
		||||
    if (rcount <= 1) {
 | 
			
		||||
        _read_sem.release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _pending += 1;
 | 
			
		||||
    if (_callback && _pending == 1) {
 | 
			
		||||
        _callback();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
/* TCPSocket
 | 
			
		||||
 * 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 TCPSOCKET_H
 | 
			
		||||
#define TCPSOCKET_H
 | 
			
		||||
 | 
			
		||||
#include "network-socket/Socket.h"
 | 
			
		||||
#include "network-socket/NetworkStack.h"
 | 
			
		||||
#include "network-socket/NetworkInterface.h"
 | 
			
		||||
#include "rtos/Semaphore.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** TCP socket connection
 | 
			
		||||
 */
 | 
			
		||||
class TCPSocket : public Socket {
 | 
			
		||||
public:
 | 
			
		||||
    /** Create an uninitialized socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Must call open to initialize the socket on a network stack.
 | 
			
		||||
     */
 | 
			
		||||
    TCPSocket();
 | 
			
		||||
 | 
			
		||||
    /** Create a socket on a network interface
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates and opens a socket on the network stack of the given
 | 
			
		||||
     *  network interface.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket
 | 
			
		||||
     */
 | 
			
		||||
    template <typename S>
 | 
			
		||||
    TCPSocket(S *stack)
 | 
			
		||||
        : _pending(0), _read_sem(0), _write_sem(0),
 | 
			
		||||
          _read_in_progress(false), _write_in_progress(false)
 | 
			
		||||
    {
 | 
			
		||||
        open(stack);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Destroy a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Closes socket if the socket is still open
 | 
			
		||||
     */
 | 
			
		||||
    virtual ~TCPSocket();
 | 
			
		||||
 | 
			
		||||
    /** Connects TCP socket to a remote host
 | 
			
		||||
     *
 | 
			
		||||
     *  Initiates a connection to a remote server specified by either
 | 
			
		||||
     *  a domain name or an IP address and a port.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param host     Hostname of the remote host
 | 
			
		||||
     *  @param port     Port of the remote host
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int connect(const char *host, uint16_t port);
 | 
			
		||||
 | 
			
		||||
    /** Connects TCP socket to a remote host
 | 
			
		||||
     *
 | 
			
		||||
     *  Initiates a connection to a remote server specified by the
 | 
			
		||||
     *  indicated address.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param address  The SocketAddress of the remote host
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int connect(const SocketAddress &address);
 | 
			
		||||
    
 | 
			
		||||
    /** Send data over a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The socket must be connected to a remote host. Returns the number of
 | 
			
		||||
     *  bytes sent from the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  By default, send blocks until data is sent. If socket is set to
 | 
			
		||||
     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
 | 
			
		||||
     *  immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param data     Buffer of data to send to the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of sent bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int send(const void *data, unsigned size);
 | 
			
		||||
    
 | 
			
		||||
    /** Receive data over a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The socket must be connected to a remote host. Returns the number of
 | 
			
		||||
     *  bytes received into the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  By default, recv blocks until data is sent. If socket is set to
 | 
			
		||||
     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
 | 
			
		||||
     *  immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param data     Destination buffer for data received from the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of received bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int recv(void *data, unsigned size);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    friend class TCPServer;
 | 
			
		||||
 | 
			
		||||
    virtual nsapi_protocol_t get_proto();
 | 
			
		||||
    virtual void event();
 | 
			
		||||
 | 
			
		||||
    volatile unsigned _pending;
 | 
			
		||||
    rtos::Semaphore _read_sem;
 | 
			
		||||
    rtos::Semaphore _write_sem;
 | 
			
		||||
    bool _read_in_progress;
 | 
			
		||||
    bool _write_in_progress;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,151 @@
 | 
			
		|||
/* Socket
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "UDPSocket.h"
 | 
			
		||||
#include "Timer.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
 | 
			
		||||
UDPSocket::UDPSocket()
 | 
			
		||||
    : _pending(0), _read_sem(0), _write_sem(0),
 | 
			
		||||
      _read_in_progress(false), _write_in_progress(false)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UDPSocket::~UDPSocket()
 | 
			
		||||
{
 | 
			
		||||
    close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_protocol_t UDPSocket::get_proto()
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_UDP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int UDPSocket::sendto(const char *host, uint16_t port, const void *data, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress address(_stack, host, port);
 | 
			
		||||
    if (!address) {
 | 
			
		||||
        return NSAPI_ERROR_DNS_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // sendto is thread safe
 | 
			
		||||
    return sendto(address, data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int UDPSocket::sendto(const SocketAddress &address, const void *data, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    // If this assert is hit then there are two threads
 | 
			
		||||
    // performing a send at the same time which is undefined
 | 
			
		||||
    // behavior
 | 
			
		||||
    MBED_ASSERT(!_write_in_progress);
 | 
			
		||||
    _write_in_progress = true;
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (!_socket) {
 | 
			
		||||
            ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _pending = 0;
 | 
			
		||||
        int sent = _stack->socket_sendto(_socket, address, data, size);
 | 
			
		||||
        if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
 | 
			
		||||
            ret = sent;
 | 
			
		||||
            break;
 | 
			
		||||
        } else {
 | 
			
		||||
            int32_t count;
 | 
			
		||||
 | 
			
		||||
            // Release lock before blocking so other threads
 | 
			
		||||
            // accessing this object aren't blocked
 | 
			
		||||
            _lock.unlock();
 | 
			
		||||
            count = _write_sem.wait(_timeout);
 | 
			
		||||
            _lock.lock();
 | 
			
		||||
 | 
			
		||||
            if (count < 1) {
 | 
			
		||||
                // Semaphore wait timed out so break out and return
 | 
			
		||||
                ret = NSAPI_ERROR_WOULD_BLOCK;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _write_in_progress = false;
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int UDPSocket::recvfrom(SocketAddress *address, void *buffer, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    _lock.lock();
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    // If this assert is hit then there are two threads
 | 
			
		||||
    // performing a recv at the same time which is undefined
 | 
			
		||||
    // behavior
 | 
			
		||||
    MBED_ASSERT(!_read_in_progress);
 | 
			
		||||
    _read_in_progress = true;
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (!_socket) {
 | 
			
		||||
            ret = NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _pending = 0;
 | 
			
		||||
        int recv = _stack->socket_recvfrom(_socket, address, buffer, size);
 | 
			
		||||
        if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
 | 
			
		||||
            ret = recv;
 | 
			
		||||
            break;
 | 
			
		||||
        } else {
 | 
			
		||||
            int32_t count;
 | 
			
		||||
 | 
			
		||||
            // Release lock before blocking so other threads
 | 
			
		||||
            // accessing this object aren't blocked
 | 
			
		||||
            _lock.unlock();
 | 
			
		||||
            count = _read_sem.wait(_timeout);
 | 
			
		||||
            _lock.lock();
 | 
			
		||||
 | 
			
		||||
            if (count < 1) {
 | 
			
		||||
                // Semaphore wait timed out so break out and return
 | 
			
		||||
                ret = NSAPI_ERROR_WOULD_BLOCK;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _read_in_progress = false;
 | 
			
		||||
    _lock.unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UDPSocket::event()
 | 
			
		||||
{
 | 
			
		||||
    int32_t wcount = _write_sem.wait(0);
 | 
			
		||||
    if (wcount <= 1) {
 | 
			
		||||
        _write_sem.release();
 | 
			
		||||
    }
 | 
			
		||||
    int32_t rcount = _read_sem.wait(0);
 | 
			
		||||
    if (rcount <= 1) {
 | 
			
		||||
        _read_sem.release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _pending += 1;
 | 
			
		||||
    if (_callback && _pending == 1) {
 | 
			
		||||
        _callback();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,122 @@
 | 
			
		|||
/* UDPSocket
 | 
			
		||||
 * 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 UDPSOCKET_H
 | 
			
		||||
#define UDPSOCKET_H
 | 
			
		||||
 | 
			
		||||
#include "network-socket/Socket.h"
 | 
			
		||||
#include "network-socket/NetworkStack.h"
 | 
			
		||||
#include "network-socket/NetworkInterface.h"
 | 
			
		||||
#include "rtos/Semaphore.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** UDP socket
 | 
			
		||||
 */
 | 
			
		||||
class UDPSocket : public Socket {
 | 
			
		||||
public:
 | 
			
		||||
    /** Create an uninitialized socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Must call open to initialize the socket on a network stack.
 | 
			
		||||
     */
 | 
			
		||||
    UDPSocket();
 | 
			
		||||
 | 
			
		||||
    /** Create a socket on a network interface
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates and opens a socket on the network stack of the given
 | 
			
		||||
     *  network interface.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket
 | 
			
		||||
     */
 | 
			
		||||
    template <typename S>
 | 
			
		||||
    UDPSocket(S *stack)
 | 
			
		||||
        : _pending(0), _read_sem(0), _write_sem(0),
 | 
			
		||||
          _read_in_progress(false), _write_in_progress(false)
 | 
			
		||||
    {
 | 
			
		||||
        open(stack);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Destroy a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Closes socket if the socket is still open
 | 
			
		||||
     */
 | 
			
		||||
    virtual ~UDPSocket();
 | 
			
		||||
 | 
			
		||||
    /** Send a packet over a UDP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Sends data to the specified address specified by either a domain name
 | 
			
		||||
     *  or an IP address and port. Returns the number of bytes sent from the
 | 
			
		||||
     *  buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  By default, sendto blocks until data is sent. If socket is set to
 | 
			
		||||
     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
 | 
			
		||||
     *  immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param host     Hostname of the remote host
 | 
			
		||||
     *  @param port     Port of the remote host
 | 
			
		||||
     *  @param data     Buffer of data to send to the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of sent bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int sendto(const char *host, uint16_t port, const void *data, unsigned size);
 | 
			
		||||
 | 
			
		||||
    /** Send a packet over a UDP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Sends data to the specified address. Returns the number of bytes
 | 
			
		||||
     *  sent from the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  By default, sendto blocks until data is sent. If socket is set to
 | 
			
		||||
     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
 | 
			
		||||
     *  immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param address  The SocketAddress of the remote host
 | 
			
		||||
     *  @param data     Buffer of data to send to the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of sent bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int sendto(const SocketAddress &address, const void *data, unsigned size);
 | 
			
		||||
 | 
			
		||||
    /** Receive a packet over a UDP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Receives data and stores the source address in address if address
 | 
			
		||||
     *  is not NULL. Returns the number of bytes received into the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  By default, recvfrom blocks until data is sent. If socket is set to
 | 
			
		||||
     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
 | 
			
		||||
     *  immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param address  Destination for the source address or NULL
 | 
			
		||||
     *  @param data     Destination buffer for data received from the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of received bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int recvfrom(SocketAddress *address, void *data, unsigned size);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual nsapi_protocol_t get_proto();
 | 
			
		||||
    virtual void event();
 | 
			
		||||
 | 
			
		||||
    volatile unsigned _pending;
 | 
			
		||||
    rtos::Semaphore _read_sem;
 | 
			
		||||
    rtos::Semaphore _write_sem;
 | 
			
		||||
    bool _read_in_progress;
 | 
			
		||||
    bool _write_in_progress;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,70 @@
 | 
			
		|||
/* WiFiInterface
 | 
			
		||||
 * 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 WIFI_INTERFACE_H
 | 
			
		||||
#define WIFI_INTERFACE_H
 | 
			
		||||
 | 
			
		||||
#include "network-socket/NetworkInterface.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Enum of WiFi encryption types
 | 
			
		||||
 *
 | 
			
		||||
 *  The security type specifies a particular security to use when
 | 
			
		||||
 *  connected to a WiFi network
 | 
			
		||||
 *
 | 
			
		||||
 *  @enum nsapi_protocol_t
 | 
			
		||||
 */
 | 
			
		||||
enum nsapi_security_t {
 | 
			
		||||
    NSAPI_SECURITY_NONE = 0,   /*!< open access point */
 | 
			
		||||
    NSAPI_SECURITY_WEP,        /*!< phrase conforms to WEP */
 | 
			
		||||
    NSAPI_SECURITY_WPA,        /*!< phrase conforms to WPA */
 | 
			
		||||
    NSAPI_SECURITY_WPA2,       /*!< phrase conforms to WPA2 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** WiFiInterface class
 | 
			
		||||
 *
 | 
			
		||||
 *  Common interface that is shared between WiFi devices
 | 
			
		||||
 */
 | 
			
		||||
class WiFiInterface: public NetworkInterface
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** Start the interface
 | 
			
		||||
     *
 | 
			
		||||
     *  Attempts to connect to a WiFi network. If passphrase is invalid,
 | 
			
		||||
     *  NSAPI_ERROR_AUTH_ERROR is returned.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param ssid      Name of the network to connect to
 | 
			
		||||
     *  @param pass      Security passphrase to connect to the network
 | 
			
		||||
     *  @param security  Type of encryption for connection
 | 
			
		||||
     *  @return          0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE) = 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
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
/* nsapi.h - The network socket API
 | 
			
		||||
 * 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 NSAPI_H
 | 
			
		||||
#define NSAPI_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// entry point for nsapi types
 | 
			
		||||
#include "nsapi_types.h"
 | 
			
		||||
 | 
			
		||||
// disable bug-compatible mbed inclusion
 | 
			
		||||
#define NSAPI_NO_INCLUDE_MBED
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 | 
			
		||||
// entry point for C++ api
 | 
			
		||||
#include "network-socket/SocketAddress.h"
 | 
			
		||||
#include "network-socket/NetworkStack.h"
 | 
			
		||||
 | 
			
		||||
#include "network-socket/NetworkInterface.h"
 | 
			
		||||
#include "network-socket/EthInterface.h"
 | 
			
		||||
#include "network-socket/WiFiInterface.h"
 | 
			
		||||
#include "network-socket/CellularInterface.h"
 | 
			
		||||
#include "network-socket/MeshInterface.h"
 | 
			
		||||
 | 
			
		||||
#include "network-socket/Socket.h"
 | 
			
		||||
#include "network-socket/UDPSocket.h"
 | 
			
		||||
#include "network-socket/TCPSocket.h"
 | 
			
		||||
#include "network-socket/TCPServer.h"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,445 @@
 | 
			
		|||
/* nsapi.h - The network socket API
 | 
			
		||||
 * 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 NSAPI_TYPES_H
 | 
			
		||||
#define NSAPI_TYPES_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Enum of standardized error codes 
 | 
			
		||||
 *
 | 
			
		||||
 *  Valid error codes have negative values and may
 | 
			
		||||
 *  be returned by any network operation.
 | 
			
		||||
 *
 | 
			
		||||
 *  @enum nsapi_error_t
 | 
			
		||||
 */
 | 
			
		||||
typedef enum nsapi_error {
 | 
			
		||||
    NSAPI_ERROR_WOULD_BLOCK   = -3001,     /*!< no data is not available but call is non-blocking */
 | 
			
		||||
    NSAPI_ERROR_UNSUPPORTED   = -3002,     /*!< unsupported functionality */
 | 
			
		||||
    NSAPI_ERROR_PARAMETER     = -3003,     /*!< invalid configuration */
 | 
			
		||||
    NSAPI_ERROR_NO_CONNECTION = -3004,     /*!< not connected to a network */
 | 
			
		||||
    NSAPI_ERROR_NO_SOCKET     = -3005,     /*!< socket not available for use */
 | 
			
		||||
    NSAPI_ERROR_NO_ADDRESS    = -3006,     /*!< IP address is not known */
 | 
			
		||||
    NSAPI_ERROR_NO_MEMORY     = -3007,     /*!< memory resource not available */
 | 
			
		||||
    NSAPI_ERROR_DNS_FAILURE   = -3008,     /*!< DNS failed to complete successfully */
 | 
			
		||||
    NSAPI_ERROR_DHCP_FAILURE  = -3009,     /*!< DHCP failed to complete successfully */
 | 
			
		||||
    NSAPI_ERROR_AUTH_FAILURE  = -3010,     /*!< connection to access point faield */
 | 
			
		||||
    NSAPI_ERROR_DEVICE_ERROR  = -3011,     /*!< failure interfacing with the network procesor */
 | 
			
		||||
} nsapi_error_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Maximum size of IP address representation
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_IP_SIZE NSAPI_IPv6_SIZE
 | 
			
		||||
 | 
			
		||||
/** Maximum number of bytes for IP address
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_IP_BYTES NSAPI_IPv6_BYTES
 | 
			
		||||
 | 
			
		||||
/** Maximum size of MAC address representation
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_MAC_SIZE 18
 | 
			
		||||
 | 
			
		||||
/** Maximum number of bytes for MAC address
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_MAC_BYTES 6
 | 
			
		||||
 | 
			
		||||
/** Size of IPv4 representation
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_IPv4_SIZE 16
 | 
			
		||||
 | 
			
		||||
/** Number of bytes in IPv4 address
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_IPv4_BYTES 4
 | 
			
		||||
 | 
			
		||||
/** Size of IPv6 representation
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_IPv6_SIZE 40
 | 
			
		||||
 | 
			
		||||
/** Number of bytes in IPv6 address
 | 
			
		||||
 */
 | 
			
		||||
#define NSAPI_IPv6_BYTES 16
 | 
			
		||||
 | 
			
		||||
/** Enum of IP address versions
 | 
			
		||||
 *
 | 
			
		||||
 *  The IP version specifies the type of an IP address.
 | 
			
		||||
 *
 | 
			
		||||
 *  @enum nsapi_version_t
 | 
			
		||||
 */
 | 
			
		||||
typedef enum nsapi_version {
 | 
			
		||||
    NSAPI_IPv4, /*!< Address is IPv4 */
 | 
			
		||||
    NSAPI_IPv6, /*!< Address is IPv6 */
 | 
			
		||||
} nsapi_version_t;
 | 
			
		||||
 | 
			
		||||
/** IP address structure for passing IP addresses by value
 | 
			
		||||
 */
 | 
			
		||||
typedef struct nsapi_addr {
 | 
			
		||||
    /** IP version
 | 
			
		||||
     *  NSAPI_IPv4 or NSAPI_IPv6
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_version_t version;
 | 
			
		||||
 | 
			
		||||
    /** IP address
 | 
			
		||||
     *  The raw bytes of the IP address stored in big-endian format
 | 
			
		||||
     */
 | 
			
		||||
    uint8_t bytes[NSAPI_IP_BYTES];
 | 
			
		||||
} nsapi_addr_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Opaque handle for network sockets
 | 
			
		||||
 */
 | 
			
		||||
typedef void *nsapi_socket_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Enum of socket protocols
 | 
			
		||||
 *
 | 
			
		||||
 *  The socket protocol specifies a particular protocol to
 | 
			
		||||
 *  be used with a newly created socket. 
 | 
			
		||||
 *
 | 
			
		||||
 *  @enum nsapi_protocol_t
 | 
			
		||||
 */
 | 
			
		||||
typedef enum nsapi_protocol {
 | 
			
		||||
   NSAPI_TCP, /*!< Socket is of TCP type */
 | 
			
		||||
   NSAPI_UDP, /*!< Socket is of UDP type */
 | 
			
		||||
} nsapi_protocol_t;
 | 
			
		||||
 | 
			
		||||
/*  Enum of standardized stack option levels
 | 
			
		||||
 *
 | 
			
		||||
 *  @enum nsapi_level_t
 | 
			
		||||
 */
 | 
			
		||||
typedef enum nsapi_level {
 | 
			
		||||
    NSAPI_STACK,  /*!< Stack option level */
 | 
			
		||||
    NSAPI_SOCKET, /*!< Socket option level */
 | 
			
		||||
} nsapi_level_t;
 | 
			
		||||
 | 
			
		||||
/*  Enum of standardized stack options
 | 
			
		||||
 *
 | 
			
		||||
 *  These options may not be supported on all stacks, in which
 | 
			
		||||
 *  case NSAPI_ERROR_UNSUPPORTED may be returned from setsockopt.
 | 
			
		||||
 *
 | 
			
		||||
 *  @enum nsapi_option_t
 | 
			
		||||
 */
 | 
			
		||||
typedef enum nsapi_option {
 | 
			
		||||
    NSAPI_REUSEADDR, /*!< Allow bind to reuse local addresses */
 | 
			
		||||
    NSAPI_KEEPALIVE, /*!< Enables sending of keepalive messages */
 | 
			
		||||
    NSAPI_KEEPIDLE,  /*!< Sets timeout value to initiate keepalive */
 | 
			
		||||
    NSAPI_KEEPINTVL, /*!< Sets timeout value for keepalive */
 | 
			
		||||
    NSAPI_LINGER,    /*!< Keeps close from returning until queues empty */
 | 
			
		||||
    NSAPI_SNDBUF,    /*!< Sets send buffer size */
 | 
			
		||||
    NSAPI_RCVBUF,    /*!< Sets recv buffer size */
 | 
			
		||||
} nsapi_option_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** nsapi_stack structure
 | 
			
		||||
 *
 | 
			
		||||
 *  Stack structure representing a specific instance of a stack.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct nsapi_stack {
 | 
			
		||||
    /** Network stack operation table
 | 
			
		||||
     *
 | 
			
		||||
     *  Provides access to the underlying api of the stack. This is not
 | 
			
		||||
     *  flattened into the nsapi_stack to allow allocation in read-only
 | 
			
		||||
     *  memory.
 | 
			
		||||
     */
 | 
			
		||||
    const struct nsapi_stack_api *stack_api;
 | 
			
		||||
 | 
			
		||||
    /** Opaque handle for network stacks
 | 
			
		||||
     */
 | 
			
		||||
    void *stack;
 | 
			
		||||
 | 
			
		||||
    // Internal nsapi buffer
 | 
			
		||||
    unsigned _stack_buffer[16];
 | 
			
		||||
} nsapi_stack_t;
 | 
			
		||||
 | 
			
		||||
/** nsapi_stack_api structure
 | 
			
		||||
 *
 | 
			
		||||
 *  Common api structure for network stack operations. A network stack
 | 
			
		||||
 *  can provide a nsapi_stack_api structure filled out with the
 | 
			
		||||
 *  appropriate implementation.
 | 
			
		||||
 *
 | 
			
		||||
 *  Unsupported operations can be left as null pointers.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct nsapi_stack_api
 | 
			
		||||
{
 | 
			
		||||
    /** Get the local IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @return         Local IP Address or null address if not connected
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_addr_t (*get_ip_address)(nsapi_stack_t *stack);
 | 
			
		||||
 | 
			
		||||
    /** Translates a hostname to an IP address
 | 
			
		||||
     *
 | 
			
		||||
     *  The hostname may be either a domain name or an IP address. If the
 | 
			
		||||
     *  hostname is an IP address, no network transactions will be performed.
 | 
			
		||||
     *  
 | 
			
		||||
     *  If no stack-specific DNS resolution is provided, the hostname
 | 
			
		||||
     *  will be resolve using a UDP socket on the stack. 
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param addr     Destination for the host IP address
 | 
			
		||||
     *  @param host     Hostname to resolve
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*gethostbyname)(nsapi_stack_t *stack, nsapi_addr_t *addr, const char *host);
 | 
			
		||||
 | 
			
		||||
    /*  Set stack-specific stack options
 | 
			
		||||
     *
 | 
			
		||||
     *  The setstackopt allow an application to pass stack-specific hints
 | 
			
		||||
     *  to the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and the stack is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*setstackopt)(nsapi_stack_t *stack, int level, int optname, const void *optval, unsigned optlen);
 | 
			
		||||
 | 
			
		||||
    /*  Get stack-specific stack options
 | 
			
		||||
     *
 | 
			
		||||
     *  The getstackopt allow an application to retrieve stack-specific hints
 | 
			
		||||
     *  from the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Destination for option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    int (*getstackopt)(nsapi_stack_t *stack, int level, int optname, void *optval, unsigned *optlen);
 | 
			
		||||
 | 
			
		||||
    /** Opens a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates a network socket and stores it in the specified handle.
 | 
			
		||||
     *  The handle must be passed to following calls on the socket.
 | 
			
		||||
     *
 | 
			
		||||
     *  A stack may have a finite number of sockets, in this case
 | 
			
		||||
     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack context
 | 
			
		||||
     *  @param socket   Destination for the handle to a newly created socket
 | 
			
		||||
     *  @param proto    Protocol of socket to open, NSAPI_TCP or NSAPI_UDP
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_open)(nsapi_stack_t *stack, nsapi_socket_t *socket, nsapi_protocol_t proto);
 | 
			
		||||
 | 
			
		||||
    /** Close the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Closes any open connection and deallocates any memory associated
 | 
			
		||||
     *  with the socket.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_close)(nsapi_stack_t *stack, nsapi_socket_t socket);
 | 
			
		||||
 | 
			
		||||
    /** Bind a specific address to a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Binding a socket specifies the address and port on which to recieve
 | 
			
		||||
     *  data. If the IP address is zeroed, only the port is bound.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param addr     Local address to bind, may be null
 | 
			
		||||
     *  @param port     Local port to bind
 | 
			
		||||
     *  @return         0 on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_bind)(nsapi_stack_t *stack, nsapi_socket_t socket, nsapi_addr_t addr, uint16_t port);
 | 
			
		||||
 | 
			
		||||
    /** Listen for connections on a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Marks the socket as a passive socket that can be used to accept
 | 
			
		||||
     *  incoming connections.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param backlog  Number of pending connections that can be queued
 | 
			
		||||
     *                  simultaneously
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_listen)(nsapi_stack_t *stack, nsapi_socket_t socket, int backlog);
 | 
			
		||||
 | 
			
		||||
    /** Connects TCP socket to a remote host
 | 
			
		||||
     *
 | 
			
		||||
     *  Initiates a connection to a remote server specified by the
 | 
			
		||||
     *  indicated address.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param addr     The address of the remote host
 | 
			
		||||
     *  @param port     The port of the remote host
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_connect)(nsapi_stack_t *stack, nsapi_socket_t socket, nsapi_addr_t addr, uint16_t port);
 | 
			
		||||
 | 
			
		||||
    /** Accepts a connection on a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The server socket must be bound and set to listen for connections.
 | 
			
		||||
     *  On a new connection, creates a network socket and stores it in the
 | 
			
		||||
     *  specified handle. The handle must be passed to following calls on
 | 
			
		||||
     *  the socket.
 | 
			
		||||
     *
 | 
			
		||||
     *  A stack may have a finite number of sockets, in this case
 | 
			
		||||
     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If accept would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Destination for a handle to the newly created sockey
 | 
			
		||||
     *  @param server   Socket handle to server to accept from
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_accept)(nsapi_stack_t *stack, nsapi_socket_t *socket, nsapi_socket_t server);
 | 
			
		||||
 | 
			
		||||
    /** Send data over a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The socket must be connected to a remote host. Returns the number of
 | 
			
		||||
     *  bytes sent from the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If send would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param data     Buffer of data to send to the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of sent bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_send)(nsapi_stack_t *stack, nsapi_socket_t socket, const void *data, unsigned size);
 | 
			
		||||
 | 
			
		||||
    /** Receive data over a TCP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The socket must be connected to a remote host. Returns the number of
 | 
			
		||||
     *  bytes received into the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If recv would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param data     Destination buffer for data received from the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of received bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_recv)(nsapi_stack_t *stack, nsapi_socket_t socket, void *data, unsigned size);
 | 
			
		||||
 | 
			
		||||
    /** Send a packet over a UDP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Sends data to the specified address. Returns the number of bytes
 | 
			
		||||
     *  sent from the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If sendto would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param addr     The address of the remote host
 | 
			
		||||
     *  @param port     The port of the remote host
 | 
			
		||||
     *  @param data     Buffer of data to send to the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of sent bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_sendto)(nsapi_stack_t *stack, nsapi_socket_t socket, nsapi_addr_t addr, uint16_t port, const void *data, unsigned size);
 | 
			
		||||
 | 
			
		||||
    /** Receive a packet over a UDP socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Receives data and stores the source address in address if address
 | 
			
		||||
     *  is not NULL. Returns the number of bytes received into the buffer.
 | 
			
		||||
     *
 | 
			
		||||
     *  This call is non-blocking. If recvfrom would block,
 | 
			
		||||
     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param addr     Destination for the address of the remote host
 | 
			
		||||
     *  @param port     Destination for the port of the remote host
 | 
			
		||||
     *  @param data     Destination buffer for data received from the host
 | 
			
		||||
     *  @param size     Size of the buffer in bytes
 | 
			
		||||
     *  @return         Number of received bytes on success, negative error
 | 
			
		||||
     *                  code on failure
 | 
			
		||||
     */
 | 
			
		||||
    int (*socket_recvfrom)(nsapi_stack_t *stack, nsapi_socket_t socket, nsapi_addr_t *addr, uint16_t *port, void *buffer, unsigned size);
 | 
			
		||||
 | 
			
		||||
    /** Register a callback on state change of the socket
 | 
			
		||||
     *
 | 
			
		||||
     *  The specified callback will be called on state changes such as when
 | 
			
		||||
     *  the socket can recv/send/accept successfully and on when an error
 | 
			
		||||
     *  occurs. The callback may also be called spuriously without reason.
 | 
			
		||||
     *
 | 
			
		||||
     *  The callback may be called in an interrupt context and should not
 | 
			
		||||
     *  perform expensive operations such as recv/send calls.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param callback Function to call on state change
 | 
			
		||||
     *  @param data     Argument to pass to callback
 | 
			
		||||
     */
 | 
			
		||||
    void (*socket_attach)(nsapi_stack_t *stack, nsapi_socket_t socket, void (*callback)(void *), void *data);
 | 
			
		||||
 | 
			
		||||
    /*  Set stack-specific socket options
 | 
			
		||||
     *
 | 
			
		||||
     *  The setsockopt allow an application to pass stack-specific hints
 | 
			
		||||
     *  to the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    int (*setsockopt)(nsapi_stack_t *stack, nsapi_socket_t socket, int level, int optname, const void *optval, unsigned optlen);
 | 
			
		||||
 | 
			
		||||
    /*  Get stack-specific socket options
 | 
			
		||||
     *
 | 
			
		||||
     *  The getstackopt allow an application to retrieve stack-specific hints
 | 
			
		||||
     *  from the underlying stack. For unsupported options,
 | 
			
		||||
     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Stack handle
 | 
			
		||||
     *  @param socket   Socket handle
 | 
			
		||||
     *  @param level    Stack-specific protocol level
 | 
			
		||||
     *  @param optname  Stack-specific option identifier
 | 
			
		||||
     *  @param optval   Destination for option value
 | 
			
		||||
     *  @param optlen   Length of the option value
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */    
 | 
			
		||||
    int (*getsockopt)(nsapi_stack_t *stack, nsapi_socket_t socket, int level, int optname, void *optval, unsigned *optlen);
 | 
			
		||||
} nsapi_stack_api_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Loading…
	
		Reference in New Issue