Wrapper of NetworkSocketAPI for BSD sockets on POSIX systems

Dependents:   BSDInterfaceTests HelloBSDInterface

Committer:
Christopher Haster
Date:
Sat Feb 27 21:01:54 2016 -0600
Revision:
1:29c61c1420c8
Parent:
0:d92b89886434
Child:
2:0978e139e1c5
Added base implementation of BSDInterface

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 1:29c61c1420c8 20 #include <net/if.h>
Christopher Haster 1:29c61c1420c8 21 #include <unistd.h>
Christopher Haster 1:29c61c1420c8 22 #include <netinet/in.h>
Christopher Haster 1:29c61c1420c8 23 #include <sys/socket.h>
Christopher Haster 1:29c61c1420c8 24 #include <arpa/inet.h>
Christopher Haster 1:29c61c1420c8 25 #include <errno.h>
Christopher Haster 1:29c61c1420c8 26 #include <string.h>
Christopher Haster 1:29c61c1420c8 27 #include <stdio.h>
geky 0:d92b89886434 28
geky 0:d92b89886434 29
Christopher Haster 1:29c61c1420c8 30 // BSDInterface implementation
Christopher Haster 1:29c61c1420c8 31 const char *BSDInterface::getMACAddress()
Christopher Haster 1:29c61c1420c8 32 {
Christopher Haster 1:29c61c1420c8 33 static char mac_address[NS_MAC_SIZE] = "\0";
Christopher Haster 1:29c61c1420c8 34 if (mac_address[0]) {
Christopher Haster 1:29c61c1420c8 35 return mac_address;
geky 0:d92b89886434 36 }
geky 0:d92b89886434 37
Christopher Haster 1:29c61c1420c8 38 struct ifreq ifr;
Christopher Haster 1:29c61c1420c8 39 struct ifconf ifc;
Christopher Haster 1:29c61c1420c8 40 char buffer[1024];
geky 0:d92b89886434 41
Christopher Haster 1:29c61c1420c8 42 int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
Christopher Haster 1:29c61c1420c8 43 if (sock < 0) {
Christopher Haster 1:29c61c1420c8 44 return 0;
geky 0:d92b89886434 45 }
geky 0:d92b89886434 46
Christopher Haster 1:29c61c1420c8 47 ifc.ifc_buf = buffer;
Christopher Haster 1:29c61c1420c8 48 ifc.ifc_len = sizeof buffer;
Christopher Haster 1:29c61c1420c8 49 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
Christopher Haster 1:29c61c1420c8 50 return 0;
geky 0:d92b89886434 51 }
geky 0:d92b89886434 52
Christopher Haster 1:29c61c1420c8 53 for (int i = 0; i < ifc.ifc_len; i++) {
Christopher Haster 1:29c61c1420c8 54 strcpy(ifr.ifr_name, ifc.ifc_req[i].ifr_name);
Christopher Haster 1:29c61c1420c8 55
Christopher Haster 1:29c61c1420c8 56 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0
Christopher Haster 1:29c61c1420c8 57 && !(ifr.ifr_flags & IFF_LOOPBACK)
Christopher Haster 1:29c61c1420c8 58 && ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
geky 0:d92b89886434 59
Christopher Haster 1:29c61c1420c8 60 sprintf(mac_address, "%02x:%02x:%02x:%02x:%02x:%02x",
Christopher Haster 1:29c61c1420c8 61 ifr.ifr_hwaddr.sa_data[0],
Christopher Haster 1:29c61c1420c8 62 ifr.ifr_hwaddr.sa_data[1],
Christopher Haster 1:29c61c1420c8 63 ifr.ifr_hwaddr.sa_data[2],
Christopher Haster 1:29c61c1420c8 64 ifr.ifr_hwaddr.sa_data[3],
Christopher Haster 1:29c61c1420c8 65 ifr.ifr_hwaddr.sa_data[4],
Christopher Haster 1:29c61c1420c8 66 ifr.ifr_hwaddr.sa_data[5]);
Christopher Haster 1:29c61c1420c8 67 return mac_address;
geky 0:d92b89886434 68 }
geky 0:d92b89886434 69 }
geky 0:d92b89886434 70
geky 0:d92b89886434 71 return 0;
geky 0:d92b89886434 72 }
geky 0:d92b89886434 73
geky 0:d92b89886434 74
Christopher Haster 1:29c61c1420c8 75 /** BSDSocket class
Christopher Haster 1:29c61c1420c8 76 * Implementation of the SocketInterface for BSD
geky 0:d92b89886434 77 */
Christopher Haster 1:29c61c1420c8 78 class BSDSocket : public SocketInterface
geky 0:d92b89886434 79 {
geky 0:d92b89886434 80 public:
Christopher Haster 1:29c61c1420c8 81 BSDSocket(int fd) : fd(fd) {}
geky 0:d92b89886434 82
geky 0:d92b89886434 83 // Implementation of SocketInterface
geky 0:d92b89886434 84 virtual int32_t open(const char *ip, uint16_t port);
geky 0:d92b89886434 85 virtual int32_t close();
geky 0:d92b89886434 86
geky 0:d92b89886434 87 virtual int32_t send(const void *data, uint32_t size);
geky 0:d92b89886434 88 virtual int32_t recv(void *data, uint32_t size);
geky 0:d92b89886434 89
geky 0:d92b89886434 90 int fd;
geky 0:d92b89886434 91 };
geky 0:d92b89886434 92
geky 0:d92b89886434 93
Christopher Haster 1:29c61c1420c8 94 SocketInterface *BSDInterface::createSocket(socket_protocol_t proto)
geky 0:d92b89886434 95 {
geky 0:d92b89886434 96 int type = (proto == SOCK_UDP) ? SOCK_DGRAM : SOCK_STREAM;
Christopher Haster 1:29c61c1420c8 97 int prot = (proto == SOCK_UDP) ? IPPROTO_UDP : IPPROTO_TCP;
Christopher Haster 1:29c61c1420c8 98 int fd = socket(PF_INET, type, prot);
geky 0:d92b89886434 99 if (fd < 0) {
geky 0:d92b89886434 100 return 0;
geky 0:d92b89886434 101 }
geky 0:d92b89886434 102
Christopher Haster 1:29c61c1420c8 103 return new BSDSocket(fd);
geky 0:d92b89886434 104 }
geky 0:d92b89886434 105
Christopher Haster 1:29c61c1420c8 106 void BSDInterface::destroySocket(SocketInterface *socket)
geky 0:d92b89886434 107 {
Christopher Haster 1:29c61c1420c8 108 close(((BSDSocket*)socket)->fd);
geky 0:d92b89886434 109 delete socket;
geky 0:d92b89886434 110 }
geky 0:d92b89886434 111
geky 0:d92b89886434 112
Christopher Haster 1:29c61c1420c8 113 // UDP SocketInterface implementation
Christopher Haster 1:29c61c1420c8 114 int32_t BSDSocket::open(const char *ip, uint16_t port)
geky 0:d92b89886434 115 {
Christopher Haster 1:29c61c1420c8 116 struct sockaddr_in host;
geky 0:d92b89886434 117 memset(&host, 0, sizeof host);
geky 0:d92b89886434 118 host.sin_family = AF_INET;
geky 0:d92b89886434 119 host.sin_port = htons(port);
Christopher Haster 1:29c61c1420c8 120 inet_pton(AF_INET, ip, &host.sin_addr);
geky 0:d92b89886434 121
Christopher Haster 1:29c61c1420c8 122 if (connect(fd, (struct sockaddr *)&host, sizeof host) < 0) {
geky 0:d92b89886434 123 return NS_ERROR_NO_CONNECTION;
geky 0:d92b89886434 124 }
geky 0:d92b89886434 125
geky 0:d92b89886434 126 return 0;
geky 0:d92b89886434 127 }
geky 0:d92b89886434 128
Christopher Haster 1:29c61c1420c8 129 int32_t BSDSocket::close()
geky 0:d92b89886434 130 {
geky 0:d92b89886434 131 return 0;
geky 0:d92b89886434 132 }
geky 0:d92b89886434 133
Christopher Haster 1:29c61c1420c8 134 int32_t BSDSocket::send(const void *data, uint32_t size)
geky 0:d92b89886434 135 {
Christopher Haster 1:29c61c1420c8 136 if (::send(fd, data, size, 0) < 0) {
Christopher Haster 1:29c61c1420c8 137 return NS_ERROR_DEVICE_ERROR;
geky 0:d92b89886434 138 }
geky 0:d92b89886434 139
geky 0:d92b89886434 140 return 0;
geky 0:d92b89886434 141 }
geky 0:d92b89886434 142
Christopher Haster 1:29c61c1420c8 143 int32_t BSDSocket::recv(void *data, uint32_t size)
geky 0:d92b89886434 144 {
Christopher Haster 1:29c61c1420c8 145 int ret = ::recv(fd, data, size, MSG_DONTWAIT);
geky 0:d92b89886434 146
geky 0:d92b89886434 147 if (ret > 0) {
geky 0:d92b89886434 148 return ret;
Christopher Haster 1:29c61c1420c8 149 } else if (errno == EAGAIN) {
geky 0:d92b89886434 150 return 0;
geky 0:d92b89886434 151 } else {
geky 0:d92b89886434 152 return NS_ERROR_DEVICE_ERROR;
geky 0:d92b89886434 153 }
geky 0:d92b89886434 154 }
geky 0:d92b89886434 155
geky 0:d92b89886434 156