Files
interactive/SDK/version_3/main.c
2026-08-07 17:38:18 +09:00

1643 lines
34 KiB
C

#include "SHSSDK.h"
#include "main.h"
#include "solbox_util.h"
#include "GTS_INFO.h"
#undef HAVE_SSPI
#include "ne_request.h"
#include "ne_socket.h"
#include "ne_string.h"
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#endif
#ifdef WIN32
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
#endif
#define AUTHPRIME 137897
typedef struct _s_time_sync_t
{
int32_t sync_info;
}time_sync_t;
#pragma pack(1)
typedef struct {
char id[32];
char domain[128];
char domain2[128];
} SERVICE_STRUCT, *PSERVICE_STRUCT;
#pragma pack()
#pragma pack(1)
typedef struct {
char szTranId[52];
__int32 nMode;
char szIssuer[128];
char szServiceId[128];
__int32 nResult;
__int32 nLength;
} COMMAND_STRUCT, *PCOMMAND_STRUCT;
typedef struct {
char path[2048];
} PATHINFO_STRUCT, *PPATHINFO_STRUCT;
#pragma pack()
#define CENTER_HOST G_CENTERADDR
#define CENTER_PORT G_CENTERADDR_PORT
#define RCTS_PORT 13104
#define PRIVATE_KEY "I'm your father"
// 2013-12-27 dadamin
// GTS(cc_tsd) 통신 시 이용되는 구분자 변경
// sp-console => SP-Console3
// SHSSDK => SSDK
#ifdef _SP_SDK_
#define SERVER_NAME "SP-Console3"
#else // !_SP_SDK_
#define SERVER_NAME "SSDK"
#endif // _SP_SDK_
#define DELIMITER 0x1b
// cc_tsd
#define MODE_SRV_LST_2ND_REQUEST 0x0080
#define MODE_SRV_TRAFFIC_REQUEST 0x0082
// rc_mngd(rc_tsd)
#define SDK_REQ_VOLUME_INFO 0x0012 // old : MSG_MODE_SPCONS_RCTRAN_VOLUME_SIZE
#define SDK_REQ_SET_ANONY_DIR 0x0014 // old : MSG_MODE_SPCONS_RCTRAN_SET_ANONY
#define SDK_REQ_UNSET_ANONY_DIR 0x0018 // old : MSG_MODE_SPCONS_RCTRAN_UNSET_ANONY
#define SDK_REQ_ANONY_DIR 0x0030 // old : MSG_MODE_SPCONS_RCTRAN_RETRIVE_ANONY
/* Elenoa MOD : START */
/* default timeout 5 second */
#include <fcntl.h>
static int timeout = 5;
static char szCacheFile[MAX_PATH]={0};
static char g_cnthost[255] = CENTER_HOST;
static int g_cntport = CENTER_PORT;
static char g_sntphost[255] = SNTP_DOMAIN;
static int g_sntpport = SNTP_PORT;
static int _sh_send(SOCKET s, char *buf, int len);
static int _sh_recv(SOCKET s, char *buf, int len);
const char *sh_get_rcts_host(const char *userId, const char *password, const char *serviceId);
char* get_address(const char *userId, const char *password, const char *serviceId,int nFlag);
int get_psl_from_cache(PSERVICE_STRUCT *psl);
int set_psl_to_cache(PSERVICE_STRUCT *psl,int nCount);
#ifdef _WIN32
static int __nonblock_win32(SOCKET s)
{
int ul = 1;
int result;
result = ioctlsocket( s, FIONBIO, (u_long FAR*)&ul );
return result;
}
#else
static int __nonblock(int fd)
{
int result;
int flags;
flags = fcntl(fd, F_GETFL, 0);
result = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
return result;
}
#endif
void sh_set_timeout(int second)
{
timeout = second;
}
/* Elenoa MOD : END */
int get_psl_from_cache(PSERVICE_STRUCT *psl)
{
int nCount = 0;
FILE* fp=NULL;
int i=0;
int numread=0;
int nErr = GetLastError();
if (strlen(szCacheFile) == 0)
{
if(nErr) SetLastError(nErr);
return 0;
}
fp = fopen(szCacheFile,"rb");
if(fp)
{
fread(&nCount,sizeof(int),1,fp);
*psl = malloc(sizeof(SERVICE_STRUCT) * nCount);
numread = fread(*psl,sizeof(SERVICE_STRUCT) * nCount,1,fp);
if (numread < 1)
{
SetLastError(SHERRNO_INVALIDCACHEFILE);
return 0;
}
fclose(fp);
}
if(nErr) SetLastError(nErr);
return nCount;
}
int set_psl_to_cache(PSERVICE_STRUCT *psl,int nCount)
{
FILE* fp=NULL;
int i=0;
if (strlen(szCacheFile) == 0)
return 0;
fp = fopen(szCacheFile,"wb");
if (fp)
{
fwrite(&nCount,sizeof(int),1,fp);
fwrite(*psl,sizeof(SERVICE_STRUCT)*nCount,1,fp);
fclose(fp);
}
return 1;
}
time_t get_time_from_sntp()
{
char szHost[128];
int nRecv;
time_sync_t tst;
int nWrite;
time_sync_t *pSyncInfo = NULL;
#ifdef WIN32
struct tm *ttm=NULL;
#endif
SOCKET sock;
struct sockaddr_in sa;
long ltime;
ltime = (long)time(NULL);
if (ne_sock_init() != NE_OK)
{
return ltime;
}
// Get server time
strcpy(szHost, g_sntphost);
if (isalpha(szHost[0]))
{
struct addrinfo *result;
struct addrinfo hints = {0};
struct sockaddr_in * addr;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if( getaddrinfo( szHost, NULL, &hints, &result ) != 0 )
{
return ltime;
}
sprintf(szHost, "%s", inet_ntoa(((struct sockaddr_in *)result->ai_addr)->sin_addr));
freeaddrinfo(result);
}
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
return ltime;
}
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr(szHost);
sa.sin_port = htons(g_sntpport);
#ifdef WIN32
__nonblock_win32(sock);
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK == WSAGetLastError())
{
fd_set wfd, efd;
struct timeval tv;
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(sock, &wfd);
FD_SET(sock, &efd);
tv.tv_sec = timeout;
tv.tv_usec = 0;
nRecv = select(0, 0, &wfd, &efd,&tv);
if (SOCKET_ERROR == nRecv || 0 == nRecv)
{
int nRet = WSAGetLastError();
return ltime;
}
}
else
{
return ltime;
}
}
#else
__nonblock(sock);
{
int i, nRet;
for (i = 0; i < (timeout * 10); i++) {
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) != SOCKET_ERROR) {
errno = 0;
break;
} else {
nRet = errno;
}
if (errno == EISCONN)
break;
if (((i + 1) % 10) == 0) {
shutdown(sock, 2);
//close(sock);
//fprintf(stderr, "RETRY ");
}
usleep(100000);
//fprintf(stderr, "CLI %d\n", i);
}
if (errno != EISCONN && errno != 0)
{
return ltime;
}
}
#endif
tst.sync_info = ltime + AUTHPRIME - (ltime % AUTHPRIME);
tst.sync_info = htonl(tst.sync_info);
nWrite = _sh_send(sock, (char *)&tst, sizeof(tst));
if(nWrite < 0)
{
closesocket(sock);
return ltime;
}
nRecv = _sh_recv(sock, szHost, sizeof(szHost));
if (nRecv < 4)
{
closesocket(sock);
return ltime;
}
pSyncInfo = (time_sync_t *)&szHost;
pSyncInfo->sync_info = ntohl(pSyncInfo->sync_info);
closesocket(sock);
return pSyncInfo->sync_info;
}
PSERVICE_STRUCT get_addressex(const char *userId, const char *password, int *cnt)
{
// define varialbles
char *pszResult = NULL;
char szMD5[256], szVerifyKey[256], szPassword[128], szAuth[256];
__int64 nRandom;
struct tm *ptmNow = NULL;
time_t tmtNow;
COMMAND_STRUCT cmd;
PSERVICE_STRUCT psl = NULL;
int i, nServiceCount = 0;
char szHost[30];
SOCKET sock = INVALID_SOCKET;
struct sockaddr_in sa;
BOOL bIsCache = FALSE;
// get current time & random number
if (ne_sock_init() != NE_OK)
{
SetLastError(GetLastError());
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
tmtNow = get_time_from_sntp();
srand((unsigned int)tmtNow);
nRandom = rand() * rand();
ptmNow = gmtime((const time_t *)&tmtNow);
tmtNow %= 10000000000; // MAX 10
nRandom %= 10000000000; // MAX 10
// create command struct
#ifdef WIN32
sprintf(szMD5, "%010d%010I64d%s%s", tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#else
sprintf(szMD5, "%010d%010lld%s%s", (int)tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#endif
md5_buffer(szMD5, szVerifyKey);
md5_buffer(password, szPassword);
sprintf(szMD5, "%s%s%d", userId, szPassword, (int)tmtNow);
md5_buffer(szMD5, szPassword);
sprintf(szAuth, "%s%c%s%c%d", userId, DELIMITER, szPassword, DELIMITER, (int)tmtNow);
// Make header
#ifdef WIN32
memset((void *)&cmd, NULL, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010I64d",
#else
memset((void *)&cmd, 0, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010lld",
#endif
ptmNow->tm_year + 1900, ptmNow->tm_mon, ptmNow->tm_wday, ptmNow->tm_hour, ptmNow->tm_min, ptmNow->tm_sec,
szVerifyKey, (int)tmtNow, nRandom);
cmd.nMode = htonl(MODE_SRV_LST_2ND_REQUEST);
strcpy(cmd.szIssuer, SERVER_NAME);
cmd.nLength = htonl((u_long)strlen(szAuth));
// create socket
strcpy(szHost, g_cnthost);
if (isalpha(szHost[0])) {
struct addrinfo *result;
struct addrinfo hints = {0};
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if( getaddrinfo( szHost, NULL, &hints, &result ) != 0 )
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
sa.sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
}
else
sa.sin_addr.s_addr = inet_addr(szHost);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
sa.sin_family = AF_INET;
sa.sin_port = htons(g_cntport);
/* Elenoa MOD : START */
#ifdef _WIN32
__nonblock_win32(sock);
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK == WSAGetLastError())
{
fd_set wfd, efd;
struct timeval tv;
int result;
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(sock, &wfd);
FD_SET(sock, &efd);
tv.tv_sec = timeout;
tv.tv_usec = 0;
result = select(0, 0, &wfd, &efd,&tv);
if (SOCKET_ERROR == result || 0 == result)
{
if(result == 0)
{
// time_out
SetLastError(WSAETIMEDOUT);
}
result = WSAGetLastError();
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
}
else
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
}
#else
__nonblock(sock);
{
int i;
for (i = 0; i < (timeout * 10); i++) {
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) != SOCKET_ERROR) {
errno = 0;
break;
}
if (errno == EISCONN)
break;
if (((i + 1) % 10) == 0)
{
shutdown(sock, 2);
//close(sock);
}
usleep(100000);
//fprintf(stderr, "%d\n", i);
}
if (errno != EISCONN && errno != 0)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
// goto EXIT_FUNCTION;
}
}
#endif
// Send packet
if (_sh_send(sock, (char *)&cmd, sizeof(cmd)) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
if (_sh_send(sock, szAuth, (int)strlen(szAuth)) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
if (_sh_recv(sock, (char*)&cmd, sizeof(cmd)) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
cmd.nLength = ntohl(cmd.nLength);
cmd.nResult = ntohl(cmd.nResult);
if (cmd.nResult != 0x1000) {
if (cmd.nResult == 0x3000)
SetLastError(SHERRNO_UNDEFINED);
else if (cmd.nResult == 0x3001)
SetLastError(SHERRNO_AUTHORIZATION);
else if (cmd.nResult == 0x9000)
SetLastError(SHERRNO_INTERNAL);
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
if (_sh_recv(sock, (char*)&nServiceCount, 4) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
nServiceCount = ntohl(nServiceCount);
if(cnt) *cnt = nServiceCount;
psl = malloc(sizeof(SERVICE_STRUCT) * nServiceCount);
if (!psl)
goto EXIT_FUNCTION;
if (_sh_recv(sock, (char*)psl, sizeof(SERVICE_STRUCT) * nServiceCount) == SOCKET_ERROR)
{
bIsCache = TRUE;
if (psl)
free(psl);
goto CACHE_FUNCTION;
}
closesocket(sock);
sock = INVALID_SOCKET;
set_psl_to_cache(&psl,nServiceCount); // 캐쉬파일에 기록
if ( nServiceCount == 0 )
SetLastError(SHERRNO_NOSERVICE);
CACHE_FUNCTION:
if( bIsCache)
nServiceCount = get_psl_from_cache(&psl);
EXIT_FUNCTION:
i = GetLastError();
//if (psl)
// free(psl);
if (sock != INVALID_SOCKET)
closesocket(sock);
SetLastError(i);
return psl;
}
char* get_address(const char *userId, const char *password, const char *serviceId,int nFlag)
{
// define varialbles
char *pszResult = NULL;
char szMD5[256], szVerifyKey[256], szPassword[128], szAuth[256];
__int64 nRandom;
struct tm *ptmNow = NULL;
time_t tmtNow;
COMMAND_STRUCT cmd;
PSERVICE_STRUCT psl = NULL;
int i, nServiceCount = 0;
char szHost[30];
SOCKET sock = INVALID_SOCKET;
struct sockaddr_in sa;
BOOL bIsCache = FALSE;
// get current time & random number
if (ne_sock_init() != NE_OK)
{
SetLastError(GetLastError());
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
tmtNow = get_time_from_sntp();
srand((unsigned int)tmtNow);
nRandom = rand() * rand();
ptmNow = gmtime((const time_t *)&tmtNow);
tmtNow %= 10000000000; // MAX 10
nRandom %= 10000000000; // MAX 10
// create command struct
#ifdef WIN32
sprintf(szMD5, "%010d%010I64d%s%s", tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#else
sprintf(szMD5, "%010d%010lld%s%s", (int)tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#endif
//md5_buffer(szMD5, szVerifyKey);
md5_buffer(password, szPassword);
sprintf(szMD5, "%s%s%d", userId, szPassword, (int)tmtNow);
md5_buffer(szMD5, szPassword);
sprintf(szAuth, "%s%c%s%c%d", userId, DELIMITER, szPassword, DELIMITER, (int)tmtNow);
// Make header
#ifdef WIN32
memset((void *)&cmd, NULL, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010I64d",
#else
memset((void *)&cmd, 0, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010lld",
#endif
ptmNow->tm_year + 1900, ptmNow->tm_mon, ptmNow->tm_wday, ptmNow->tm_hour, ptmNow->tm_min, ptmNow->tm_sec,
szVerifyKey, (int)tmtNow, nRandom);
cmd.nMode = htonl(MODE_SRV_LST_2ND_REQUEST);
strcpy(cmd.szIssuer, SERVER_NAME);
cmd.nLength = htonl((u_long)strlen(szAuth));
// create socket
strcpy(szHost, g_cnthost);
if (isalpha(szHost[0])) {
struct addrinfo *result;
struct addrinfo hints = {0};
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if( getaddrinfo( szHost, NULL, &hints, &result ) != 0 )
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
sa.sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
}
else
sa.sin_addr.s_addr = inet_addr(szHost);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
sa.sin_family = AF_INET;
sa.sin_port = htons(g_cntport);
/* Elenoa MOD : START */
#ifdef _WIN32
__nonblock_win32(sock);
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK == WSAGetLastError())
{
fd_set wfd, efd;
struct timeval tv;
int result;
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(sock, &wfd);
FD_SET(sock, &efd);
tv.tv_sec = timeout;
tv.tv_usec = 0;
result = select(0, 0, &wfd, &efd,&tv);
if (SOCKET_ERROR == result || 0 == result)
{
if(result == 0)
{
// time_out
SetLastError(WSAETIMEDOUT);
}
result = WSAGetLastError();
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
}
else
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
}
#else
__nonblock(sock);
{
int i;
for (i = 0; i < (timeout * 10); i++) {
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) != SOCKET_ERROR) {
errno = 0;
break;
}
if (errno == EISCONN)
break;
if (((i + 1) % 10) == 0)
{
shutdown(sock, 2);
//close(sock);
}
usleep(100000);
//fprintf(stderr, "%d\n", i);
}
if (errno != EISCONN && errno != 0)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
// goto EXIT_FUNCTION;
}
}
#endif
// Send packet
if (_sh_send(sock, (char *)&cmd, sizeof(cmd)) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
if (_sh_send(sock, szAuth, (int)strlen(szAuth)) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
if (_sh_recv(sock, (char*)&cmd, sizeof(cmd)) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
cmd.nLength = ntohl(cmd.nLength);
cmd.nResult = ntohl(cmd.nResult);
if (cmd.nResult != 0x1000) {
if (cmd.nResult == 0x3000)
SetLastError(SHERRNO_UNDEFINED);
else if (cmd.nResult == 0x3001)
SetLastError(SHERRNO_AUTHORIZATION);
else if (cmd.nResult == 0x9000)
SetLastError(SHERRNO_INTERNAL);
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
if (_sh_recv(sock, (char*)&nServiceCount, 4) == SOCKET_ERROR)
{
bIsCache = TRUE;
goto CACHE_FUNCTION;
}
nServiceCount = ntohl(nServiceCount);
psl = malloc(sizeof(SERVICE_STRUCT) * nServiceCount);
if (!psl)
goto EXIT_FUNCTION;
if (_sh_recv(sock, (char*)psl, sizeof(SERVICE_STRUCT) * nServiceCount) == SOCKET_ERROR)
{
bIsCache = TRUE;
if (psl)
free(psl);
goto CACHE_FUNCTION;
}
closesocket(sock);
sock = INVALID_SOCKET;
set_psl_to_cache(&psl,nServiceCount); // 캐쉬파일에 기록
if (!pszResult)
SetLastError(SHERRNO_NOSERVICE);
CACHE_FUNCTION:
if( bIsCache)
nServiceCount = get_psl_from_cache(&psl);
for (i = 0; i < nServiceCount; i++) {
if (strcmp((const char *)psl[i].id, serviceId) == 0)
{
switch(nFlag)
{
case 0: // dav address
strcat(psl[i].domain2, "/dav");
pszResult = strdup((const char *)psl[i].domain2);
break;
case 1: // rcts adress
pszResult = strdup((const char *)psl[i].domain);
break;
}
break;
}
}
EXIT_FUNCTION:
i = GetLastError();
if (psl)
free(psl);
if (sock != INVALID_SOCKET)
closesocket(sock);
SetLastError(i);
return pszResult;
}
const char *sh_get_service_host(const char *userId, const char *password, const char *serviceId)
{
return get_address(userId,password,serviceId,0);
}
const char *sh_get_rcts_host(const char *userId, const char *password, const char *serviceId)
{
return get_address(userId,password,serviceId,1);
}
void sh_mem_free(void* pData)
{
free(pData);
}
const int sh_get_service_info(const char *userId, const char *password, const char *serviceId, PINT64 totalSpace, PINT64 freeSpace)
{
// define varialbles
int nResult = 0;
char szMD5[256], szVerifyKey[256], szPassword[128], szAuth[256];
__int64 nRandom;
struct tm *ptmNow = NULL;
time_t tmtNow;
char* pdata;
COMMAND_STRUCT cmd;
char szRecvBuf[1024], *pszUsedSpace;
int i;
SOCKET sock = INVALID_SOCKET;
struct sockaddr_in sa;
char* pszHost = (char *)sh_get_rcts_host(userId, password, serviceId);
if (!pszHost)
return 0;
pdata = strstr(pszHost,"/");
if (pdata)
*pdata = 0x00;
// get current time & random number
tmtNow = get_time_from_sntp();
srand((unsigned int)tmtNow);
nRandom = rand() * rand();
ptmNow = gmtime((const time_t *)&tmtNow);
tmtNow %= 10000000000; // MAX 10
nRandom %= 10000000000; // MAX 10
// create command struct
#ifdef WIN32
sprintf(szMD5, "%010d%010I64d%s%s", tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#else
sprintf(szMD5, "%010d%010lld%s%s", (int)tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#endif
md5_buffer(szMD5, szVerifyKey);
md5_buffer(password, szPassword);
sprintf(szMD5, "%s@%s%s%d", serviceId, userId, szPassword, (int)tmtNow);
md5_buffer(szMD5, szPassword);
sprintf(szAuth, "%s@%s%c%s%c%d", serviceId, userId, DELIMITER, szPassword, DELIMITER, (int)tmtNow);
// Make header
#ifdef WIN32
memset((void *)&cmd, NULL, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010I64d",
#else
memset((void *)&cmd, 0, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010lld",
#endif
ptmNow->tm_year + 1900, ptmNow->tm_mon+1, ptmNow->tm_mday, ptmNow->tm_hour, ptmNow->tm_min, ptmNow->tm_sec,
szVerifyKey, (int)tmtNow, nRandom);
cmd.nMode = htonl(SDK_REQ_VOLUME_INFO);
strcpy(cmd.szIssuer, SERVER_NAME);
strcpy(cmd.szServiceId, serviceId);
cmd.nLength = htonl((u_long)strlen(szAuth));
// create socket
if (isalpha(pszHost[0])) {
struct addrinfo *result;
struct addrinfo hints = {0};
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if( getaddrinfo( pszHost, NULL, &hints, &result ) != 0 )
goto EXIT_FUNCTION;
sa.sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
}
else
sa.sin_addr.s_addr = inet_addr(pszHost);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
goto EXIT_FUNCTION;
sa.sin_family = AF_INET;
sa.sin_port = htons(RCTS_PORT);
/* Elenoa MOD : START */
#ifdef _WIN32
__nonblock_win32(sock);
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK == WSAGetLastError())
{
fd_set wfd, efd;
struct timeval tv;
int result;
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(sock, &wfd);
FD_SET(sock, &efd);
tv.tv_sec = timeout;
tv.tv_usec = 0;
result = select(0, 0, &wfd, &efd,&tv);
if (SOCKET_ERROR == result || 0 == result)
{
int nRet = WSAGetLastError();
goto EXIT_FUNCTION;
}
}
else
goto EXIT_FUNCTION;
}
#else
__nonblock(sock);
{
int i;
for (i = 0; i < (timeout * 10); i++) {
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) != SOCKET_ERROR) {
errno = 0;
break;
}
if (errno == EISCONN)
break;
if (((i + 1) % 10) == 0)
{
shutdown(sock, 2);
close(sock);
}
usleep(100000);
//fprintf(stderr, "%d\n", i);
}
if (errno != EISCONN && errno != 0)
goto EXIT_FUNCTION;
}
#endif
// Send packet
if (_sh_send(sock, (char *)&cmd, sizeof(cmd)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
if (_sh_send(sock, szAuth, (int)strlen(szAuth)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
if (_sh_recv(sock, (char*)&cmd, sizeof(cmd)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
cmd.nLength = ntohl(cmd.nLength);
cmd.nResult = ntohl(cmd.nResult);
if (cmd.nResult != 0x1000) {
if (cmd.nResult == 0x3000)
SetLastError(SHERRNO_UNDEFINED);
else if (cmd.nResult == 0x3001)
SetLastError(SHERRNO_AUTHORIZATION);
else if (cmd.nResult == 0x9000)
SetLastError(SHERRNO_INTERNAL);
goto EXIT_FUNCTION;
}
if (_sh_recv(sock, szRecvBuf, cmd.nLength) == SOCKET_ERROR)
goto EXIT_FUNCTION;
closesocket(sock);
sock = INVALID_SOCKET;
pszUsedSpace = strchr(szRecvBuf, DELIMITER);
*(pszUsedSpace++) = (char)NULL;
#ifdef WIN32
*totalSpace = _atoi64(szRecvBuf);
*freeSpace = *totalSpace - _atoi64(pszUsedSpace);
#else
*totalSpace = strtoll(szRecvBuf, NULL, 10);
*freeSpace = *totalSpace - strtoll(pszUsedSpace, NULL, 10);
#endif
nResult = 1;
EXIT_FUNCTION:
i = GetLastError();
if (pszHost)
free(pszHost);
if (sock != INVALID_SOCKET)
closesocket(sock);
SetLastError(i);
return nResult;
}
#ifndef WIN32
void SetLastError(int nErrCode)
{
errno = nErrCode;
}
#endif
/* Elenoa MOD START */
static int _sh_send(SOCKET s, char *pszBuf, int nLen)
{
int iSent = 0, nSentLen;
fd_set wset;
struct timeval tv;
FD_ZERO(&wset);
FD_SET(s, &wset);
tv.tv_sec = timeout;
tv.tv_usec = 0;
do {
//if (select(s + 1, NULL, &wset, NULL, &tv) < 0) break;
int n = select(s + 1, NULL, &wset, NULL, &tv);
if(n == 0)
{
// time_out
#ifdef WIN32
SetLastError(WSAETIMEDOUT);
#else // WIN32
SetLastError(ETIMEDOUT);
#endif // WIN32
break;
}
else if ( n < 0 )
{
// error
SetLastError(GetLastError());
break;
}
if (!FD_ISSET(s, &wset)) break;
nSentLen = send(s, pszBuf + iSent, nLen, 0);
iSent += nSentLen;
nLen -= nSentLen;
} while (nLen > 0 && nSentLen > 0);
return nLen > 0 ? SOCKET_ERROR : iSent;
}
static int _sh_recv(SOCKET s, char *pszBuf, int nLen)
{
int iRecv = 0, nRecvLen;
fd_set rset;
struct timeval tv;
int nRet;
FD_ZERO(&rset);
FD_SET(s, &rset);
tv.tv_sec = timeout;
tv.tv_usec = 0;
do {
nRet = select(s + 1, &rset, NULL, NULL, &tv);
if (nRet == 0)
{
// time out
#ifdef WIN32
SetLastError(WSAETIMEDOUT);
#else // WIN32
SetLastError(ETIMEDOUT);
#endif // WIN32
break;
}
else if (nRet < 0)
{
// error
SetLastError(GetLastError());
break;
}
if (!FD_ISSET(s, &rset)) break;
nRecvLen = recv(s, pszBuf + iRecv, nLen, 0);
iRecv += nRecvLen;
nLen -= nRecvLen;
} while (nLen > 0 && nRecvLen > 0);
return nLen < 0 ? SOCKET_ERROR : iRecv;
}
void sh_set_cache_file(const char *file_path)
{
strncpy(szCacheFile,file_path,sizeof(szCacheFile));
}
void * sh_get_service_list(const char *userId, const char *password, int *cnt)
{
PSERVICE_STRUCT psl = NULL;
if(cnt)
*cnt = 0;
psl = get_addressex(userId, password, cnt);
return (void*) psl;
}
void sh_set_center_info ( const char *host, int port )
{
if(host && strlen(host) > 0 )
strcpy(g_cnthost, host);
else
strcpy(g_cnthost, CENTER_HOST);
if(port > 0)
g_cntport = port;
else
g_cntport = CENTER_PORT;
}
void sh_set_sntp_info ( const char *host, int port )
{
if(host && strlen(host) > 0 )
strcpy(g_sntphost, host);
else
strcpy(g_sntphost, SNTP_DOMAIN);
if(port > 0)
g_sntpport = port;
else
g_sntpport = SNTP_PORT;
}
void* sh_get_anonyauth( const char *userId, const char *password, const char *serviceId, int * cnt)
{
PPATHINFO_STRUCT ppl = NULL;
char szMD5[256], szVerifyKey[256], szPassword[128], szAuth[256];
__int64 nRandom;
struct tm *ptmNow = NULL;
time_t tmtNow;
char* pdata;
COMMAND_STRUCT cmd;
char szRecvBuf[1024], *pszUsedSpace;
int i;
int nCount = 0;
SOCKET sock = INVALID_SOCKET;
struct sockaddr_in sa;
char* pszHost = (char *)sh_get_rcts_host(userId, password, serviceId);
if (!pszHost)
return 0;
pdata = strstr(pszHost,"/");
if (pdata)
*pdata = 0x00;
// get current time & random number
tmtNow = get_time_from_sntp();
srand((unsigned int)tmtNow);
nRandom = rand() * rand();
ptmNow = gmtime((const time_t *)&tmtNow);
tmtNow %= 10000000000; // MAX 10
nRandom %= 10000000000; // MAX 10
// create command struct
#ifdef WIN32
sprintf(szMD5, "%010d%010I64d%s%s", tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#else
sprintf(szMD5, "%010d%010lld%s%s", (int)tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#endif
md5_buffer(szMD5, szVerifyKey);
md5_buffer(password, szPassword);
sprintf(szMD5, "%s@%s%s%d", serviceId, userId, szPassword, (int)tmtNow);
md5_buffer(szMD5, szPassword);
sprintf(szAuth, "%s@%s%c%s%c%d", serviceId, userId, DELIMITER, szPassword, DELIMITER, (int)tmtNow);
// Make header
#ifdef WIN32
memset((void *)&cmd, NULL, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010I64d",
#else
memset((void *)&cmd, 0, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010lld",
#endif
ptmNow->tm_year + 1900, ptmNow->tm_mon+1, ptmNow->tm_mday, ptmNow->tm_hour, ptmNow->tm_min, ptmNow->tm_sec,
szVerifyKey, (int)tmtNow, nRandom);
cmd.nMode = htonl(SDK_REQ_ANONY_DIR);
strcpy(cmd.szIssuer, SERVER_NAME);
strcpy(cmd.szServiceId, serviceId);
cmd.nLength = htonl((u_long)strlen(szAuth));
// create socket
if (isalpha(pszHost[0])) {
struct addrinfo *result;
struct addrinfo hints = {0};
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if( getaddrinfo( pszHost, NULL, &hints, &result ) != 0 )
goto EXIT_FUNCTION;
sa.sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
}
else
sa.sin_addr.s_addr = inet_addr(pszHost);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
goto EXIT_FUNCTION;
sa.sin_family = AF_INET;
sa.sin_port = htons(RCTS_PORT);
/* Elenoa MOD : START */
#ifdef _WIN32
__nonblock_win32(sock);
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK == WSAGetLastError())
{
fd_set wfd, efd;
struct timeval tv;
int result;
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(sock, &wfd);
FD_SET(sock, &efd);
tv.tv_sec = timeout;
tv.tv_usec = 0;
result = select(0, 0, &wfd, &efd,&tv);
if (SOCKET_ERROR == result || 0 == result)
{
int nRet = WSAGetLastError();
goto EXIT_FUNCTION;
}
}
else
goto EXIT_FUNCTION;
}
#else
__nonblock(sock);
{
int i;
for (i = 0; i < (timeout * 10); i++) {
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) != SOCKET_ERROR) {
errno = 0;
break;
}
if (errno == EISCONN)
break;
if (((i + 1) % 10) == 0)
{
shutdown(sock, 2);
close(sock);
}
usleep(100000);
//fprintf(stderr, "%d\n", i);
}
if (errno != EISCONN && errno != 0)
goto EXIT_FUNCTION;
}
#endif
// Send packet
if (_sh_send(sock, (char *)&cmd, sizeof(cmd)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
if (_sh_send(sock, szAuth, (int)strlen(szAuth)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
if (_sh_recv(sock, (char*)&cmd, sizeof(cmd)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
cmd.nLength = ntohl(cmd.nLength);
cmd.nResult = ntohl(cmd.nResult);
if (cmd.nResult != 0x1000) {
if (cmd.nResult == 0x3000)
SetLastError(SHERRNO_UNDEFINED);
else if (cmd.nResult == 0x3001)
SetLastError(SHERRNO_AUTHORIZATION);
else if (cmd.nResult == 0x9000)
SetLastError(SHERRNO_INTERNAL);
goto EXIT_FUNCTION;
}
if (_sh_recv(sock, (char*)&nCount, 4) == SOCKET_ERROR)
{
goto EXIT_FUNCTION;
}
nCount = ntohl(nCount);
if(cnt) *cnt = nCount;
if(nCount > 0)
{
ppl = malloc(sizeof(PATHINFO_STRUCT) * nCount);
if (!ppl)
goto EXIT_FUNCTION;
if (_sh_recv(sock, (char*)ppl, sizeof(PATHINFO_STRUCT) * nCount) == SOCKET_ERROR)
{
if (ppl)
{
free(ppl);
ppl = NULL;
}
goto EXIT_FUNCTION;
}
}
closesocket(sock);
sock = INVALID_SOCKET;
EXIT_FUNCTION:
i = GetLastError();
if (pszHost)
free(pszHost);
if (sock != INVALID_SOCKET)
closesocket(sock);
SetLastError(i);
return ppl;
}
int sh_set_anonyauth(const char *userId, const char *password, const char *serviceId, int set, int sendlen, const void *sendmsg)
{
char szMD5[256], szVerifyKey[256], szPassword[128], szAuth[256];
__int64 nRandom;
struct tm *ptmNow = NULL;
time_t tmtNow;
char* pdata;
char* pSendData = NULL;
COMMAND_STRUCT cmd;
char szRecvBuf[1024], *pszUsedSpace;
int i;
int nCount = 0, ret = 0;
SOCKET sock = INVALID_SOCKET;
struct sockaddr_in sa;
int nCommand = (set ? SDK_REQ_SET_ANONY_DIR : SDK_REQ_UNSET_ANONY_DIR);
char* pszHost = (char *)sh_get_rcts_host(userId, password, serviceId);
if (!pszHost)
return 0;
pdata = strstr(pszHost,"/");
if (pdata)
*pdata = 0x00;
// get current time & random number
tmtNow = get_time_from_sntp();
srand((unsigned int)tmtNow);
nRandom = rand() * rand();
ptmNow = gmtime((const time_t *)&tmtNow);
tmtNow %= 10000000000; // MAX 10
nRandom %= 10000000000; // MAX 10
// create command struct
#ifdef WIN32
sprintf(szMD5, "%010d%010I64d%s%s", tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#else
sprintf(szMD5, "%010d%010lld%s%s", (int)tmtNow, nRandom, PRIVATE_KEY, SERVER_NAME);
#endif
md5_buffer(szMD5, szVerifyKey);
md5_buffer(password, szPassword);
sprintf(szMD5, "%s@%s%s%d", serviceId, userId, szPassword, (int)tmtNow);
md5_buffer(szMD5, szPassword);
sprintf(szAuth, "%s@%s%c%s%c%d", serviceId, userId, DELIMITER, szPassword, DELIMITER, (int)tmtNow);
// Make header
#ifdef WIN32
memset((void *)&cmd, NULL, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010I64d",
#else
memset((void *)&cmd, 0, sizeof(cmd));
sprintf(cmd.szTranId, "%04d%02d%02d%02d%02d%02d-%.10s-%010d-%010lld",
#endif
ptmNow->tm_year + 1900, ptmNow->tm_mon+1, ptmNow->tm_mday, ptmNow->tm_hour, ptmNow->tm_min, ptmNow->tm_sec,
szVerifyKey, (int)tmtNow, nRandom);
cmd.nMode = htonl(nCommand);
strcpy(cmd.szIssuer, SERVER_NAME);
strcpy(cmd.szServiceId, serviceId);
cmd.nLength = htonl((u_long)strlen(szAuth) + sendlen);
if(sendlen > 0)
{
pSendData = malloc(strlen(szAuth) + sendlen);
memcpy(pSendData, szAuth, strlen(szAuth));
memcpy(pSendData+strlen(szAuth), sendmsg, sendlen);
}
// create socket
if (isalpha(pszHost[0])) {
struct addrinfo *result;
struct addrinfo hints = {0};
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if( getaddrinfo( pszHost, NULL, &hints, &result ) != 0 )
goto EXIT_FUNCTION;
sa.sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
}
else
sa.sin_addr.s_addr = inet_addr(pszHost);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
goto EXIT_FUNCTION;
sa.sin_family = AF_INET;
sa.sin_port = htons(RCTS_PORT);
/* Elenoa MOD : START */
#ifdef _WIN32
__nonblock_win32(sock);
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK == WSAGetLastError())
{
fd_set wfd, efd;
struct timeval tv;
int result;
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(sock, &wfd);
FD_SET(sock, &efd);
tv.tv_sec = timeout;
tv.tv_usec = 0;
result = select(0, 0, &wfd, &efd,&tv);
if (SOCKET_ERROR == result || 0 == result)
{
int nRet = WSAGetLastError();
goto EXIT_FUNCTION;
}
}
else
goto EXIT_FUNCTION;
}
#else
__nonblock(sock);
{
int i;
for (i = 0; i < (timeout * 10); i++) {
if (connect(sock, (SOCKADDR*)&sa, sizeof(sa)) != SOCKET_ERROR) {
errno = 0;
break;
}
if (errno == EISCONN)
break;
if (((i + 1) % 10) == 0)
{
shutdown(sock, 2);
close(sock);
}
usleep(100000);
//fprintf(stderr, "%d\n", i);
}
if (errno != EISCONN && errno != 0)
goto EXIT_FUNCTION;
}
#endif
// Send packet
if (_sh_send(sock, (char *)&cmd, sizeof(cmd)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
if (_sh_send(sock, pSendData, strlen(szAuth)+sendlen) == SOCKET_ERROR)
goto EXIT_FUNCTION;
if (_sh_recv(sock, (char*)&cmd, sizeof(cmd)) == SOCKET_ERROR)
goto EXIT_FUNCTION;
cmd.nLength = ntohl(cmd.nLength);
cmd.nResult = ntohl(cmd.nResult);
if (cmd.nResult != 0x1000) {
if (cmd.nResult == 0x3000)
SetLastError(SHERRNO_UNDEFINED);
else if (cmd.nResult == 0x3001)
SetLastError(SHERRNO_AUTHORIZATION);
else if (cmd.nResult == 0x9000)
SetLastError(SHERRNO_INTERNAL);
goto EXIT_FUNCTION;
}
closesocket(sock);
sock = INVALID_SOCKET;
ret = 1;
EXIT_FUNCTION:
i = GetLastError();
if (pszHost)
free(pszHost);
if(pSendData)
free(pSendData);
if (sock != INVALID_SOCKET)
closesocket(sock);
SetLastError(i);
return ret;
}
int sh_get_lasterror()
{
return GetLastError();
}
void sh_get_error_msg( int code, char* errstr)
{
if (code >= SHERRNO_UNDEFINED && code < SHERRNO_INVALIDCACHEFILE) {
switch (code) {
case SHERRNO_UNDEFINED:
strcpy(errstr, "알 수 없는 오류입니다.");
break;
case SHERRNO_AUTHORIZATION:
strcpy(errstr, "인증 실패입니다.");
break;
case SHERRNO_INTERNAL:
strcpy(errstr, "내부 오류 입니다.");
break;
case SHERRNO_NOSERVICE:
strcpy(errstr, "서비스가 존재하지 않습니다.");
break;
case SHERRNO_NOCACHEFILE:
strcpy(errstr, "캐쉬 파일이 없습니다.");
break;
case SHERRNO_INVALIDCACHEFILE:
strcpy(errstr, "올바르지 않는 캐쉬 파일입니다.");
break;
}
}
else {
#ifdef WIN32
char * tmp;
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL))
strcpy(errstr, "알 수 없는 오류입니다.");
else
strcpy(errstr, tmp);
LocalFree(tmp);
#else
strcpy(errstr, strerror(code));
#endif
}
}