test
Diff: TCPSocket.cpp
- Revision:
- 3:e6474399e057
- Parent:
- 2:b227d242f3c7
- Child:
- 4:75988d748e4d
diff -r b227d242f3c7 -r e6474399e057 TCPSocket.cpp --- a/TCPSocket.cpp Mon Jul 23 11:52:50 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -/* Copyright (C) 2012 mbed.org, MIT License - * - * 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 "TCPSocket.h" - -#include <cstring> - -using std::memset; - -TCPSocket::TCPSocket() : m_sock(-1) -{ -} - -TCPSocket::~TCPSocket() -{ - close(); //Don't want to leak -} - -int TCPSocket::connect(char* host, int port, int timeout) -{ - int ret = init(); - if( ret < 0 ) - { - return -1; - } - - //Populate m_remoteHost - std::memset(&m_remoteHost, 0, sizeof(struct sockaddr_in)); - - //Resolve DNS address or populate hard-coded IP address - struct hostent *server = gethostbyname(host); - if(server == NULL) - { - return -1; //Could not resolve address - } - std::memcpy((char*)&m_remoteHost.sin_addr.s_addr, (char*)server->h_addr_list[0], server->h_length); - - m_remoteHost.sin_family = AF_INET; - m_remoteHost.sin_port = htons(port); - - ret = ::connect(m_sock, (const struct sockaddr *)&m_remoteHost, sizeof(m_remoteHost)); - if (ret < 0) - { - close(); - return -1; - } - - return 0; -} - -int TCPSocket::bind(int port) -{ - int ret = init(); - if( ret < 0 ) - { - return -1; - } - - struct sockaddr_in localHost; - std::memset(&localHost, 0, sizeof(localHost)); - - localHost.sin_family = AF_INET; - localHost.sin_port = htons(port); - localHost.sin_addr.s_addr = INADDR_ANY; - - ret = ::bind(m_sock, (const struct sockaddr *)&localHost, sizeof(localHost)); - if (ret < 0) - { - close(); - return -1; - } - - return 0; -} - -int TCPSocket::listen(int max) -{ - if( m_sock < 0 ) - { - return -1; - } - - int ret = ::listen(m_sock, max); - if (ret < 0) - { - close(); - return -1; - } - - return 0; -} - -int TCPSocket::accept(TCPSocket& socket, char** host, int* port, int timeout) -{ - if( m_sock < 0 ) - { - return -1; - } - - //Populate m_remoteHost - std::memset(&socket.m_remoteHost, 0, sizeof(struct sockaddr_in)); - - struct timeval t_val; //t_val will be decremented on each call to select() - t_val.tv_sec = timeout / 1000; - t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000; - //Wait for socket to get some connection request (i.e. to be "readable") - //Creating FS set - fd_set socksSet; - FD_ZERO(&socksSet); - FD_SET(m_sock, &socksSet); - int ret = ::select(FD_SETSIZE, &socksSet, NULL, NULL, &t_val); - if(ret <= 0 || !FD_ISSET(m_sock, &socksSet)) - { - return -1; //Timeout - } - - socklen_t newSockRemoteHostLen = sizeof(socket.m_remoteHost); - - ret = ::accept(m_sock, (struct sockaddr*)&socket.m_remoteHost, &newSockRemoteHostLen); - if( ret < 0 ) - { - return -1; //Accept failed - } - - socket.m_sock = ret; //ret is the new socket's fd - socket.m_closedByRemoteHost = false; - - static char hostBuf[16]; - inet_ntoa_r(socket.m_remoteHost.sin_addr, hostBuf, sizeof(hostBuf)); - - *host = hostBuf; - *port = ntohs(socket.m_remoteHost.sin_port); - - return 0; -} - -// -1 if unsuccessful, else number of bytes written -int TCPSocket::send(char* data, int length, int timeout) -{ - if( m_sock < 0 ) - { - return -1; - } - - if( m_closedByRemoteHost ) - { - return 0; - } - - size_t writtenLen = 0; - struct timeval t_val; //t_val will be decremented on each call to select() - t_val.tv_sec = timeout / 1000; - t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000; - while(writtenLen < length) - { - //Wait for socket to be writeable - //Creating FS set - fd_set socksSet; - FD_ZERO(&socksSet); - FD_SET(m_sock, &socksSet); - - int ret = ::select(FD_SETSIZE, NULL, &socksSet, NULL, &t_val); - if(ret <= 0 || !FD_ISSET(m_sock, &socksSet)) - { - return writtenLen; //Timeout -- FIXME should we return -1 or writtenLength ? - } - - ret = ::send(m_sock, data + writtenLen, length - writtenLen, 0); - if( ret > 0) - { - writtenLen += ret; - continue; - } - else if( ret == 0 ) - { - m_closedByRemoteHost = true; - return writtenLen; //Connection was closed by remote host -- FIXME how do we signal that the connection was closed ? - } - else - { - return -1; //Connnection error - } - } - - return writtenLen; -} - -// -1 if unsuccessful, else number of bytes received -int TCPSocket::receive(char* data, int length, int timeout) -{ - if( m_sock < 0 ) - { - return -1; - } - - if( m_closedByRemoteHost ) - { - return 0; - } - - size_t readLen = 0; - struct timeval t_val; //t_val will be decremented on each call to select() - t_val.tv_sec = timeout / 1000; - t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000; - while(readLen < length) - { - //Wait for socket to be readable - //Creating FS set - fd_set socksSet; - FD_ZERO(&socksSet); - FD_SET(m_sock, &socksSet); - int ret = ::select(FD_SETSIZE, &socksSet, NULL, NULL, &t_val); - if(ret <= 0 || !FD_ISSET(m_sock, &socksSet)) - { - return readLen; //Timeout -- FIXME should we return -1 or writtenLength ? - } - - ret = ::recv(m_sock, data + readLen, length - readLen, 0); - if( ret > 0) - { - readLen += ret; - continue; - } - else if( ret == 0 ) - { - m_closedByRemoteHost = true; - return readLen; //Connection was closed by remote host -- FIXME how do we signal that the connection was closed ? - } - else - { - return -1; //Connnection error - } - } - return readLen; -} - -int TCPSocket::close() -{ - if( m_sock < 0 ) - { - return -1; - } - - ::close(m_sock); - m_sock = -1; - - return 0; -} - -int TCPSocket::init() -{ - if( m_sock != -1 ) - { - return -1; - } - m_sock = ::socket(AF_INET, SOCK_STREAM, 0); //TCP socket - if (m_sock < 0) - { - return -1; //Could not create socket (Out of memory / available descriptors) - } - m_closedByRemoteHost = false; - return 0; -}