blob: 152f8622409d0654e4fb649f5a9aff5ddfb6082e [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you 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.
*/
#ifdef SOCKET_INC_HEADER
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#endif
#ifdef SOCKET_INC_MEMBER
private:
int32_t mSocket;
struct sockaddr_in mServerAddress;
struct hostent *mServer;
public:
friend class ServerSocket;
private:
//private constructor needed in ServerSocket
inline Socket(int32_t socket);
#endif
#ifdef SOCKET_INC_IMPL
inline Socket::Socket() {
mSocket = -1;
mSocket = socket(AF_INET, SOCK_STREAM, 0);
}
inline Socket::Socket(int32_t socket) {
mSocket = socket;
}
inline Socket::~Socket() {
close();
}
inline status_t Socket::send(unsigned char * buffer, int32_t length) {
if ((buffer == NULL) || (length < 0)) {
return CAPU_EINVAL;
}
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
int32_t res = ::send(mSocket, buffer, length, 0);
if (res < 0) {
return CAPU_ERROR;
}
return CAPU_OK;
}
inline status_t Socket::receive(unsigned char * buffer, int32_t length, int32_t & numBytes) {
if ((buffer == NULL) || (length < 0)) {
return CAPU_EINVAL;
}
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
int32_t res = ::recv(mSocket, buffer, length, 0);
if (res == -1) {
numBytes = 0;
if (errno == EAGAIN)
return CAPU_ETIMEOUT;
else
return CAPU_ERROR;
}
numBytes = res;
return CAPU_OK;
}
inline status_t Socket::close() {
if (mSocket == -1) {
return CAPU_SOCKET_ESOCKET;
} else {
shutdown(mSocket, SHUT_RDWR);
if (::close(mSocket) < 0)
return CAPU_SOCKET_ECLOSE;
mSocket = -1;
return CAPU_OK;
}
}
inline status_t Socket::connect(unsigned char * dest_addr, uint16_t port) {
if ((dest_addr == NULL) || (port == 0))
return CAPU_EINVAL;
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
mServer = gethostbyname((const char *) dest_addr);
if (mServer == NULL)
return CAPU_SOCKET_EADDR;
// for padding
memset((char *) &mServerAddress, 0x00, sizeof (mServerAddress));
mServerAddress.sin_family = AF_INET;
//destination ip is set
memcpy((char *) &mServerAddress.sin_addr.s_addr, (char *) mServer->h_addr_list[0], mServer->h_length);
//port is set
mServerAddress.sin_port = htons(port);
int32_t res = ::connect(mSocket, (const sockaddr *) &mServerAddress, sizeof (mServerAddress));
if (res == -1)
return CAPU_SOCKET_ECONNECT;
return CAPU_OK;
}
inline status_t Socket::setBufferSize(int32_t bufferSize) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
if (bufferSize < 0)
return CAPU_EINVAL;
if (setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof (bufferSize)) < 0)
return CAPU_ERROR;
return CAPU_OK;
}
inline status_t Socket::setLingerOption(bool_t isLinger, int32_t linger) {
if (linger < 0) {
return CAPU_EINVAL;
}
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
struct linger so_linger;
if (isLinger) {
so_linger.l_onoff = 1;
so_linger.l_linger = linger;
} else {
so_linger.l_onoff = 0;
so_linger.l_linger = 0;
}
if (setsockopt(mSocket, SOL_SOCKET, SO_LINGER, &so_linger, sizeof (so_linger)) < 0)
return CAPU_ERROR;
return CAPU_OK;
}
inline status_t Socket::setNoDelay(bool_t noDelay) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
int32_t opt;
if (noDelay)
opt = 1;
else
opt = 0;
if (setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof (opt)) < 0)
return CAPU_ERROR;
return CAPU_OK;
}
inline status_t Socket::setKeepAlive(bool_t keepAlive) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
int32_t opt;
if (keepAlive)
opt = 1;
else
opt = 0;
if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof (opt)) < 0)
return CAPU_ERROR;
return CAPU_OK;
}
inline status_t Socket::setTimeout(int32_t timeout) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
struct timeval _timeout;
_timeout.tv_sec = timeout;
_timeout.tv_usec = 0;
if (setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &_timeout, sizeof (_timeout)) < 0)
return CAPU_ERROR;
if (setsockopt(mSocket, SOL_SOCKET, SO_SNDTIMEO, &_timeout, sizeof (_timeout)) < 0)
return CAPU_ERROR;
return CAPU_OK;
}
inline status_t Socket::getBufferSize(int32_t& bufferSize) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
int32_t size;
socklen_t len = sizeof (size);
if (getsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, &size, &len) < 0)
return CAPU_ERROR;
bufferSize = size;
return CAPU_OK;
}
inline status_t Socket::getLingerOption(bool_t& isLinger, int32_t& _linger) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
struct linger so_linger;
socklen_t len = sizeof (so_linger);
if (getsockopt(mSocket, SOL_SOCKET, SO_LINGER, &so_linger, &len) < 0)
return CAPU_ERROR;
_linger = so_linger.l_linger;
if (so_linger.l_onoff == 1)
isLinger = true;
else
isLinger = false;
return CAPU_OK;
}
inline status_t Socket::getNoDelay(bool_t& noDelay) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
int32_t opt;
socklen_t len = sizeof (opt);
if (getsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, &opt, &len) < 0)
return CAPU_ERROR;
if (opt == 1)
noDelay = true;
else
noDelay = false;
return CAPU_OK;
}
inline status_t Socket::getKeepAlive(bool_t& keepAlive) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
int32_t opt;
socklen_t len = sizeof (opt);
if (getsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &opt, &len) < 0)
return CAPU_ERROR;
if (opt == 1)
keepAlive = true;
else
keepAlive = false;
return CAPU_OK;
}
inline status_t Socket::getTimeout(int32_t& timeout) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
struct timeval _timeout;
socklen_t len = sizeof (_timeout);
if (getsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &_timeout, &len) < 0)
return CAPU_ERROR;
timeout = _timeout.tv_sec;
return CAPU_OK;
}
#endif