#include "ProcessSocket.h"

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <endian.h>


// 본 Class 에서 내부적으로 사용할 Packet 수신 결과 매크로 정의
// 본 정의값은 GetPacketHeader() 함수의 결과값임.
#define PACKET_HEADER_RECEIVE_SUCCESS			 1	// Packet Header 정보 수신 정상 처리
#define PACKET_HEADER_RECEIVE_TIMEOUT			 0	// Packet Header 정보 수신시 Timeout 발생한 경우
#define PACKET_HEADER_RECEIVE_SOCK_CLOSED		-1	// Packet Header 정보 수신시 socket 이 Close 된 경우
#define PACKET_HEADER_RECEIVE_INVALID_PROTOCOL	-2	// Packet Header 정보 수신시 잘못된 Packet 형식인 경우
#define PACKET_HEADER_RECEIVE_READ_ERROR		-3	// Packet Header 정보 수신시 시스템 함수 오류 발생한 경우


// 생성자.
// socket [in] 처리할 socket descriptor
CProcessSocket::CProcessSocket( const int& socket )
	: CBaseSocket( socket )
	  , m_nPacketHeaderLen ( sizeof(m_packetHeader))
	  , m_nPacketDataLen( 0 )
{
}

// 소멸자
CProcessSocket::~CProcessSocket()
{
	// 소멸자 Socket 명시적 Close 처리.
	Close();
}


// Packet Header 부분의 수신 처리를 위한 함수.
// @param timeout [in] 대기시간.
// @retrun 
//         1 : PACKET_HEADER_RECEIVE_SUCCESS          : 성공시           
//         0 : PACKET_HEADER_RECEIVE_TIMEOUT          : Timeout 발생시
//        -1 : PACKET_HEADER_RECEIVE_SOCK_CLOSED      : socket 종료된 경우
//        -2 : PACKET_HEADER_RECEIVE_INVALID_PROTOCOL : 잘못된 Packet 형식인 경우
//        -3 : PACKET_HEADER_RECEIVE_READ_ERROR       : 기타 오류
int CProcessSocket::GetPacketHeader( int timeout )
{
	if( IsValidSocket() == false )
	{
		LOG( LERR, "IsValidSocket return false." );

		// 유효하지 않은 socket 이므로 -1 을 반환
		// return false;
		return PACKET_HEADER_RECEIVE_SOCK_CLOSED;
	}

	int nRead;
	bool isAlivePacket;
	do
	{
		isAlivePacket = false;

		// Socket 으로 부터 Packet Header 부분 수신.
		// 수신된 정보는 멤버변수에 저장처리.
		// ReadNTimeout() 반환값은 read 된 데이터의 크기. 0: fd closed, -1: 오류 , -2: Timeout
		nRead = ReadNTimeout( &m_packetHeader, m_nPacketHeaderLen, timeout );

		// 정상적으로 Data 를 수신한 경우
		if( nRead > 0 )
		{
			// Packet 형식 코드 중 STX code 검사.
			if( m_packetHeader.stx != HEADER_STX_CODE )
			{
				LOG( LERR, "Not valid STX code " );
				PrintHeaderToLog();

				// 잘못된 Packet 형식인 경우 -2 값을 반환
				//return false;
				return PACKET_HEADER_RECEIVE_INVALID_PROTOCOL;
			}

			// Data Length 부분 값을 멤버 변수에 저장처리.
			m_nPacketDataLen = ntohl( m_packetHeader.data_length );

			// Alive Check Packet 인 경우 해당 패킷은 무시처리 후 다시 수신 처리한다.
			if( m_packetHeader.type == HEADER_TYPE_REQUEST
				&& m_packetHeader.command[0] == COMMON_ALIVE_CHECK
				&& m_nPacketDataLen == 0 )
			{
				isAlivePacket = true;
			}

		}
		else
		{
			// Socket 이 종료된 경우
			if( nRead == 0 )
			{
				//LOG( LINF, "Connection already closed.");
				Close();	// 확실하게 종료 처리 한 후

				// Connection 이 종료된 경우 -1 을 반환
				return PACKET_HEADER_RECEIVE_SOCK_CLOSED;
			}
			else if( nRead == -1 )	// read 함수 관련 오류가 발생한 경우
			{
				LOG( LERR, "Socket read() function error. Connection closed by forced." );
				Close();	// 확실하게 종료 처리 한 후

				// 오류 발생시 -3 을 반환
				return PACKET_HEADER_RECEIVE_READ_ERROR;

			}
			else if( nRead == -2 )	// Timeout 이 발생한 경우
			{
				LOG( LDBG, "Socket read() timeout [%d]", timeout );

				// Timeout 발생시에는 0 을 반환
				return PACKET_HEADER_RECEIVE_TIMEOUT;
			}
		}

	} while( isAlivePacket == true );


	return PACKET_HEADER_RECEIVE_SUCCESS;
}

// Packet Header 정보를 Log 파일에 Logging 처리
void CProcessSocket::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 에서 지정된 크기만큼의 데이터를 읽어 출력변수에 저장처리.
// @param size [in] read 할 데이터 크기
// @param value [out] 읽은 데이터를 저장할 string 변수
// @return On success return true, otherwise return false.
bool CProcessSocket::GetPacketData( unsigned int& size, std::string& value )
{
	if( size == 0 )
	{
		value.clear();
		return true;
	}
	
	// 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;
}

// socket 에서 지정된 크기만큼의 데이터를 읽어 내부 임시버퍼인 m_tempBuffer 에 저장처리.
// @param size [in] read 할 데이터 크기
// @return On success return true, otherwise return false.
bool CProcessSocket::GetPacketData( unsigned int size )
{
	if( size == 0 )
		return true;
	
	// 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;
}

// 전달받은 데이터를 unsigned int 형으로 변환처리 및 Endian 변환
unsigned int CProcessSocket::GetDataToUInt( BYTE * pValue, bool bConvertEndian )
{
	BYTE tempBuffer[4];
	unsigned int result;

	memcpy(tempBuffer, pValue, 4);
	unsigned int * pInt = (unsigned int *)tempBuffer;

	// Endian 변환처리.
	if( bConvertEndian == true )
	{
		result = ntohl( *pInt );
	}
	else
		result = *pInt;

	return result;
}

// pValue 에 저장된 데이터를 unsigned long long (64Byte) 형으로 변환처리.
unsigned long long CProcessSocket::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;
}


// Socket 으로 부터 수신받은 데이터를 파일에 Write 처리한다.
// 만약 File Write 처리시 오류가 발생하는 경우 Socket Data 의 정상적인 처리를 위해
// Socket 데이터 수신만 처리하고 오류를 반환한다.
// @returnFile Write 가 오류 없이 정상적으로 처리된 경우 true, 오류발생시 false 및 오류메시지 반환
bool CProcessSocket::ReceiveToFile( FILE * pFile, unsigned long long nFileSize, std::string& errorMessage )
{
	if( IsValidSocket() == false )
		return false;
	
	// 0 Byte 크기의 파일인 경우 그냥 SUCCESS 처리.
	if( nFileSize == 0 )
		return true;

	char tempBuffer[FILE_DATA_BUFFER_SIZE];
	int onceReadSize;
	int nRead;
	unsigned long long nLeft = nFileSize;
	bool bFileWriteSuccess = true;

	int nLockResult;

		
	// 동일 파일에 대한 동시 Write 처리를 방어하기 위해 file lock 개념을 추가한다.
	int fd = fileno( pFile );
	nLockResult = lockf( fd, F_TLOCK, 0 );	// 파일 전체에 대해 lock 시도.

	if( nLockResult == -1 )
	{
		int errorNum = errno;
		if( errorNum == EAGAIN )
		{
			// 이미 Lock 이 걸려 있는 상태인 경우... 5 sec 후 재시도 처리..
			// 만약 재시도가 실패하는 경우.. 실패로 반환.
			LOG( LWAR, "File lock 1th fail. 5 sec sleep and retry [%d][%s]", errorNum, strerror(errorNum));

			sleep(5);
			nLockResult = lockf( fd, F_TLOCK, 0 );	// 파일 전체에 대해 lock 재시도.

			if( nLockResult == -1 )
			{
				errorNum = errno;

				// Lock 재시도 실패시.. 오류 반환.
				LOG( LERR, "File lock fail. file receive fail [%d][%s]", errorNum, strerror(errorNum));

				errorMessage = "File data receive error [file lock fail]";
				return false;
			}
		}
		else
		{
			// 이미 Lock 상태로 인한 lock 처리 실패가 아닌 경우.
			LOG( LERR, "File lock fail by system error. file receive fail [%d][%s]", errorNum, strerror(errorNum));
			errorMessage = "File data receive error [file lock fail]";
			return false;
		}
	}
	
	while( nLeft > 0 )
	{
		// 한번에 읽을 용량 계산.
		if( nLeft > FILE_DATA_BUFFER_SIZE )
			onceReadSize = FILE_DATA_BUFFER_SIZE;
		else
			onceReadSize = nLeft;

		// Socket Read
		if( (nRead = read( m_sock, tempBuffer, onceReadSize )) < 0 )
		{
			int errorNum = errno;
			if( errorNum == EINTR || errorNum == EAGAIN || errorNum == EWOULDBLOCK )
			{
				nRead = 0;
				continue;
			}
			else if( errorNum == ECONNRESET )
			{
				m_bConnected = false;
				errorMessage = "File receive error [connection closed].";

				lockf( fd, F_ULOCK, 0 );
				return false;
			}
			else
			{
				errorMessage = "File data receive error [socket read error]";
				LOG( LERR, "Socket read error.[%d][%s]", errorNum, strerror(errorNum));

				lockf( fd, F_ULOCK, 0 );
				return false;
			}
		}
		else if( nRead == 0 )  // Connection Closed..
		{
			m_bConnected = false;
			errorMessage = "File receive error [connection closed].";

			lockf( fd, F_ULOCK, 0 );
			return false;
		}
		
		// 정상적인 경우.
		// File Write 시도
		if( bFileWriteSuccess == true )
		{
			if( (int)fwrite( tempBuffer, 1, nRead, pFile ) != nRead )
			{
				// file write 실패시.
				int errorNum = errno;
				LOG( LERR, "File write to local error.[%d][%s]", errorNum, strerror(errorNum));

				// TODO 소켓을 읽어 전송받은 데이터를 날려버려야 할까요..?
				errorMessage = "File write failed from receive data";
				bFileWriteSuccess = false;
			}
		}

		nLeft -= nRead;
	}

	// file Lock 해제 처리.
	lockf( fd, F_ULOCK, 0 );

	// File Write 가 오류 없이 정상적으로 처리된 경우 true
	// 오류발생시 false 반환처리.
	if( bFileWriteSuccess == true )
		return true;
	else
		return false;
}


// Packet 정보 중 String 정보를 전송하기 위한 함수.
bool CProcessSocket::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;
}

///////////////////////////////////////////////////////////////////////////////
// 업무 Flow 관련 interface 함수.
///////////////////////////////////////////////////////////////////////////////


// Packet 의 Header 정보를 수신하여 각 정보를 전달받은 Command 정보를 참조변수로 반환.
// @param command [out] Command 정보
// @return 1 : Data 수신 성공시
//         0 : Timeout 발생시
//        -1 : 접속 종료시
int CProcessSocket::GetHeaderInfo( char& command )
{
	if( IsValidSocket() == false )
		return -1;

	// Packet Header 정보 수신처리.
	// Socket 응답 대기상태( select) 에서 응답이 들어온 경우 이를 바로 처리하기 위해
	// Timeout 시간을 3 sec 로 처리함.
	int nResult = GetPacketHeader( 3 );

	// Header Data 수신 실패시
	if( nResult != PACKET_HEADER_RECEIVE_SUCCESS )
	{
		if( nResult == PACKET_HEADER_RECEIVE_TIMEOUT )	// Timeout 발생시
		{
			if( IsValidSocket() == false )	// socket 종료 여부를 다시 한번 확인
				return -1;
			else
				return 0;
		}
		else
		{
			// 잘못된 프로토콜 형식인 경우
			if( nResult == PACKET_HEADER_RECEIVE_INVALID_PROTOCOL )
			{
				// Socket 강제 종료 처리. 
				LOG( LERR, "Not valid protocol header. Connection closed by forced." );
				Close();
			}

			return -1;
		}
	}

	// Data 수신 성공시
	// - 정상적인 Request 요청인지 확인 처리..
	// - 비정상 요청인 경우.. command 값을 REQUEST_NOT_VALID 으로 설정 처리한다.	

	// Type 값 확인
	if( m_packetHeader.type == HEADER_TYPE_REQUEST )
	{
		// request 요청인 경우...
		command = m_packetHeader.command[0];
	}
	else
	{
		// request 가 아닌.. reponse 등의 요청인 경우...
		// - 이렇게 되면.. 통신 Flow 문제이므로 코드 수정 필요.
		command = REQUEST_NOT_VALID;
	}

	return 1;
}



// REQUEST_AVAILABLE_SIZE 요청에 대한 응답을 Client 로 전송한다.
bool CProcessSocket::SendResultAvailableSizeToClient( 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_RESPONSE;
	stHeader.command[0] = REQUEST_AVAILABLE_SIZE;

	// 성공, 실패 여부 설정
	// - 추출된 값만 전송하면 되므로. 무조건 성공으로 전송 처리.
	stHeader.result[0] = HEADER_RESULT_SUCCESS;

	// Data body 구성
	// - 전송해야 할 항목은 unisigned long long 8 Byte 값이다.
	// - client 는 꼭 centos를 사용하는 client 가 아닐 수가 있어....Network byte order 에 따라 전송 처리한다.	
	stHeader.data_length = htonl( 8 );
	
	// Packet Header 정보 전송
	if( WriteN( &stHeader, m_nPacketHeaderLen ) != m_nPacketHeaderLen )
	{
		LOG( LERR, "reponse [REQUEST_AVAILABLE_SIZE] send fail to client" );
		return false;
	}
	else
	{
		// Available size 항목 전송
		// - unsigned long long type 을 Network Byte order(Big Endian) 로 변환하여 전달.
		unsigned long long uTemp;
		//uTemp = htobe64( uSize );
		uTemp = do_htonll( uSize );

		WriteN( &uTemp, 8 );
	}
	
	return true;
}

// REQUEST_FILE_SAVE 요청에 대한 Body 부분을 수신한다.
bool CProcessSocket::RecvBodyFileSaveFromClient( std::string& strHostName, std::string& strProcessName, std::string& strFileName, unsigned long long& uFileSize )
{
	if( IsValidSocket() == false )
		return false;

	// Body 부분 수신 처리.	
	// strHostName    : string ( 4 + string.size() )
	// strProcessName : string ( 4 + string.size() )
	// strFileName    : string ( 4 + string.size() )
	// uFileSize      : 8 Byte	---------->본 항목까지만 header data_length 에 포함시킨다.
	// 저장할 파일 내용.
	unsigned int nLength;

	// strHostName
	if( GetPacketData( 4 ) == false )
	{
		LOG( LERR, "host name size get failed." );
		return false;
	}
	nLength = GetDataToUInt( m_tempBuffer, true );
	GetPacketData( nLength, strHostName );

	// strProcessName
	if( GetPacketData( 4 ) == false )
	{
		LOG( LERR, "process name size get failed." );
		return false;
	}
	nLength = GetDataToUInt( m_tempBuffer, true );
	GetPacketData( nLength, strProcessName );

	// strFileName
	if( GetPacketData( 4 ) == false )
	{
		LOG( LERR, "file name size get failed." );
		return false;
	}
	nLength = GetDataToUInt( m_tempBuffer, true );
	GetPacketData( nLength, strFileName );


	// uFileSize
	if( GetPacketData( 8 ) == false )
	{
		LOG( LERR, "file size body receive failed." );
		return false;
	}
	BYTE * pPos = m_tempBuffer;
	uFileSize = GetDataToUInt64( pPos, true );

	return true;
}

// REQUEST_FILE_SAVE 요청에 대한 처리 결과를 전송한다.
bool CProcessSocket::SendResultFileSaveToClient( bool bSuccess, std::string& strMessage )
{
	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_RESPONSE;
	stHeader.command[0] = REQUEST_FILE_SAVE;

	
	// 성공, 실패 여부 설정
	if( bSuccess == true )
		stHeader.result[0] = HEADER_RESULT_SUCCESS;
	else
		stHeader.result[0] = HEADER_RESULT_ERROR;
	
	// Data body length
	stHeader.data_length = htonl( strMessage.size() );

	// Packet Header 정보 전송
	if( WriteN( &stHeader, m_nPacketHeaderLen ) != m_nPacketHeaderLen )
	{
		LOG( LERR, "reponse [REQUEST_FILE_SAVE] send fail to client" );
		return false;
	}
	else
	{
		// message 부분이 존재하는 경우.. 전송 처리.
		if( strMessage.empty() == false )
		{
			WriteN( strMessage.c_str(), strMessage.size() );
		}
	}

	return true;
}


// REQUEST_FILE_CHECK 요청에 대한 Body 부분을 수신한다.
bool CProcessSocket::RecvBodyFileCheckFromClient( std::string& strHostName, std::string& strProcessName, std::string& strFileName )
{
	if( IsValidSocket() == false )
		return false;

	// Body 부분 수신 처리.	
	// strHostName    : string ( 4 + string.size() )
	// strProcessName : string ( 4 + string.size() )
	// strFileName    : string ( 4 + string.size() )	
	// 저장할 파일 내용.
	unsigned int nLength;

	// strHostName
	if( GetPacketData( 4 ) == false )
	{
		LOG( LERR, "host name size get failed." );
		return false;
	}
	nLength = GetDataToUInt( m_tempBuffer, true );
	GetPacketData( nLength, strHostName );

	// strProcessName
	if( GetPacketData( 4 ) == false )
	{
		LOG( LERR, "process name size get failed." );
		return false;
	}
	nLength = GetDataToUInt( m_tempBuffer, true );
	GetPacketData( nLength, strProcessName );

	// strFileName
	if( GetPacketData( 4 ) == false )
	{
		LOG( LERR, "file name size get failed." );
		return false;
	}
	nLength = GetDataToUInt( m_tempBuffer, true );
	GetPacketData( nLength, strFileName );
	
	return true;
}

// REQUEST_FILE_CHECK 요청에 대한 정상 처리 결과를 전송한다.
bool CProcessSocket::SendResultFileCheckToClient( 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_RESPONSE;
	stHeader.command[0] = REQUEST_FILE_CHECK;

	// 성공, 실패 여부 설정
	// - 추출된 값만 전송하면 되므로. 무조건 성공으로 전송 처리.
	stHeader.result[0] = HEADER_RESULT_SUCCESS;

	// Data body 구성
	// - 전송해야 할 항목은 unisigned long long 8 Byte 값이다.
	// - client 는 꼭 centos를 사용하는 client 가 아닐 수가 있어....Network byte order 에 따라 전송 처리한다.	
	stHeader.data_length = htonl( 8 );

	// Packet Header 정보 전송
	if( WriteN( &stHeader, m_nPacketHeaderLen ) != m_nPacketHeaderLen )
	{
		LOG( LERR, "reponse [REQUEST_FILE_CHECK] send fail to client" );
		return false;
	}
	else
	{
		// 추출된 물리파일 size 항목 전송
		// - unsigned long long type 을 Network Byte order(Big Endian) 로 변환하여 전달.
		unsigned long long uTemp;		
		uTemp = do_htonll( uSize );

		WriteN( &uTemp, 8 );
	}

	return true;
}

// REQUEST_FILE_CHECK 요청에 대한 오류 발생 내역을 전송한다.
bool CProcessSocket::SendResultFileCheckErrorToClient( std::string& strErrorMessage )
{
	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_RESPONSE;
	stHeader.command[0] = REQUEST_FILE_CHECK;
	
	// 성공, 실패 여부 설정
	// - 오류가 발생한 경우이므로... 실패로 처리
	stHeader.result[0] = HEADER_RESULT_ERROR;

	// Data body length
	stHeader.data_length = htonl( strErrorMessage.size() );

	// Packet Header 정보 전송
	if( WriteN( &stHeader, m_nPacketHeaderLen ) != m_nPacketHeaderLen )
	{
		LOG( LERR, "error reponse [REQUEST_FILE_CHECK] send fail to client" );
		return false;
	}
	else
	{
		// message 부분이 존재하는 경우.. 전송 처리.
		if( strErrorMessage.empty() == false )
		{
			WriteN( strErrorMessage.c_str(), strErrorMessage.size() );
		}
	}

	return true;
}


// byte ordering function for 64bit variable
uint64_t CProcessSocket::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 CProcessSocket::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;
 
}
