415 lines
8.4 KiB
C++
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;
|
|
}
|