Wrapper of NetworkSocketAPI for BSD sockets on POSIX systems

Dependents:   BSDInterfaceTests HelloBSDInterface

Committer:
Christopher Haster
Date:
Sun Feb 28 10:32:22 2016 -0600
Revision:
2:0978e139e1c5
Parent:
1:29c61c1420c8
Child:
3:eabc4ea66a64
Fixed link level naming conflict with sockets

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 1:29c61c1420c8 1 /* BSD implementation of NetworkInterfaceAPI
geky 0:d92b89886434 2 * Copyright (c) 2015 ARM Limited
geky 0:d92b89886434 3 *
geky 0:d92b89886434 4 * Licensed under the Apache License, Version 2.0 (the "License");
geky 0:d92b89886434 5 * you may not use this file except in compliance with the License.
geky 0:d92b89886434 6 * You may obtain a copy of the License at
geky 0:d92b89886434 7 *
geky 0:d92b89886434 8 * http://www.apache.org/licenses/LICENSE-2.0
geky 0:d92b89886434 9 *
geky 0:d92b89886434 10 * Unless required by applicable law or agreed to in writing, software
geky 0:d92b89886434 11 * distributed under the License is distributed on an "AS IS" BASIS,
geky 0:d92b89886434 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
geky 0:d92b89886434 13 * See the License for the specific language governing permissions and
geky 0:d92b89886434 14 * limitations under the License.
geky 0:d92b89886434 15 */
geky 0:d92b89886434 16
Christopher Haster 1:29c61c1420c8 17 #include "BSDInterface.h"
geky 0:d92b89886434 18
Christopher Haster 1:29c61c1420c8 19 #include <sys/ioctl.h>
Christopher Haster 2:0978e139e1c5 20 #include <netdb.h>
Christopher Haster 1:29c61c1420c8 21 #include <net/if.h>
Christopher Haster 1:29c61c1420c8 22 #include <unistd.h>
Christopher Haster 1:29c61c1420c8 23 #include <netinet/in.h>
Christopher Haster 1:29c61c1420c8 24 #include <sys/socket.h>
Christopher Haster 1:29c61c1420c8 25 #include <arpa/inet.h>
Christopher Haster 1:29c61c1420c8 26 #include <errno.h>
Christopher Haster 1:29c61c1420c8 27 #include <string.h>
Christopher Haster 1:29c61c1420c8 28 #include <stdio.h>
geky 0:d92b89886434 29
geky 0:d92b89886434 30
Christopher Haster 1:29c61c1420c8 31 // BSDInterface implementation
Christopher Haster 1:29c61c1420c8 32 const char *BSDInterface::getMACAddress()
Christopher Haster 1:29c61c1420c8 33 {
Christopher Haster 1:29c61c1420c8 34 static char mac_address[NS_MAC_SIZE] = "\0";
Christopher Haster 1:29c61c1420c8 35 if (mac_address[0]) {
Christopher Haster 1:29c61c1420c8 36 return mac_address;
geky 0:d92b89886434 37 }
geky 0:d92b89886434 38
Christopher Haster 1:29c61c1420c8 39 struct ifreq ifr;
Christopher Haster 1:29c61c1420c8 40 struct ifconf ifc;
Christopher Haster 1:29c61c1420c8 41 char buffer[1024];
geky 0:d92b89886434 42
Christopher Haster 2:0978e139e1c5 43 int sock = ::socket(AF_INET, SOCK_DGRAM, 0);
Christopher Haster 1:29c61c1420c8 44 if (sock < 0) {
Christopher Haster 1:29c61c1420c8 45 return 0;
geky 0:d92b89886434 46 }
geky 0:d92b89886434 47
Christopher Haster 1:29c61c1420c8 48 ifc.ifc_buf = buffer;
Christopher Haster 1:29c61c1420c8 49 ifc.ifc_len = sizeof buffer;
Christopher Haster 1:29c61c1420c8 50 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
Christopher Haster 1:29c61c1420c8 51 return 0;
geky 0:d92b89886434 52 }
geky 0:d92b89886434 53
Christopher Haster 1:29c61c1420c8 54 for (int i = 0; i < ifc.ifc_len; i++) {
Christopher Haster 1:29c61c1420c8 55 strcpy(ifr.ifr_name, ifc.ifc_req[i].ifr_name);
Christopher Haster 1:29c61c1420c8 56
Christopher Haster 1:29c61c1420c8 57 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0
Christopher Haster 1:29c61c1420c8 58 && !(ifr.ifr_flags & IFF_LOOPBACK)
Christopher Haster 1:29c61c1420c8 59 && ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
geky 0:d92b89886434 60
Christopher Haster 1:29c61c1420c8 61 sprintf(mac_address, "%02x:%02x:%02x:%02x:%02x:%02x",
Christopher Haster 2:0978e139e1c5 62 (unsigned char)ifr.ifr_hwaddr.sa_data[0],
Christopher Haster 2:0978e139e1c5 63 (unsigned char)ifr.ifr_hwaddr.sa_data[1],
Christopher Haster 2:0978e139e1c5 64 (unsigned char)ifr.ifr_hwaddr.sa_data[2],
Christopher Haster 2:0978e139e1c5 65 (unsigned char)ifr.ifr_hwaddr.sa_data[3],
Christopher Haster 2:0978e139e1c5 66 (unsigned char)ifr.ifr_hwaddr.sa_data[4],
Christopher Haster 2:0978e139e1c5 67 (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
Christopher Haster 1:29c61c1420c8 68 return mac_address;
geky 0:d92b89886434 69 }
geky 0:d92b89886434 70 }
geky 0:d92b89886434 71
geky 0:d92b89886434 72 return 0;
geky 0:d92b89886434 73 }
geky 0:d92b89886434 74
geky 0:d92b89886434 75
Christopher Haster 2:0978e139e1c5 76 int32_t BSDInterface::getHostByName(const char *name, char *ip)
Christopher Haster 2:0978e139e1c5 77 {
Christopher Haster 2:0978e139e1c5 78 struct hostent *host = gethostbyname(name);
Christopher Haster 2:0978e139e1c5 79 if (!host || host->h_addrtype != AF_INET) {
Christopher Haster 2:0978e139e1c5 80 return NS_ERROR_DNS_FAILURE;
Christopher Haster 2:0978e139e1c5 81 }
Christopher Haster 2:0978e139e1c5 82
Christopher Haster 2:0978e139e1c5 83 strcpy(ip, inet_ntoa(*(struct in_addr *)host->h_addr));
Christopher Haster 2:0978e139e1c5 84 return 0;
Christopher Haster 2:0978e139e1c5 85 }
Christopher Haster 2:0978e139e1c5 86
Christopher Haster 2:0978e139e1c5 87
Christopher Haster 1:29c61c1420c8 88 /** BSDSocket class
Christopher Haster 1:29c61c1420c8 89 * Implementation of the SocketInterface for BSD
geky 0:d92b89886434 90 */
Christopher Haster 1:29c61c1420c8 91 class BSDSocket : public SocketInterface
geky 0:d92b89886434 92 {
geky 0:d92b89886434 93 public:
Christopher Haster 1:29c61c1420c8 94 BSDSocket(int fd) : fd(fd) {}
geky 0:d92b89886434 95
geky 0:d92b89886434 96 // Implementation of SocketInterface
geky 0:d92b89886434 97 virtual int32_t open(const char *ip, uint16_t port);
geky 0:d92b89886434 98 virtual int32_t close();
geky 0:d92b89886434 99
geky 0:d92b89886434 100 virtual int32_t send(const void *data, uint32_t size);
geky 0:d92b89886434 101 virtual int32_t recv(void *data, uint32_t size);
geky 0:d92b89886434 102
geky 0:d92b89886434 103 int fd;
geky 0:d92b89886434 104 };
geky 0:d92b89886434 105
geky 0:d92b89886434 106
Christopher Haster 1:29c61c1420c8 107 SocketInterface *BSDInterface::createSocket(socket_protocol_t proto)
geky 0:d92b89886434 108 {
geky 0:d92b89886434 109 int type = (proto == SOCK_UDP) ? SOCK_DGRAM : SOCK_STREAM;
Christopher Haster 2:0978e139e1c5 110 int fd = ::socket(AF_INET, type, 0);
geky 0:d92b89886434 111 if (fd < 0) {
geky 0:d92b89886434 112 return 0;
geky 0:d92b89886434 113 }
geky 0:d92b89886434 114
Christopher Haster 1:29c61c1420c8 115 return new BSDSocket(fd);
geky 0:d92b89886434 116 }
geky 0:d92b89886434 117
Christopher Haster 1:29c61c1420c8 118 void BSDInterface::destroySocket(SocketInterface *socket)
geky 0:d92b89886434 119 {
Christopher Haster 2:0978e139e1c5 120 ::close(((BSDSocket*)socket)->fd);
geky 0:d92b89886434 121 delete socket;
geky 0:d92b89886434 122 }
geky 0:d92b89886434 123
geky 0:d92b89886434 124
Christopher Haster 1:29c61c1420c8 125 // UDP SocketInterface implementation
Christopher Haster 1:29c61c1420c8 126 int32_t BSDSocket::open(const char *ip, uint16_t port)
geky 0:d92b89886434 127 {
Christopher Haster 1:29c61c1420c8 128 struct sockaddr_in host;
geky 0:d92b89886434 129 memset(&host, 0, sizeof host);
geky 0:d92b89886434 130 host.sin_family = AF_INET;
geky 0:d92b89886434 131 host.sin_port = htons(port);
Christopher Haster 1:29c61c1420c8 132 inet_pton(AF_INET, ip, &host.sin_addr);
geky 0:d92b89886434 133
Christopher Haster 2:0978e139e1c5 134 if (::connect(fd, (struct sockaddr *)&host, sizeof host) < 0) {
geky 0:d92b89886434 135 return NS_ERROR_NO_CONNECTION;
geky 0:d92b89886434 136 }
geky 0:d92b89886434 137
geky 0:d92b89886434 138 return 0;
geky 0:d92b89886434 139 }
geky 0:d92b89886434 140
Christopher Haster 1:29c61c1420c8 141 int32_t BSDSocket::close()
geky 0:d92b89886434 142 {
geky 0:d92b89886434 143 return 0;
geky 0:d92b89886434 144 }
geky 0:d92b89886434 145
Christopher Haster 1:29c61c1420c8 146 int32_t BSDSocket::send(const void *data, uint32_t size)
geky 0:d92b89886434 147 {
Christopher Haster 1:29c61c1420c8 148 if (::send(fd, data, size, 0) < 0) {
Christopher Haster 1:29c61c1420c8 149 return NS_ERROR_DEVICE_ERROR;
geky 0:d92b89886434 150 }
geky 0:d92b89886434 151
geky 0:d92b89886434 152 return 0;
geky 0:d92b89886434 153 }
geky 0:d92b89886434 154
Christopher Haster 1:29c61c1420c8 155 int32_t BSDSocket::recv(void *data, uint32_t size)
geky 0:d92b89886434 156 {
Christopher Haster 1:29c61c1420c8 157 int ret = ::recv(fd, data, size, MSG_DONTWAIT);
geky 0:d92b89886434 158
geky 0:d92b89886434 159 if (ret > 0) {
geky 0:d92b89886434 160 return ret;
Christopher Haster 1:29c61c1420c8 161 } else if (errno == EAGAIN) {
geky 0:d92b89886434 162 return 0;
geky 0:d92b89886434 163 } else {
geky 0:d92b89886434 164 return NS_ERROR_DEVICE_ERROR;
geky 0:d92b89886434 165 }
geky 0:d92b89886434 166 }
geky 0:d92b89886434 167
geky 0:d92b89886434 168