base
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "SmsSender.h"
|
||||
#include <iterator>
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 9216
|
||||
#define MaxSizeOfTRxBuffer 1024
|
||||
|
||||
|
||||
string CSmsSender::RemoveBlankSpace(const char* pszData, size_t nLength)
|
||||
{
|
||||
char * szTemp = NULL;
|
||||
string strReturn;
|
||||
const char * src;
|
||||
char * dest;
|
||||
|
||||
|
||||
szTemp = (char*) ::malloc(sizeof(char) * nLength +1);
|
||||
::memset(szTemp, 0 , sizeof(char)*nLength +1);
|
||||
|
||||
src = pszData;
|
||||
dest = szTemp;
|
||||
|
||||
if( pszData == NULL )
|
||||
{
|
||||
strReturn.clear();
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
if( *src == '\0' )
|
||||
{
|
||||
strReturn = src;
|
||||
return strReturn;
|
||||
}
|
||||
// start with 2nd position
|
||||
src++;
|
||||
while ( src <= (pszData + nLength) && *(src-1) != '\0' )
|
||||
{
|
||||
if( *(src-1) == ' ' && *(src) == ' ' )
|
||||
{ // 연속된 공백이 발견되면, 스킵한다.
|
||||
src++;
|
||||
continue;
|
||||
}
|
||||
*dest = *(src-1);
|
||||
src++;
|
||||
dest++;
|
||||
}
|
||||
// 종료표기
|
||||
dest++;
|
||||
*(dest) = '\0';
|
||||
|
||||
strReturn = szTemp;
|
||||
if (szTemp != NULL)
|
||||
{
|
||||
free(szTemp);
|
||||
szTemp = NULL;
|
||||
}
|
||||
return strReturn;
|
||||
}
|
||||
char hexchars[] = "0123456789ABCDEF";
|
||||
string CSmsSender::PostDataEncode(const char *pszCommand, size_t length)
|
||||
{
|
||||
int i;
|
||||
char tmpBuffer[MaxSizeOfTRxBuffer];
|
||||
string strReturn;
|
||||
|
||||
if( pszCommand == NULL )
|
||||
{
|
||||
strReturn.clear();
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
::memset(tmpBuffer, 0 , MaxSizeOfTRxBuffer);
|
||||
i = 0;
|
||||
while( *pszCommand != '\0' )
|
||||
{
|
||||
if( *pszCommand == ' ' )
|
||||
{ // ' ' => '+'
|
||||
tmpBuffer[i++] = '+';
|
||||
pszCommand++;
|
||||
}
|
||||
else if(*pszCommand == '%')
|
||||
{ // % => %%
|
||||
tmpBuffer[i++] = '%';
|
||||
tmpBuffer[i++] = '%';
|
||||
pszCommand++;
|
||||
}
|
||||
else if( (*pszCommand < '0' && *pszCommand != '-' && *pszCommand != '.' )
|
||||
|| (*pszCommand < 'A' && *pszCommand > '9' )
|
||||
|| (*pszCommand > 'Z' && *pszCommand < 'a' && *pszCommand != '_' )
|
||||
|| (*pszCommand > 'z' ) )
|
||||
{
|
||||
tmpBuffer[i++] = '%';
|
||||
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand >> 4];
|
||||
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand & 15];
|
||||
pszCommand++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpBuffer[i++] = *pszCommand++;
|
||||
}
|
||||
}
|
||||
tmpBuffer[i] = '\0';
|
||||
|
||||
strReturn = tmpBuffer;
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CSmsSender::CSmsSender(const std::string& szHost, const int nPort, const std::string& szPath)
|
||||
: CBaseSocket( SOCKET_NOT_VALID), m_szHost(szHost), m_nPort(nPort), m_szPath(szPath)
|
||||
{
|
||||
// 생성자
|
||||
}
|
||||
|
||||
CSmsSender::~CSmsSender()
|
||||
{
|
||||
// 소멸자에 BaseSocket의 명시적 Close 처리를 한다.
|
||||
Close();
|
||||
}
|
||||
|
||||
bool CSmsSender::Init(void)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
// 데이터 체크
|
||||
if( m_szHost.empty() || m_nPort < 0 || m_szPath.empty() )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSmsSender::SendToWebServ(const string& pszHost, const string& pszTime, const string& pszMsg)
|
||||
{
|
||||
string szHost;
|
||||
string szTime;
|
||||
string szMsg;
|
||||
char szSndBuffer[DEFAULT_BUFFER_SIZE];
|
||||
char szRcvBuffer[DEFAULT_BUFFER_SIZE];
|
||||
bool bRet = false;
|
||||
int nRet = 0;
|
||||
|
||||
|
||||
if( pszHost.empty() || pszMsg.empty() || pszTime.empty() )
|
||||
{
|
||||
LOG(LERR, "Invalid Parameter.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connect
|
||||
bRet = Connect(m_szHost, m_nPort);
|
||||
if( bRet == false )
|
||||
{
|
||||
LOG(LERR, "Socket Connect Error.[%s:%d]", m_szHost.c_str(), m_nPort);
|
||||
return false;
|
||||
}
|
||||
if( IsValidSocket() == false )
|
||||
{
|
||||
LOG(LERR, "Invalid Socket.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
::bzero(szSndBuffer, DEFAULT_BUFFER_SIZE);
|
||||
::bzero(szRcvBuffer, DEFAULT_BUFFER_SIZE);
|
||||
|
||||
szHost = PostDataEncode(pszHost.c_str(), pszHost.size());
|
||||
szTime = PostDataEncode(pszTime.c_str(), pszTime.size());
|
||||
szMsg = RemoveBlankSpace(pszMsg.c_str(), pszMsg.size());
|
||||
LOG(LDBG, "SMSMsg = [%s]", szMsg.c_str());
|
||||
szMsg = PostDataEncode(szMsg.c_str(), szMsg.size());
|
||||
|
||||
|
||||
// CHG 2019-09-16 huibong HTTP 관련 줄바꿈문자 LF->CR+LF 변경 (#32794)
|
||||
// - CVE-2016-8743 이슈에 따라 Apache 2.2.32 버전부터 HTTP header 상에서
|
||||
// - 줄바꿈문자가 CR+LF 가 아닌 경우 HTTP 400 응답 발생
|
||||
// - 이를 해결하기 위해 기존 줄바꿈 문자 \n -> \r\n 으로 변경처리한다.
|
||||
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "GET %s?host=%s&time=%s&msg=%s HTTP/1.0\r\n"\
|
||||
"Content-Type: text/plain\r\n"\
|
||||
"User-Agent: Arcmond\r\n"\
|
||||
"Host: %s\r\n"\
|
||||
"Connection: close\r\n"\
|
||||
"Cache-Control: no-cache\r\n\r\n"
|
||||
,m_szPath.c_str(), szHost.c_str(), szTime.c_str(), szMsg.c_str() ,m_szHost.c_str());
|
||||
|
||||
//DEBUG_LOG("%s", szSndBuffer);
|
||||
//요청 전송 시작
|
||||
nRet = WriteN(&szSndBuffer, ::strlen(szSndBuffer)+1);
|
||||
// MAX_SEND_RETRY_COUNT 회수만큼 재시도 후 실패처리된다.
|
||||
if( nRet == 0 )
|
||||
{
|
||||
LOG(LERR, "write socket closed.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else if( nRet == -1 )
|
||||
{
|
||||
LOG(LERR, "write socket error.(%s)",strerror(errno));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 응답 결과 받기.
|
||||
nRet = ReadNTimeout(szRcvBuffer, DEFAULT_BUFFER_SIZE);
|
||||
if( nRet == 0 )
|
||||
{
|
||||
// Remain이 0일 경우가 모두 받은 상황인데, 그것을 알 수 없다면,
|
||||
// Ret==0일 때가 다 준 상황으로 판단해야 하지 않을까? 그렇다면 에러가 아니다.
|
||||
LOG(LDBG, "read socket closed.");
|
||||
}
|
||||
else if( nRet == -1 )
|
||||
{ // 단순 소켓 에러.
|
||||
LOG(LERR, "read socket error.(%s)",strerror(errno));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else if( nRet == -2 )
|
||||
{ // 타임아웃.
|
||||
LOG(LERR, "read socket timed out.");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
// 정상 결과는 아래와 같은 형태이다.
|
||||
//----------------------------------------------------------------
|
||||
// HTTP/1.1 200 OK
|
||||
// Date: Thu, 10 Jun 2010 03:59:23 GMT
|
||||
// Server: Apache/2.0.55 (Unix) DAV/2 PHP/5.2.1
|
||||
// X-Powered-By: PHP/5.2.1
|
||||
// Content-Length: 87
|
||||
// Connection: close
|
||||
// Content-Type: text/html; charset=EUC-KR
|
||||
//
|
||||
// [RAID:qcrts4.ktsh.co.kr]::2010-07-09 12:59:19:Controller#1: SW API Interface API Log In
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// 첫번째 라인만 출력하기 위해서 \n을 \0으로 바꾸고 출력한다.
|
||||
char* pEnd = strchr(szRcvBuffer, '\n');
|
||||
*pEnd = '\0';
|
||||
|
||||
LOG(LINF, "Result:%s", szRcvBuffer);
|
||||
|
||||
// Close()는 return값이 없음.
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user