mbed socket API

Dependents:   EthernetInterface EthernetInterface_RSF EthernetInterface EthernetInterface ... more

Deprecated

This is an mbed 2 sockets library. For mbed 5, network sockets have been revised to better support additional network stacks and thread safety here.

Committer:
donatien
Date:
Tue Jun 26 15:32:12 2012 +0000
Revision:
1:8080965f5d76
Parent:
0:1f77255a22f5
Child:
2:b227d242f3c7
Changed data type from uint8_t* to char*

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donatien 0:1f77255a22f5 1 /* Copyright (C) 2012 mbed.org, MIT License
donatien 0:1f77255a22f5 2 *
donatien 0:1f77255a22f5 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
donatien 0:1f77255a22f5 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
donatien 0:1f77255a22f5 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
donatien 0:1f77255a22f5 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
donatien 0:1f77255a22f5 7 * furnished to do so, subject to the following conditions:
donatien 0:1f77255a22f5 8 *
donatien 0:1f77255a22f5 9 * The above copyright notice and this permission notice shall be included in all copies or
donatien 0:1f77255a22f5 10 * substantial portions of the Software.
donatien 0:1f77255a22f5 11 *
donatien 0:1f77255a22f5 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
donatien 0:1f77255a22f5 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
donatien 0:1f77255a22f5 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
donatien 0:1f77255a22f5 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
donatien 0:1f77255a22f5 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
donatien 0:1f77255a22f5 17 */
donatien 0:1f77255a22f5 18
donatien 0:1f77255a22f5 19 #include "TCPSocket.h"
donatien 0:1f77255a22f5 20
donatien 0:1f77255a22f5 21 #include "bsd_socket.h"
donatien 0:1f77255a22f5 22
donatien 0:1f77255a22f5 23 #include <cstring>
donatien 0:1f77255a22f5 24
donatien 0:1f77255a22f5 25 using std::memset;
donatien 0:1f77255a22f5 26
donatien 0:1f77255a22f5 27 TCPSocket::TCPSocket() : m_sock(-1)
donatien 0:1f77255a22f5 28 {
donatien 0:1f77255a22f5 29 }
donatien 0:1f77255a22f5 30
donatien 0:1f77255a22f5 31 TCPSocket::~TCPSocket()
donatien 0:1f77255a22f5 32 {
donatien 0:1f77255a22f5 33 close(); //Don't want to leak
donatien 0:1f77255a22f5 34 }
donatien 0:1f77255a22f5 35
donatien 0:1f77255a22f5 36 int TCPSocket::connect(char* host, int port, int timeout)
donatien 0:1f77255a22f5 37 {
donatien 0:1f77255a22f5 38 int ret = init();
donatien 0:1f77255a22f5 39 if( ret < 0 )
donatien 0:1f77255a22f5 40 {
donatien 0:1f77255a22f5 41 return -1;
donatien 0:1f77255a22f5 42 }
donatien 0:1f77255a22f5 43
donatien 0:1f77255a22f5 44 //Populate m_remoteHost
donatien 0:1f77255a22f5 45 std::memset(&m_remoteHost, 0, sizeof(struct sockaddr_in));
donatien 0:1f77255a22f5 46
donatien 0:1f77255a22f5 47 //Resolve DNS address or populate hard-coded IP address
donatien 0:1f77255a22f5 48 struct hostent *server = ::gethostbyname(host);
donatien 0:1f77255a22f5 49 if(server == NULL)
donatien 0:1f77255a22f5 50 {
donatien 0:1f77255a22f5 51 return -1; //Could not resolve address
donatien 0:1f77255a22f5 52 }
donatien 0:1f77255a22f5 53 std::memcpy((char*)&m_remoteHost.sin_addr.s_addr, (char*)server->h_addr_list[0], server->h_length);
donatien 0:1f77255a22f5 54
donatien 0:1f77255a22f5 55 m_remoteHost.sin_family = AF_INET;
donatien 0:1f77255a22f5 56 m_remoteHost.sin_port = htons(port);
donatien 0:1f77255a22f5 57
donatien 0:1f77255a22f5 58 ret = ::connect(m_sock, (const struct sockaddr *)&m_remoteHost, sizeof(m_remoteHost));
donatien 0:1f77255a22f5 59 if (ret < 0)
donatien 0:1f77255a22f5 60 {
donatien 0:1f77255a22f5 61 close();
donatien 0:1f77255a22f5 62 return -1;
donatien 0:1f77255a22f5 63 }
donatien 0:1f77255a22f5 64
donatien 0:1f77255a22f5 65 return 0;
donatien 0:1f77255a22f5 66 }
donatien 0:1f77255a22f5 67
donatien 0:1f77255a22f5 68 int TCPSocket::bind(int port)
donatien 0:1f77255a22f5 69 {
donatien 0:1f77255a22f5 70 int ret = init();
donatien 0:1f77255a22f5 71 if( ret < 0 )
donatien 0:1f77255a22f5 72 {
donatien 0:1f77255a22f5 73 return -1;
donatien 0:1f77255a22f5 74 }
donatien 0:1f77255a22f5 75
donatien 0:1f77255a22f5 76 struct sockaddr_in localHost;
donatien 0:1f77255a22f5 77 std::memset(&localHost, 0, sizeof(localHost));
donatien 0:1f77255a22f5 78
donatien 0:1f77255a22f5 79 localHost.sin_family = AF_INET;
donatien 0:1f77255a22f5 80 localHost.sin_port = htons(port);
donatien 0:1f77255a22f5 81 localHost.sin_addr.s_addr = INADDR_ANY;
donatien 0:1f77255a22f5 82
donatien 0:1f77255a22f5 83 ret = ::bind(m_sock, (const struct sockaddr *)&localHost, sizeof(localHost));
donatien 0:1f77255a22f5 84 if (ret < 0)
donatien 0:1f77255a22f5 85 {
donatien 0:1f77255a22f5 86 close();
donatien 0:1f77255a22f5 87 return -1;
donatien 0:1f77255a22f5 88 }
donatien 0:1f77255a22f5 89
donatien 0:1f77255a22f5 90 return 0;
donatien 0:1f77255a22f5 91 }
donatien 0:1f77255a22f5 92
donatien 0:1f77255a22f5 93 int TCPSocket::listen(int max)
donatien 0:1f77255a22f5 94 {
donatien 0:1f77255a22f5 95 if( m_sock < 0 )
donatien 0:1f77255a22f5 96 {
donatien 0:1f77255a22f5 97 return -1;
donatien 0:1f77255a22f5 98 }
donatien 0:1f77255a22f5 99
donatien 0:1f77255a22f5 100 int ret = ::listen(m_sock, max);
donatien 0:1f77255a22f5 101 if (ret < 0)
donatien 0:1f77255a22f5 102 {
donatien 0:1f77255a22f5 103 close();
donatien 0:1f77255a22f5 104 return -1;
donatien 0:1f77255a22f5 105 }
donatien 0:1f77255a22f5 106
donatien 0:1f77255a22f5 107 return 0;
donatien 0:1f77255a22f5 108 }
donatien 0:1f77255a22f5 109
donatien 0:1f77255a22f5 110 int TCPSocket::accept(TCPSocket& socket, char** host, int* port, int timeout)
donatien 0:1f77255a22f5 111 {
donatien 0:1f77255a22f5 112 if( m_sock < 0 )
donatien 0:1f77255a22f5 113 {
donatien 0:1f77255a22f5 114 return -1;
donatien 0:1f77255a22f5 115 }
donatien 0:1f77255a22f5 116
donatien 0:1f77255a22f5 117 //Populate m_remoteHost
donatien 0:1f77255a22f5 118 std::memset(&socket.m_remoteHost, 0, sizeof(struct sockaddr_in));
donatien 0:1f77255a22f5 119
donatien 0:1f77255a22f5 120 struct timeval t_val; //t_val will be decremented on each call to select()
donatien 0:1f77255a22f5 121 t_val.tv_sec = timeout / 1000;
donatien 0:1f77255a22f5 122 t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000;
donatien 0:1f77255a22f5 123 //Wait for socket to get some connection request (i.e. to be "readable")
donatien 0:1f77255a22f5 124 //Creating FS set
donatien 0:1f77255a22f5 125 fd_set socksSet;
donatien 0:1f77255a22f5 126 FD_ZERO(&socksSet);
donatien 0:1f77255a22f5 127 FD_SET(m_sock, &socksSet);
donatien 0:1f77255a22f5 128 int ret = ::select(FD_SETSIZE, &socksSet, NULL, NULL, &t_val);
donatien 0:1f77255a22f5 129 if(ret <= 0 || !FD_ISSET(m_sock, &socksSet))
donatien 0:1f77255a22f5 130 {
donatien 0:1f77255a22f5 131 return -1; //Timeout
donatien 0:1f77255a22f5 132 }
donatien 0:1f77255a22f5 133
donatien 0:1f77255a22f5 134 socklen_t newSockRemoteHostLen = sizeof(socket.m_remoteHost);
donatien 0:1f77255a22f5 135
donatien 0:1f77255a22f5 136 ret = ::accept(m_sock, (struct sockaddr*)&socket.m_remoteHost, &newSockRemoteHostLen);
donatien 0:1f77255a22f5 137 if( ret < 0 )
donatien 0:1f77255a22f5 138 {
donatien 0:1f77255a22f5 139 return -1; //Accept failed
donatien 0:1f77255a22f5 140 }
donatien 0:1f77255a22f5 141
donatien 0:1f77255a22f5 142 socket.m_sock = ret; //ret is the new socket's fd
donatien 0:1f77255a22f5 143 socket.m_closedByRemoteHost = false;
donatien 0:1f77255a22f5 144
donatien 0:1f77255a22f5 145 static char hostBuf[16];
donatien 0:1f77255a22f5 146 inet_ntoa_r(socket.m_remoteHost.sin_addr, hostBuf, sizeof(hostBuf));
donatien 0:1f77255a22f5 147
donatien 0:1f77255a22f5 148 *host = hostBuf;
donatien 0:1f77255a22f5 149 *port = ntohs(socket.m_remoteHost.sin_port);
donatien 0:1f77255a22f5 150
donatien 0:1f77255a22f5 151 return 0;
donatien 0:1f77255a22f5 152 }
donatien 0:1f77255a22f5 153
donatien 0:1f77255a22f5 154 // -1 if unsuccessful, else number of bytes written
donatien 1:8080965f5d76 155 int TCPSocket::send(char* data, int length, int timeout)
donatien 0:1f77255a22f5 156 {
donatien 0:1f77255a22f5 157 if( m_sock < 0 )
donatien 0:1f77255a22f5 158 {
donatien 0:1f77255a22f5 159 return -1;
donatien 0:1f77255a22f5 160 }
donatien 0:1f77255a22f5 161
donatien 0:1f77255a22f5 162 if( m_closedByRemoteHost )
donatien 0:1f77255a22f5 163 {
donatien 0:1f77255a22f5 164 return 0;
donatien 0:1f77255a22f5 165 }
donatien 0:1f77255a22f5 166
donatien 0:1f77255a22f5 167 size_t writtenLen = 0;
donatien 0:1f77255a22f5 168 struct timeval t_val; //t_val will be decremented on each call to select()
donatien 0:1f77255a22f5 169 t_val.tv_sec = timeout / 1000;
donatien 0:1f77255a22f5 170 t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000;
donatien 0:1f77255a22f5 171 while(writtenLen < length)
donatien 0:1f77255a22f5 172 {
donatien 0:1f77255a22f5 173 //Wait for socket to be writeable
donatien 0:1f77255a22f5 174 //Creating FS set
donatien 0:1f77255a22f5 175 fd_set socksSet;
donatien 0:1f77255a22f5 176 FD_ZERO(&socksSet);
donatien 0:1f77255a22f5 177 FD_SET(m_sock, &socksSet);
donatien 0:1f77255a22f5 178
donatien 0:1f77255a22f5 179 int ret = ::select(FD_SETSIZE, NULL, &socksSet, NULL, &t_val);
donatien 0:1f77255a22f5 180 if(ret <= 0 || !FD_ISSET(m_sock, &socksSet))
donatien 0:1f77255a22f5 181 {
donatien 0:1f77255a22f5 182 return writtenLen; //Timeout -- FIXME should we return -1 or writtenLength ?
donatien 0:1f77255a22f5 183 }
donatien 0:1f77255a22f5 184
donatien 0:1f77255a22f5 185 ret = ::send(m_sock, data + writtenLen, length - writtenLen, 0);
donatien 0:1f77255a22f5 186 if( ret > 0)
donatien 0:1f77255a22f5 187 {
donatien 0:1f77255a22f5 188 writtenLen += ret;
donatien 0:1f77255a22f5 189 continue;
donatien 0:1f77255a22f5 190 }
donatien 0:1f77255a22f5 191 else if( ret == 0 )
donatien 0:1f77255a22f5 192 {
donatien 0:1f77255a22f5 193 m_closedByRemoteHost = true;
donatien 0:1f77255a22f5 194 return writtenLen; //Connection was closed by remote host -- FIXME how do we signal that the connection was closed ?
donatien 0:1f77255a22f5 195 }
donatien 0:1f77255a22f5 196 else
donatien 0:1f77255a22f5 197 {
donatien 0:1f77255a22f5 198 return -1; //Connnection error
donatien 0:1f77255a22f5 199 }
donatien 0:1f77255a22f5 200 }
donatien 0:1f77255a22f5 201
donatien 0:1f77255a22f5 202 return writtenLen;
donatien 0:1f77255a22f5 203 }
donatien 0:1f77255a22f5 204
donatien 0:1f77255a22f5 205 // -1 if unsuccessful, else number of bytes received
donatien 1:8080965f5d76 206 int TCPSocket::receive(char* data, int length, int timeout)
donatien 0:1f77255a22f5 207 {
donatien 0:1f77255a22f5 208 if( m_sock < 0 )
donatien 0:1f77255a22f5 209 {
donatien 0:1f77255a22f5 210 return -1;
donatien 0:1f77255a22f5 211 }
donatien 0:1f77255a22f5 212
donatien 0:1f77255a22f5 213 if( m_closedByRemoteHost )
donatien 0:1f77255a22f5 214 {
donatien 0:1f77255a22f5 215 return 0;
donatien 0:1f77255a22f5 216 }
donatien 0:1f77255a22f5 217
donatien 0:1f77255a22f5 218 size_t readLen = 0;
donatien 0:1f77255a22f5 219 struct timeval t_val; //t_val will be decremented on each call to select()
donatien 0:1f77255a22f5 220 t_val.tv_sec = timeout / 1000;
donatien 0:1f77255a22f5 221 t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000;
donatien 0:1f77255a22f5 222 while(readLen < length)
donatien 0:1f77255a22f5 223 {
donatien 0:1f77255a22f5 224 //Wait for socket to be readable
donatien 0:1f77255a22f5 225 //Creating FS set
donatien 0:1f77255a22f5 226 fd_set socksSet;
donatien 0:1f77255a22f5 227 FD_ZERO(&socksSet);
donatien 0:1f77255a22f5 228 FD_SET(m_sock, &socksSet);
donatien 0:1f77255a22f5 229 int ret = ::select(FD_SETSIZE, &socksSet, NULL, NULL, &t_val);
donatien 0:1f77255a22f5 230 if(ret <= 0 || !FD_ISSET(m_sock, &socksSet))
donatien 0:1f77255a22f5 231 {
donatien 0:1f77255a22f5 232 return readLen; //Timeout -- FIXME should we return -1 or writtenLength ?
donatien 0:1f77255a22f5 233 }
donatien 0:1f77255a22f5 234
donatien 0:1f77255a22f5 235 ret = ::recv(m_sock, data + readLen, length - readLen, 0);
donatien 0:1f77255a22f5 236 if( ret > 0)
donatien 0:1f77255a22f5 237 {
donatien 0:1f77255a22f5 238 readLen += ret;
donatien 0:1f77255a22f5 239 continue;
donatien 0:1f77255a22f5 240 }
donatien 0:1f77255a22f5 241 else if( ret == 0 )
donatien 0:1f77255a22f5 242 {
donatien 0:1f77255a22f5 243 m_closedByRemoteHost = true;
donatien 0:1f77255a22f5 244 return readLen; //Connection was closed by remote host -- FIXME how do we signal that the connection was closed ?
donatien 0:1f77255a22f5 245 }
donatien 0:1f77255a22f5 246 else
donatien 0:1f77255a22f5 247 {
donatien 0:1f77255a22f5 248 return -1; //Connnection error
donatien 0:1f77255a22f5 249 }
donatien 0:1f77255a22f5 250 }
donatien 0:1f77255a22f5 251 return readLen;
donatien 0:1f77255a22f5 252 }
donatien 0:1f77255a22f5 253
donatien 0:1f77255a22f5 254 int TCPSocket::close()
donatien 0:1f77255a22f5 255 {
donatien 0:1f77255a22f5 256 if( m_sock < 0 )
donatien 0:1f77255a22f5 257 {
donatien 0:1f77255a22f5 258 return -1;
donatien 0:1f77255a22f5 259 }
donatien 0:1f77255a22f5 260
donatien 0:1f77255a22f5 261 ::close(m_sock);
donatien 0:1f77255a22f5 262 m_sock = -1;
donatien 0:1f77255a22f5 263
donatien 0:1f77255a22f5 264 return 0;
donatien 0:1f77255a22f5 265 }
donatien 0:1f77255a22f5 266
donatien 0:1f77255a22f5 267 int TCPSocket::init()
donatien 0:1f77255a22f5 268 {
donatien 0:1f77255a22f5 269 if( m_sock != -1 )
donatien 0:1f77255a22f5 270 {
donatien 0:1f77255a22f5 271 return -1;
donatien 0:1f77255a22f5 272 }
donatien 0:1f77255a22f5 273 m_sock = ::socket(AF_INET, SOCK_STREAM, 0); //TCP socket
donatien 0:1f77255a22f5 274 if (m_sock < 0)
donatien 0:1f77255a22f5 275 {
donatien 0:1f77255a22f5 276 return -1; //Could not create socket (Out of memory / available descriptors)
donatien 0:1f77255a22f5 277 }
donatien 0:1f77255a22f5 278 m_closedByRemoteHost = false;
donatien 0:1f77255a22f5 279 return 0;
donatien 0:1f77255a22f5 280 }