
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <signal.h>
#include <unistd.h>
#include "pgLibTunnel.h"


static void DebugLogOut(unsigned int uLevel, const char* lpszOut)
{
}

static void InitDaemon()
{
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);
	signal(SIGHUP, SIG_IGN);

	if (fork() != 0) {
		exit(1);
	}

	if (setsid() < 0) {
		printf("pgTunnelStatic: init_daemon: setsid failed.\n");
		exit(1);
	}

	if (fork() != 0) {
		exit(1);
	}

	if (chdir("/") == -1) {
		printf("pgTunnelStatic: init_daemon: chdir failed.\n");
		exit(1);
	}

	// Close all files.
	int fd, fdtablesize;
	for (fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd++) {
		close(fd);
	}

	// Clean file masks.
	umask(0);

	// Igorne signal.
	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGABRT, SIG_IGN);
	signal(SIGALRM, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGUSR1, SIG_IGN);
	signal(SIGUSR2, SIG_IGN);
	signal(SIGVTALRM, SIG_IGN);
} 

static void ReplaceDevID(char* lpszSysInfo, char* lpszDevID)
{
	if (lpszDevID[0] == '\0') {
		return;
	}

	char* pszTemp = strstr(lpszSysInfo, "(DevID){");
	if (pszTemp == 0) {
		return;
	}

	pszTemp += strlen("(DevID){");
	char* pszTemp1 = strchr(pszTemp, '}');
	if (pszTemp1 == 0) {
		return;
	}

	unsigned int uDevIDSize = strlen(lpszDevID);
	unsigned int uDevIDSize1 = pszTemp1 - pszTemp;
	if (uDevIDSize != uDevIDSize1) {
		memmove((pszTemp + uDevIDSize), pszTemp1, strlen(pszTemp1));
	}

	memcpy(pszTemp, lpszDevID, uDevIDSize);
}

static void StrTrim(char* lpszStr)
{
	char* pszTemp0 = lpszStr;
	while ((*pszTemp0) != '\0') {
		if (strchr(" \r\n\t", (*pszTemp0)) == 0) {
			break;
		}
		pszTemp0++;
	}

	char* pszTemp1 = lpszStr + strlen(lpszStr);
	while (pszTemp1 > pszTemp0) {
		if (strchr(" \r\n\t", (*(pszTemp1 - 1))) == 0) {
			break;
		}
		pszTemp1--;
	}
	
	int iSize = (pszTemp1 - pszTemp0);
	memmove(lpszStr, pszTemp0, iSize);
	lpszStr[iSize] = '\0';
}

static unsigned int LoadDevID(const char* lpszCfgFile, char* lpszDevID, unsigned int uSize)
{
	unsigned int uRet = 0;

	FILE* pFile = fopen(lpszCfgFile, "r");
	if (pFile != 0) {
		while (1) {
			char szLine[256] = {0};
			if (fgets(szLine, sizeof(szLine), pFile) == 0) {
				break;
			}

			StrTrim(szLine);

			if (strstr(szLine, "id=") == szLine) {
				unsigned int uSizeLine = strlen(szLine);
				unsigned int uSizeTag = strlen("id=");
				if ((uSizeLine - uSizeTag) < uSize) {
					strcpy(lpszDevID, &(szLine[uSizeTag]));
					StrTrim(lpszDevID);
					uRet = 1;
				}
				break;
			}
		}

		fclose(pFile);
	}

	return uRet;
}


int main(int argc, char* argv[])
{
	// Run as daemon
//	InitDaemon();

	// Build ID file name.
	char szIdFile[256] = {0};
	sprintf(szIdFile, "%s.id", argv[0]);

	// Load device id from file.
	char szDevID[128] = {0};
	if (!LoadDevID(szIdFile, szDevID, sizeof(szDevID))) {
		printf("pgTunnelStatic: Load device id from file failed!\n");
		return 0;
	}

	// Build config file name.
	char szCfgFile[256] = {0};
	sprintf(szCfgFile, "%s.cfg", argv[0]);

	// Build system info.
	char szSysInfo[256] = {0};
	if (pgTunnelSysInfo(szCfgFile, szSysInfo, sizeof(szSysInfo)) != PG_TUNNEL_ERROR_OK) {
		printf("pgTunnelStatic: Build system info failed!\n");
		sprintf(szSysInfo, "(DevID){0}");
	}

	// Replace the device id.
	ReplaceDevID(szSysInfo, szDevID);

	// Start tunnel.
	int iErr = pgTunnelStart(szCfgFile, szSysInfo, 0, DebugLogOut);
	if (iErr != PG_TUNNEL_ERROR_OK) {
		printf("pgTunnelStatic: Tunnel start failed, Error=%d\n", iErr);
		return 0;
	}

	// Pending the main thread.
	while (1) {
		usleep(10 * 1000 * 1000);
	}
	
	// Stop tunnel.
	pgTunnelStop();
	return 0;
}

