/*************************************************************************** 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; }