blob: 58347380bfc5d37c294268cd50459f4cfd1517d3 [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 UDPSOCKET_INC_HEADER
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include "capu/os/StringUtils.h"
#endif
#ifdef UDPSOCKET_INC_MEMBER
public:
private:
int32_t mSocket;
int32_t mAddressFamily;
int32_t mSocketType;
bool_t mIsBound;
#endif
#ifdef UDPSOCKET_INC_IMPL
inline UdpSocket::UdpSocket() {
//create the socket which is used to connect the server
mAddressFamily = AF_INET;
mSocketType = SOCK_DGRAM;
mSocket = socket(mAddressFamily, mSocketType, 0);
if (mSocket != -1) {
int32_t optval = 1;
setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval));
}
mIsBound = false;
}
inline UdpSocket::~UdpSocket() {
close();
}
inline status_t UdpSocket::bind(uint16_t port, const char *addr) {
if (port == 0) {
return CAPU_EINVAL;
}
if (mIsBound) {
return CAPU_ERROR;
}
if (mSocket == -1) {
return CAPU_SOCKET_ESOCKET;
}
struct sockaddr_in mServerAddress;
memset((char *) &mServerAddress, 0x00, sizeof (mServerAddress));
mServerAddress.sin_family = AF_INET;
if (addr == NULL)
mServerAddress.sin_addr.s_addr = INADDR_ANY;
else if (inet_aton(addr, &mServerAddress.sin_addr) == 0)
return CAPU_SOCKET_EADDR;
mServerAddress.sin_port = htons(port);
int32_t res = ::bind(mSocket, (sockaddr *) &mServerAddress, sizeof (struct sockaddr_in));
if (res < 0) {
printf("%d\n", errno);
return CAPU_SOCKET_EBIND;
}
mIsBound = true;
return CAPU_OK;
}
inline status_t UdpSocket::send(unsigned char *buffer, int32_t length, const char *receiverAddr, uint16_t receiverPort) {
if ((buffer == NULL) || (length < 0)) {
return CAPU_EINVAL;
}
if (mSocket == -1) {
return CAPU_SOCKET_ESOCKET;
}
struct hostent *receiverAddrIp = gethostbyname(receiverAddr);
if (receiverAddrIp == NULL) {
return CAPU_SOCKET_EADDR;
}
struct sockaddr_in receiverSockAddr;
receiverSockAddr.sin_family = AF_INET;
memcpy((char *) &receiverSockAddr.sin_addr.s_addr, (char *) receiverAddrIp->h_addr_list[0], receiverAddrIp->h_length);
receiverSockAddr.sin_port = htons(receiverPort);
int32_t result = sendto(mSocket,(char*)buffer, length, 0, (sockaddr*)&receiverSockAddr, sizeof(receiverSockAddr));
if(result == -1)
{
return CAPU_ERROR;
}
return CAPU_OK;
}
inline status_t UdpSocket::send(unsigned char *buffer, int32_t length, SocketAddrInfo& receiverAddr) {
return send(buffer, length, receiverAddr.addr, receiverAddr.port);
}
inline status_t UdpSocket::receive(unsigned char *buffer, int32_t length, int32_t &numBytes, SocketAddrInfo* sender) {
if ((buffer == NULL) || (length < 0)) {
return CAPU_EINVAL;
}
if (mSocket == -1) {
return CAPU_SOCKET_ESOCKET;
}
sockaddr remoteSocketAddr;
socklen_t remoteSocketAddrSize = sizeof(remoteSocketAddr);
int32_t result = recvfrom(mSocket, (char*)buffer, length, 0, &remoteSocketAddr, &remoteSocketAddrSize);
if (result == -1) {
numBytes = 0;
if (errno == EAGAIN) {
return CAPU_ETIMEOUT;
} else {
return CAPU_ERROR;
}
}else{
if(sender != 0)
{
sender->port = ntohs(((sockaddr_in*)&remoteSocketAddr)->sin_port);
char* addr = inet_ntoa(((sockaddr_in*)&remoteSocketAddr)->sin_addr);
StringUtils::Strncpy(sender->addr, sizeof(sender->addr), addr);
}
}
numBytes = result;
return CAPU_OK;
}
inline status_t UdpSocket::close() {
if (mSocket == -1) {
return CAPU_SOCKET_ESOCKET;
} else {
if (::close(mSocket) < 0)
return CAPU_SOCKET_ECLOSE;
mSocket = -1;
return CAPU_OK;
}
}
inline status_t UdpSocket::setBufferSize(int32_t bufferSize) {
if (bufferSize < 0) {
return CAPU_EINVAL;
}
if (mSocket == -1) {
return CAPU_SOCKET_ESOCKET;
}
if (setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(bufferSize)) == -1) {
return CAPU_ERROR;
}
return CAPU_OK;
}
inline status_t UdpSocket::setTimeout(int32_t timeout) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
struct timeval soTimeout;
soTimeout.tv_sec = timeout;
soTimeout.tv_usec = 0;
if (setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&soTimeout, sizeof(soTimeout)) == -1) {
return CAPU_ERROR;
}
if (setsockopt(mSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&soTimeout, sizeof(soTimeout)) == -1) {
return CAPU_ERROR;
}
return CAPU_OK;
}
inline status_t UdpSocket::getBufferSize(int32_t& bufferSize) {
if (mSocket == -1) {
return CAPU_SOCKET_ESOCKET;
}
socklen_t len = sizeof (bufferSize);
if (getsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, &len) == -1) {
return CAPU_ERROR;
}
return CAPU_OK;
}
inline status_t UdpSocket::getTimeout(int32_t& timeout) {
if (mSocket == -1)
return CAPU_SOCKET_ESOCKET;
struct timeval soTimeout;
socklen_t len = sizeof(soTimeout);
if (getsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&soTimeout, &len) == -1) {
return CAPU_ERROR;
}
timeout = soTimeout.tv_sec;
return CAPU_OK;
}
#endif