123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- /*---------------------------------------------------------------------------*/
- /* */
- /* CActiveSocket.cpp - Active Socket Implementation */
- /* */
- /* Author : Mark Carrier (mark@carrierlabs.com) */
- /* */
- /*---------------------------------------------------------------------------*/
- /* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * 4. The name "CarrierLabs" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * mark@carrierlabs.com.
- *
- * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *----------------------------------------------------------------------------*/
- #include "ActiveSocket.h"
- CActiveSocket::CActiveSocket(CSocketType nType) : CSimpleSocket(nType)
- {
- }
- //------------------------------------------------------------------------------
- //
- // ConnectTCP() -
- //
- //------------------------------------------------------------------------------
- bool CActiveSocket::ConnectTCP(const char *pAddr, uint16 nPort)
- {
- bool bRetVal = false;
- struct in_addr stIpAddress;
- //------------------------------------------------------------------
- // Preconnection setup that must be preformed
- //------------------------------------------------------------------
- memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
- m_stServerSockaddr.sin_family = AF_INET;
- if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
- {
- #ifdef WIN32
- TranslateSocketError();
- #else
- if (h_errno == HOST_NOT_FOUND)
- {
- SetSocketError(SocketInvalidAddress);
- }
- #endif
- return bRetVal;
- }
- memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
- m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
- if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
- {
- TranslateSocketError();
- return bRetVal;
- }
- m_stServerSockaddr.sin_port = htons(nPort);
- //------------------------------------------------------------------
- // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
- //
- //------------------------------------------------------------------
- m_timer.Initialize();
- m_timer.SetStartTime();
- if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) ==
- CSimpleSocket::SocketError)
- {
- //--------------------------------------------------------------
- // Get error value this might be a non-blocking socket so we
- // must first check.
- //--------------------------------------------------------------
- TranslateSocketError();
- //--------------------------------------------------------------
- // If the socket is non-blocking and the current socket error
- // is SocketEinprogress or SocketEwouldblock then poll connection
- // with select for designated timeout period.
- // Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK.
- //--------------------------------------------------------------
- if ((IsNonblocking()) &&
- ((GetSocketError() == CSimpleSocket::SocketEwouldblock) ||
- (GetSocketError() == CSimpleSocket::SocketEinprogress)))
- {
- bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec());
- }
- }
- else
- {
- TranslateSocketError();
- bRetVal = true;
- }
- m_timer.SetEndTime();
- return bRetVal;
- }
- //------------------------------------------------------------------------------
- //
- // ConnectUDP() -
- //
- //------------------------------------------------------------------------------
- bool CActiveSocket::ConnectUDP(const char *pAddr, uint16 nPort)
- {
- bool bRetVal = false;
- struct in_addr stIpAddress;
- //------------------------------------------------------------------
- // Pre-connection setup that must be preformed
- //------------------------------------------------------------------
- memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
- m_stServerSockaddr.sin_family = AF_INET;
- if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
- {
- #ifdef WIN32
- TranslateSocketError();
- #else
- if (h_errno == HOST_NOT_FOUND)
- {
- SetSocketError(SocketInvalidAddress);
- }
- #endif
- return bRetVal;
- }
- memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
- m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
- if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
- {
- TranslateSocketError();
- return bRetVal;
- }
- m_stServerSockaddr.sin_port = htons(nPort);
- //------------------------------------------------------------------
- // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
- //
- //------------------------------------------------------------------
- m_timer.Initialize();
- m_timer.SetStartTime();
- if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
- {
- bRetVal = true;
- }
- TranslateSocketError();
- m_timer.SetEndTime();
- return bRetVal;
- }
- //------------------------------------------------------------------------------
- //
- // ConnectRAW() -
- //
- //------------------------------------------------------------------------------
- bool CActiveSocket::ConnectRAW(const char *pAddr, uint16 nPort)
- {
- bool bRetVal = false;
- struct in_addr stIpAddress;
- //------------------------------------------------------------------
- // Pre-connection setup that must be preformed
- //------------------------------------------------------------------
- memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
- m_stServerSockaddr.sin_family = AF_INET;
- if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
- {
- #ifdef WIN32
- TranslateSocketError();
- #else
- if (h_errno == HOST_NOT_FOUND)
- {
- SetSocketError(SocketInvalidAddress);
- }
- #endif
- return bRetVal;
- }
- memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
- m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
- if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
- {
- TranslateSocketError();
- return bRetVal;
- }
- m_stServerSockaddr.sin_port = htons(nPort);
- //------------------------------------------------------------------
- // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
- //
- //------------------------------------------------------------------
- m_timer.Initialize();
- m_timer.SetStartTime();
- if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
- {
- bRetVal = true;
- }
- TranslateSocketError();
- m_timer.SetEndTime();
- return bRetVal;
- }
- //------------------------------------------------------------------------------
- //
- // Open() - Create a connection to a specified address on a specified port
- //
- //------------------------------------------------------------------------------
- bool CActiveSocket::Open(const char *pAddr, uint16 nPort)
- {
- bool bRetVal = false;
- if (IsSocketValid() == false)
- {
- SetSocketError(CSimpleSocket::SocketInvalidSocket);
- return bRetVal;
- }
- if (pAddr == NULL)
- {
- SetSocketError(CSimpleSocket::SocketInvalidAddress);
- return bRetVal;
- }
- if (nPort == 0)
- {
- SetSocketError(CSimpleSocket::SocketInvalidPort);
- return bRetVal;
- }
- switch (m_nSocketType)
- {
- case CSimpleSocket::SocketTypeTcp :
- {
- bRetVal = ConnectTCP(pAddr, nPort);
- break;
- }
- case CSimpleSocket::SocketTypeUdp :
- {
- bRetVal = ConnectUDP(pAddr, nPort);
- break;
- }
- case CSimpleSocket::SocketTypeRaw :
- break;
- default:
- break;
- }
- //--------------------------------------------------------------------------
- // If successful then create a local copy of the address and port
- //--------------------------------------------------------------------------
- if (bRetVal)
- {
- socklen_t nSockLen = sizeof(struct sockaddr);
- memset(&m_stServerSockaddr, 0, nSockLen);
- getpeername(m_socket, (struct sockaddr *)&m_stServerSockaddr, &nSockLen);
- nSockLen = sizeof(struct sockaddr);
- memset(&m_stClientSockaddr, 0, nSockLen);
- getsockname(m_socket, (struct sockaddr *)&m_stClientSockaddr, &nSockLen);
- SetSocketError(SocketSuccess);
- }
- return bRetVal;
- }
|