summaryrefslogtreecommitdiff
path: root/src/ActiveSocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ActiveSocket.cpp')
-rw-r--r--src/ActiveSocket.cpp314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/ActiveSocket.cpp b/src/ActiveSocket.cpp
new file mode 100644
index 0000000..6da25e8
--- /dev/null
+++ b/src/ActiveSocket.cpp
@@ -0,0 +1,314 @@
+/*---------------------------------------------------------------------------*/
+/* */
+/* 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 uint8 *pAddr, int16 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 uint8 *pAddr, int16 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 uint8 *pAddr, int16 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 uint8 *pAddr, int16 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;
+}