Files
interactive/rcts/rc_mngd/src/SocketControl.cpp
T
2026-08-07 17:38:18 +09:00

415 lines
8.4 KiB
C++

/***************************************************************************
Socket Control Class (SocketControl.cpp)
-----------------------------------------
begin : 2013/02/20
copyright : (C) 2013 Solbox Inc.
author : Development 1 Team
- 2013/02/20 - 1st dadamin
email : dev1@solbox.com
version : 3.2.0
CopyRight(C) 2005 Solbox Inc. All Rights reserved.
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "rc_mngd.h"
#include "SocketControl.h"
#include "Logger.h"
#include "UtilFn.h"
#define SOCKET_TIMEOUT 5
CSocketControl::CSocketControl()
: CBaseSocket( SOCKET_NOT_VALID ), m_ssl(NULL)
{
}
CSocketControl::CSocketControl( const int & socket, SSL * ssl)
: CBaseSocket( socket ), m_ssl(ssl)
{
}
CSocketControl::~CSocketControl()
{
}
int CSocketControl::SetOption()
{
if( m_sock == SOCKET_NOT_VALID )
return -1;
int result = 0;
/* Time wait 방지 */
struct linger ling;
ling.l_onoff = 1;
ling.l_linger = 10; /* 0 for abortive disconnect */
result = setsockopt(m_sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
if( result != 0 )
{
int errorNum = errno;
LOG( LERR, "SO_LINGER set error.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
struct timeval tv_timeo = { SOCKET_TIMEOUT, 0 };
/* Recv Timeout 설정. */
result = setsockopt( m_sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo));
if( result != 0 )
{
int errorNum = errno;
LOG( LERR, "SO_RCVTIMEO set error.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
/* Send Timeout 설정. */
result = setsockopt( m_sock, SOL_SOCKET, SO_SNDTIMEO, &tv_timeo, sizeof(tv_timeo));
if( result != 0 )
{
int errorNum = errno;
LOG( LERR, "SO_SNDTIMEO set error.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
return 0;
}
ssize_t CSocketControl::ReadnSSL( void *vptr, size_t n )
{
ssize_t nread = 0;
size_t nleft = n;
char * ptr = (char *)vptr;
while(nleft > 0)
{
if((nread = SSL_read(m_ssl, ptr, nleft)) < 0)
{
int error_code = SSL_get_error(m_ssl, nread);
LOG( LDBG, "SSL read error code [%d]", error_code);
switch( error_code)
{
char tempBuffer[1024];
memset(tempBuffer, 0x00, sizeof(tempBuffer));
case SSL_ERROR_NONE:
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
nread = 0;
LOG( LWAR, "SSL read sleep [%d]", error_code);
solusleep(50000);
break;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
case SSL_ERROR_WANT_X509_LOOKUP:
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
ERR_error_string_n(ERR_get_error(), tempBuffer, sizeof(tempBuffer));
LOG( LERR, "SSL Read Error :[%s]", tempBuffer);
return -1;
}
}
else if(nread == 0)
{
LOG(LWAR, "SSL read return 0.[%zd]", nread);
return 0;
}
nleft -= nread;
ptr += nread;
}
return n;/* ?? */
}
ssize_t CSocketControl::WritenSSL(void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char * ptr = (const char *)vptr;
nleft = n;
int tryCount = 0;
while(nleft > 0)
{
//fprintf(stderr, "[%s] ssl write before nleft[%d]\n", __func__, nleft);
nwritten = SSL_write( m_ssl, ptr, nleft);
//fprintf(stderr, "[%s] ssl write after n[%d]\n", __func__, nwritten);
if( nwritten < 0 )
{
int error_code = SSL_get_error(m_ssl, nwritten);
LOG( LDBG, "SSL Write error code [%d]", error_code);
switch( error_code )
{
char tempBuffer[1024];
memset(tempBuffer, 0x00, sizeof(tempBuffer));
case SSL_ERROR_NONE:
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
nwritten = 0;
++tryCount;
LOG( LWAR, "SSL Write sleep [%d]", error_code);
solusleep(50000);
break;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
case SSL_ERROR_WANT_X509_LOOKUP:
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
ERR_error_string_n(ERR_get_error(), tempBuffer, sizeof(tempBuffer));
LOG( LERR, "SSL Write Error [%s]", tempBuffer);
return -1;
}
}
else if( nwritten == 0)
{
return 0;
}
if( tryCount > 60 )
{
LOG( LERR, "SSL Write Try Count Over !!!");
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
ssize_t CSocketControl::ReadData(void *vptr, size_t n)
{
ssize_t nret = 0;
if(m_ssl)
nret = ReadnSSL(vptr, n);
else
nret = ReadNTimeout(vptr, n);
ostringstream msg;
msg << "Socket ReadData() result.[" << nret << "]";
LOGACONSOLE( LDBG, msg);
return nret;
}
ssize_t CSocketControl::ReadDataEx(void *vptr, size_t n)
{
ssize_t nret = 0;
if (m_ssl)
nret = ReadSSL(vptr, n);
else
nret = ReadTimeout(vptr, n);
ostringstream msg;
msg << "Socket ReadDataEx() result.[" << nret << "]";
LOGACONSOLE(LDBG, msg);
return nret;
}
ssize_t CSocketControl::ReadTimeout(void *vptr, size_t n, int timeout)
{
if (IsValidSocket() == false)
return 0;
ssize_t nRead = 0;
char * ptr = (char *)vptr;
struct timeval timeOver;
int result;
fd_set selectFds;
FD_ZERO(&selectFds);
timeOver.tv_sec = timeout;
timeOver.tv_usec = 0;
FD_SET(m_sock, &selectFds);
do {
result = select(m_sock + 1, &selectFds, (fd_set *)NULL, (fd_set *)NULL, &timeOver);
if (result > 0)
{
if (FD_ISSET(m_sock, &selectFds))
{
if ((nRead = read(m_sock, ptr, n)) < 0)
{
int errorNum = errno;
if (errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK)
{
nRead = 0;
continue;
}
else if (errorNum == ECONNRESET || errorNum == EPIPE)
{
// 2015-08-28 CHG huibong EPIPE(32) 오류 발생시.. 연결 종료로 처리되도록 수정
m_bConnected = false;
return 0;
}
else
{
LOG(LERR, "read func fail.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
}
else if (nRead == 0)
{
m_bConnected = false;
return 0;
}
}
}
else if (result == 0) // Timeout
{
//LOG( LDBG, "read timeout");
return -2;
}
else
{
int errorNum = errno;
LOG(LERR, "select func error.[%d][%s]", errorNum, strerror(errorNum));
return -1;
}
} while (false);
return nRead;
}
ssize_t CSocketControl::ReadSSL(void *vptr, size_t n)
{
ssize_t nread = 0;
char * ptr = (char *)vptr;
if ((nread = SSL_read(m_ssl, ptr, n)) < 0)
{
int error_code = SSL_get_error(m_ssl, nread);
LOG(LDBG, "SSL read error code [%d]", error_code);
switch (error_code)
{
char tempBuffer[1024];
memset(tempBuffer, 0x00, sizeof(tempBuffer));
case SSL_ERROR_NONE:
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
nread = 0;
LOG(LWAR, "SSL read sleep [%d]", error_code);
solusleep(50000);
break;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
case SSL_ERROR_WANT_X509_LOOKUP:
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
ERR_error_string_n(ERR_get_error(), tempBuffer, sizeof(tempBuffer));
LOG(LERR, "SSL Read Error :[%s]", tempBuffer);
return -1;
}
}
else if (nread == 0)
{
LOG(LWAR, "SSL read return 0.[%zd]", nread);
return 0;
}
return nread;/* ?? */
}
ssize_t CSocketControl::WriteData(void *vptr, size_t n)
{
ssize_t nret = 0;
if(m_ssl)
nret = WritenSSL(vptr, n);
else
nret = WriteN(vptr, n);
ostringstream msg;
msg << "Socket WriteData() result.[" << nret << "]";
LOGACONSOLE( LDBG, msg);
return nret;
}
string CSocketControl::GetMyIPString()
{
string r;
union {
struct sockaddr s;
struct sockaddr_in v4;
#ifdef AF_INET6
struct sockaddr_in6 v6;
#endif // AF_INET6
} u;
if (m_sock == SOCKET_NOT_VALID) return r;
socklen_t slen = sizeof(u);
if (getsockname(m_sock, &u.s, &slen) == 0)
{
#ifdef AF_INET6
if (u.s.sa_family == AF_INET6)
{
socklen_t clientSockLen;
char tempBuffer[INET6_ADDRSTRLEN] = {0};
clientSockLen = sizeof(u.v6);
if (inet_ntop(AF_INET6, (void *)&u.v6.sin6_addr, tempBuffer, sizeof(tempBuffer)) != NULL)
{
r = tempBuffer;
}
} else
#endif // AF_INET6
if (u.s.sa_family == AF_INET)
{
socklen_t clientSockLen;
char tempBuffer[INET_ADDRSTRLEN] = {0};
clientSockLen = sizeof(&u.v4);
if (inet_ntop(AF_INET, (void *)& u.v4.sin_addr, tempBuffer, sizeof(tempBuffer)) != NULL)
{
r = tempBuffer;
}
}
else
{
LOG( LERR, "My IP String : UNKNOWN??");
}
}
LOG( LDBG, "My IP String : %s",r.c_str());
return r;
}