| /* $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 |
| |
| |