base
This commit is contained in:
@@ -0,0 +1,792 @@
|
||||
#include "CcCollectdClientSocket.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#else
|
||||
#include <endian.h>
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define HOSTNAME_SIZE 256
|
||||
|
||||
|
||||
// 생성자.
|
||||
CCcCollectdClientSocket::CCcCollectdClientSocket()
|
||||
: CBaseSocket( SOCKET_NOT_VALID )
|
||||
, m_nPacketHeaderLen ( sizeof(m_packetHeader))
|
||||
, m_nPacketDataLen( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
// 소멸자
|
||||
CCcCollectdClientSocket::~CCcCollectdClientSocket()
|
||||
{
|
||||
// 소멸자 Socket 명시적 Close 처리.
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
// Packet Header 정보를 Log 파일에 Logging 처리
|
||||
void CCcCollectdClientSocket::PrintHeaderToLog()
|
||||
{
|
||||
_LOG( LINF, "------------------------------------" );
|
||||
_LOG( LINF, "stx [%02x]", m_packetHeader.stx );
|
||||
_LOG( LINF, "type [%02x]", m_packetHeader.type );
|
||||
_LOG( LINF, "command [%02x][%02x][%02x][%02x]", m_packetHeader.command[0], m_packetHeader.command[1], m_packetHeader.command[2], m_packetHeader.command[3] );
|
||||
_LOG( LINF, "result [%02x][%02x][%02x][%02x]", m_packetHeader.result[0], m_packetHeader.result[1], m_packetHeader.result[2], m_packetHeader.result[3] );
|
||||
_LOG( LINF, "data_length [%u]", m_nPacketDataLen );
|
||||
_LOG( LINF, "extend_code [%02x][%02x]", m_packetHeader.extend_code[0], m_packetHeader.extend_code[1] );
|
||||
_LOG( LINF, "------------------------------------" );
|
||||
}
|
||||
|
||||
|
||||
// socket 에서 지정된 크기만큼의 데이터를 읽어 내부 임시버퍼인 m_tempBuffer 에 저장처리.
|
||||
// @param size [in] read 할 데이터 크기
|
||||
// @return On success return true, otherwise return false.
|
||||
bool CCcCollectdClientSocket::GetPacketData( unsigned int size )
|
||||
{
|
||||
// 1. 수신할 크기가 임시버퍼보다 큰 경우 오류 반환.
|
||||
if( size > DEFAULT_SOCKET_TEMP_BUFFER_SIZE )
|
||||
return false;
|
||||
|
||||
// 2. 데이터 수신 처리.
|
||||
int nRead = ReadNTimeout( m_tempBuffer, size );
|
||||
|
||||
// 오류 발생시
|
||||
if( nRead <= 0 )
|
||||
return false;
|
||||
|
||||
// 3. 정상인 경우는 ReadNTimeout 함수가 무조건 요청 크기만큼 read 처리하므로 정상수신임.
|
||||
return true;
|
||||
}
|
||||
|
||||
// socket 에서 지정된 크기만큼의 데이터를 읽어 출력변수에 저장처리.
|
||||
// @param size [in] read 할 데이터 크기
|
||||
// @param value [out] 읽은 데이터를 저장할 string 변수
|
||||
// @return On success return true, otherwise return false.
|
||||
bool CCcCollectdClientSocket::GetPacketData( unsigned int& size, std::string& value )
|
||||
{
|
||||
// 1. 수신할 크기가 임시버퍼보다 큰 경우 새로운 버퍼를 생성한다.
|
||||
BYTE * pBuffer = NULL;
|
||||
bool bNewBufferCreated = false;
|
||||
if( size > DEFAULT_SOCKET_TEMP_BUFFER_SIZE )
|
||||
{
|
||||
pBuffer = new BYTE[size]; // 신규 메모리 할당.
|
||||
bNewBufferCreated = true;
|
||||
}
|
||||
else
|
||||
pBuffer = m_tempBuffer;
|
||||
|
||||
// 2. 데이터 수신 처리.
|
||||
int nRead = ReadNTimeout( pBuffer, size );
|
||||
|
||||
// 오류 발생시
|
||||
if( nRead <= 0 )
|
||||
{
|
||||
// 신규로 생성된 버퍼인 경우 메모리 해제 처리.
|
||||
if( bNewBufferCreated == true )
|
||||
delete[] pBuffer;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 수신 데이터 저장 처리 - 기존 데이터 뒤에 붙여 준다=> 이게 사용하기 편함.
|
||||
value.append( (char *)pBuffer, size );
|
||||
|
||||
// 신규로 생성된 버퍼인 경우 메모리 해제 처리.
|
||||
if( bNewBufferCreated == true )
|
||||
delete[] pBuffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// pValue 에 저장된 데이터를 unsigned long long (64Byte) 형으로 변환처리 및 Endian 변환
|
||||
unsigned long long CCcCollectdClientSocket::GetDataToUInt64( BYTE * pValue, bool bConvertEndian )
|
||||
{
|
||||
BYTE tempBuffer[8];
|
||||
unsigned long long result;
|
||||
|
||||
memcpy( tempBuffer, pValue, 8 );
|
||||
unsigned long long * pResult = ( unsigned long long * )tempBuffer;
|
||||
|
||||
// Endian 변환처리.
|
||||
if( bConvertEndian == true )
|
||||
{
|
||||
// Network byte order (big endian) 을 Host byte order 로 변환 처리
|
||||
//result = be64toh( *pResult );
|
||||
result = do_ntohll( *pResult );
|
||||
}
|
||||
else
|
||||
result = *pResult;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Packet 정보 중 String 정보를 전송하기 위한 함수.
|
||||
bool CCcCollectdClientSocket::SendString( const std::string& strData )
|
||||
{
|
||||
if( IsValidSocket() == false )
|
||||
return false;
|
||||
|
||||
// 크기값을 저장하기 위한 임시 변수.
|
||||
unsigned int nSize = 0;
|
||||
|
||||
// String Data 전송
|
||||
nSize = htonl( strData.size() );
|
||||
WriteN( &nSize, 4 );
|
||||
if( strData.size() > 0 )
|
||||
WriteN( strData.c_str(), strData.size() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// byte ordering function for 64bit variable
|
||||
uint64_t CCcCollectdClientSocket::do_htonll( uint64_t hostlonglong )
|
||||
{
|
||||
int x = 1;
|
||||
|
||||
/* little endian */
|
||||
if( *(char *)&x == 1 )
|
||||
return ( ( ( (uint64_t)htonl( hostlonglong ) ) << 32 ) + htonl( hostlonglong >> 32 ) );
|
||||
|
||||
/* big endian */
|
||||
else
|
||||
return hostlonglong;
|
||||
}
|
||||
|
||||
uint64_t CCcCollectdClientSocket::do_ntohll( uint64_t netlonglong )
|
||||
{
|
||||
int x = 1;
|
||||
|
||||
/* little endian */
|
||||
if( *(char *)&x == 1 )
|
||||
return ( ( ( (uint64_t)ntohl( netlonglong ) ) << 32 ) + ntohl( netlonglong >> 32 ) );
|
||||
|
||||
/* big endian */
|
||||
else
|
||||
return netlonglong;
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
// 전달받은 Target 으로 Socket 접속을 수행
|
||||
bool CCcCollectdClientSocket::ConnectTarget( const std::string& szTarget, int nPort )
|
||||
{
|
||||
return Connect( szTarget, nPort );
|
||||
}
|
||||
|
||||
// cc_collect 로부터 available size 정보를 요청, 결과를 수신처리한다.
|
||||
bool CCcCollectdClientSocket::GetAvailableSize( unsigned long long& uSize )
|
||||
{
|
||||
if( IsValidSocket() == false )
|
||||
return false;
|
||||
|
||||
// 정보 요청을 위한 Packet Header 생성.
|
||||
struct CcCollectdPacketHeader stHeader;
|
||||
memset( &stHeader, 0x00, sizeof( struct CcCollectdPacketHeader ) );
|
||||
|
||||
stHeader.stx = HEADER_STX_CODE;
|
||||
stHeader.type = HEADER_TYPE_REQUEST;
|
||||
stHeader.command[0] = REQUEST_AVAILABLE_SIZE;
|
||||
|
||||
// Data 부분의 길이를 계산한다.
|
||||
// - Data 부분 길이는 없음.
|
||||
stHeader.data_length = htonl( 0 );
|
||||
|
||||
// Packet Header 정보 전송
|
||||
if( WriteN( &stHeader, m_nPacketHeaderLen ) != m_nPacketHeaderLen )
|
||||
{
|
||||
LOG( LERR, "request [REQUEST_AVAILABLE_SIZE] send fail to cc_collectd. " );
|
||||
return false;
|
||||
}
|
||||
|
||||
// 응답 대기...
|
||||
// 최대 3분 대기
|
||||
int nTimeout = 60 * 3; // 최대 3분간 대기
|
||||
int nRead;
|
||||
|
||||
// Socket 으로 부터 Packet Header 부분 수신.
|
||||
// 수신된 정보는 멤버변수에 저장처리.
|
||||
nRead = ReadNTimeout( &m_packetHeader, m_nPacketHeaderLen, nTimeout );
|
||||
|
||||
// nRead 0: Socket Closed
|
||||
// -1: error
|
||||
// -2: Timeout 이므로
|
||||
if( nRead == -2 )
|
||||
{
|
||||
// Timeout 발생시
|
||||
LOG( LERR, "cc_collectd REQUEST_AVAILABLE_SIZE reponse wait. but timeout[%d sec] occured.", nTimeout );
|
||||
return false;
|
||||
}
|
||||
else if( nRead == 0 || nRead == -1 )
|
||||
{
|
||||
// Socket Close 또는 오류 발생시
|
||||
LOG( LERR, "cc_collectd REQUEST_AVAILABLE_SIZE reponse wait. but socket closed or error [%d]", nRead );
|
||||
return false;
|
||||
}
|
||||
|
||||
// STX code 검사.
|
||||
if( m_packetHeader.stx != HEADER_STX_CODE )
|
||||
{
|
||||
LOG( LERR, "Not valid stx code." );
|
||||
PrintHeaderToLog();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data Length 부분 값을 멤버 변수에 저장처리.
|
||||
m_nPacketDataLen = ntohl( m_packetHeader.data_length );
|
||||
|
||||
// 해당 Packet 에 대한 응답패킷인지 검사.
|
||||
if( m_packetHeader.type != HEADER_TYPE_RESPONSE
|
||||
|| m_packetHeader.command[0] != REQUEST_AVAILABLE_SIZE )
|
||||
{
|
||||
// 다른 패킷이 들어온 경우
|
||||
|
||||
// ** 정석대로라면 그냥 냅둬어 수신부에서 처리해야 하지만
|
||||
// 현재 수신 처리부가 없어 당장 문제가 생길수 있으므로
|
||||
// 데이터 부분까지 수신하여 임시버퍼에 저장처리 해 놓는다.
|
||||
GetPacketData( m_nPacketDataLen );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data 부분이 존재하는 경우.. 수신 처리.
|
||||
if( m_nPacketDataLen > 0 )
|
||||
{
|
||||
// Data 항목은
|
||||
// - 8 Byte Network byte order 로 구성된 available size 정보가 들어 있음.
|
||||
if( GetPacketData( m_nPacketDataLen ) == false )
|
||||
{
|
||||
LOG( LERR, "available size body receive failed." );
|
||||
return false;
|
||||
}
|
||||
|
||||
BYTE * pPos = m_tempBuffer;
|
||||
uSize = GetDataToUInt64( pPos, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
// cc_collectd 로 부터 Available size 응답을 받았지만.. body 가 없는 경우.
|
||||
// 이런 경우는 없지만.. 오류 처리를 위해 코딩.
|
||||
LOG( LERR, "available size body length zero. check." );
|
||||
return false;
|
||||
}
|
||||
|
||||
_LOG( LDBG, "cc_collectd available size result received. [%llu]", uSize );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// cc_collect 로 File 저장 목적으로 전송
|
||||
bool CCcCollectdClientSocket::SendFile( const std::string strProcessName, const std::string strFileName
|
||||
, const int& fd, const unsigned long long& uFileSize
|
||||
, std::string& strMessage )
|
||||
{
|
||||
// 입력 받은 정보가 유효한지 검사.
|
||||
// strProcessName : 생략 가능하지만.. 문자열에 '/' 가 포함되서는 안된다.
|
||||
// strFileName : 생략 불가, 문자열에 '/' 가 포함되서는 안된다.
|
||||
if( strProcessName.empty() == false )
|
||||
{
|
||||
std::string::size_type pos = strProcessName.find( '/' );
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
// '/' 문자가 포함된 경우...
|
||||
char tempBuffer[1024];
|
||||
snprintf( tempBuffer, sizeof( tempBuffer ) - 1
|
||||
, "process name[%s] not valid that include slash."
|
||||
, strProcessName.c_str() );
|
||||
|
||||
strMessage.append( tempBuffer );
|
||||
LOG( LERR, "%s", strMessage.c_str() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( strFileName.empty() == false )
|
||||
{
|
||||
std::string::size_type pos = strFileName.find( '/' );
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
// '/' 문자가 포함된 경우...
|
||||
char tempBuffer[1024];
|
||||
snprintf( tempBuffer, sizeof( tempBuffer ) - 1
|
||||
, "file name[%s] not valid that include slash."
|
||||
, strFileName.c_str() );
|
||||
|
||||
strMessage.append( tempBuffer );
|
||||
LOG( LERR, "%s", strMessage.c_str() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// filename 이 없는 경우.
|
||||
strMessage = "filename not vaild. empty.";
|
||||
LOG( LERR, "filename not vaild. empty." );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long uAvailableSize = 0;
|
||||
|
||||
// 1. cc_collectd 로 부터 available size 정보를 수신
|
||||
if( GetAvailableSize( uAvailableSize ) == false )
|
||||
{
|
||||
// available size 체크 실패시...
|
||||
strMessage = "cc_collectd available size check fail.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 수신된 uAvailableSize 과 전송할 File size 비교
|
||||
if( uAvailableSize <= uFileSize )
|
||||
{
|
||||
char tempBuffer[1024];
|
||||
snprintf( tempBuffer, sizeof( tempBuffer ) - 1
|
||||
, "file size[%llu] too large than cc_collect available size [%llu]"
|
||||
, uFileSize, uAvailableSize );
|
||||
|
||||
strMessage.append( tempBuffer );
|
||||
LOG( LERR, "%s", strMessage.c_str() );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 장비의 hostname 정보를 추출한다.
|
||||
char szHostName[HOSTNAME_SIZE];
|
||||
memset( szHostName, 0x00, HOSTNAME_SIZE );
|
||||
if( gethostname( szHostName, HOSTNAME_SIZE - 1 ) != 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
|
||||
strMessage = "hostname get failed. check hostname.";
|
||||
LOG( LERR, "hostname get failed. [%d][%s]", errorNum, strerror( errorNum ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( strlen( szHostName ) == 0 )
|
||||
{
|
||||
strMessage = "hostname not vaild. check hostname.";
|
||||
LOG( LERR, "hostname not valid. length 0" );
|
||||
return false;
|
||||
}
|
||||
std::string strHostName = szHostName; // 추출된 hostname 정보를 전송하기 편하도록 string 객체에 저장처리.
|
||||
|
||||
|
||||
// 4. 파일 전송 관련 요청 송신
|
||||
struct CcCollectdPacketHeader stHeader;
|
||||
memset( &stHeader, 0x00, sizeof( struct CcCollectdPacketHeader ) );
|
||||
|
||||
stHeader.stx = HEADER_STX_CODE;
|
||||
stHeader.type = HEADER_TYPE_REQUEST;
|
||||
stHeader.command[0] = REQUEST_FILE_SAVE;
|
||||
|
||||
// Data 부분
|
||||
// strHostName : string ( 4 + string.size() )
|
||||
// strProcessName : string ( 4 + string.size() )
|
||||
// strFileName : string ( 4 + string.size() )
|
||||
// uFileSize : 8 Byte ---------->본 항목까지만 header data_length 에 포함시킨다.
|
||||
// 저장할 파일 내용.
|
||||
|
||||
// Data 부분의 길이를 계산한다.
|
||||
unsigned int nTemp = 0;
|
||||
nTemp += ( 4 + strHostName.size() ); // strHostName
|
||||
nTemp += ( 4 + strProcessName.size() ); // strProcessName
|
||||
nTemp += ( 4 + strFileName.size() ); // strFileName
|
||||
nTemp += 8; // uFileSize
|
||||
|
||||
stHeader.data_length = htonl( nTemp );
|
||||
|
||||
// Packet Header 정보 전송
|
||||
if( WriteN( &stHeader, m_nPacketHeaderLen ) != m_nPacketHeaderLen )
|
||||
{
|
||||
strMessage = "request [REQUEST_FILE_SAVE] send fail to cc_collectd.";
|
||||
LOG( LERR, "%s", strMessage.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Body 부분 전송
|
||||
// strHostName
|
||||
SendString( strHostName );
|
||||
// strProcessName
|
||||
SendString( strProcessName );
|
||||
// strFileName
|
||||
SendString( strFileName );
|
||||
// uFileSize (Network byte order )
|
||||
//uAvailableSize = htobe64( uFileSize );
|
||||
uAvailableSize = do_htonll( uFileSize );
|
||||
|
||||
WriteN( &uAvailableSize, 8 );
|
||||
|
||||
// 파일 내용 전송
|
||||
if( uFileSize > 0 )
|
||||
{
|
||||
off_t offset = 0;
|
||||
|
||||
// sendfile() 에 대한 함수 정의가 Linux, FreeBSD 에서 다르므로.. OS 별로 처리한다.
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
// FreeBSD 의 경우.. 10G 까지 전송 테스트 됨.
|
||||
|
||||
off_t sbytes;
|
||||
int ret = sendfile( fd, m_sock, offset, uFileSize, NULL, &sbytes, 0 );
|
||||
|
||||
if( ret == -1 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
LOG( LERR, "sendfile function error. [%d][%s]", errorNum, strerror( errorNum ) );
|
||||
// 전송 실패 발생시...
|
||||
strMessage = "file send fail to cc_collectd";
|
||||
return false;
|
||||
}
|
||||
else if( ( unsigned long long )sbytes != uFileSize )
|
||||
{
|
||||
LOG( LERR, "sendfile error. file[%s] size[%llu] send size[%ld]", strFileName.c_str(), uFileSize, sbytes );
|
||||
strMessage = "file send fail to cc_collectd. file size not match.";
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
// Linux 의 경우 sendfile 함수가 2G 까지만 전송 가능하므로....루프로 전송 처리가 되도록 처리한다.
|
||||
|
||||
ssize_t bytes_sent;
|
||||
size_t total_bytes_sent = 0;
|
||||
|
||||
while( total_bytes_sent < uFileSize )
|
||||
{
|
||||
if( (bytes_sent = sendfile(m_sock, fd, &offset, uFileSize - total_bytes_sent)) <= 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
if (errorNum == EINTR || errorNum == EAGAIN)
|
||||
{
|
||||
// Interrupted system call/try again
|
||||
// Just skip to the top of the loop and try again
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG( LERR, "sendfile function error. [%d][%s]", errorNum, strerror( errorNum ) );
|
||||
|
||||
// 전송 실패 발생시...
|
||||
strMessage = "file send fail to cc_collectd";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
total_bytes_sent += bytes_sent;
|
||||
}
|
||||
|
||||
if( ( unsigned long long )total_bytes_sent != uFileSize )
|
||||
{
|
||||
LOG( LERR, "sendfile error. file[%s] size[%llu] send size[%ld]", strFileName.c_str(), uFileSize, total_bytes_sent );
|
||||
strMessage = "file send fail to cc_collectd. file size not match.";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// 5. File 전송 처리 결과 수신.
|
||||
// - 최대 10 분 동안 응답 대기
|
||||
int nTimeout = 60 * 10; // 최대 10분간 대기
|
||||
int nRead;
|
||||
|
||||
// Socket 으로 부터 Packet Header 부분 수신.
|
||||
// 수신된 정보는 멤버변수에 저장처리.
|
||||
nRead = ReadNTimeout( &m_packetHeader, m_nPacketHeaderLen, nTimeout );
|
||||
|
||||
// nRead 0: Socket Closed
|
||||
// -1: error
|
||||
// -2: Timeout 이므로
|
||||
if( nRead == -2 )
|
||||
{
|
||||
// Timeout 발생시
|
||||
LOG( LERR, "cc_collectd REQUEST_FILE_SAVE reponse wait. but timeout[%d sec] occured.", nTimeout );
|
||||
strMessage = "cc_collectd REQUEST_FILE_SAVE reponse timeout[10 min] occured.";
|
||||
return false;
|
||||
}
|
||||
else if( nRead == 0 || nRead == -1 )
|
||||
{
|
||||
// Socket Close 또는 오류 발생시
|
||||
LOG( LERR, "cc_collectd REQUEST_FILE_SAVE reponse wait. but socket closed or error [%d]", nRead );
|
||||
strMessage = "cc_collectd REQUEST_FILE_SAVE reponse wait. but session closed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// STX code 검사.
|
||||
if( m_packetHeader.stx != HEADER_STX_CODE )
|
||||
{
|
||||
LOG( LERR, "Not valid stx code." );
|
||||
strMessage = "cc_collectd REQUEST_FILE_SAVE reponse not valid.";
|
||||
PrintHeaderToLog();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data Length 부분 값을 멤버 변수에 저장처리.
|
||||
m_nPacketDataLen = ntohl( m_packetHeader.data_length );
|
||||
|
||||
// 해당 Packet 에 대한 응답패킷인지 검사.
|
||||
if( m_packetHeader.type != HEADER_TYPE_RESPONSE
|
||||
|| m_packetHeader.command[0] != REQUEST_FILE_SAVE )
|
||||
{
|
||||
// 다른 패킷이 들어온 경우
|
||||
|
||||
// ** 정석대로라면 그냥 냅둬어 수신부에서 처리해야 하지만
|
||||
// 현재 수신 처리부가 없어 당장 문제가 생길수 있으므로
|
||||
// 데이터 부분까지 수신하여 임시버퍼에 저장처리 해 놓는다.
|
||||
GetPacketData( m_nPacketDataLen );
|
||||
|
||||
strMessage = "cc_collectd REQUEST_FILE_SAVE reponse not valid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data 부분이 존재하는 경우.. 수신 처리.
|
||||
if( m_nPacketDataLen > 0 )
|
||||
{
|
||||
if( GetPacketData( m_nPacketDataLen, strMessage ) == false )
|
||||
{
|
||||
LOG( LERR, "cc_collectd REQUEST_FILE_SAVE body receive failed." );
|
||||
strMessage = "cc_collectd REQUEST_FILE_SAVE body receive failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 성공 실패 여부 확인
|
||||
if( m_packetHeader.result[0] != HEADER_RESULT_SUCCESS )
|
||||
{
|
||||
_LOG( LDBG, "cc_collectd REQUEST_FILE_SAVE result received. error[%s]", strMessage.c_str() );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_LOG( LDBG, "cc_collectd REQUEST_FILE_SAVE result received. success." );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// cc_collect 로 File 존재 여부 확인
|
||||
bool CCcCollectdClientSocket::CheckFile( const std::string strProcessName, const std::string strFileName
|
||||
, unsigned long long& uFileSize, std::string& strErrorMessage )
|
||||
{
|
||||
// 입력 받은 정보가 유효한지 검사.
|
||||
// strProcessName : 생략 가능하지만.. 문자열에 '/' 가 포함되서는 안된다.
|
||||
// strFileName : 생략 불가, 문자열에 '/' 가 포함되서는 안된다.
|
||||
if( strProcessName.empty() == false )
|
||||
{
|
||||
std::string::size_type pos = strProcessName.find( '/' );
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
// '/' 문자가 포함된 경우...
|
||||
char tempBuffer[1024];
|
||||
snprintf( tempBuffer, sizeof( tempBuffer ) - 1
|
||||
, "process name[%s] not valid that include slash."
|
||||
, strProcessName.c_str() );
|
||||
|
||||
strErrorMessage.append( tempBuffer );
|
||||
LOG( LERR, "%s", strErrorMessage.c_str() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( strFileName.empty() == false )
|
||||
{
|
||||
std::string::size_type pos = strFileName.find( '/' );
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
// '/' 문자가 포함된 경우...
|
||||
char tempBuffer[1024];
|
||||
snprintf( tempBuffer, sizeof( tempBuffer ) - 1
|
||||
, "file name[%s] not valid that include slash."
|
||||
, strFileName.c_str() );
|
||||
|
||||
strErrorMessage.append( tempBuffer );
|
||||
LOG( LERR, "%s", strErrorMessage.c_str() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// filename 이 없는 경우.
|
||||
strErrorMessage = "filename not vaild. empty.";
|
||||
LOG( LERR, "filename not vaild. empty." );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 장비의 hostname 정보를 추출한다.
|
||||
char szHostName[HOSTNAME_SIZE];
|
||||
memset( szHostName, 0x00, HOSTNAME_SIZE );
|
||||
if( gethostname( szHostName, HOSTNAME_SIZE - 1 ) != 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
|
||||
strErrorMessage = "hostname get failed. check hostname.";
|
||||
LOG( LERR, "hostname get failed. [%d][%s]", errorNum, strerror( errorNum ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( strlen( szHostName ) == 0 )
|
||||
{
|
||||
strErrorMessage = "hostname not vaild. check hostname.";
|
||||
LOG( LERR, "hostname not valid. length 0" );
|
||||
return false;
|
||||
}
|
||||
std::string strHostName = szHostName; // 추출된 hostname 정보를 전송하기 편하도록 string 객체에 저장처리.
|
||||
|
||||
// 파일 Check 관련 요청 송신
|
||||
struct CcCollectdPacketHeader stHeader;
|
||||
memset( &stHeader, 0x00, sizeof( struct CcCollectdPacketHeader ) );
|
||||
|
||||
stHeader.stx = HEADER_STX_CODE;
|
||||
stHeader.type = HEADER_TYPE_REQUEST;
|
||||
stHeader.command[0] = REQUEST_FILE_CHECK;
|
||||
|
||||
// Data 부분
|
||||
// strHostName : string ( 4 + string.size() )
|
||||
// strProcessName : string ( 4 + string.size() )
|
||||
// strFileName : string ( 4 + string.size() )
|
||||
|
||||
|
||||
// Data 부분의 길이를 계산한다.
|
||||
unsigned int nTemp = 0;
|
||||
nTemp += ( 4 + strHostName.size() ); // strHostName
|
||||
nTemp += ( 4 + strProcessName.size() ); // strProcessName
|
||||
nTemp += ( 4 + strFileName.size() ); // strFileName
|
||||
|
||||
stHeader.data_length = htonl( nTemp );
|
||||
|
||||
// Packet Header 정보 전송
|
||||
if( WriteN( &stHeader, m_nPacketHeaderLen ) != m_nPacketHeaderLen )
|
||||
{
|
||||
strErrorMessage = "request [REQUEST_FILE_CHECK] send fail to cc_collectd.";
|
||||
LOG( LERR, "%s", strErrorMessage.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Body 부분 전송
|
||||
// strHostName
|
||||
SendString( strHostName );
|
||||
// strProcessName
|
||||
SendString( strProcessName );
|
||||
// strFileName
|
||||
SendString( strFileName );
|
||||
|
||||
|
||||
// File Check 처리 결과 수신.
|
||||
// - 최대 30 sec 동안 응답 대기
|
||||
int nTimeout = 30;
|
||||
int nRead;
|
||||
|
||||
// Socket 으로 부터 Packet Header 부분 수신.
|
||||
// 수신된 정보는 멤버변수에 저장처리.
|
||||
nRead = ReadNTimeout( &m_packetHeader, m_nPacketHeaderLen, nTimeout );
|
||||
|
||||
// nRead 0: Socket Closed
|
||||
// -1: error
|
||||
// -2: Timeout 이므로
|
||||
if( nRead == -2 )
|
||||
{
|
||||
// Timeout 발생시
|
||||
LOG( LERR, "cc_collectd REQUEST_FILE_CHECK reponse wait. but timeout[%d sec] occured.", nTimeout );
|
||||
strErrorMessage = "cc_collectd REQUEST_FILE_CHECK reponse timeout[30 sec] occured.";
|
||||
return false;
|
||||
}
|
||||
else if( nRead == 0 || nRead == -1 )
|
||||
{
|
||||
// Socket Close 또는 오류 발생시
|
||||
LOG( LERR, "cc_collectd REQUEST_FILE_CHECK reponse wait. but socket closed or error [%d]", nRead );
|
||||
strErrorMessage = "cc_collectd REQUEST_FILE_CHECK reponse wait. but session closed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// STX code 검사.
|
||||
if( m_packetHeader.stx != HEADER_STX_CODE )
|
||||
{
|
||||
LOG( LERR, "Not valid stx code." );
|
||||
strErrorMessage = "cc_collectd REQUEST_FILE_CHECK reponse not valid.";
|
||||
PrintHeaderToLog();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data Length 부분 값을 멤버 변수에 저장처리.
|
||||
m_nPacketDataLen = ntohl( m_packetHeader.data_length );
|
||||
|
||||
// 해당 Packet 에 대한 응답패킷인지 검사.
|
||||
if( m_packetHeader.type != HEADER_TYPE_RESPONSE
|
||||
|| m_packetHeader.command[0] != REQUEST_FILE_CHECK )
|
||||
{
|
||||
// 다른 패킷이 들어온 경우
|
||||
|
||||
// ** 정석대로라면 그냥 냅둬어 수신부에서 처리해야 하지만
|
||||
// 현재 수신 처리부가 없어 당장 문제가 생길수 있으므로
|
||||
// 데이터 부분까지 수신하여 임시버퍼에 저장처리 해 놓는다.
|
||||
GetPacketData( m_nPacketDataLen );
|
||||
|
||||
strErrorMessage = "cc_collectd REQUEST_FILE_CHECK reponse not valid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 성공 실패 여부 확인
|
||||
if( m_packetHeader.result[0] == HEADER_RESULT_SUCCESS )
|
||||
{
|
||||
// 성공인 경우...
|
||||
// - File Size 정보를 수신 처리한다.
|
||||
|
||||
// Data 항목은
|
||||
// - 8 Byte Network byte order 로 구성된 available size 정보가 들어 있음.
|
||||
if( GetPacketData( m_nPacketDataLen ) == false )
|
||||
{
|
||||
LOG( LERR, "cc_collectd REQUEST_FILE_CHECK file size body receive failed." );
|
||||
strErrorMessage = "cc_collectd REQUEST_FILE_CHECK file size body receive failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
BYTE * pPos = m_tempBuffer;
|
||||
uFileSize = GetDataToUInt64( pPos, true );
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 오류가 발생한 경우..
|
||||
// - 수신할 메시지가 존재하는 경우.. 수신 처리한다.
|
||||
if( m_nPacketDataLen > 0 )
|
||||
{
|
||||
if( GetPacketData( m_nPacketDataLen, strErrorMessage ) == false )
|
||||
{
|
||||
LOG( LERR, "cc_collectd REQUEST_FILE_CHECK error body receive failed." );
|
||||
strErrorMessage = "cc_collectd REQUEST_FILE_CHECK error body receive failed.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 오류 반환 처리.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/***************************************************************************
|
||||
client 에서 cc_collectd 와의 통신을 수행하기 위한 class
|
||||
-----------------------------------------
|
||||
begin : 2014/09/29
|
||||
copyright : (C) 2005 Solbox Inc.
|
||||
author : Storage Dev Team
|
||||
email : storage.sd@solbox.com
|
||||
version : 3.4
|
||||
|
||||
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.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __CC_COLLECTD_CLIENT_SOCKET_H__
|
||||
#define __CC_COLLECTD_CLIENT_SOCKET_H__
|
||||
|
||||
#include "BaseSocket.h"
|
||||
#include "CcCollectdProtocol.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
///< BYTE 타입 정의
|
||||
#ifndef _BYTE_DEFINED
|
||||
#define _BYTE_DEFINED
|
||||
typedef unsigned char BYTE;
|
||||
#endif // _BYTE_DEFINED
|
||||
|
||||
|
||||
#define DEFAULT_SOCKET_TEMP_BUFFER_SIZE 1024 // Socket 관련 data 송수신시 사용할 임시버퍼 크기.
|
||||
|
||||
|
||||
// CCcCollectdClientSocket
|
||||
// cc_collectd 모듈과 통신 수행 관련 Interface 지원 목적을 위한 통신 관련 처리 class
|
||||
class CCcCollectdClientSocket : public CBaseSocket
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// 생성자
|
||||
CCcCollectdClientSocket();
|
||||
|
||||
// 소멸자
|
||||
~CCcCollectdClientSocket();
|
||||
|
||||
|
||||
// 전달받은 Target 으로 Socket 접속을 수행
|
||||
// @param szTarget [in] 접속 대상 Host name 또는 IP
|
||||
// @param nPort [in] 접속 Port
|
||||
// @return 접속 성공시 true, 실패시 false 반환. ( 오류 내역은 로깅처리됨.)
|
||||
bool ConnectTarget( const std::string& szTarget, int nPort );
|
||||
|
||||
// cc_collect 로 File 존재 여부 확인
|
||||
// @param strProcessName [in] 프로세스 명, 저장시 프로세스 명에 따른 폴더 생성 후 파일 수신, 저장 처리함.
|
||||
// 생략 가능하지만.. '/' 문자가 포함되서는 안됨.
|
||||
//
|
||||
// @param strFileName [in] 저장 파일명
|
||||
// a.log 같은 단순 형식 사용,
|
||||
// /a/b.log 같은 경로 정보 포함시 오류 발생.
|
||||
//
|
||||
// @param nFileSize [out] 해당 파일이 존재할 경우 파일의 크기
|
||||
// 만약 해당 파일이 존재하지 않을 경우.. 크기는 0
|
||||
//
|
||||
// @param strErrorMessage [out] 수신된 오류 메시지 저장
|
||||
// @return
|
||||
// 성공시 true, 파일 크기는 nFileSize 항목 참고.
|
||||
// 오류 발생시 false, 오류 내역은 strMessage 항목 참고
|
||||
bool CheckFile( const std::string strProcessName, const std::string strFileName
|
||||
, unsigned long long& uFileSize
|
||||
, std::string& strErrorMessage );
|
||||
|
||||
|
||||
// cc_collect 로 File 저장 목적으로 전송
|
||||
// @param strProcessName [in] 프로세스 명, 저장시 프로세스 명에 따른 폴더 생성 후 파일 수신, 저장 처리함.
|
||||
// 생략 가능하지만.. '/' 문자가 포함되서는 안됨.
|
||||
//
|
||||
// @param strFileName [in] 저장 파일명
|
||||
// a.log 같은 단순 형식 사용,
|
||||
// /a/b.log 같은 경로 정보 포함시 오류 발생.
|
||||
//
|
||||
// @param fd [in] 전송할 파일에 대한 descriter
|
||||
// @param nFileSize [in] 전송할 파일의 크기
|
||||
// 0 파일 전송 가능.
|
||||
// @param strMessage [out] 수신된 메시지 저장 (정상, 오류 모두 메시지 수신 가능)
|
||||
// @return
|
||||
// 저장 성공시 true
|
||||
// 실패 발생시 false, 오류 내역은 strMessage 항목 참고
|
||||
bool SendFile( const std::string strProcessName, const std::string strFileName
|
||||
, const int& fd, const unsigned long long& uFileSize
|
||||
, std::string& strMessage );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// cc_collect 로부터 available size 정보를 요청, 결과를 수신처리한다.
|
||||
bool GetAvailableSize( unsigned long long& uSize );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Packet Header 정보를 Log 파일에 Logging 처리
|
||||
void PrintHeaderToLog();
|
||||
|
||||
// socket 에서 지정된 크기만큼의 데이터를 읽어 내부 임시버퍼인 m_tempBuffer 에 저장처리.
|
||||
// @param size [in] read 할 데이터 크기
|
||||
// @return On success return true, otherwise return false.
|
||||
bool GetPacketData( unsigned int size );
|
||||
|
||||
// pValue 에 저장된 데이터를 unsigned long long (64Byte) 형으로 변환처리.
|
||||
unsigned long long GetDataToUInt64( BYTE * pValue, bool bConvertEndian = true );
|
||||
|
||||
// socket 에서 지정된 크기만큼의 데이터를 읽어 출력변수에 저장처리.
|
||||
// @param size [in] read 할 데이터 크기
|
||||
// @param value [out] 읽은 데이터를 저장할 string 변수
|
||||
// @return On success return true, otherwise return false.
|
||||
bool GetPacketData( unsigned int& size, std::string& value );
|
||||
|
||||
// Packet 정보 중 String 정보를 전송하기 위한 함수.
|
||||
bool SendString( const std::string& strData );
|
||||
|
||||
// Linux 5.4 의 경우 unsigned long long 의 byteorder 변환함수 제공 안함.
|
||||
// Linux 6.X, FreeBSD 에서는 be64toh 등의 함수 제공
|
||||
// - Liunx 5.X 장비 지원해야 하므로... 64bit 변환 함수 개발하여 사용.
|
||||
// - 기존 htonl 등의 함수와의 혼동을 피하기 위해 함수명은 C Style 로 구성.
|
||||
uint64_t do_htonll( uint64_t hostlonglong );
|
||||
uint64_t do_ntohll( uint64_t netlonglong );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Packet Header 변수
|
||||
struct CcCollectdPacketHeader m_packetHeader;
|
||||
|
||||
// m_packetHeader 구조체의 크기를 저장하기 위한 상수
|
||||
const int m_nPacketHeaderLen;
|
||||
|
||||
// Packet Header 에 저장된 Data 부분의 길이 정보값.
|
||||
unsigned int m_nPacketDataLen;
|
||||
|
||||
// Packet Data 부분의 수신처리시 임시로 사용할 버퍼.
|
||||
BYTE m_tempBuffer[DEFAULT_SOCKET_TEMP_BUFFER_SIZE];
|
||||
|
||||
};
|
||||
|
||||
#endif /* __CC_COLLECTD_CLIENT_SOCKET_H__ */
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/***************************************************************************
|
||||
cc_collectd 통신 관련 protocol header
|
||||
-----------------------------------------
|
||||
begin : 2014/09/25
|
||||
copyright : (C) 2005 Solbox Inc.
|
||||
author : Storage Dev Team
|
||||
email : storage.sd@solbox.com
|
||||
version : 3.4
|
||||
|
||||
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.
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __CC_COLLECTD_PROTOCOL_H__
|
||||
#define __CC_COLLECTD_PROTOCOL_H__
|
||||
|
||||
|
||||
// cc_collectd 에서 사용할 통신 Header 구조체
|
||||
// - 계산상 크기는 16Byte 이지만...
|
||||
// - 통신상 sizeof() : 20Byte ( 64Bit OS )
|
||||
struct CcCollectdPacketHeader {
|
||||
|
||||
char stx; // Packet 유효성 관리 코드
|
||||
char type; // Request or Response 여부 ( 0x00: Request, 0x01: Response )
|
||||
char command[4]; // Command Code ( 4 Byte) : 0th client-cc_collectd 간 사용, 그외는 미사용.
|
||||
char result[4]; // Result Code ( 4 Byte )
|
||||
unsigned int data_length; // Packet Data 부분의 길이값 ( Network Byte Order 사용)
|
||||
char extend_code[2]; // 확장 및 Padding bits ( 2 Byte )
|
||||
};
|
||||
|
||||
// Packet Header stx 코드
|
||||
#define HEADER_STX_CODE 0x04
|
||||
|
||||
// Packet Header type 구분코드
|
||||
#define HEADER_TYPE_REQUEST 0x00
|
||||
#define HEADER_TYPE_RESPONSE 0x01
|
||||
|
||||
|
||||
// Packet command 공통.
|
||||
#define COMMON_ALIVE_CHECK 0x7F
|
||||
|
||||
// Packet command
|
||||
// client <-> cc_collect 통신 (command 0th byte 만 사용)
|
||||
#define REQUEST_NOT_VALID 0x00 // 유효하지 않은 요청.
|
||||
#define REQUEST_AVAILABLE_SIZE 0x01 // Client 에서 전송 가능한 Available Size 요청
|
||||
#define REQUEST_FILE_SAVE 0x02 // Client 에서 저장 목적의 File 전송
|
||||
#define REQUEST_FILE_CHECK 0x03 // Client 에서 File 존재 여부 확인 요청
|
||||
|
||||
|
||||
// Packet Result
|
||||
// => type이 Response 인 경우에만 세팅됨.( 0th Byte 만 사용시 )
|
||||
#define HEADER_RESULT_SUCCESS 0x00
|
||||
#define HEADER_RESULT_ERROR 0x01
|
||||
|
||||
|
||||
// 기타 정보
|
||||
#define LENGTH_FIELD_SIZE 4 // 가변데이터 형식 사용시 Length 필드의 메모리 크기 (unsigned int)
|
||||
|
||||
|
||||
#endif /* __CC_COLLECTD_PROTOCOL_H__ */
|
||||
@@ -0,0 +1,62 @@
|
||||
#****************************************************************************
|
||||
# Makefile for cc_collectd client interface sample
|
||||
# -----------------------------------------
|
||||
#
|
||||
# begin : 2014/09/29
|
||||
# copyright : (C) 2005 Solbox Inc.
|
||||
# author : Storage Dev Team
|
||||
# email : storage.sd@solbox.com
|
||||
# version : 3.5
|
||||
#
|
||||
# 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.
|
||||
#*****************************************************************************
|
||||
|
||||
|
||||
# Program info
|
||||
PROG_NAME = collectd_client
|
||||
|
||||
|
||||
# Compiler info
|
||||
CC = /usr/bin/g++
|
||||
CFLAGS = -Wall -O3 -g -Wreturn-type -Wunused -Wuninitialized -Wparentheses -Wshadow -Wpointer-arith -Woverloaded-virtual -fno-rtti -D_REENTRANT
|
||||
LFLAGS =
|
||||
DFLAGS = -D_DEBUG_ -DPROG_NAME=\"$(PROG_NAME)\"
|
||||
|
||||
|
||||
# Enviroment
|
||||
DIR_INCLUDE = -I./. -I./.. -I./../../lib
|
||||
DIR_LIB =
|
||||
|
||||
OBJ = ../../lib/Logger.o ../../lib/BaseSocket.o ../CcCollectdClientSocket.o main.o
|
||||
|
||||
|
||||
LIBS =
|
||||
|
||||
APP = $(PROG_NAME)
|
||||
############################
|
||||
|
||||
|
||||
all:$(APP)
|
||||
sync
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(CFLAGS) -o $@ -c $^ $(DFLAGS) $(DIR_INCLUDE)
|
||||
|
||||
|
||||
$(PROG_NAME): $(OBJ)
|
||||
$(CC) $(LFLAGS) -o $@ $^ $(DFLAGS) $(DIR_LIB) $(LIBS)
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f *.o core *.out *.log ./../*.o
|
||||
-rm -f $(APP)
|
||||
sync
|
||||
|
||||
|
||||
install : $(APP)
|
||||
sync
|
||||
|
||||
# End of Makefile
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
#include "Logger.h"
|
||||
#include "CcCollectdClientSocket.h"
|
||||
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_PATH "/user/service/logs" // Log 경로
|
||||
|
||||
|
||||
#define SERVER_ADDR "222.122.152.5" // KT LogBackup Server IP
|
||||
//#define SERVER_ADDR "210.124.122.211" // LG U+ LogBackup Server IP
|
||||
|
||||
#define SERVER_LISTEN_PORT 13103 // cc_collectd Listen Port
|
||||
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
|
||||
std::string strServerAddr = SERVER_ADDR;
|
||||
std::string strFullFileName;
|
||||
|
||||
if( argc == 2 )
|
||||
{
|
||||
strFullFileName = argv[1];
|
||||
}
|
||||
else if ( argc > 2 )
|
||||
{
|
||||
fprintf( stderr, "Too many parameter.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// default
|
||||
strFullFileName = "/root/work/cc_collectd/interface/sample/test1.txt";
|
||||
}
|
||||
|
||||
|
||||
// 파일 Full 경로에서 파일명 추출 처리.
|
||||
std::string::size_type pos = strFullFileName.rfind( '/' );
|
||||
if( pos == std::string::npos )
|
||||
{
|
||||
// 찾지 못한 경우...
|
||||
fprintf( stderr, "File path is FULL PATH use. [%s]\n", strFullFileName.c_str() );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// 전송할 파일 정보
|
||||
std::string strTargetDir = strFullFileName.substr( 0, pos );
|
||||
std::string strTragetFileName = strFullFileName.substr( pos+1 );
|
||||
|
||||
|
||||
|
||||
// 전송할 파일 관련 정보 추출.
|
||||
struct stat resultFileStat;
|
||||
|
||||
if( stat( strFullFileName.c_str(), &resultFileStat ) != 0 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
fprintf( stderr, "file[%s] stat check error.[%d][%s]\n", strFullFileName.c_str(), errorNum, strerror( errorNum ) );
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// 파일 size 추출.
|
||||
unsigned long long uFileSize = resultFileStat.st_size;
|
||||
|
||||
// fd open
|
||||
int fd = open(strFullFileName.c_str(), O_RDONLY );
|
||||
if( fd == -1 )
|
||||
{
|
||||
int errorNum = errno;
|
||||
fprintf( stderr, "file[%s] open fail.[%d][%s]\n", strFullFileName.c_str(), errorNum, strerror( errorNum ) );
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Log 처리용 객체 생성 및 초기화.
|
||||
if( CLogger::Init( PROG_NAME, LOG_PATH, LDBG ) == false )
|
||||
{
|
||||
close( fd );
|
||||
|
||||
fprintf( stderr, "[error] Logger object created failed..");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// socket 생성 및 연결
|
||||
CCcCollectdClientSocket serverSocket;
|
||||
if( serverSocket.ConnectTarget( strServerAddr, SERVER_LISTEN_PORT ) == false )
|
||||
{
|
||||
// 접속 실패시
|
||||
close( fd );
|
||||
|
||||
_LOG( LERR, "cc_collectd connect fail. [%s][%d]", strServerAddr.c_str(), SERVER_LISTEN_PORT );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::string szErrorMessage;
|
||||
|
||||
// Log 파일 존재 여부 확인
|
||||
unsigned long long uExistFileSize = 0;
|
||||
|
||||
if( serverSocket.CheckFile( "collectd_client", strTragetFileName, uExistFileSize, szErrorMessage ) == false )
|
||||
{
|
||||
close( fd );
|
||||
|
||||
_LOG( LERR, "cc_collectd exist check fail.[%s][%llu] -> [%s]", strTragetFileName.c_str(), uFileSize, szErrorMessage.c_str() );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_LOG( LDBG, "cc_collectd exist check OK.local[%s][%llu] remote[%llu]", strTragetFileName.c_str(), uFileSize, uExistFileSize );
|
||||
|
||||
|
||||
// Log 파일 크기가 다른 경우에만 전송 처리한다.
|
||||
if( uFileSize == uExistFileSize )
|
||||
{
|
||||
_LOG( LDBG, "cc_collectd same file exist. not send. local[%s][%llu] remote[%llu]", strTragetFileName.c_str(), uFileSize, uExistFileSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 파일 크기가 다른 경우에만 전송 처리.
|
||||
// Log 파일 전송 처리
|
||||
if( serverSocket.SendFile( "collectd_client", strTragetFileName, fd, uFileSize, szErrorMessage ) == false )
|
||||
{
|
||||
close( fd );
|
||||
|
||||
_LOG( LERR, "cc_collectd send fail.[%s][%llu] -> [%s]", strTragetFileName.c_str(), uFileSize, szErrorMessage.c_str() );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
_LOG( LDBG, "cc_collectd send OK.[%s][%llu]", strTragetFileName.c_str(), uFileSize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close( fd );
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
This is test file for cc_collectd transfer.
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
CMD="$1"
|
||||
SLEEP="$2"
|
||||
|
||||
while [ 1 ]; do
|
||||
date
|
||||
eval $CMD
|
||||
echo " "
|
||||
sleep $SLEEP
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user