/***************************************************************************
               cc_collectd 의 통신 처리 담당 class
                -----------------------------------------
	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 __PROCESS_SOCKET_H__
#define __PROCESS_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 송수신시 사용할 임시버퍼 크기.
#define FILE_DATA_BUFFER_SIZE				1048576    // 1 Mbyte, 파일 송수신시 사용할 임시 버퍼의 크기.


class CProcessSocket : public CBaseSocket
{

	public:

		// 생성자.
		// socket [in] 처리할 socket descriptor		
		CProcessSocket( const int & socket );
		
		// 소멸자.
		~CProcessSocket();


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

		
		// Packet Header 정보를 Log 파일에 Logging 처리
		void PrintHeaderToLog( void );


		// REQUEST_AVAILABLE_SIZE 요청에 대한 응답을 Client 로 전송한다.
		bool SendResultAvailableSizeToClient( unsigned long long & uSize );
		
		// REQUEST_FILE_SAVE 요청에 대한 Body 부분을 수신한다.
		bool RecvBodyFileSaveFromClient( std::string& strHostName, std::string& strProcessName
										 , std::string& strFileName, unsigned long long& uFileSize );		

		// REQUEST_FILE_SAVE 요청에 대한 처리 결과를 전송한다.
		bool SendResultFileSaveToClient( bool bSuccess, std::string& strMessage );

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

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

		// REQUEST_FILE_CHECK 요청에 대한 정상 처리 결과를 전송한다.
		bool SendResultFileCheckToClient( unsigned long long & uSize );

		// REQUEST_FILE_CHECK 요청에 대한 오류 발생 내역을 전송한다.
		bool SendResultFileCheckErrorToClient( std::string& strErrorMessage );


	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];
		
	private:
		
		// 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 GetPacketHeader(int timeout = DEFAULT_DATA_RECEIVE_TIMEOUT);
		
		// 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 );

		// socket 에서 지정된 크기만큼의 데이터를 읽어 내부 임시버퍼인 m_tempBuffer 에 저장처리.
		// @param size [in] read 할 데이터 크기
		// @return On success return true, otherwise return false.
		bool GetPacketData( unsigned int size );

		// pValue 에 저장된 데이터를 unsigned int 형으로 변환처리 및 Endian 변환
		unsigned int GetDataToUInt( BYTE * pValue, bool bConvertEndian = true );

		// pValue 에 저장된 데이터를 unsigned long long (64Byte) 형으로 변환처리.
		unsigned long long GetDataToUInt64( BYTE * pValue, bool bConvertEndian = true );

		// 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);

};

#endif /* __PROCESS_SOCKET_CONTROL_H__ */

