/**
 * EH_ToolKit.cpp
 *
 * Copyright by AirDream Co., Ltd. 2010-2011 All right reserved
 *
 * Description:
 * Created on:2011-8-25
 * Modified on:2011-8-25
 *
 */

#include <EH_Exception.h>
#include <regex.h>

#include "ace/FILE_Addr.h"
#include "ace/FILE_IO.h"
#include "ace/FILE_Connector.h"

#include "EH_ToolKit.h"
#include "EH_DEBUG.h"


#define BOOL    uint8_t
#define TRUE    1
#define FALSE   0

uint32_t EH_ToolKit::ms_uiCrc32Tab[256] = { /* CRC polynomial 0xedb88320 */
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
    0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};



void EH_ToolKit::PrintMsg(const uint8_t* msg, uint16_t msg_len,bool isDebug) {
#if 0
    if (isDebug) {
        ACE_DEBUG((LM_DEBUG,"msg is： \n"));
    } else {
        ACE_DEBUG((LM_WARNING,"msg is： \n"));
    }
    //performance problem
    for (int i = 0; i < msg_len; i++) {
        if (isDebug) {
            ACE_DEBUG((LM_DEBUG,"0x%02X ",msg[i]));
        } else {
            ACE_DEBUG((LM_WARNING,"0x%02X ",msg[i]));
        }
    }
    if (isDebug) {
        ACE_DEBUG((LM_DEBUG,"\n msg content len is %d: \n", msg_len));
    } else {
        ACE_DEBUG((LM_WARNING,"\n msg content len is %d: \n", msg_len));
    }
#else
	#define MAX_LOG         4096

    char* buf = new char[MAX_LOG];
    char* p = buf;
    char* errinfo = "";
    int   leftLen = MAX_LOG-1;
    int	  i = 0;

    while (i < msg_len) {
    	int len = ACE_OS::snprintf(p,leftLen,"0x%02X ",msg[i]);
    	leftLen -= len;
    	if (leftLen < 0) {
    		errinfo = "[msg length over msg dump buffer!]";
    		break;
    	}
    	p += len;
    	i++;
    }
    if (isDebug) {
        EH_DEBUG("%s\nmsg content len is %d.%s\n", buf, msg_len,errinfo);
    } else {
        EH_WARNING("%s\nmsg content len is %d.%s\n", buf, msg_len,errinfo);
    }

    delete[] buf;
#endif
}

void EH_ToolKit::Split(const string& src, const string& separator, vector<string>& dest) {
    if (src == "") {
        return;
    }

    string str = src;
    string substring;
    string::size_type start = 0, index;
    do {
        index = str.find_first_of(separator, start);
        if (index != string::npos) {
            substring = str.substr(start, index - start);
            dest.push_back(substring);

            start = str.find_first_not_of(separator, index);
            if (start == string::npos) {
            	dest.push_back("");
            	return;
            }
        }
    } while (index != string::npos);

    substring = str.substr(start);
    dest.push_back(substring);
}

string EH_ToolKit::Trim(string &s) {
    if (s.length() == 0)
        return s;
    size_t beg = s.find_first_not_of(" \a\b\f\n\r\t\v");
    size_t end = s.find_last_not_of(" \a\b\f\n\r\t\v");
    if (beg == string::npos)
        return "";
    return string(s, beg, end-beg+1);
}

int EH_ToolKit::HexToStringNoSpace(const char* input, char* output, int len) {
    char * p = output;
    int total = 0, ret;
    for (int i = 0; i < len; i++) {
        ret = sprintf(p, "%02X", (unsigned char) (*(input + i)));
        p += ret;
        total += ret;
    }
    return total;
}

int EH_ToolKit::HexToString(const char* input, char* output, int len,const char* sep) {
    char * p = output;
    int total = 0, ret;
    for (int i = 0; i < len; i++) {
        ret = sprintf(p, "%02X", (unsigned char) (*(input + i)));
        p += ret;
        total += ret;
        if (i < len - 1) {
            *p = *sep;
        }
        ++p;
        ++total;
    }
    return total;
}

int EH_ToolKit::StringToHex(const char* input, unsigned char* output,const int bufLen) {
    int i, len = strlen(input);
    int j = 0; //length
    for (i = 0; i < len; i += 3) {
        if(j > bufLen) {
            return -1;
        }
        int c;
        sscanf(input + i, "%02X", &c);
        *(output + j) = c;
        j++;
    }
    return j;
}

int EH_ToolKit::StringToHexNoSpace(const char* input, unsigned char* output,const int bufLen) {
    int i, len = strlen(input);
    int j = 0; //length
    for (i = 0; i < len; i += 2) {
        if(j > bufLen) {
            return -1;
        }
        int c;
        sscanf(input + i, "%02X", &c);
        *(output + j) = c;
        j++;
    }
    return j;
}

unsigned short EH_ToolKit::CheckSum(const unsigned char* in,const int len) {
    unsigned short sum = 0;
    for (int i = 0; i < len; i++) {
        sum += *(in+i);
    }
    return sum;
}

int EH_ToolKit::StringToInt(const string input) {
    stringstream oss;
    oss << input;
    int output = 0;
    oss >> output;
    if (oss.fail() || !oss.eof()) {
        string exception = "Convert string to int error. string is"+input;
        EH_WARNING("%s.\n",exception.c_str());
        output = -1;
    }

    return output;
}

uint EH_ToolKit::StringToUInt(const string input) {
    stringstream oss;
    oss << input;
    uint output = 0;
    oss >> output;
    if (oss.fail() || !oss.eof()) {
        string exception = "Convert string to uint error. string is"+input;
        EH_WARNING("%s.\n",exception.c_str());
        output = 0;
    }
    return output;
}

double EH_ToolKit::StringToDouble(const string input) {
    stringstream oss;
    oss << input;
    double output = -1;
    oss >> output;
    if (oss.fail() || !oss.eof()) {
        string exception = "Convert string to double error. string is"+input;
        EH_WARNING("%s.\n",exception.c_str());
    }
    return output;
}

string EH_ToolKit::IntToString(const int input) {
    stringstream oss;
    oss << input;
    string output;
    oss >> output;
    return output;
}

string EH_ToolKit::UIntToString(const uint input) {
    stringstream oss;
    oss << input;
    string output;
    oss >> output;
    return output;
}

string EH_ToolKit::UInt64ToString(const ACE_UINT64 input) {
    stringstream oss;
    oss << input;
    string output;
    oss >> output;
    return output;
}

string EH_ToolKit::DoubleToString(const double input) {
    stringstream oss;
    oss << input;
    string output;
    oss >> output;
    return output;
}

string EH_ToolKit::JsonToString(const EH::Json::Value& json) {
	EH::Json::FastWriter writer;
	string jsonStr = writer.write(json);
	return Trim(jsonStr);
}

string EH_ToolKit::CreateRespJsonMsg(string opcode,string arg,int status,string nodeid) {
	EH::Json::Reader reader;
	EH::Json::Value msgObj;
	EH::Json::Value argObj;

	if (!reader.parse(arg.c_str(), argObj)) {
		argObj = EH::Json::Value(arg);
	}

	msgObj["nodeid"] = EH::Json::Value(nodeid);
	msgObj["opcode"] = EH::Json::Value(opcode);
	msgObj["arg"] = argObj;
	msgObj["status"] = EH::Json::Value(status == -1 ? "failed" : "success");
	string ret = msgObj.toStyledString();
	return Trim(ret);
}

string CreateRespJsonMsgWithErrorCode(string opcode,string arg,int status,string nodeid,int error) {

	return "";
}

string EH_ToolKit::CreateReqJsonMsg(string opcode,string arg,string requester,string nodeid) {
	EH::Json::Reader reader;
	EH::Json::Value msgObj;
	EH::Json::Value argObj;

	if(!reader.parse(arg.c_str(), argObj)) {
		argObj = EH::Json::Value(arg);//as string
	}

	msgObj["nodeid"] = EH::Json::Value(nodeid);
	msgObj["opcode"] = EH::Json::Value(opcode);
	msgObj["arg"] = argObj;
	msgObj["requester"] = requester;
	string ret = JsonToString(msgObj); //msgObj.toStyledString(); //两种方法有区别
	return Trim(ret);
}

string EH_ToolKit::CreateReqJsonMsgWithReqId(string opcode,string arg,string requester,string nodeid,string reqId) {
	EH::Json::Reader reader;
	EH::Json::Value msgObj;
	EH::Json::Value argObj;

	if(!reader.parse(arg.c_str(), argObj)) {
		argObj = EH::Json::Value(arg);//as string
	}

	msgObj["nodeid"] = EH::Json::Value(nodeid);
	msgObj["opcode"] = EH::Json::Value(opcode);
	msgObj["arg"] = argObj;
	if(reqId!= ""){
			msgObj["reqId"] = reqId;
		}
	msgObj["requester"] = requester;
	string ret = msgObj.toStyledString();
	return Trim(ret);
}

string EH_ToolKit::CreateReqJsonMsgWithArgJson(string opcode,EH::Json::Value argObj,string requester,string nodeid,string reqId) {
	EH::Json::Reader reader;
	EH::Json::Value msgObj;

	msgObj["nodeid"] = EH::Json::Value(nodeid);
	msgObj["opcode"] = EH::Json::Value(opcode);
	msgObj["arg"] = argObj;
	if(reqId!= ""){
		msgObj["reqId"] = reqId;
	}
	msgObj["requester"] = requester;
	string ret = msgObj.toStyledString();
	return Trim(ret);
}
bool EH_ToolKit::CompareNoCase(string str1,string str2) {
	if (strcasecmp(str1.c_str(),str2.c_str()) == 0) {
		return true;
	} else {
		return false;
	}
}

bool EH_ToolKit::HasSpareProcess(const string processName) {
    static ACE_Process_Mutex processMutex(processName.c_str());
    if (processMutex.tryacquire() < 0) {
        EH_WARNING("The same process is running.This process will abort.\n");
        return true;
    }
    return false;
}

bool EH_ToolKit::CheckRoot() {
    if (ACE_OS::geteuid() == 0) {
        EH_ERROR("\"root\" execution of the  program is not permitted.\n"
                "The program must be started under an unprivileged user ID to prevent\n"
                "possible system security compromise.\n");
        return false;
    }

    if (ACE_OS::getuid() != ACE_OS::geteuid()) {
        EH_ERROR("real and effective user IDs must match\n");
        return false;
    }
    return true;
}

void EH_ToolKit::BuildAbsTimeOut(ACE_Time_Value* timeout,int timeoutMS) {
	*timeout = ACE_OS::gettimeofday();
	timeout->usec(timeout->usec()+timeoutMS);
}

/*if you need use the return string,you should copy it.*/
const char* EH_ToolKit::GetLocalIP(string interface) {
	int MAXINTERFACES = 16;
	char* localIP = "";
	int fd, intrface;
	struct ifreq buf[MAXINTERFACES];
	struct ifconf ifc;

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
		ifc.ifc_len = sizeof(buf);
		ifc.ifc_buf = (caddr_t) buf;

		if (!ioctl(fd, SIOCGIFCONF, (char *) &ifc)) {
			intrface = ifc.ifc_len / sizeof(struct ifreq);

			while (intrface-- > 0) {
				if (interface == "NOT_SET") {/*get first ip*/
					if (!(ioctl(fd, SIOCGIFADDR, (char *) &buf[intrface]))) {
						localIP = inet_ntoa(((struct sockaddr_in*) (&buf[intrface].ifr_addr))->sin_addr);
						break;
					}
				} else {
					if (string(buf[intrface].ifr_name) == interface) {
						if (!(ioctl(fd, SIOCGIFADDR, (char *) &buf[intrface]))) {
							localIP = inet_ntoa(((struct sockaddr_in*) (&buf[intrface].ifr_addr))->sin_addr);
							break;
						}
					}
				}
			}
		}

		close(fd);
	}

	return localIP;
}


string EH_ToolKit::GetFileContent(string filePath, bool& error) {
	string fileContent;
	ACE_FILE_IO file;
	ACE_FILE_Connector fileConnector;
	error = false;

	if (fileConnector.connect(file, ACE_FILE_Addr(filePath.c_str()), 0, ACE_Addr::sap_any,
			                                 0, O_RDONLY, ACE_DEFAULT_FILE_PERMS) == -1) {
		EH_WARNING("Open file:%s error:%s.\n", filePath.c_str(), ACE_OS::strerror(ACE_OS::last_error()));
		error = true;
		fileContent = "";
	} else {
		char buf[200] = { 0 };

		while(true) {
			bzero(buf,sizeof(buf));

			int len = file.recv(buf, sizeof(buf) - 1);
			if (len == -1) {/*ERROR*/
				EH_WARNING("Read from file:%s error:%s.\n", filePath.c_str(), ACE_OS::strerror(ACE_OS::last_error()));
				fileContent = "";
				error = true;
				break;
			} else if (len == 0) {/*EOF*/
				break;
			} else {
				fileContent.append(buf);
			}
		}
		file.close();
	}

	return fileContent;
}


bool EH_ToolKit::Ping(string destIP) {
	bool pingOk;
	string ping_cmd = "ping -c 1 -W 1 "+destIP+" > /dev/null";

	int sys_ret = DoSystem(ping_cmd);
	if (sys_ret == 0) {
		pingOk = true;
	} else {
		pingOk = false;
	}

	return pingOk;
}


int EH_ToolKit::GetCpuCoreNum() {
	return sysconf(_SC_NPROCESSORS_ONLN);
}


bool EH_ToolKit::MatchVersion(string version,string pattern) {
    const size_t nmatch = 10;
    regmatch_t pm[10];
    int z;
    regex_t reg;

    regcomp(&reg, pattern.c_str(), REG_EXTENDED | REG_NOSUB);
    z = regexec(&reg, version.c_str(), nmatch, pm, REG_NOTBOL);

    return z != REG_NOMATCH;
}



typedef pthread_t ThreadId;

int GetCallstack(ThreadId, void **buffer, int size);
pthread_t mainThreadId;

static void WidebrightSegvHandler(int signum) {
	EH_ToolKit::PrintBacktrace(signum);

	if (mainThreadId != (ThreadId)pthread_self()) {
		GetCallstack(mainThreadId, NULL, 1);
	} else {
		EH_ERROR("Main thread call stack as above.\n");
	}

	exit(1);
}

void EH_ToolKit::SetCoredumpMsgDump() {
	mainThreadId = pthread_self();

	signal(SIGSEGV, WidebrightSegvHandler);
	signal(SIGABRT, WidebrightSegvHandler);
	signal(SIGALRM, WidebrightSegvHandler);
	signal(SIGBUS, WidebrightSegvHandler);
	signal(SIGFPE, WidebrightSegvHandler);
	signal(SIGHUP, WidebrightSegvHandler);
	signal(SIGILL, WidebrightSegvHandler);
	signal(SIGINT, WidebrightSegvHandler);
	signal(SIGIO, WidebrightSegvHandler);
	signal(SIGIOT, WidebrightSegvHandler);
	signal(SIGPOLL, WidebrightSegvHandler);
	signal(SIGPWR, WidebrightSegvHandler);
	signal(SIGPROF, WidebrightSegvHandler);
	signal(SIGQUIT, WidebrightSegvHandler);
	//signal(SIGSTKFLT, WidebrightSegvHandler);
	signal(SIGTERM, WidebrightSegvHandler);
	signal(SIGTRAP, WidebrightSegvHandler);
	signal(SIGSYS, WidebrightSegvHandler);
	signal(SIGVTALRM, WidebrightSegvHandler);
	signal(SIGXCPU, WidebrightSegvHandler);
	signal(SIGXFSZ, WidebrightSegvHandler);
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>

void EH_ToolKit::PrintBacktrace(int signum) {
	void *array[20];
	size_t size;
	char **strings;
	size_t i;

	signal(signum, SIG_DFL); /* 还原默认的信号处理handler */

	size = backtrace (array, 20);
	strings = (char **)backtrace_symbols (array, size);

	string sig;
	if (signum == SIGSEGV) {
		sig = "SIGSEGV";
	} else if(signum == SIGABRT) {
		sig = "SIGABRT";
	} else {
		sig = EH_ToolKit::IntToString(signum);
	}

	EH_ERROR("Process received %s! Stack trace:\n",sig.c_str());
	for (i = 0; i < size; i++) {
		EH_ERROR("%d %s.\n",i,strings[i]);
	}
	free (strings);
}

string EH_ToolKit::GetTimestamp(){
	struct timeval now;
	gettimeofday(&now, 0);
	ACE_UINT64 nowInMs = (ACE_UINT64)now.tv_sec * 1000;
	nowInMs += now.tv_usec / 1000;
	return EH_ToolKit::UInt64ToString(nowInMs);
}

string EH_ToolKit::GetUUID() {
	ACE_Utils::UUID_GENERATOR::instance()->init();
	ACE_Utils::UUID uuid;
	ACE_Utils::UUID_GENERATOR::instance()->generate_UUID(uuid);
	return uuid.to_string()->c_str();
}

string EH_ToolKit::GetCurrentTime() {
	long nowSec = time(NULL);
	struct tm *nowTM = localtime(&nowSec);

	char currentTime[256] = {0};
	snprintf(currentTime, sizeof(currentTime)-1,"%d-%02d-%02d %02d:%02d:%02d",
			                                              nowTM->tm_year+1900,
			                                                  nowTM->tm_mon+1,
			                                                   nowTM->tm_mday,
											                   nowTM->tm_hour,
											                    nowTM->tm_min,
											                   nowTM->tm_sec);
	return currentTime;
}

ACE_UINT64 EH_ToolKit::getSystemTimeInMs() {
	struct timeval now;
	gettimeofday(&now, 0);

	ACE_UINT64 nowInMs = now.tv_sec * 1000;
	nowInMs += now.tv_usec / 1000;
	return nowInMs;
}

int EH_ToolKit::DoSystem(string cmd) {
	int ret = 0;
	sighandler_t old_handler;

	old_handler = signal(SIGCHLD, SIG_DFL);
	int status = system(cmd.c_str());
	signal(SIGCHLD, old_handler);
	if (-1 != status) {
		if (WIFEXITED(status)) {/*normal exit*/
			if (0 == WEXITSTATUS(status)) {/*success*/
				EH_INFO("do cmd:%s ok.exit with code:%d\n",cmd.c_str(),WEXITSTATUS(status));
				return 0;
			} else {
				EH_WARNING("do cmd:%s failed.exit with code:%d\n",cmd.c_str(),WEXITSTATUS(status));
				return WEXITSTATUS(status);
			}
		} else {
			EH_WARNING("do cmd:%s failed.exit none normal.\n",cmd.c_str());
		}
	} else {
		EH_WARNING("do cmd:%s failed.system return -1.error:%s\n",cmd.c_str(),strerror(errno));
	}

	return -1;
}


#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>


// data structs to store interface name list
char ifname_buf[2048];
char *ifnames = ifname_buf;
int mac_count = 0;

void add_interface_name(const char * name)
{
    int i;
    for (i=0;i<mac_count;i++)
    {
        if (!strcmp(ifnames+i*IFNAMSIZ, name))
            return;
    }

    strncpy(ifnames+(mac_count++)*IFNAMSIZ, name, IFNAMSIZ-1);
}

char * get_name(char *name, char *p)
{
    while (isspace(*p))
    p++;
    while (*p) {
    if (isspace(*p))
        break;
    if (*p == ':') {    /* could be an alias */
        char *dot = p, *dotname = name;
        *name++ = *p++;
        while (isdigit(*p))
        *name++ = *p++;
        if (*p != ':') {    /* it wasn't, backup */
        p = dot;
        name = dotname;
        }
        if (*p == '\0')
        return NULL;
        p++;
        break;
    }
    *name++ = *p++;
    }
    *name++ = '\0';
    return p;
}

// get /proc/net/dev interface name list into buffer
// return 0 if success
int get_procnet_list()
{
    FILE *fh;
    char buf[512];
    fh = fopen("/proc/net/dev", "r");
    if (!fh)
        return -1;

    fgets(buf, sizeof buf, fh); /* eat title lines */
    fgets(buf, sizeof buf, fh);
    while (fgets(buf, sizeof buf, fh))
    {
        char name[IFNAMSIZ];
        get_name(name, buf);
        add_interface_name(name);
    }
    fclose(fh);
    return 0;
}

long mac_addr_sys ( char *addr) {
	/* implementation for Linux */
    struct ifreq ifr;
    struct ifreq *IFR;
    struct ifconf ifc;
    char buf[1024];
    int s, i;
    int ok = 0;

    // clear buffer
    memset(ifname_buf, 0, sizeof(ifname_buf));
    mac_count = 0;

    s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s==-1) {
        return -1;
    }

    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    ioctl(s, SIOCGIFCONF, &ifc);

    IFR = ifc.ifc_req;
    // put the ioctl interface names in the list
    for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; IFR++) {
            add_interface_name(IFR->ifr_name);
    }
    // put the /proc/net/dev interface names in the list
    if (get_procnet_list())
        return -1;

    // get the first mac address of eth* device hardware address
    for (i = 0; i < mac_count; i++) {
        strcpy(ifr.ifr_name, ifnames + i*IFNAMSIZ);

#if !defined(MIPS_ENCHANCE)
        if (!strncmp(ifr.ifr_name, "eth", 3))
         	if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
                 if (! (ifr.ifr_flags & IFF_LOOPBACK)) {
                     if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) {
                         char *p = (char *)ifr.ifr_hwaddr.sa_data;
                         if (!*((int *)p) && !*((int *)(p+2)) )
                             continue;
                         // if not 00:00:00:00:00:00, yes, we get the real mac addr
                         ok = 1;
                         break;
                     }
                 }
             }
#else
        if (!strncmp(ifr.ifr_name, "eth1", 4))
         	if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
                 if (! (ifr.ifr_flags & IFF_LOOPBACK)) {
                     if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) {
                         char *p = (char *)ifr.ifr_hwaddr.sa_data;
                         if (!*((int *)p) && !*((int *)(p+2)) )
                             continue;
                         // if not 00:00:00:00:00:00, yes, we get the real mac addr
                         ok = 1;
                         break;
                     }
                 }
             }
#endif
    }

    close(s);
    if (ok) {
        bcopy( ifr.ifr_hwaddr.sa_data, addr, 6);
    }
    else {
        return -1;
    }
    return 0;
}



string EH_ToolKit::GetMac() {
    long stat;
    char addr[6] = {0};
    char macStr[30] = {0};

    stat = mac_addr_sys(addr);
    if (0 == stat) {
    	HexToString(addr,macStr,6,":");
    	return macStr;
    } else {
    	return "";
    }
}

string EH_ToolKit::GetMacNoSpace() {
    long stat;
    char addr[6] = {0};
    char macStr[30] = {0};

    stat = mac_addr_sys(addr);
    if (0 == stat) {
    	HexToStringNoSpace(addr,macStr,6);
    	return macStr;
    } else {
    	return "";
    }
}

void EH_ToolKit::ShowHelpInfo() {
	cout<<("	-A : 'A' means 'Print All Log Message'\n");
	cout<<("	-D : 'D' means 'Print Above(include) DEBUG Message'\n");
	cout<<("	-I : 'I' means 'Print Above(include) INFO Message'\n");
	cout<<("	-N : 'N' means 'Print Above(include) NOTICE Message'\n");
	cout<<("	-W : 'W' means 'Print Above(include) WARNING Message'\n");
	cout<<("	-E : 'E' means 'Print Above(include) ERROR Message'\n");
	cout<<("	-H : printing help information\n");
	cout<<("	-V : printing version information\n");
}

void EH_ToolKit::ShowVersionInfo(string proc,string version) {
	cout<<"["<<proc<<"]:"<<version<<endl;
}

/*
 * version type:
 * v_x.x.x
 */
int EH_ToolKit::GetVersionInfo(string version, int& majorV, int& minorV, int& betaV, bool hasVersionPrefix) {
	string digitVersion;

	if (hasVersionPrefix) {
		vector<string> versionInfo;
		EH_ToolKit::Split(version, "_", versionInfo);

		if (versionInfo.size() == 2) {
			digitVersion = versionInfo[1];
		} else {
			return -1;
		}
	} else {
		digitVersion = version;
	}

	vector<string> subversionInfo;
	EH_ToolKit::Split(digitVersion,".",subversionInfo);
	if (subversionInfo.size() == 3) {
		majorV = StringToInt(subversionInfo[0]);
		minorV = StringToInt(subversionInfo[1]);
		betaV = StringToInt(subversionInfo[2]);
	} else {
		return -1;
	}

    return 0;
}

/*
 * version type:
 * x.x.x
 */
int EH_ToolKit::CompareVersion(string checkVersion, string baseVersion) {
	int ret = -1;

	do {
		int checkMajorV;
		int checkMinoV;
		int checkBetaV;
		int checkGetRet = GetVersionInfo(checkVersion,checkMajorV,checkMinoV,checkBetaV,false);
		if (checkGetRet == -1) {
			break;
		}

		int baseMajorV;
		int baseMinoV;
		int baseBetaV;
		int baseGetRet = GetVersionInfo(baseVersion, baseMajorV, baseMinoV, baseBetaV, false);
		if (baseGetRet == -1) {
			break;
		}

		int checkVersionSum = checkMajorV * 1000000 + checkMinoV * 1000 + checkBetaV;
		int baseVersionSum = baseMajorV * 1000000 + baseMinoV * 1000 + baseBetaV;

		if (checkVersionSum > baseVersionSum) {
			ret = COMPARE_VER_MORE_THAN;
		} else if (checkVersionSum < baseVersionSum) {
			ret = COMPARE_VER_LESS_THAN;
		} else {
			ret = COMPARE_VER_EQ_THAN;
		}
	} while (false);

	return ret;
}

uint32_t EH_ToolKit::CreateCrc32(const uint8_t* s, uint32_t len) {
    uint32_t i;
    uint32_t crc32val;
    crc32val = ~0;
    for (i = 0; i < len; i++) {
        crc32val = EH_ToolKit::ms_uiCrc32Tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
    }

    return ~crc32val;
}

uint16_t EH_ToolKit::CreateCrc16(const uint8_t* msg, uint32_t len) {
    uint16_t crc = 0xFFFF;
    uint32_t i, j = 0;
    for (i = 0; i < len; i++) {
        for (j = 0; j < 8; j++) {
            BOOL c15 = ((crc >> 15 & 1) == 1);
            BOOL bit = ((msg[i] >> (7 - j) & 1) == 1);
            crc <<= 1;
            if (c15 ^ bit) {
                crc ^= 0x1021;
            }
        }
    }

    return crc;
}

uint16_t EH_ToolKit::CrcByte(uint16_t crc, uint8_t b) {
    crc = (uint8_t) (crc >> 8) | (crc << 8);
    crc ^= b;
    crc ^= (uint8_t) (crc & 0xff) >> 4;
    crc ^= crc << 12;
    crc ^= (crc & 0xff) << 5;

    return crc;
}

uint16_t EH_ToolKit::Crc16(void* buf, uint8_t len) {
    uint8_t* tmpBuf = (uint8_t* ) buf;
    uint16_t crc;
    for (crc = 0; len > 0; len--) {
        crc = CrcByte(crc, *tmpBuf); // Calculates running CRC
        tmpBuf++;
    }

    return crc;
}




