Initial commit

This commit is contained in:
2026-07-09 11:27:59 +08:00
commit 3f1edda843
126 changed files with 34446 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/../common",
"${workspaceFolder}/../param",
"${workspaceFolder}/../StoredProcedure"
],
"defines": ["_DEBUG","_SERVER"],
"cStandard": "c11",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
+36
View File
@@ -0,0 +1,36 @@
{
"configurations": [
{
"name": "C/C++: g++ build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../deploy/DBService",
"args": ["-debug", "s"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/../deploy",
"environment": [
{
"name": "LD_LIBRARY_PATH",
"value": "LD_LIBRARY_PATH:${workspaceFolder}/../deploy"
}
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ build DBService",
"miDebuggerPath": "/usr/bin/gdb",
}
],
"version": "2.0.0"
}
+54
View File
@@ -0,0 +1,54 @@
{
"C_Cpp.default.includePath": [
"${workspaceFolder}/../common",
"${workspaceFolder}/**"
],
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp"
}
}
+41
View File
@@ -0,0 +1,41 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build DBService",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"-D","_DEBUG",
"-D","_SERVER",
"${workspaceFolder}/*.cpp",
"${workspaceFolder}/../common/thread.cpp",
"${workspaceFolder}/../common/Socket.cpp",
"${workspaceFolder}/../common/MessageDef.cpp",
"-std=c++11",
"-I","${workspaceFolder}/../common",
"-I","${workspaceFolder}/../param",
"-I","${workspaceFolder}/../StoredProcedure",
"-L","${workspaceFolder}/../deploy",
"-l","StoredProcedure",
"-l","Params",
"-Wl,--copy-dt-needed-entries",
"-o","${workspaceFolder}/../deploy/DBService",
"-pthread",
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}
+68
View File
@@ -0,0 +1,68 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include "ServiceThread.h"
#include "debug.h"
int g_eDebug = 0;
int g_iChkStyle = 0;
extern int g_iSignal;
extern CSema* g_pSemaService;
CSema* g_pSemaStop = NULL;
void CmdDebugService()
{
CServiceThread* pServiceThread = new CServiceThread();
pServiceThread->Resume();
g_pSemaStop = new CSema(NULL, 0);
g_pSemaStop->ActP();
pServiceThread->Terminate();
if( g_pSemaService ){
if( g_pSemaService->ActP(15000) ){
printf("service eixt innormally\n");
}
delete g_pSemaService;
}
delete pServiceThread;
delete g_pSemaStop;
}
int main(int argc, char *argv[])
{
if ( (argc > 1) &&((*argv[1] == '-') || (*argv[1] == '/')) ){
if ( strcasecmp( "debug", argv[1]+1 ) == 0 ){
g_eDebug = 4;
if( argc>2 ){
if ( strcasecmp( "f", argv[2] ) == 0 ){
g_eDebug = 1;
}
else if ( strcasecmp( "n", argv[2] ) == 0 ){
g_eDebug = 2;
}
else if ( strcasecmp( "s", argv[2] ) == 0 ){
g_eDebug = 3;
}
}
}
else if( strcasecmp( "check", argv[1]+1 ) == 0 && argc>2 ){
g_iChkStyle = atoi(argv[2]);
if( g_iChkStyle>0 ){
g_eDebug = 3;
}
}
CmdDebugService();
}
return g_iSignal;
}
+213
View File
@@ -0,0 +1,213 @@
#ifdef _WIN32
#include <windows.h>
#else
#include "typedef.h"
#include "commonstruct.h"
#include "ProCommon.h"
#include "ServerInner.h"
#include "Param.h"
#include "StoredProcedure.h"
#endif
#include "DBInterface.h"
#include "debug.h"
typedef DLLAPI int (*DB_INITDATABASES)(char* strHost, char* strUser, char* strPwd);
typedef DLLAPI int (*DB_RELEASE)();
DB_INITDATABASES f_DB_InitDatabases = NULL;
DB_RELEASE f_DB_Release = NULL;
PM_HANDLEPARAM f_PM_HandleParam = NULL;
DB_GETCLIENTVERSION f_DB_GetClientVersion = NULL;
DB_GETCLIENTTYPENUMBER f_DB_GetClientTypeNumber = NULL;
DB_GETPATH f_DB_GetPath = NULL;
DB_CLEANVIPLOG f_DB_CleanVipLog = NULL;
DB_PHONECHECK f_DB_PhoneCheck = NULL;
DB_REGISTER f_DB_Register = NULL;
DB_LOGIN f_DB_Login = NULL;
DB_LOGOFF f_DB_Logoff = NULL;
DB_GETSTYLEUPDATENUMBER f_DB_GetStyleUpdateNumber = NULL;
DB_GETCLIENTUPDATEFLAG f_DB_GetClientUpdateFlag = NULL;
DB_VERIFY f_DB_Verify = NULL;
DB_PURCHASE f_DB_Purchase = NULL;
DB_INSERTSTYLE f_DB_InsertStyle = NULL;
DB_GETSTYLEUPDATELIST f_DB_GetStyleUpdateList = NULL;
DB_CHECKSTYLEINFO f_DB_CheckStyleInfo = NULL;
DB_GETRECOMSTYLEIDS f_DB_GetRecomStyleIDs = NULL;
DB_CHECKUSERAUTHORITY f_DB_CheckUserAuthority = NULL;
DB_SETSTYLECHECK f_DB_SetStyleCheck = NULL;
DB_GETCOMMONQNA f_DB_GetCommonQnA = NULL;
DB_GETUSERQNA f_DB_GetUserQnA = NULL;
DB_SUBMITQUESTION f_DB_SubmitQuestion = NULL;
DB_GETNOTICE f_DB_GetNotice = NULL;
DB_INSERTSONG f_DB_InsertSong = NULL;
DB_GETSTYLEUPDATELISTNEW f_DB_GetStyleUpdateListNew = NULL;
DB_GETSHAREUPDATELIST f_DB_GetShareUpdateList = NULL;
DB_GETCHECKUPDATELIST f_DB_GetCheckUpdateList = NULL;
DB_GETSTYLEINFONEW f_DB_GetStyleInfoNew = NULL;
DB_UPDATESTYLE f_DB_UpdateStyle = NULL;
DB_CHECKPAYMENT f_DB_CheckPayment = NULL;
DB_CONFIRMPAYMENT f_DB_ConfirmPayment = NULL;
DB_STYLESCORE f_DB_StyleScore = NULL;
DB_INSERTSHARESTYLE f_DB_InsertShareStyle = NULL;
DB_GETWEBURL f_DB_GetWebURL = NULL;
#ifdef _WIN32
HINSTANCE g_hDBDll = NULL,
g_hPMDll = NULL;
#endif
bool LoadDB()
{
#ifdef _WIN32
g_hDBDll = LoadLibrary( DB_DLL );
if( g_hDBDll==NULL ){
DWORD dwRet = GetLastError();
DebugPrint( "载入数据库接口模块失败, 程序终止! errcode=%d", dwRet );
return FALSE;
}
//获取数据库函数入口
f_DB_InitDatabases = (DB_INITDATABASES)GetProcAddress( g_hDBDll, "DB_InitDatabases" );
f_DB_Release = (DB_RELEASE)GetProcAddress( g_hDBDll, "DB_Release" );
f_DB_GetPath = (DB_GETPATH)GetProcAddress( g_hDBDll, "DB_GetPath" );
f_DB_CleanVipLog = (DB_CLEANVIPLOG)GetProcAddress( g_hDBDll, "DB_CleanVipLog" );
f_DB_GetClientVersion = (DB_GETCLIENTVERSION)GetProcAddress( g_hDBDll, "DB_GetClientVersion" );
f_DB_GetClientTypeNumber = (DB_GETCLIENTTYPENUMBER)GetProcAddress( g_hDBDll, "DB_GetClientTypeNumber" );
f_DB_GetStyleUpdateNumber = (DB_GETSTYLEUPDATENUMBER)GetProcAddress( g_hDBDll, "DB_GetStyleUpdateNumber" );
f_DB_GetClientUpdateFlag = (DB_GETCLIENTUPDATEFLAG)GetProcAddress( g_hDBDll, "DB_GetClientUpdateFlag" );
f_DB_PhoneCheck = (DB_PHONECHECK)GetProcAddress( g_hDBDll, "DB_PhoneCheck" );
f_DB_Register = (DB_REGISTER)GetProcAddress( g_hDBDll, "DB_Register" );
f_DB_Login = (DB_LOGIN)GetProcAddress( g_hDBDll, "DB_Login" );
f_DB_Logoff = (DB_LOGOFF)GetProcAddress( g_hDBDll, "DB_Logoff" );
f_DB_Verify = (DB_VERIFY)GetProcAddress( g_hDBDll, "DB_Verify" );
f_DB_Purchase = (DB_PURCHASE)GetProcAddress( g_hDBDll, "DB_Purchase" );
f_DB_InsertStyle = (DB_INSERTSTYLE)GetProcAddress( g_hDBDll, "DB_InsertStyle" );
f_DB_GetStyleUpdateList = (DB_GETSTYLEUPDATELIST)GetProcAddress( g_hDBDll, "DB_GetStyleUpdateList" );
f_DB_CheckStyleInfo = (DB_CHECKSTYLEINFO)GetProcAddress( g_hDBDll, "DB_CheckStyleInfo" );
f_DB_GetRecomStyleIDs = (DB_GETRECOMSTYLEIDS)GetProcAddress( g_hDBDll, "DB_GetRecomStyleIDs" );
f_DB_CheckUserAuthority = (DB_CHECKUSERAUTHORITY)GetProcAddress( g_hDBDll, "DB_CheckUserAuthority" );
f_DB_SetStyleCheck = (DB_SETSTYLECHECK)GetProcAddress( g_hDBDll, "DB_SetStyleCheck" );
f_DB_GetCommonQnA = (DB_GETCOMMONQNA)GetProcAddress( g_hDBDll, "DB_GetCommonQnA" );
f_DB_GetUserQnA = (DB_GETUSERQNA)GetProcAddress( g_hDBDll, "DB_GetUserQnA" );
f_DB_GetNotice = (DB_GETNOTICE)GetProcAddress( g_hDBDll, "DB_GetNotice" );
f_DB_SubmitQuestion = (DB_SUBMITQUESTION)GetProcAddress( g_hDBDll, "DB_SubmitQuestion" );
f_DB_InsertSong = (DB_INSERTSONG)GetProcAddress( g_hDBDll, "DB_InsertSong" );
f_DB_GetStyleUpdateListNew = (DB_GETSTYLEUPDATELISTNEW)GetProcAddress( g_hDBDll, "DB_GetStyleUpdateListNew" );
f_DB_GetShareUpdateList = (DB_GETSHAREUPDATELIST)GetProcAddress( g_hDBDll, "DB_GetShareUpdateList" );
f_DB_GetCheckUpdateList = (DB_GETCHECKUPDATELIST)GetProcAddress( g_hDBDll, "DB_GetCheckUpdateList" );
f_DB_GetStyleInfoNew = (DB_GETSTYLEINFONEW)GetProcAddress( g_hDBDll, "DB_GetStyleInfoNew" );
f_DB_UpdateStyle = (DB_UPDATESTYLE)GetProcAddress( g_hDBDll, "DB_UpdateStyle" );
f_DB_CheckPayment = (DB_CHECKPAYMENT)GetProcAddress( g_hDBDll, "DB_CheckPayment" );
f_DB_ConfirmPayment = (DB_CONFIRMPAYMENT)GetProcAddress( g_hDBDll, "DB_ConfirmPayment" );
f_DB_StyleScore = (DB_STYLESCORE)GetProcAddress( g_hDBDll, "DB_StyleScore" );
f_DB_InsertShareStyle = (DB_INSERTSHARESTYLE)GetProcAddress( g_hDBDll, "DB_InsertShareStyle" );
f_DB_GetWebURL = (DB_GETWEBURL)GetProcAddress( g_hDBDll, "DB_GetWebURL" );
#else
f_DB_InitDatabases = (DB_INITDATABASES)DB_InitDatabases;
f_DB_Release = (DB_RELEASE)DB_Release;
f_DB_GetPath = (DB_GETPATH)DB_GetPath;
f_DB_CleanVipLog = (DB_CLEANVIPLOG)DB_CleanVipLog;
f_DB_GetClientVersion = (DB_GETCLIENTVERSION)DB_GetClientVersion;
f_DB_GetClientTypeNumber = (DB_GETCLIENTTYPENUMBER)DB_GetClientTypeNumber;
f_DB_GetStyleUpdateNumber = (DB_GETSTYLEUPDATENUMBER)DB_GetStyleUpdateNumber;
f_DB_GetClientUpdateFlag = (DB_GETCLIENTUPDATEFLAG)DB_GetClientUpdateFlag;
f_DB_PhoneCheck = (DB_PHONECHECK)DB_PhoneCheck;
f_DB_Register = (DB_REGISTER)DB_Register;
f_DB_Login = (DB_LOGIN)DB_Login;
f_DB_Logoff = (DB_LOGOFF)DB_Logoff;
f_DB_Verify = (DB_VERIFY)DB_Verify;
f_DB_Purchase = (DB_PURCHASE)DB_Purchase;
f_DB_InsertStyle = (DB_INSERTSTYLE)DB_InsertStyle;
f_DB_GetStyleUpdateList = (DB_GETSTYLEUPDATELIST)DB_GetStyleUpdateList;
f_DB_CheckStyleInfo = (DB_CHECKSTYLEINFO)DB_CheckStyleInfo;
f_DB_GetRecomStyleIDs = (DB_GETRECOMSTYLEIDS)DB_GetRecomStyleIDs;
f_DB_CheckUserAuthority = (DB_CHECKUSERAUTHORITY)DB_CheckUserAuthority;
f_DB_SetStyleCheck = (DB_SETSTYLECHECK)DB_SetStyleCheck;
f_DB_GetCommonQnA = (DB_GETCOMMONQNA)DB_GetCommonQnA;
f_DB_GetUserQnA = (DB_GETUSERQNA)DB_GetUserQnA;
f_DB_GetNotice = (DB_GETNOTICE)DB_GetNotice;
f_DB_SubmitQuestion = (DB_SUBMITQUESTION)DB_SubmitQuestion;
f_DB_InsertSong = (DB_INSERTSONG)DB_InsertSong;
f_DB_GetStyleUpdateListNew = (DB_GETSTYLEUPDATELISTNEW)DB_GetStyleUpdateListNew;
f_DB_GetShareUpdateList = (DB_GETSHAREUPDATELIST)DB_GetShareUpdateList;
f_DB_GetCheckUpdateList = (DB_GETCHECKUPDATELIST)DB_GetCheckUpdateList;
f_DB_GetStyleInfoNew = (DB_GETSTYLEINFONEW)DB_GetStyleInfoNew;
f_DB_UpdateStyle = (DB_UPDATESTYLE)DB_UpdateStyle;
f_DB_CheckPayment = (DB_CHECKPAYMENT)DB_CheckPayment;
f_DB_ConfirmPayment = (DB_CONFIRMPAYMENT)DB_ConfirmPayment;
f_DB_StyleScore = (DB_STYLESCORE)DB_StyleScore;
f_DB_InsertShareStyle = (DB_INSERTSHARESTYLE)DB_InsertShareStyle;
f_DB_GetWebURL = (DB_GETWEBURL)DB_GetWebURL;
#endif
if( !( f_DB_InitDatabases && f_DB_Release && f_DB_GetClientVersion && f_DB_GetClientTypeNumber &&
f_DB_GetStyleUpdateNumber && f_DB_GetClientUpdateFlag && f_DB_Login && f_DB_Verify &&
f_DB_Purchase && f_DB_GetPath && f_DB_InsertStyle && f_DB_GetStyleUpdateList &&
f_DB_CheckStyleInfo && f_DB_GetRecomStyleIDs && f_DB_CheckUserAuthority && f_DB_Register &&
f_DB_SetStyleCheck && f_DB_GetCommonQnA && f_DB_GetUserQnA && f_DB_SubmitQuestion &&
f_DB_GetNotice && f_DB_InsertSong && f_DB_GetStyleUpdateListNew && f_DB_GetStyleInfoNew &&
f_DB_UpdateStyle && f_DB_CheckPayment && f_DB_ConfirmPayment && f_DB_StyleScore &&
f_DB_InsertShareStyle && f_DB_GetShareUpdateList && f_DB_GetCheckUpdateList &&
f_DB_Logoff && f_DB_CleanVipLog && f_DB_PhoneCheck && f_DB_GetWebURL )){
DebugPrint( "获取数据库访问函数失败, 程序终止!" );
return FALSE;
}
#ifdef _DEBUG
// int ret = f_DB_InitDatabases("localhost", "root", "168soft.xyz");
// int ret = f_DB_InitDatabases("192.168.5.2", "root", "168soft.xyz");
// int ret = f_DB_InitDatabases("printer", "root", "");
// int ret = f_DB_InitDatabases("composemusic.xicp.net", "test", "123456");
int ret = f_DB_InitDatabases("localhost", "root", "168soft.xyz");
#else
int ret = f_DB_InitDatabases("localhost", "root", "168soft.xyz");
#endif
if( ret==-1 ){
DebugPrint( "初始化数据库失败, 程序终止!" );
return FALSE;
}
#ifdef _WIN32
//载入网参模块
g_hPMDll = LoadLibrary( PM_DLL );
if( g_hPMDll==NULL ){
DWORD dwRet = GetLastError();
DebugPrint( "载入网参模块失败,程序终止! errcode=%d", dwRet );
return FALSE;
}
//获取网参函数
f_PM_HandleParam = (PM_HandleParam)GetProcAddress( g_hPMDll, "PM_HandleParam" );
#else
f_PM_HandleParam = (PM_HANDLEPARAM)PM_HandleParam;
#endif
if( !f_PM_HandleParam ){
DebugPrint( "获取网参函数失败, 程序终止!" );
return FALSE;
}
return TRUE;
}
void FreeDB()
{
#ifdef _WIN32
if( g_hPMDll ){
FreeLibrary( g_hPMDll );
g_hPMDll = NULL;
}
if( g_hDBDll ){
f_DB_Release();
FreeLibrary( g_hDBDll );
g_hDBDll = NULL;
}
#endif
}
+544
View File
@@ -0,0 +1,544 @@
#ifndef DBInterfaceH
#define DBInterfaceH
#include "ProCommon.h"
#include "ServerInner.h"
#include <string>
#include <vector>
using namespace std;
#ifndef StoredProcedureH
typedef struct tClientVersion
{
TSOFTWAREINFO swInfo;
int iClientType;
char strFilePath[256];
tClientVersion(){
iClientType = 0;
memset(strFilePath, 0, sizeof(strFilePath));
}
} TCLIENTVERSION, *PTCLIENTVERSION;
typedef struct
{
int iClientType;
TVERSION version;
} TTESTVERSION, *PTTESTVERSION;
typedef struct tQnAItem{
UINT id;
int iClientType[8];
UINT state;
UINT idUser;
UINT dtUpdate;
char strQuestion[320];
char strAnswer[640];
tQnAItem(){
id = state = idUser = dtUpdate = 0;
memset( strQuestion, 0, 320 );
memset( strAnswer, 0, 640 );
memset( iClientType, -1, sizeof(int)*8 );
}
} TQNAITEM, *PTQNAITEM;
typedef vector<TQNAITEM*> TQNAITEMLIST;
typedef struct tNoticeItem{
UINT id;
UINT iType;
char strTitle[320];
char strContent[640];
tNoticeItem(){
id = iType = 0;
memset( strTitle, 0, 320 );
memset( strContent, 0, 640 );
}
} TNOTICEITEM, *PTNOTICEITEM;
typedef vector<TNOTICEITEM*> TNOTICEITEMLIST;
#endif
#ifdef _WIN32
#define DLLAPI __stdcall
#else //!_WIN32
#define DLLAPI
#endif
//Param function
typedef DLLAPI DWORD (*PM_HANDLEPARAM)( DWORD dwParam1, DWORD dwParam2 );
//Database storeprocedure
//---------------------------------------------------------获取目录-------------------------------------------------------------
//--函数名: DB_GetPath
//--功 能: 获取相关目录的绝对路径
//--输 入:
//-/chPathStyle: 调用时定义char[256]用于接收风格路径;
//-/chPathFile: 调用时定义char[256]用于接收web路径;
// chPathMusic: 调用时定义char[256]用于接收音乐路径;
//--返 回: 成功返回 0 失败 -1
//-----------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETPATH)(char *chPathStyle, char *chPathFile, char* chPathMusic);
//--函数名: DB_CleanVipLog
//--功 能: 清理VIP登录表
//--输 入:
//--返 回: 成功返回 0 失败 -1
//-----------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_CLEANVIPLOG)();
//-----------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_Register
//--功 能: 软件用户注册
//--输 入:
//-/user:用户名
//-/password:密码
// isEmailOrMobile 捆绑邮箱或手机号 1=邮箱 2=手机号
// idUser 用户ID
// 返回strNickName用户昵称
// iClientType 客户端类型
//--返 回: 成功返回0;用户名已存在返回1;函数调用失败返回 -1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_REGISTER)(char *user, char *password, int isEmailOrMobile, int& idUser, char* strNickName, int iClinetType);
//-----------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_PhoneCheck
//--功 能: 短信验证
//--输 入:
// idDevice: 设备号
// strPhone: 手机号
// strCode: 验证码
//--返 回: 成功返回0;验证失败返回1;函数调用失败返回 -1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_PHONECHECK)( char* idDevice, char* strPhone, char* strCode );
//-------------------------------------------------------------登陆-----------------------------------------------------------------
//--函数名: Prc_user_checkLogin
//--功 能: 登陆验证
//--输 入:
//--user:用户名
//--password:密码
// idDevice: 设备号
//--chUserMsg:外部定义char[256] 用于接收帐户信息,以"|"分隔,如"3|sadwjf222|8308.44|100|1"
// strNickName:用户昵称
// strIconFile:用户头像文件名
// iClientType 客户端类型
//--返 回: 成功返回0;密码错误返回1;帐号不存在返回2;函数调用失败返回 -1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_LOGIN)(char *user, char *password, char *idDevice, TACCOUNTINFO *stUserMsg,
char* strNickName, char* strIconFile, int iClinetType);
//-----------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_Logoff
//--功 能: 用户注销
//--输 入:
//-/idUser:用户号
// idDevice: 设备号
//--返 回: 成功返回0
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_LOGOFF)( int idUser, char *idDevice );
//------------------------------------检查更新-----------------------------------------------------------------
//--函数名: DB_GetClientUpdateFlag
//--功 能: 检查版本更新
//--输 入:
// iClientType: 客户端类型
// clientVersion: 客户端版本信息;
// idDevice: 设备号
//--返 回:
//--如果是最新版本,返回0;;
//--如果有更新但不是强制更新,返回1;
//--如果强制更新,返回2;
//--非法版本,返回3
//--调用失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETCLIENTUPDATEFLAG)(int iClientType, TVERSION* clientVersion, char *idDevice);
//-------------------------------------------------------版本类型个数-----------------------------------------------------------
//--函数名: getClientTypeNum
//--功 能: 获取版本类型个数
//--输 入:
//--返 回:
//--①成功返回版本类型个数 N >= 1
//--②失败 -1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETCLIENTTYPENUMBER)();
//-------------------------------------------------------版本类型信息-----------------------------------------------------------
//--函数名: getClientVersion
//--功 能: 获取多个版本类型的信息
//--输 入:
//--aVersion
//--nArraySize:个数
//--返 回:
//--①成功返回0
//--②失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETCLIENTVERSION)(TCLIENTVERSION aVersion[], int nArraySize);
//
//-------------------------------------------------------------更新风格数目-----------------------------------------------------------------
//--函数名: DB_GetStyleUpdateNumber
//--功 能: 获取风格更新数目
//--输 入:
//--chCltTime: Client上次更新时间点(YEAR<<16)+(MON<<8)+DAY)
//--UpdataNum:调用时定义 int 变量 用于接收检测到的更新总数
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETSTYLEUPDATENUMBER)(int tCltTime, int *UpdataNum);
//---------------------------------------------------------保存鉴权-------------------------------------------------------------
//--函数名: Prc_user_verify
//--功 能: 保存鉴权,显示用到的风格列表,以及实际价格和VIP价格,如果余额充足,支付完成后可保存,如果余额不足,则提示,并引导冲值的方式
//--输 入:
//--dwStyleID:风格ID数组
//--nStyleID :风格个数
//--dStyleOriginPrice: 定义double[ nStyleID ]数组接收每个个风格的实际价格
//--StyleCurrentPrice:定义double[ nStyleID ]数组接收每个个风格的应付价格
//--dBalance 定义double变量接收余额
//--返 回:
//--①如果余额充足(通过本次鉴权)返回 0;
//--②如果余额不足(未通过鉴权)返回 1;
//--③如果调用失败返回-1
// userID无效(未通过鉴权)返回2
// styleID无效(未通过鉴权)返回3,同时在相应的styleoriginprice填写-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_VERIFY)( int nUserID,
int dwStyleID[],
int nStyleID,
int aStyleOriginCost[],
int aStyleCurrentCost[],
int *nBalance);
//---------------------------------------------------------支 付-------------------------------------------------------------
//--函数名: Prc_user_purchase
//--功 能: 支付
//--输 入:
//--userID:用户号
//--dwStyleID:风格ID数组
//--nStyleID :风格个数
//--nBalance:调用时定义int变量用于接收帐户余额
//iapType: 支付方式 0=个人账户支付,1=中移动iap
//--返 回:
//--①(余额充足)购买成功返回0;
//--②(余额不足)购买失败返回1;
//--③调用失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (* DB_PURCHASE)(int nUserID, int dwStyleID[],int nStyleID, int *nBalance, int iapType);
//--------------------------------------------------------新增风格数据--------------------------------------------------------------
//--函数名: DB_InsertStyle
//--功 能: 新增风格数据
//--输 入:
// iType 新增类型,0=待审核,1=发布
// pStyleInfo 风格信息
//--返回:成功返回风格ID,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_INSERTSTYLE)( int iType, TMAKESTYLEINFO* pStyleInfo ); //新增风格数据
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_InsertShareStyle
//--功 能: 新增分享风格数据
//--输 入:
// pInfo 风格信息
//--返回:成功返回风格ID,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_INSERTSHARESTYLE)( TSTYLESHARE* pInfo ); //新增分享风格信息
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetStyleUpdataList
//--功 能: 获取风格更新数目
//--输 入:
//iClientType: 客户端类型,<3为伴奏魔方,4=Checker
//tUpdateTime: 更新时间点,如"2012-02-01" (高16位表示年 接下来饿8位表示月 低8位表示日),返回最新更新时间
//UpdataNum:调用时定义 int 变量 用于接收检测到的更新总数
//aUpdate:返回的列表数据,外部分配,外部释放
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETSTYLEUPDATELIST)(int iClientType, int* tUpdateTime, int *UpdataNum, TSTYLEUPDATE0 aUpdate[] );
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetStyleUpdateListNew
//--功 能: 获取风格更新数目新接口
//--输 入:
//tUpdateTime: 更新时间点,如"2012-02-01" (高16位表示年 接下来饿8位表示月 低8位表示日),返回最新更新时间
//UpdataNum:调用时定义 int 变量 用于接收检测到的更新总数
//aUpdate:返回的列表数据,外部分配,外部释放
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETSTYLEUPDATELISTNEW)(int* tUpdateTime, int *UpdataNum, TSTYLEUPDATE aUpdate[] );
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetShareUpdataList
//--功 能: 获取分享风格更新数目
//--输 入:
//tUpdateDate: 更新时间点,如"2012-02-01" (高16位表示年 接下来饿8位表示月 低8位表示日),返回最新更新时间
//UpdataNum:调用时定义 int 变量 用于接收检测到的更新总数
//aUpdate: 返回的列表数据,内部分配,外部释放
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETSHAREUPDATELIST)(int* tUpdateDate, int *nListSize, TSHAREUPDATE aUpdate[] );
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetCheckUpdataList
//--功 能: 获取分享风格更新数目
//--输 入:
//tUpdateDate: 更新时间点,如"2012-02-01" (高16位表示年 接下来饿8位表示月 低8位表示日),返回最新更新时间
//UpdataNum:调用时定义 int 变量 用于接收检测到的更新总数
//aUpdate: 返回的列表数据,内部分配,外部释放
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETCHECKUPDATELIST)(int* tUpdateDate, int *nListSize, TCHECKUPDATE aUpdate[] );
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_CheckStyleInfo
//--功 能: 确认风格信息有效性
//--输 入:
//iType: 风格类型 1=发布风格 2=临时风格 3=共享风格
//idStyle: 风格ID
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_CHECKSTYLEINFO)( int iType, int idStyle );
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetStyleInfoNew
//--功 能: 获取风格信息
//--输 入:
//iClientType: 客户端类型,<3为伴奏魔方,4=Checker
//idStyle: 风格ID
//pInfo:返回风格信息
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETSTYLEINFONEW)(int iClientType, int idStyle, TSTYLEDETAIL* pInfo );
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetRecomStyleIDs
//--功 能: 获取推荐风格ID列表
//--输 入:
//idCount:调用时定义 int 变量 用于接收检测到的id总数
//lstID:返回的列表数据,外部分配,外部释放
//--返 回: 成功返回0; 失败返回-1;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (* DB_GETRECOMSTYLEIDS)( int* idCount, int lstID[] );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_CheckUserAuthority
//--功 能: 获取用户权限
//--输 入:
//idUser:用户ID
//anthority:查询权限
//--返 回: 无权限返回0; 失败返回-1;有权限返回非零值
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_CHECKUSERAUTHORITY)( int idUser, int authority );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_SetStyleCheck
//--功 能: 设置风格审核结果
//--输 入:
// idChecker: 审核者ID
// idStyle: 临时风格ID
// score: 评分 0=未通过
// strMsg: 审核信息,审核通过时忽略
//--返 回: 成功返回发布风格ID,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_SETSTYLECHECK)( int idUser, int idStyle, int score, char* strMsg );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetCommonQnA
//--功 能: 查询常见问题
//--输 入:
// dtUpdate 最后更新时间
// listSize 输入问题个数
// listQA 返回问题数组
//--返 回: 成功返回问题个数,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETCOMMONQNA)( int dtUpdate, int nListSize, TQNAITEM listQA[] );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetUserQnA
//--功 能: 查询用户提问
//--输 入:
// idNum 待查询ID个数
// idList 待查询ID
// idUser 用户ID
// iClientType 客户端类型
// dtUpdate 更新时间
// listSize 输入listQA大小
// listQA 返回问题列表
//--返 回: 成功返回问题个数,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETUSERQNA)( int idNum, int idList[], int idUser, int iClientType, int dtUpdate,
int nListSize, TQNAITEM listQA[] );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_SubmitQuestion
//--功 能: 提交问题
//--输 入:
// idUser: 提交者ID
// iClientType: 客户端类型
// strMsg: 提交信息
// strVersion: 客户端版本
//--返 回: 成功返回问题ID,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_SUBMITQUESTION)( int idUser, int iClientType, char* strMsg, char* strVersion );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetNotice
//--功 能: 查询系统公告或用户通知
//--输 入:
// listSize 输入通知个数
// listNotece 返回通知数组
// idUser 查询用户号
//--返 回: 成功返回公告个数,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETNOTICE)( int nListSize, TNOTICEITEM listNotice[], UINT idUser );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_InsertSong
//--功 能: 新增上传歌曲
//--输 入:
//--idUser 用户号
// iClientType 客户端类型
//--pSongInfo 歌曲信息
//--nSongSize 歌曲文件大小
//--path 歌曲文件路径
//--strCover 缺省封面
//--location 文件存放盘符,空不填写
//--返回:成功返回歌曲ID,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_INSERTSONG)(int idUser, int iClientType, TSONGINFO0* pSongInfo, int nSongSize,
char* path, char* strCover, char* location );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_UpdateStyle
//--功 能: 修改风格数据
//--输 入: idStyle 风格ID
//--pStyleInfo 风格信息
//--返回:成功返回风格ID,失败返回-1
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_UPDATESTYLE)( UINT idStyle, TMAKESTYLEINFO* pStyleInfo );
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_CheckPayment
//--功 能: 检查支付
//--输 入:
//idUser:用户号
//iOperation: 操作号 0=使用 1=编辑
//dwStyleID:风格ID数组
//nStyleCount :风格个数
//pCost: 接收积分消耗
//pBalance 接收用户积分余额
//pFee: 接收功能费
//--返 回:
//--①如果余额充足(可以完成本次购买)返回 0;
//--②如果余额不足(不能完成本次购买)返回 1;
//--③如果调用失败返回-1
//--④如果用户无效,返回2
//--⑤如果有不存在的风格,返回3;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_CHECKPAYMENT)(int iClientType, UINT idUser, int iOperation, int nStyleCount, UINT dwStyleID[], int* pCost, int *pBalance, int *pFee);
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_ConfirmPayment
//--功 能: 确认支付
//--输 入:
// iClientType 客户端类型
//idUser:用户号
//iOperation: 操作号 0=使用 1=编辑
//nStyleCount :风格个数
//dwStyleID:风格ID数组
//nPaidCount :已支付风格个数
//dwPaidID:已支付风格ID数组
//pBalance 接收用户积分余额
//--返 回:
//--①如果余额充足(可以完成本次购买)返回 0;
//--②如果余额不足(不能完成本次购买)返回 1;
//--③如果调用失败返回-1
//--④如果用户无效,返回2
//--⑤如果有不存在的风格,返回3;
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_CONFIRMPAYMENT)(int iClientType, UINT idUser, int iOperation, int nStyleCount, UINT dwStyleID[],
int nPaidCount, UINT dwPaidID[], int *pBalance);
//------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_StyleScore
//--功 能: 风格评分
//--输 入:
// iType 风格类型 1=发布风格 2=临时风格 3=共享风格
// idStyle:风格ID
// pScore:风格当前评分
// bGet:获取/设置
//--返 回: 错误号
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_STYLESCORE)( int iType, UINT idStyle, int *pScore, bool bGet);
//------------------------------------------------------------------------------------------------------------------------------
//--函数名: DB_GetWebURL
//--功 能: 获取网络地址
//--输 入:
//-/iPage: 请求页面编号
// strURL: 接收网络地址
//--返 回: 成功返回0
//------------------------------------------------------------------------------------------------------------------------------
typedef DLLAPI int (*DB_GETWEBURL)( int iPage, char *strURL );
extern PM_HANDLEPARAM f_PM_HandleParam;
extern DB_GETCLIENTVERSION f_DB_GetClientVersion;
extern DB_GETCLIENTTYPENUMBER f_DB_GetClientTypeNumber;
extern DB_GETPATH f_DB_GetPath;
extern DB_CLEANVIPLOG f_DB_CleanVipLog;
extern DB_GETSTYLEUPDATENUMBER f_DB_GetStyleUpdateNumber;
extern DB_GETCLIENTUPDATEFLAG f_DB_GetClientUpdateFlag;
extern DB_PHONECHECK f_DB_PhoneCheck;
extern DB_REGISTER f_DB_Register;
extern DB_LOGIN f_DB_Login;
extern DB_LOGOFF f_DB_Logoff;
extern DB_VERIFY f_DB_Verify;
extern DB_PURCHASE f_DB_Purchase;
extern DB_INSERTSTYLE f_DB_InsertStyle;
extern DB_GETSTYLEUPDATELIST f_DB_GetStyleUpdateList;
extern DB_CHECKSTYLEINFO f_DB_CheckStyleInfo;
extern DB_GETRECOMSTYLEIDS f_DB_GetRecomStyleIDs;
extern DB_CHECKUSERAUTHORITY f_DB_CheckUserAuthority;
extern DB_SETSTYLECHECK f_DB_SetStyleCheck;
extern DB_GETCOMMONQNA f_DB_GetCommonQnA;
extern DB_GETUSERQNA f_DB_GetUserQnA;
extern DB_SUBMITQUESTION f_DB_SubmitQuestion;
extern DB_GETNOTICE f_DB_GetNotice;
extern DB_INSERTSONG f_DB_InsertSong;
extern DB_GETSTYLEUPDATELISTNEW f_DB_GetStyleUpdateListNew;
extern DB_GETSHAREUPDATELIST f_DB_GetShareUpdateList;
extern DB_GETCHECKUPDATELIST f_DB_GetCheckUpdateList;
extern DB_GETSTYLEINFONEW f_DB_GetStyleInfoNew;
extern DB_UPDATESTYLE f_DB_UpdateStyle;
extern DB_CHECKPAYMENT f_DB_CheckPayment;
extern DB_CONFIRMPAYMENT f_DB_ConfirmPayment;
extern DB_STYLESCORE f_DB_StyleScore;
extern DB_INSERTSHARESTYLE f_DB_InsertShareStyle;
extern DB_GETWEBURL f_DB_GetWebURL;
#define DB_DLL "StoredProcedure.dll"
#define PM_DLL "params.dll"
bool LoadDB();
void FreeDB();
#endif
+466
View File
@@ -0,0 +1,466 @@
/*******************************************************************************
*
* 模 块 名:DBService 文件名:DBService.c
* 相关文件:DBService.h
* 提交日期:2012.2.1 作 者:Alex
* 版 本:0.1
* 模块描述:
* 本模块提供了Service程序的框架
* main(int argc, char **argv);
* service_ctrl(DWORD dwCtrlCode);
* service_main(DWORD dwArgc, LPTSTR *lpszArgv);
* CmdInstallService();
* CmdRemoveService();
* CmdDebugService(int argc, char **argv);
* ControlHandler ( DWORD dwCtrlType );
* GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
* 修改记录:
* 日 期 版本 修改人 修改内容
*
*
*******************************************************************************/
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>
#define _DBSERVICE_C
#include "DBService.h"
#undef _DBSERVICE_C
// internal variables
SERVICE_STATUS ssStatus; // current status of the service
SERVICE_STATUS_HANDLE sshStatusHandle;
DWORD dwErr = 0;
TCHAR szErr[256];
char SZDEPENDENCIES[10] = "";
// internal function prototypes
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
VOID CmdInstallService();
VOID CmdRemoveService();
VOID CmdDebugService(int argc, char **argv);
BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
// main() either performs the command line task, or
// call StartServiceCtrlDispatcher to register the
// main service thread. When the this call returns,
// the service has stopped, so exit.
//
//void _CRTAPI1 main(int argc, char **argv)
int __cdecl _tmain(int argc, TCHAR *argv[])
{
SERVICE_TABLE_ENTRY dispatchTable[] = {
{ TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
if ( (argc > 1) &&((*argv[1] == '-') || (*argv[1] == '/')) ){
int cmd = 0;
if ( _stricmp( "install", argv[1]+1 ) == 0 ){
if( argc>2 ){
strcpy( SZDEPENDENCIES, argv[2] );
}
cmd = 1;
}
else if ( _stricmp( "remove", argv[1]+1 ) == 0 ){
cmd = 2;
}
else if ( _stricmp( "debug", argv[1]+1 ) == 0 ){
g_eDebug = 4;
if( argc>2 ){
if ( _stricmp( "f", argv[2] ) == 0 ){
g_eDebug = 1;
}
else if ( _stricmp( "n", argv[2] ) == 0 ){
g_eDebug = 2;
}
else if ( _stricmp( "s", argv[2] ) == 0 ){
g_eDebug = 3;
}
}
cmd = 3;
}
else if( _stricmp( "check", argv[1]+1 ) == 0 && argc>2 ){
g_iChkStyle = atoi(argv[2]);
if( g_iChkStyle>0 ){
g_eDebug = 3;
cmd = 3;
}
}
if( cmd==1 ){
CmdInstallService();
}
else if( cmd==2 ){
CmdRemoveService();
}
else if( cmd==3 ){
CmdDebugService(argc, argv);
}
else{
// this is just to be friendly
printf( "%s -install <params> to install the service\n", SZAPPNAME );
printf( "%s -remove to remove the service\n", SZAPPNAME );
printf( "%s -debug <params> to run as a console app for debugging\n", SZAPPNAME );
printf( "%s -check <index> to run as a console app for check style\n", SZAPPNAME );
printf( "\nStartServiceCtrlDispatcher being called.\n" );
printf( "This may take several seconds. Please wait.\n" );
}
return 0;
}
// if it doesn't match any of the above parameters
// the service control manager may be starting the service
// so we must call StartServiceCtrlDispatcher
if (!StartServiceCtrlDispatcher(dispatchTable))
AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
return 0;
}
// This routine performs the service initialization and then calls
// the user defined ServiceStart() routine to perform majority
// of the work.
//
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
// register our service control handler:
sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);
if (!sshStatusHandle)
goto cleanup;
// SERVICE_STATUS members that don't change in example
ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode = 0;
// report the status to the service control manager.
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
goto cleanup;
ServiceStart( dwArgc, lpszArgv );
cleanup:
// try to report the stopped status to the service control manager.
if (sshStatusHandle)
(VOID)ReportStatusToSCMgr(
SERVICE_STOPPED,
dwErr,
0);
printf( "%s stopped the service\n", SZAPPNAME );
// getchar();
return;
}
//This function is called by the SCM whenever
//ControlService() is called on this service.
VOID WINAPI service_ctrl(DWORD dwCtrlCode)
{
// Handle the requested control code.
//
switch(dwCtrlCode){
// Stop the service.
// SERVICE_STOP_PENDING should be reported before
// setting the Stop Event - hServerStopEvent - in
// ServiceStop(). This avoids a race condition
// which may result in a 1053 - The Service did not respond...
// error.
case SERVICE_CONTROL_STOP:
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
ServiceStop();
return;
// Update the service status.
case SERVICE_CONTROL_INTERROGATE:
break;
// invalid control code
default:
break;
}
ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
}
//Sets the current status of the service and
//reports it to the Service Control Manager
BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
BOOL fResult = TRUE;
if( g_eDebug==0 ){
if (dwCurrentState == SERVICE_START_PENDING)
ssStatus.dwControlsAccepted = 0;
else
ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
ssStatus.dwCurrentState = dwCurrentState;
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
ssStatus.dwWaitHint = dwWaitHint;
if ( ( dwCurrentState == SERVICE_RUNNING ) ||
( dwCurrentState == SERVICE_STOPPED ) )
ssStatus.dwCheckPoint = 0;
else
ssStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the service control manager.
//
if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))){
AddToMessageLog(TEXT("SetServiceStatus"));
}
}
return fResult;
}
//Allows any thread to log an error message
VOID AddToMessageLog(LPTSTR lpszMsg)
{
TCHAR szMsg[256];
HANDLE hEventSource;
LPCTSTR lpszStrings[2];
// if ( g_eDebug<0 ){
dwErr = GetLastError();
// Use event logging to log the error.
//
hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
_stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
lpszStrings[0] = szMsg;
lpszStrings[1] = lpszMsg;
if (hEventSource != NULL) {
ReportEvent(hEventSource, // handle of event source
EVENTLOG_ERROR_TYPE, // event type
0, // event category
0, // event ID
NULL, // current user's SID
2, // strings in lpszStrings
0, // no bytes of raw data
lpszStrings, // array of error strings
NULL); // no raw data
(VOID) DeregisterEventSource(hEventSource);
}
// }
}
//Installs the service
void CmdInstallService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
TCHAR szPath[512];
DWORD dwBytesNeeded;
if ( GetModuleFileName( NULL, szPath, 512 ) == 0 ){
_tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
return;
}
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager ){
schService = CreateService(
schSCManager, // SCManager database
TEXT(SZSERVICENAME), // name of service
TEXT(SZSERVICEDISPLAYNAME), // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
TEXT(SZDEPENDENCIES), // dependencies
NULL, // LocalSystem account
NULL); // no password
if ( schService ){
_tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
if( !StartService(schService, 0, NULL) ){
printf("StartService failed (%d)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // info level
(LPBYTE) &ssStatus, // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) ) // if buffer too small
{
return;
}
CloseServiceHandle(schService);
}
else{
_tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
}
CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
}
// PURPOSE: Stops and removes the service
void CmdRemoveService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager ){
schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);
if (schService){
// try to stop the service
if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ){
_tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
Sleep( 1000 );
while( QueryServiceStatus( schService, &ssStatus ) ){
if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ){
_tprintf(TEXT("."));
Sleep( 1000 );
}
else
break;
}
if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
_tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );
}
// now remove the service
if( DeleteService(schService) )
_tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
CloseServiceHandle(schService);
}
else
_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
}
//Runs the service as a console application
void CmdDebugService(int argc, char ** argv)
{
DWORD dwArgc;
LPTSTR *lpszArgv;
#ifdef UNICODE
lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
#else
dwArgc = (DWORD) argc;
lpszArgv = argv;
#endif
_tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
_tprintf(TEXT("Press Ctl+C to stop %s...\n"), TEXT(SZSERVICEDISPLAYNAME));
SetConsoleCtrlHandler( ControlHandler, TRUE );
ServiceStart( dwArgc, lpszArgv );
}
//Handled console control events
BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
{
switch( dwCtrlType ){
case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
_tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
ServiceStop();
return TRUE;
break;
}
return FALSE;
}
//copies error message text to string
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
{
DWORD dwRet;
LPTSTR lpszTemp = NULL;
dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
NULL );
// supplied buffer is not long enough
if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
lpszBuf[0] = TEXT('\0');
else{
lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character
_stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
}
if ( lpszTemp )
LocalFree((HLOCAL) lpszTemp );
return lpszBuf;
}
#endif
+50
View File
@@ -0,0 +1,50 @@
/*******************************************************************************
*
* 模 块 名:DBService 文件名:DBService.h
* 相关文件:DBService.c
* 提交日期:2012.2.1 作 者:Alex
* 版 本:0.1
* 修改记录:
* 日 期 版本 修改人 修改内容
*
*
*******************************************************************************/
#ifndef DBServiceH
#define DBServiceH
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _DBSERVICE_C
int g_eDebug = 0;
int g_iChkStyle = 0;
#else
extern int g_eDebug;
extern int g_iChkStyle;
#endif
#define SZAPPNAME "DBService"
#define SZSERVICENAME "DBService"
#define SZSERVICEDISPLAYNAME "DBService"
#define SZSTOPEVENTNAME "DBService"
//user-defined ServiceStart and ServiceStop
VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
VOID ServiceStop();
//Sets the current status of the service and
//reports it to the Service Control Manager
BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
//Allows any thread to log an error message
void AddToMessageLog(LPTSTR lpszMsg);
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
#ifdef __cplusplus
}
#endif
#endif
+236
View File
@@ -0,0 +1,236 @@
// DataReceiver.cpp: implementation of the CDataReceiver class.
//
//////////////////////////////////////////////////////////////////////
//#include <windows.h>
#include <stdlib.h>
#include "debug.h"
#include "DataBuffers.h"
#include "MessageDef.h"
#define MAX_BUFFER_NUM 500
//////////////////////////////////////////////////////////////////////
// CDataReceiver
//////////////////////////////////////////////////////////////////////
CDataBufferManager::CDataBufferManager()
:m_smProcess("mDBMProcess",1)
{
m_seqFileNo = 1;
}
CDataBufferManager::~CDataBufferManager()
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstBuffers.size()>0 ){
DATABUFFERLIST::iterator iter = m_lstBuffers.begin();
while( iter!=m_lstBuffers.end() ){
delete *iter;
iter++;
}
m_lstBuffers.clear();
}
}
int CDataBufferManager::NewDataBuffer( int idUser, int iType, int nDataSize, char* pData, int iClientType )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstBuffers.size()>0 ){
DATABUFFERLIST::iterator iter = m_lstBuffers.begin();
while( iter!=m_lstBuffers.end() ){
DATABUFFER *pBuffer = (*iter);
if( pBuffer->iDataType==iType && pBuffer->idUser==idUser && pBuffer->iClientType==iClientType && pBuffer->nDataSize==nDataSize){
pBuffer->idPack = pBuffer->nRecvSize = pBuffer->tSeconds = 0;
// DebugPrint("repeat buffer %d (type: %d)", pBuffer->idBuffer, iType);
return -pBuffer->idBuffer;
}
iter++;
}
}
if( m_lstBuffers.size()>MAX_BUFFER_NUM ){
DebugPrint("buffer full!!!");
return ERR_BUFFER_NUM;
}
//分配文件号
int idFile = m_seqFileNo++;
if( m_seqFileNo>MAX_BUFFER_ID ) m_seqFileNo = 1;
//创建DataBuffer
DATABUFFER * pBuffer = new DATABUFFER;
pBuffer->idUser = idUser;
pBuffer->idBuffer = idFile;
pBuffer->iDataType = iType;
pBuffer->nDataSize = nDataSize;
pBuffer->iClientType = iClientType;
pBuffer->idPack = pBuffer->nRecvSize = pBuffer->tSeconds = 0;
if( pData ){
pBuffer->pData = pData;
}
else{
pBuffer->pData = new char[nDataSize];
}
m_lstBuffers.push_back( pBuffer );
return idFile;
}
int CDataBufferManager::ReceiveData( int idBuffer, int idPack, int nSize, char* pNewData )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstBuffers.size()>0 ){
DATABUFFERLIST::iterator iter = m_lstBuffers.begin();
while( iter!=m_lstBuffers.end() ){
if( (*iter)->idBuffer==idBuffer ){
int ret = 0;
PDATABUFFER pBuffer = *iter;
pBuffer->tSeconds = 0;
if( idPack > pBuffer->idPack ){
ret = ERR_PACK_ID;
}
else if( idPack==pBuffer->idPack ){
if( nSize > pBuffer->nDataSize - pBuffer->nRecvSize ){
ret = ERR_DATA_SIZE;
}
else{
memcpy( pBuffer->pData + pBuffer->nRecvSize, pNewData, nSize );
pBuffer->nRecvSize += nSize;
pBuffer->idPack++;
if( pBuffer->nRecvSize==pBuffer->nDataSize ){
ret = ERR_DATA_END;
/* ret = SaveFile( pBuffer );
delete[] pBuffer->pData;
delete pBuffer;
m_lstBuffers.erase( iter );
*/
}
}
}
return ret;
}
iter++;
}
}
return ERR_DATA_ID;
}
int CDataBufferManager::GetData( int idBuffer, int idPack, int& nSize, char*& pData )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstBuffers.size()>0 ){
DATABUFFERLIST::iterator iter = m_lstBuffers.begin();
while( iter!=m_lstBuffers.end() ){
if( (*iter)->idBuffer==idBuffer ){
int ret = 0;
PDATABUFFER pBuffer = *iter;
pBuffer->tSeconds = 0;
if( idPack > pBuffer->idPack || idPack*MAX_PACK_SIZE > pBuffer->nDataSize ){
ret = ERR_PACK_ID;
}
else if( idPack==pBuffer->idPack || idPack==pBuffer->idPack-1 ){
if( (idPack+1)*MAX_PACK_SIZE<=pBuffer->nDataSize ){
nSize = MAX_PACK_SIZE;
}
else{
nSize = pBuffer->nDataSize % MAX_PACK_SIZE;
}
pData = pBuffer->pData + idPack*MAX_PACK_SIZE;
if( idPack==pBuffer->idPack )
pBuffer->idPack++;
}
else if( idPack==-1 ){ //客户端接收完成,删除数据
// DebugPrint( "delete buffer %d due to complete", (*iter)->idBuffer );
delete pBuffer;
m_lstBuffers.erase( iter );
}
return ret;
}
iter++;
}
}
return ERR_DATA_ID;
}
DATABUFFER * CDataBufferManager::GetBuffer( int idBuffer )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstBuffers.size()>0 ){
DATABUFFERLIST::iterator iter = m_lstBuffers.begin();
while( iter!=m_lstBuffers.end() ){
if( (*iter)->idBuffer==idBuffer ){
return *iter;
}
iter++;
}
}
return NULL;
}
void CDataBufferManager::DeleteBuffer( int idBuffer )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstBuffers.size()>0 ){
DATABUFFERLIST::iterator iter = m_lstBuffers.begin();
while( iter!=m_lstBuffers.end() ){
if( (*iter)->idBuffer==idBuffer ){
//DebugPrint( "delete buffer %d due to complete", (*iter)->idBuffer );
delete *iter;
iter = m_lstBuffers.erase( iter );
break;
}
else{
iter++;
}
}
}
}
void CDataBufferManager::OnTimer()
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstBuffers.size()>0 ){
DATABUFFERLIST::iterator iter = m_lstBuffers.begin();
while( iter!=m_lstBuffers.end() ){
if( (*iter)->tSeconds>=30 ){ //超过半分钟无数据操作
// DebugPrint( "delete buffer %d due to timeout (type: %d)", (*iter)->idBuffer, (*iter)->iDataType );
delete *iter;
iter = m_lstBuffers.erase( iter );
}
else{
(*iter)->tSeconds++;
iter++;
}
}
}
}
+77
View File
@@ -0,0 +1,77 @@
// DataReceiver.h: interface for the CDataReceiver class.
//
//////////////////////////////////////////////////////////////////////
#ifndef DataBuffersH
#define DataBuffersH
#include <string.h>
#include "thread.h"
#define ERR_DATA_END 1
#define ERR_DATA_ID -1
#define ERR_PACK_ID -2
#define ERR_DATA_SIZE -3
#define ERR_BUFFER_NUM -4
#define DTYPE_STYLETEMP 0
#define DTYPE_STYLEFILE 1
#define DTYPE_STYLESTATE 2
#define DTYPE_STYLEDATA 3
#define DTYPE_QAUPDATE 4
#define DTYPE_SONGFILE 5
#define DTYPE_NTUPDATE 6
#define DTYPE_STYLESHARE 7
#define DTYPE_STYLEINFO 8
#define DTYPE_ICONFILE 9
#define MAX_BUFFER_ID 0x7FFFFFF
typedef struct tagDataBuffer
{
int idBuffer;
int idUser;
int idPack;
int iClientType;
int iDataType;
int nDataSize;
int nRecvSize;
int tSeconds;
char* pData;
tagDataBuffer(){
memset( this, 0, sizeof(tagDataBuffer) );
}
~tagDataBuffer(){
if( pData ){
delete[] pData;
pData = NULL;
}
}
} DATABUFFER, *PDATABUFFER;
#include <list>
using namespace std;
typedef list< PDATABUFFER > DATABUFFERLIST;
class CDataBufferManager
{
public:
CDataBufferManager();
virtual ~CDataBufferManager();
int NewDataBuffer( int idUser, int iType, int nDataSize, char* pData=NULL, int iClientType=0 );
int ReceiveData( int idBuffer, int idPack, int nSize, char* pNewData );
int GetData( int idBuffer, int idPack, int& nSize, char*& pData);
DATABUFFER * GetBuffer( int idBuffer );
void DeleteBuffer( int idBuffer );
void OnTimer();
private:
CSema m_smProcess;
int m_seqFileNo;
DATABUFFERLIST m_lstBuffers;
};
#endif // !defined(_DATARECEIVER_H_INCLUDED_)
+383
View File
@@ -0,0 +1,383 @@
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/epoll.h>
#include<poll.h>
#include<sys/timerfd.h>
#include<map>
#include "Socket.h"
#include "debug.h"
#include "MessageHandle.h"
#include "EpollThread.h"
#define TIMER_INTERVAL 5
#define TIMER_EXPIRE 60
////////////////////////////////////////////////////////////////////////////////
//HandlerThread
EpollHandler::HandlerThread::HandlerThread(EpollHandler* pHandler, CSema* pSema)
: CThread(3000)
{
m_pHandler = pHandler;
m_pSema = pSema;
}
void EpollHandler::HandlerThread::Main()
{
while(!m_bExit){
RECVBUFF* pRB = m_pHandler->GetBuff();
if(pRB){
// send(pRB->socket, pRB->buffer, pRB->buffsize, 0);
TNETMESSAGE msgRequest;
if( !m_bExit && ReadNetMessage( (unsigned char*)pRB->buffer, pRB->buffsize, &msgRequest )){
TNETMESSAGE msgResponse;
struct sockaddr_in peerAddr;
UINT peerLen = sizeof(peerAddr);
if( getpeername(pRB->socket, (struct sockaddr *)&peerAddr, &peerLen)<0 ){
DebugPrint("getpeername error: %d", errno);
}
USHORT peerPort = ntohs(peerAddr.sin_port);
if(msgRequest.iExtra < 0x0D00){
memcpy(msgRequest.idDevice, &peerAddr.sin_addr, 4);
memcpy(msgRequest.idDevice+4, &peerAddr.sin_port, 2);
}
else{
memcpy(msgResponse.idDevice, msgRequest.idDevice, 6);
}
// if( msgRequest.eMessageType==e_versionRequest ){
// DebugPrint( "CONNECT %s:%d type: TCP", inet_ntoa(peerAddr.sin_addr), peerPort );
// }
if( !m_bExit && HandleRequest( &msgRequest, &msgResponse, peerAddr.sin_addr.s_addr, peerPort ) ){
short nSize = DATA_BUFSIZE;
if( !m_bExit && WriteNetMessage( (unsigned char*)pRB->buffer, nSize, &msgResponse ) ){
if( send(pRB->socket, pRB->buffer, nSize, 0) == SOCKET_ERROR){
DebugPrint("send() failed with error %d", errno);
}
}
}
}
delete pRB;
}
else{
m_pSema->ActP();
}
}
DebugPrint("EpollHandlerThread exit");
}
///////////////////////////////////////////////////////////////////////////////
//EpollHandler
EpollHandler::EpollHandler()
: m_smProcess(NULL, 0), m_smBuffers(NULL, 1)
{
for(int i=0; i<MAX_THREAD_NUM; i++){
m_lstThreads[i] = new HandlerThread(this, &m_smProcess);
m_lstThreads[i]->Resume();
}
}
EpollHandler::~EpollHandler()
{
for(int i=0; i<MAX_THREAD_NUM; i++){
delete m_lstThreads[i];
m_lstThreads[i] = NULL;
}
CMutexLock lockProcess( &m_smBuffers );
while(m_lstBuff.size()){
delete m_lstBuff.back();
m_lstBuff.pop_back();
}
}
void EpollHandler::AddBuff(RECVBUFF* pRB)
{
CMutexLock lockProcess( &m_smBuffers );
m_lstBuff.push_back(pRB);
m_smProcess.ActV();
}
RECVBUFF* EpollHandler::GetBuff()
{
CMutexLock lockProcess( &m_smBuffers );
RECVBUFF* pRB = NULL;
if(!m_lstBuff.empty()){
pRB = m_lstBuff.front();
m_lstBuff.pop_front();
}
return pRB;
}
void EpollHandler::Terminate()
{
//Set Thread Terminated status
for(int i=0; i<MAX_THREAD_NUM; i++){
m_lstThreads[i]->Terminate();
}
//Release sema individully
for(int i=0; i<MAX_THREAD_NUM; i++){
m_smProcess.ActV();
usleep(10000);
}
}
//////////////////////////////////////////////////////////////////////////////
//EpollThread
EpollThread::EpollThread()
: CThread(5000)
{
m_pHandler = new EpollHandler();
if(pipe(m_fdPipe)<0){
DebugPrint("create pipe error: %d", errno);
memset(m_fdPipe,0,sizeof(m_fdPipe));
}
}
EpollThread::~EpollThread()
{
if(!IsTerminated()){
Terminate();
}
if(m_pHandler){
delete m_pHandler;
m_pHandler = NULL;
}
if(m_fdPipe[0]){
close(m_fdPipe[0]);
close(m_fdPipe[1]);
}
}
bool EpollThread::SetNoBlock(int fd)
{
int oldSocketFlag = fcntl(fd, F_GETFL, 0);
int newSocketFlag = oldSocketFlag | O_NONBLOCK;
if (fcntl(fd, F_SETFL, newSocketFlag) == -1){
close(fd);
return false;
}
return true;
}
void EpollThread::Terminate()
{
CThread::Terminate();
if(m_fdPipe[1])
write(m_fdPipe[1], "0", 1);
if(m_pHandler)
m_pHandler->Terminate();
}
void EpollThread::Main()
{
//创建一个监听socket
int listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
if (listenfd == -1){
DebugPrint("create listen socket error");
return;
}
//设置重用ip地址和端口号
int on = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char*)& on, sizeof(on));
setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (char*)& on, sizeof(on));
//初始化服务器地址
struct sockaddr_in bindaddr;
bindaddr.sin_family = AF_INET;
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindaddr.sin_port = htons(LISTEN_PORT);
if (bind(listenfd, (struct sockaddr*) & bindaddr, sizeof(bindaddr)) == -1)
{
close(listenfd);
DebugPrint("bind listen socker error.");
return;
}
//启动监听
if (listen(listenfd, SOMAXCONN) == -1){
close(listenfd);
DebugPrint("listen error.");
return;
}
//创建epollfd
int epollfd = epoll_create1(EPOLL_CLOEXEC);
if (epollfd == -1){
DebugPrint("create epollfd error.");
close(listenfd);
return;
}
epoll_event listen_fd_event;
listen_fd_event.data.fd = listenfd;
listen_fd_event.events = EPOLLIN;
//将监听sokcet绑定到epollfd上去
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &listen_fd_event) == -1){
DebugPrint("epoll_ctl error");
close(listenfd);
return;
}
if(m_fdPipe[0]){
struct epoll_event ev;
ev.data.fd = m_fdPipe[0];
ev.events = EPOLLIN; //水平触发方式,监听可读事件,即管道有数据可以读取了
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, m_fdPipe[0], &ev)<0){
DebugPrint("epoll_ctl_add pipe error: %d", errno);
}
}
int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
if(timerfd!=-1 ){
struct itimerspec newValue = {};
newValue.it_interval.tv_sec = TIMER_INTERVAL;
newValue.it_value.tv_sec = TIMER_INTERVAL;
if(timerfd_settime(timerfd, 0, &newValue, NULL)==-1){
DebugPrint("settime error");
close(timerfd);
}
else{
epoll_event timer_event;
timer_event.data.fd = timerfd;
timer_event.events = EPOLLIN;
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &timer_event)<0){
DebugPrint("epoll_ctl_add timer error: %d", errno);
close(timerfd);
}
}
}
map<int, int> mapFds; //tcp连接组
int maxCount = 0;
epoll_event epoll_events[1024];
char dataBuff[DATA_BUFSIZE];
while(!m_bExit){
int n = epoll_wait(epollfd, epoll_events, 1024, -1);
if(n < 0){
//被信号中断
if (errno == EINTR)
continue;
//出错,退出
DebugPrint("epoll exit with error: %d", errno);
break;
}
for (int i = 0; i < n && !m_bExit; ++i) {
if (epoll_events[i].data.fd == m_fdPipe[0]){ //exit signal
DebugPrint("Got epoll exit signal");
break;
}
else if (epoll_events[i].data.fd == timerfd){
// DebugPrint("epoll timer on");
uint64_t exp=0;
if(read(timerfd, &exp, sizeof(uint64_t))!=sizeof(uint64_t)){
close(timerfd);
}
int count = 0;
for(auto it=mapFds.begin(); it!=mapFds.end();){
it->second += TIMER_INTERVAL;
if( it->second >= TIMER_EXPIRE ){//空闲1分钟关闭
close(it->first);
it = mapFds.erase(it);
// DebugPrint("close expired socket");
}
else{
count++;
it++;
}
}
if(count>maxCount){
DebugPrint("mapFds max size: %d", count);
maxCount = count;
}
}
else if (epoll_events[i].data.fd == listenfd){
if(epoll_events[i].events & EPOLLIN){//侦听socket,接受新连接
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
int clientfd = accept4(listenfd, (struct sockaddr*)&clientaddr, &clientaddrlen, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (clientfd != -1){
epoll_event client_event;
client_event.data.fd = clientfd;
client_event.events = EPOLLIN | EPOLLRDHUP;// | EPOLLET;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &client_event) == -1){
DebugPrint("add client fd to epollfd error");
close(clientfd);
}
// DebugPrint("add client fd %d to epollfd", clientfd);
// mapFds.insert(clientfd, 0);
mapFds[clientfd] = 0;
}
}
}
else if (epoll_events[i].events & EPOLLRDHUP ) {
if (epoll_ctl(epollfd, EPOLL_CTL_DEL, epoll_events[i].data.fd, NULL) == -1){
// DebugPrint("EPOLL_CTL_DEL clientfd %d by event %d", epoll_events[i].data.fd, epoll_events[i].events);
// }
// else{
DebugPrint("EPOLL_CTL_DEL clientfd %d by event %d error", epoll_events[i].data.fd, epoll_events[i].events);
}
close(epoll_events[i].data.fd);
mapFds.erase(mapFds.find(epoll_events[i].data.fd));
}
else if (epoll_events[i].events & EPOLLIN){ //事件可读
// DebugPrint("client fd: %d recv data.", epoll_events[i].data.fd);
int m = recv(epoll_events[i].data.fd, dataBuff, DATA_BUFSIZE, 0);
// DebugPrint("read data size %d", m);
if( m>0 && ValidNetMessage((UCHAR*)dataBuff, m) ){
RECVBUFF* pRB = new RECVBUFF;
memcpy(pRB->buffer, dataBuff, m);
pRB->socket = epoll_events[i].data.fd;
pRB->buffsize = m;
m_pHandler->AddBuff(pRB);
}
else if (m <= 0 && errno != EWOULDBLOCK && errno != EINTR){ //对端关闭了连接,从epollfd上移除clientfd
if (epoll_ctl(epollfd, EPOLL_CTL_DEL, epoll_events[i].data.fd, NULL) == -1){
// DebugPrint("EPOLL_CTL_DEL clientfd %d normally", epoll_events[i].data.fd);
// }
// else{
DebugPrint("EPOLL_CTL_DEL clientfd %d by EPOLLIN error", epoll_events[i].data.fd);
}
close(epoll_events[i].data.fd);
mapFds.erase(mapFds.find(epoll_events[i].data.fd));
}
mapFds.find(epoll_events[i].data.fd)->second = 0;
}
}
}
close(epollfd);
DebugPrint("EPOLL main exit");
}
+61
View File
@@ -0,0 +1,61 @@
#include <sys/socket.h>
#include <list>
#include "thread.h"
#define DATA_BUFSIZE 8192
#define MAX_THREAD_NUM 10
using namespace std;
typedef unsigned int SOCKET;
typedef struct{
SOCKET socket;
char buffer[DATA_BUFSIZE];
int buffsize;
} RECVBUFF;
typedef list<RECVBUFF*> RECVBUFFLIST;
class EpollHandler
{
class HandlerThread : public CThread //inside class
{
private:
EpollHandler* m_pHandler;
CSema* m_pSema;
public:
HandlerThread(EpollHandler* pHandler, CSema* pSema);
virtual void Main();
};
private:
RECVBUFFLIST m_lstBuff;
HandlerThread* m_lstThreads[MAX_THREAD_NUM];
CSema m_smProcess;
CSema m_smBuffers;
public:
EpollHandler();
~EpollHandler();
void AddBuff(RECVBUFF*);
RECVBUFF* GetBuff();
void Terminate();
};
class EpollThread : public CThread
{
private:
EpollHandler* m_pHandler;
int m_fdPipe[2];
bool SetNoBlock(int fd);
public:
EpollThread();
~EpollThread();
virtual void Main();
virtual void Terminate();
};
+131
View File
@@ -0,0 +1,131 @@
//---------------------------------------------------------------------------
#pragma hdrstop
#include "INIParser.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//remove all blank space
string &TrimString(string &str)
{
string::size_type pos = 0;
while(str.npos != (pos = str.find(" ")))
str = str.replace(pos, pos+1, "");
return str;
}
//read in INI file and parse it
int INIParser::ReadINI(string path)
{
ifstream in_conf_file(path.c_str());
if(!in_conf_file) return 0;
string str_line = "";
string str_root = "";
vector<ININode> vec_ini;
while(getline(in_conf_file, str_line))
{
string::size_type left_pos = 0;
string::size_type right_pos = 0;
string::size_type equal_div_pos = 0;
string str_key = "";
string str_value = "";
//comment
if(str_line.npos != (left_pos = str_line.find("#"))) str_line.erase(left_pos);
if(str_line.npos != (left_pos = str_line.find(";"))) str_line.erase(left_pos);
//section
if((str_line.npos != (left_pos = str_line.find("["))) && (str_line.npos != (right_pos = str_line.find("]"))))
{
//cout << str_line.substr(left_pos+1, right_pos-1) << endl;
str_root = str_line.substr(left_pos+1, right_pos-1);
}
//key-value
else if(str_line.npos != (equal_div_pos = str_line.find("=")))
{
str_key = str_line.substr(0, equal_div_pos);
str_value = str_line.substr(equal_div_pos+1, str_line.size()-1);
str_key = TrimString(str_key);
str_value = TrimString(str_value);
//cout << str_key << "=" << str_value << endl;
}
if((!str_root.empty()) && (!str_key.empty()) && (!str_value.empty()))
{
ININode ini_node(str_root, str_key, str_value);
vec_ini.push_back(ini_node);
//cout << vec_ini.size() << endl;
}
}
in_conf_file.close();
in_conf_file.clear();
//vector convert to map
map<string, string> map_tmp;
for(vector<ININode>::iterator itr = vec_ini.begin(); itr != vec_ini.end(); ++itr)
{
map_tmp.insert(pair<string, string>(itr->root, ""));
}
SubNode sn;
for(map<string, string>::iterator itr = map_tmp.begin(); itr != map_tmp.end(); ++itr)
{
//cout << itr->first << endl;
for(vector<ININode>::iterator sub_itr = vec_ini.begin(); sub_itr != vec_ini.end(); ++sub_itr)
{
if(sub_itr->root == itr->first)
{
//cout << sub_itr->key << "=" << sub_itr->value << endl;
sn.InsertElement(sub_itr->key, sub_itr->value);
}
}
map_ini.insert(pair<string, SubNode>(itr->first, sn));
}
return 1;
}
//get value by root and key
string INIParser::GetValue(string root, string key)
{
map<string, SubNode>::iterator itr = map_ini.find(root);
if(map_ini.end() != itr)
{
//if section found
map<string, string>::iterator sub_itr = itr->second.sub_node.find(key);
if(!(sub_itr->second).empty())
return sub_itr->second;
}
return "";
}
//write ini file
int INIParser::WriteINI(string path)
{
ofstream out_conf_file(path.c_str());
if(!out_conf_file)
return -1;
//cout << map_ini.size() << endl;
for(map<string, SubNode>::iterator itr = map_ini.begin(); itr != map_ini.end(); ++itr)
{
//cout << itr->first << endl;
out_conf_file << "[" << itr->first << "]" << endl;
for(map<string, string>::iterator sub_itr = itr->second.sub_node.begin(); sub_itr != itr->second.sub_node.end(); ++sub_itr)
{
//cout << sub_itr->first << "=" << sub_itr->second << endl;
out_conf_file << sub_itr->first << "=" << sub_itr->second << endl;
}
}
out_conf_file.close();
out_conf_file.clear();
return 1;
}
//set value
vector<ININode>::size_type INIParser::SetValue(string root, string key, string value)
{
map<string, SubNode>::iterator itr = map_ini.find(root);
if(map_ini.end() != itr)
itr->second.sub_node.insert(pair<string, string>(key, value));
else
{
SubNode sn;
sn.InsertElement(key, value);
map_ini.insert(pair<string, SubNode>(root, sn));
}
return map_ini.size();
}
+55
View File
@@ -0,0 +1,55 @@
//---------------------------------------------------------------------------
#ifndef INIParserH
#define INIParserH
//---------------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <map>
using namespace std;
//INI文件结点存储结构
class ININode
{
public:
ININode(string root, string key, string value)
{
this->root = root;
this->key = key;
this->value = value;
}
string root;
string key;
string value;
};
//键值对结构体
class SubNode
{
public:
void InsertElement(string key, string value)
{
sub_node.insert(pair<string, string>(key, value));
}
map<string, string> sub_node;
};
//主要的INIParser类
class INIParser
{
public:
int ReadINI(string path);
string GetValue(string root, string key);
vector<ININode>::size_type GetSize(){return map_ini.size();}
vector<ININode>::size_type SetValue(string root, string key, string value);
int WriteINI(string path);
void Clear(){map_ini.clear();}
private:
map<string, SubNode> map_ini;
};
#endif
+333
View File
@@ -0,0 +1,333 @@
#ifdef _WIN32
#include "IOCmpltThread.h"
#include "debug.h"
#include "MessageDef.h"
#include "MessageHandle.h"
HANDLE g_hCompletionPort;
CIOCmpltThread::CIOCmpltThread(unsigned int nStackSize)
:CThread(nStackSize), m_smProcess("mProcess",1)
{
m_hListenSocket = NULL;
g_hCompletionPort = NULL;
m_nWorkerThreadNumbers = 0;
for(int i=0;i<MAX_PROCESSOR_COUNTER;i++)
m_hWorkerThread[i] = NULL;
}
void CIOCmpltThread::Main()
{
SOCKADDR_IN InternetAddr;
SOCKET hAcceptSocket;
SYSTEM_INFO SystemInfo;
WSADATA wsaData;
DWORD Ret;
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
DebugPrint("WSAStartup failed with error %d\n", Ret);
return;
}
// Setup an I/O completion port.
if ((g_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
DebugPrint( "CreateIoCompletionPort failed with error: %d\n", GetLastError());
return;
}
// Determine how many processors are on the system.
GetSystemInfo(&SystemInfo);
// Create worker threads based on the number of processors available on the
// system. Create two worker threads for each processor.
m_nWorkerThreadNumbers = SystemInfo.dwNumberOfProcessors*2+2;
if( m_nWorkerThreadNumbers>MAX_PROCESSOR_COUNTER ){
m_nWorkerThreadNumbers = MAX_PROCESSOR_COUNTER;
}
for( int i=0; i<m_nWorkerThreadNumbers; i++ )
{
// Create a server worker thread and pass the completion port to the thread.
DWORD ThreadID;
m_hWorkerThread[i] = CreateThread(NULL, 0, ServerWorkerThread, this, 0, &ThreadID);
}
// Create a listening socket
if ((m_hListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
DebugPrint("WSASocket() failed with error %d\n", WSAGetLastError());
return;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(m_hListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
DebugPrint("bind() failed with error %d\n", WSAGetLastError());
return;
}
// Prepare socket for listening
if (listen(m_hListenSocket, 20) == SOCKET_ERROR)
{
DebugPrint("listen() failed with error %d\n", WSAGetLastError());
return;
}
// Accept connections and assign to the completion port.
while(!m_bExit){
struct sockaddr_in saClient;
int iClientSize = sizeof(saClient);
if ((hAcceptSocket = WSAAccept(m_hListenSocket, (SOCKADDR*) &saClient, &iClientSize, NULL, 0)) == SOCKET_ERROR){
DebugPrint("WSAAccept() failed with error %d\n", WSAGetLastError());
return;
}
// Create a socket information structure to associate with the socket
LPCONTEXT_KEY lpContextKey = (LPCONTEXT_KEY)GlobalAlloc(GPTR, sizeof(CONTEXT_KEY));
if( !lpContextKey ){
DebugPrint("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
// Associate the accepted socket with the original completion port.
ZeroMemory(&(lpContextKey->overlapped), sizeof(OVERLAPPED));
lpContextKey->peerIp = saClient.sin_addr.S_un.S_addr;
lpContextKey->peerPort = ntohs(saClient.sin_port);
lpContextKey->socket = hAcceptSocket;
lpContextKey->dataBuf.len = DATA_BUFSIZE;
lpContextKey->dataBuf.buf = lpContextKey->buffer;
lpContextKey->iOperation = COMPLETION_KEY_RECV;
lpContextKey->nTimeCount = 0;
if (CreateIoCompletionPort((HANDLE)hAcceptSocket, g_hCompletionPort, (DWORD)lpContextKey, 0) == NULL){
DebugPrint("CreateIoCompletionPort failed with error %d\n", GetLastError());
closesocket( lpContextKey->socket );
GlobalFree( lpContextKey );
}
else{
// Create per I/O socket information structure to associate with the
// WSARecv call below.
m_lstContextKeys.push_back( lpContextKey );
DWORD RecvBytes;
DWORD Flags;
Flags = 0;
if (WSARecv(hAcceptSocket, &(lpContextKey->dataBuf), 1, &RecvBytes, &Flags,
&(lpContextKey->overlapped), NULL) == SOCKET_ERROR){
if (WSAGetLastError() != ERROR_IO_PENDING){
DebugPrint("1 WSARecv() failed with error %d\n", WSAGetLastError());
FreeContextKey( lpContextKey );
continue;
}
}
}
}
}
void CIOCmpltThread::Terminate()
{
CThread::Terminate();
int i;
if(m_hListenSocket)
{
closesocket(m_hListenSocket);
m_hListenSocket = NULL;
}
for( i=0; i<m_nWorkerThreadNumbers; i++ ){
PostQueuedCompletionStatus(g_hCompletionPort,0,COMPLETION_KEY_SHUTDOWN,NULL);
}
//关闭线程句柄
for( i=0; i<m_nWorkerThreadNumbers; i++ ){
if(m_hWorkerThread[i]){
WaitForSingleObject( m_hWorkerThread[i], INFINITE );
CloseHandle(m_hWorkerThread[i]);
}
}
if(g_hCompletionPort)
{
CloseHandle(g_hCompletionPort);
g_hCompletionPort = NULL;
}
if( m_lstContextKeys.size()>0 ){
CONTEXTKEYLIST::iterator iter = m_lstContextKeys.begin();
while( iter!=m_lstContextKeys.end() ){
closesocket( (*iter)->socket );
GlobalFree( *iter );
iter++;
}
m_lstContextKeys.clear();
}
}
bool CIOCmpltThread::IsValidContextKey( LPCONTEXT_KEY lpContextKey )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstContextKeys.size()>0 ){
CONTEXTKEYLIST::iterator iter = m_lstContextKeys.begin();
while( iter!=m_lstContextKeys.end() ){
if( *iter==lpContextKey ){
return true;
}
iter++;
}
}
return false;
}
void CIOCmpltThread::FreeContextKey( LPCONTEXT_KEY lpContextKey )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstContextKeys.size()>0 ){
CONTEXTKEYLIST::iterator iter = m_lstContextKeys.begin();
while( iter!=m_lstContextKeys.end() ){
if( *iter==lpContextKey ){
m_lstContextKeys.erase( iter );
closesocket( lpContextKey->socket );
GlobalFree( lpContextKey );
//DebugPrint( "Free client %d .\n", lpContextKey->socket );
return;
}
iter++;
}
}
}
void CIOCmpltThread::OnTimer()
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstContextKeys.size()>0 ){
CONTEXTKEYLIST::iterator iter = m_lstContextKeys.begin();
while( iter!=m_lstContextKeys.end() ){
if( (*iter)->iOperation==COMPLETION_KEY_RECV && ++(*iter)->nTimeCount>=60 ){ //超过1分钟未接收到数据
shutdown( (*iter)->socket, SD_BOTH );
DebugPrint( "Client %d shutdown by timeout.\n", (*iter)->socket );
closesocket( (*iter)->socket );
(*iter)->iOperation = COMPLETION_KEY_SHUTDOWN;
}
iter++;
}
}
}
DWORD WINAPI ServerWorkerThread(LPVOID lpVoid)
{
CIOCmpltThread* pThread = (CIOCmpltThread*)lpVoid;
DWORD dwBytesTransferred = 0;
LPOVERLAPPED lpOverlapped = NULL;
LPCONTEXT_KEY lpContextKey = NULL;
DWORD SendBytes, RecvBytes;
DWORD Flags;
BOOL bResult;
while(!pThread->IsTerminated()){
bResult = GetQueuedCompletionStatus(g_hCompletionPort, &dwBytesTransferred,
(LPDWORD)&lpContextKey, &lpOverlapped, INFINITE);
if( !bResult ){
int err = GetLastError();
DebugPrint("GetQueuedCompletionStatus failed with error %d\n", err);
//if( err!=995 ){//&& pThread->IsValidContextKey( lpContextKey ) ){
pThread->FreeContextKey( lpContextKey );
//}
}
else{
if( lpOverlapped==NULL && (DWORD)lpContextKey==COMPLETION_KEY_SHUTDOWN ){
DebugPrint("ServerWorkThread shutdown.\n" );
return 0;
}
if( lpOverlapped!=NULL && pThread->IsValidContextKey(lpContextKey) ){
ZeroMemory(&(lpContextKey->overlapped), sizeof(OVERLAPPED));
if( lpContextKey->iOperation==COMPLETION_KEY_RECV ){
if( dwBytesTransferred==0 ){
DebugPrint("Client shutdown.\n" );
pThread->FreeContextKey( lpContextKey );
}
else{
lpContextKey->nTimeCount = 0; //计数器清零
TNETMESSAGE msgRequest;
if( ReadNetMessage( (unsigned char*)lpContextKey->buffer, dwBytesTransferred, &msgRequest )){
if( msgRequest.eMessageType==e_versionRequest ){
char *pb=(char *)&(lpContextKey->peerIp);
unsigned b1=(unsigned char)(*pb);
unsigned b2=(unsigned char)(*(pb+1));
unsigned b3=(unsigned char)(*(pb+2));
unsigned b4=(unsigned char)(*(pb+3));
DebugPrint( "CONNECT %d.%d.%d.%d:%d type: TCP\n", b1, b2, b3, b4, lpContextKey->peerPort );
}
TNETMESSAGE msgResponse;
if( HandleRequest( &msgRequest, &msgResponse, lpContextKey->peerIp, lpContextKey->peerPort ) ){
int nSize = DATA_BUFSIZE;
if( WriteNetMessage( (unsigned char*)lpContextKey->buffer, nSize, &msgResponse ) ){
lpContextKey->iOperation=COMPLETION_KEY_SEND;
lpContextKey->dataBuf.len = nSize;
if( WSASend(lpContextKey->socket, &(lpContextKey->dataBuf), 1, &SendBytes, 0,
&(lpContextKey->overlapped), NULL) == SOCKET_ERROR){
if( WSAGetLastError() != ERROR_IO_PENDING){
DebugPrint("WSASend() failed with error %d\n", WSAGetLastError());
pThread->FreeContextKey( lpContextKey );
}
}
continue;
}
}
}
Flags = 0;
if (WSARecv(lpContextKey->socket, &(lpContextKey->dataBuf), 1, &RecvBytes, &Flags,
&(lpContextKey->overlapped), NULL) == SOCKET_ERROR) {
if( WSAGetLastError()!=ERROR_IO_PENDING ){
DebugPrint("2 WSARecv() failed with error %d\n", WSAGetLastError());
pThread->FreeContextKey( lpContextKey );
}
}
}
}
else if( lpContextKey->iOperation==COMPLETION_KEY_SEND ){
lpContextKey->dataBuf.len = DATA_BUFSIZE;
lpContextKey->iOperation = COMPLETION_KEY_RECV;
Flags = 0;
if (WSARecv(lpContextKey->socket, &(lpContextKey->dataBuf), 1, &RecvBytes, &Flags,
&(lpContextKey->overlapped), NULL) == SOCKET_ERROR) {
if( WSAGetLastError()!=ERROR_IO_PENDING ){
DebugPrint("3 WSARecv() failed with error %d\n", WSAGetLastError());
pThread->FreeContextKey( lpContextKey );
}
}
}
}
}
}
return 0;
}
#endif
+55
View File
@@ -0,0 +1,55 @@
#ifndef IOCmpltThreadH
#define IOCmpltThreadH
#include <winsock2.h>
#include <list>
#include "Thread.h"
#define PORT 12071
#define DATA_BUFSIZE 8192
#define MAX_PROCESSOR_COUNTER 22 //最多定义22个处理器
enum SERVER_COMPLETE_KEY
{
COMPLETION_KEY_RECV = 0,
COMPLETION_KEY_SEND = 1,
COMPLETION_KEY_SHUTDOWN = 2,
};
typedef struct
{
SERVER_COMPLETE_KEY iOperation;
int nTimeCount;
SOCKET socket;
OVERLAPPED overlapped;
WSABUF dataBuf;
char buffer[DATA_BUFSIZE];
unsigned int peerIp;
unsigned short peerPort;
} CONTEXT_KEY, * LPCONTEXT_KEY;
using namespace std;
typedef list< LPCONTEXT_KEY > CONTEXTKEYLIST;
class CIOCmpltThread : public CThread
{
public:
void Main();
CIOCmpltThread(unsigned int nStackSize);
virtual void Terminate();
bool IsValidContextKey( LPCONTEXT_KEY lpContextKey );
void FreeContextKey( LPCONTEXT_KEY lpContextKey );
void OnTimer();
private:
SOCKET m_hListenSocket;
HANDLE m_hWorkerThread[MAX_PROCESSOR_COUNTER];
int m_nWorkerThreadNumbers;
CSema m_smProcess;
CONTEXTKEYLIST m_lstContextKeys;
};
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
#endif //_IOCMPLTTHREAD_H_
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
#ifndef MessageHandleH
#define MessageHandleH
#include "MessageDef.h"
DWORD HandleVerifyParam( DWORD dwParam );
bool HandleRequest( TNETMESSAGE* pRequest, TNETMESSAGE* pResponse, UINT ip, USHORT port, bool bUDP=false );
int CreateStyle( int idUser, int iType, int nDataSize, char* pData );
int GetStyleInfo( int iType, UINT id, int& nDataSize, char** ppData );
int GetStyleData( int iType, UINT id, int& nDataSize, char** ppData );
int PublishStyle( UINT idTemp, UINT idStyle );
int GetStyleUserScore( int iType, UINT idStyle, UINT idUser, int* pScrUser, int* pScrAverage );
int CreateSong( int idUser, int iClientType, int nDataSize, char* pData, TSHAREINFO* pInfo );
int GetIconFile( char* strFile, int& nDataSize, char** ppData );
bool StyleTrans2Info( TSTYLEDETAIL& info, char* pData );
bool ShareTrans2Info( TSTYLESHARE& info, char* pData );
//////////////////////////////////////////////////////
// 统计 PC pro 函数
//void GetProCount(int& n826, int& nOth);
//
//////////////////////////////////////////////////////
#endif //_MESSAGEHANDLE_H_INCLUDED_
+192
View File
@@ -0,0 +1,192 @@
#ifdef _WIN32
#include <windows.h>
//#include <process.h>
#endif
#include "debug.h"
#include "MessageThread.h"
#include "MessageHandle.h"
MHTHREADLIST g_lstMessageHandleThreads;
////////////////////////////////////////////////////////////////////////////
//
// CUDPMessageReceiveThread
//
CUDPMessageReceiveThread::CUDPMessageReceiveThread(unsigned int nStackSize, CUDPSocket * pSocket)
:CThread(nStackSize)
{
m_pSocket = pSocket;
}
void CUDPMessageReceiveThread::Main()
{
TNETMESSAGE * pMsg = NULL;
while (!m_bExit && m_pSocket ){
unsigned int nIpAddr;
unsigned short nPort;
pMsg = ReadMessage( nIpAddr, nPort );
if( pMsg ){
MHTHREADLIST::iterator iMT;
for( iMT=g_lstMessageHandleThreads.begin(); iMT!=g_lstMessageHandleThreads.end(); iMT++ ){
CMessageHandleThread * pThread = *iMT;
if( pThread->IsSuspended() ){
pThread->SetPeerAddress( nIpAddr, nPort );
pThread->SetRequestMsg( pMsg );
pThread->Resume();
break;
}
}
if(iMT==g_lstMessageHandleThreads.end()){ //无空闲线程
delete pMsg;
}
}
}
DebugPrint("退出网络消息接收线程");
ExitThread();
}
void CUDPMessageReceiveThread::Terminate()
{
CThread::Terminate();
if( m_pSocket ){
m_pSocket->Close();
delete m_pSocket;
m_pSocket = NULL;
}
if(GetThreadID() && IsSuspended())
Resume();
// Sleep( 10 );
}
TNETMESSAGE * CUDPMessageReceiveThread::ReadMessage(unsigned int &nIpAddr,unsigned short &nPort)
{
int ret = m_pSocket->ReadFrom( m_sBuf, MAX_UDP_PACKET_SIZE, nIpAddr, nPort );
if( ret==SOCKET_ERROR ){
int err = WSAGetLastError();
DebugPrint("读取网络消息失败:错误号 %d", err);
}
else if( ret==0 ){
DebugPrint("网络连接已关闭");
}
else if(ValidNetMessage((UCHAR*)m_sBuf, ret)){
TNETMESSAGE * pMsg = new TNETMESSAGE;
if( ReadNetMessage( (unsigned char*)m_sBuf, ret, pMsg ) ){
return pMsg;
}
else{
delete pMsg;
}
}
return NULL;
}
////////////////////////////////////////////////////////////////////////////
//
// CMessageHandleThread
//
CMessageHandleThread::CMessageHandleThread(unsigned int nStackSize, CUDPSocket * pSocket)
:CThread(nStackSize)
{
m_pSocket = pSocket;
m_pRequestMsg = NULL;
m_nPeerIp = 0;
m_nPeerPort = 0;
}
void CMessageHandleThread::Main()
{
while (!m_bExit && m_pSocket){
if( m_pRequestMsg ){
bool bIngnore = false;
if(m_pRequestMsg->eMessageType!=e_connectRequest || m_pRequestMsg->iExtra>=0x0B00) //之前版本连接UDP可能有问题
HandleGerneralMessage();
delete m_pRequestMsg;
m_pRequestMsg = NULL;
}
Suspend();
}
DebugPrint("退出消息处理线程");
ExitThread();
}
void CMessageHandleThread::HandleGerneralMessage()
{
TNETMESSAGE msgResponse;
if(m_pRequestMsg->iExtra < 0x0D00){
memcpy(m_pRequestMsg->idDevice, &m_nPeerIp, 4);
memcpy(m_pRequestMsg->idDevice+4, &m_nPeerPort, 2);
}
else{
memcpy(msgResponse.idDevice, m_pRequestMsg->idDevice, 6);
}
if( HandleRequest( m_pRequestMsg, &msgResponse, m_nPeerIp, m_nPeerPort, true ) && !m_bExit){
int nRet = SendMessage( &msgResponse );
}
}
void CMessageHandleThread::HandleUpdateMessage()
{
}
void CMessageHandleThread::HandleUploadMessage()
{
}
void CMessageHandleThread::Terminate()
{
CThread::Terminate();
// if( m_pSocket ){
// m_pSocket->Close();
// delete m_pSocket;
// m_pSocket = NULL;
// }
if(GetThreadID() && IsSuspended())
Resume();
// Sleep( 10 );
}
int CMessageHandleThread::SendMessage( TNETMESSAGE *pMsg )
{
char cMsg[MAX_MSG_LENGTH];
short nSize = MAX_MSG_LENGTH;
if( !WriteNetMessage( (unsigned char*)cMsg, nSize, pMsg ) ){
return 0;
}
//发送数据
int nSend = m_pSocket->SendTo( cMsg, nSize, m_nPeerIp, m_nPeerPort );
// if( nSend==pMsg->nLength+10 ){
// char *pb=(char *)&(m_nPeerIp);
// unsigned b1=(unsigned char)(*pb);
// unsigned b2=(unsigned char)(*(pb+1));
// unsigned b3=(unsigned char)(*(pb+2));
// unsigned b4=(unsigned char)(*(pb+3));
// DebugPrint( "发送UDP消息到 %d.%d.%d.%d:%d 成功", b1, b2, b3, b4, m_nPeerPort );
// }
return nSend;
}
+66
View File
@@ -0,0 +1,66 @@
#ifndef MessageThreadH
#define MessageThreadH
#include "thread.h"
#include "Socket.h"
#include "MessageDef.h"
#pragma once
// CUDPMessageReceiveThread
//
class CUDPMessageReceiveThread : public CThread
{
public:
void Main();
CUDPMessageReceiveThread(unsigned int nStackSize, CUDPSocket * pSocket);
virtual void Terminate() ;
protected:
CUDPSocket * m_pSocket;
char m_sBuf[MAX_UDP_PACKET_SIZE];//实现一次读取需要的变量
TNETMESSAGE * ReadMessage(unsigned int &nIpAddr,unsigned short &nPort);
};
/////////////////////////////////////////////////////////////////////
//
// CMessageHandleThread
//
class CMessageHandleThread : public CThread
{
public:
void Main();
CMessageHandleThread(unsigned int nStackSize, CUDPSocket * pSocket);
virtual void Terminate() ;
void SetPeerAddress( unsigned int nIpAddr,unsigned short nPort ){
m_nPeerIp = nIpAddr;
m_nPeerPort = nPort;
};
void SetRequestMsg( TNETMESSAGE* pMsg ){
m_pRequestMsg = pMsg;
};
protected:
CUDPSocket * m_pSocket;
unsigned int m_nPeerIp;
unsigned short m_nPeerPort;
TNETMESSAGE * m_pRequestMsg;
void HandleGerneralMessage();
void HandleUpdateMessage();
void HandleUploadMessage();
int SendMessage( TNETMESSAGE * pMsg );
};
#pragma warning( disable : 4786 )
#include <list>
using namespace std;
typedef list< CMessageHandleThread* > MHTHREADLIST;
#endif //_MESSAGETHREAD_H_
+184
View File
@@ -0,0 +1,184 @@
// ResponseManger.cpp: implementation of the CResponseManger class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _WIN32
#include <windows.h>
#endif
#include <string.h>
#include "debug.h"
#include "ResponseManager.h"
#include "ServerInner.h"
#define MAX_RESPONSE_NUM 2000
int g_nMaxListSize = 0;
//////////////////////////////////////////////////////////////////////
// CDataReceiver
//////////////////////////////////////////////////////////////////////
CResponseManager::CResponseManager()
:m_smProcess("mRMProcess",1)
{
}
CResponseManager::~CResponseManager()
{
CMutexLock lockProcess( &m_smProcess );
int nSize = m_lstResponses.size();
DebugPrint( "Response remain size = %d", nSize );
if( nSize>0 ){
TRESPONSELIST::iterator iter = m_lstResponses.begin();
while( iter!=m_lstResponses.end() ){
delete *iter;
iter++;
}
m_lstResponses.clear();
}
}
bool CResponseManager::NewResponse( int iExtra, TNETMESSAGE* pResponse )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstResponses.size()>MAX_RESPONSE_NUM || !pResponse ){
return false;
}
TRESPONSENODE * pNode = new TRESPONSENODE;
pNode->iExtra = iExtra;
pNode->iTimeCount = 0;
memcpy( &(pNode->response), pResponse, pResponse->nLength+14 );
// DebugPrint("Insert response for msg: 0x%X - %d", pResponse->eMessageType, iExtra);
m_lstResponses.push_back( pNode );
if( m_lstResponses.size()>g_nMaxListSize ){
g_nMaxListSize = m_lstResponses.size();
if( g_nMaxListSize%10==0 ){
DebugPrint( "response list max size = %d.", g_nMaxListSize );
}
}
return true;
}
TNETMESSAGE* CResponseManager::GetResponse( TNETMESSAGE* pRequest )
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstResponses.size()>0 ){
TRESPONSELIST::iterator iter = m_lstResponses.begin();
while( iter!=m_lstResponses.end() ){
if( (*iter)->response.eMessageType==pRequest->eMessageType+1 ){
if( !memcmp(pRequest->idDevice, (*iter)->response.idDevice, 6) ){
if( (*iter)->response.nSequenceNum==pRequest->nSequenceNum ){ //同一请求多次发送
(*iter)->iTimeCount = 0;
return &((*iter)->response);
}
else if(pRequest->eMessageType>=e_iconRequest //非时效性请求
|| (*iter)->iTimeCount<5){ //或5秒内相同的请求
int iExtra = 0;
if(pRequest->eMessageType==e_webURLRequest){
TIntRequest * pUrlReq = (TIntRequest*)pRequest->byMessageBody;
iExtra = pUrlReq->iReq;
}
else if(pRequest->eMessageType==e_styleScoreRequest){
UINT idStyle;
int scrUser, iType = e_ST_Origin;
if( pRequest->nLength==sizeof(TStyleScoreRequest) ){
TStyleScoreRequest * pSSReq = (TStyleScoreRequest*)pRequest->byMessageBody;
idStyle = pSSReq->idStyle;
iType = pSSReq->iType;
scrUser = pSSReq->scrUser;
}
else{
TStyleScoreRequest0 * pSSReq = (TStyleScoreRequest0*)pRequest->byMessageBody;
idStyle = pSSReq->idStyle;
scrUser = pSSReq->scrUser;
}
iExtra = (idStyle<<16) + (iType<<8) + scrUser;
if(scrUser>0 && (iExtra&0xFFF0)==((*iter)->iExtra&0xFFF0) && iExtra!=(*iter)->iExtra ){
delete *iter;
iter = m_lstResponses.erase(iter);
continue;
}
}
else if(pRequest->eMessageType==e_styleInfoRequest){
TStyleInfoRequest * pSIReq = (TStyleInfoRequest*)pRequest->byMessageBody;
int iType = HIWORD( pSIReq->iType );
if( iType==0 ){
if( LOWORD( pSIReq->iType )==e_SM_Checker )
iType = e_ST_Temp;
else
iType = e_ST_Origin;
}
iExtra = (iType<<16) + pSIReq->idStyle;
}
else if(pRequest->eMessageType==e_styleDataRequest){
TStyleDataRequest * pSDReq = (TStyleDataRequest*)pRequest->byMessageBody;
int iType = HIWORD( pSDReq->iType );
if( iType==0 ){
if( LOWORD( pSDReq->iType )==e_SM_Checker )
iType = e_ST_Temp;
else
iType = e_ST_Origin;
}
iExtra = (iType<<16) + pSDReq->idStyle;
}
else if(pRequest->eMessageType==e_noticeUpdateRequest){
TNoticeUpdateRequest * pNUReq = (TNoticeUpdateRequest*)pRequest->byMessageBody;
iExtra = pNUReq->idUser;
}
else if(pRequest->eMessageType==e_qnaUpdateRequest){
TQnAUpdateRequest * pQUReq = (TQnAUpdateRequest*)pRequest->byMessageBody;
iExtra = (pQUReq->iClientType<<20) + pQUReq->idUser;
}
if((*iter)->iExtra==iExtra){
// DebugPrint("Got response for msg: 0x%X", pRequest->eMessageType);
(*iter)->response.nSequenceNum = pRequest->nSequenceNum;
(*iter)->iTimeCount = 0;
return &((*iter)->response);
}
}
}
else if( pRequest->iExtra < 0x0D00 && (*iter)->response.nSequenceNum==pRequest->nSequenceNum
&& ( pRequest->eMessageType==e_registerRequest || pRequest->eMessageType==e_qnaSubmitRequest )){
(*iter)->iTimeCount = 0;
return &((*iter)->response);
}
}
iter++;
}
}
return NULL;
}
void CResponseManager::OnTimer()
{
CMutexLock lockProcess( &m_smProcess );
if( m_lstResponses.size()>0 ){
TRESPONSELIST::iterator iter = m_lstResponses.begin();
while( iter!=m_lstResponses.end() ){
if( ++((*iter)->iTimeCount)>=30 ){ //超过30秒无数据操作
// DebugPrint("Delete response for msg: 0x%X", (*iter)->response.eMessageType);
delete *iter;
iter = m_lstResponses.erase( iter );
}
else{
iter++;
}
}
}
}
+39
View File
@@ -0,0 +1,39 @@
// ResponseManager.h: interface for the CResponseManager class.
//
//////////////////////////////////////////////////////////////////////
#ifndef ResponseManagerH
#define ResponseManagerH
#include "thread.h"
#include "MessageDef.h"
typedef struct tagResponse {
TNETMESSAGE response;
int iTimeCount;
// UINT ip;
// USHORT port;
int iExtra;
} TRESPONSENODE;
#include <list>
using namespace std;
typedef list< TRESPONSENODE* > TRESPONSELIST;
class CResponseManager
{
public:
CResponseManager();
virtual ~CResponseManager();
bool NewResponse( /*UINT ip, USHORT port, */ int iExtra, TNETMESSAGE* pResponse );
TNETMESSAGE * GetResponse( /*UINT ip, USHORT port,*/ TNETMESSAGE* pRequest );
void OnTimer();
private:
CSema m_smProcess;
TRESPONSELIST m_lstResponses;
};
#endif
+114
View File
@@ -0,0 +1,114 @@
/*******************************************************************************
*
* 模 块 名:DBService 文件名:ServiceBody.c
* 相关文件:DBService.h
* 提交日期:2012.2.1 作 者:Alex
* 版 本:0.1
* 模块描述:
* 本模块提供了用户定义的服务启动和停止程序
* ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv);
* ServiceStop();
* 修改记录:
* 日 期 版本 修改人 修改内容
*
*
*******************************************************************************/
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>
#include <assert.h>
#include <string.h>
#include "DBService.h"
#include "ServiceInit.h"
// this event is signalled when the service should end
static HANDLE hServerStopEvent = NULL;
DWORD g_unThreadId = 0;
TCHAR strErr[256];
void ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
{
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
3000)) // wait hint
{
_tprintf(TEXT("ServiceStart failed - %s\n"), GetLastErrorText(strErr,256));
return;
}
char *parm = 0;
if(dwArgc>=2)
parm = lpszArgv[1];
HANDLE thread = (HANDLE)CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)DBMain, NULL, 0, &g_unThreadId );
if( !thread ){
_tprintf(TEXT("CreateThread failed - %s\n"), GetLastErrorText(strErr,256));
goto cleanup;
}
hServerStopEvent = CreateEvent(
NULL, // no security attributes
TRUE, // manual reset event
FALSE, // not-signalled
SZSTOPEVENTNAME); // named
if ( hServerStopEvent == NULL){
_tprintf(TEXT("CreateEvent(ServerStopEvent) failed - %s\n"), GetLastErrorText(strErr,256));
goto cleanup;
}
if (!ReportStatusToSCMgr(
SERVICE_RUNNING, // service state
NO_ERROR, // exit code
0)) // wait hint
{
_tprintf(TEXT("ReportStatusToSCMgr failed - %s\n"), GetLastErrorText(strErr,256));
goto cleanup;
}
WaitForSingleObject(hServerStopEvent, INFINITE);
// _tprintf(TEXT("hServerStopEvent signaled!\n"));
cleanup:
if( g_unThreadId!=0 ){
PostThreadMessage( g_unThreadId, WM_CLOSE, 0, 0L );
}
if( g_hEvServiceThread ){
if(WAIT_OBJECT_0!=WaitForSingleObject(g_hEvServiceThread,15000))
{
TerminateThread(thread, 1);
_tprintf(TEXT("TerminateThread %s\n"), GetLastErrorText(strErr,256));
}
else{
// _tprintf(TEXT("g_hEvMcuThread signaled!\n"));
}
CloseHandle( g_hEvServiceThread );
}
if( thread ){
if (WAIT_OBJECT_0 != WaitForSingleObject(thread,1000)){
TerminateThread(thread, 2);
}
CloseHandle( thread );
_tprintf(TEXT("CloseHandle() %s\n"), GetLastErrorText(strErr,256));
}
if(hServerStopEvent){
CloseHandle(hServerStopEvent);
}
}
VOID ServiceStop()
{
if ( hServerStopEvent )
SetEvent(hServerStopEvent);
}
#endif
+736
View File
@@ -0,0 +1,736 @@
/*******************************************************************************
*
* 模 块 名:DBService 文件名:ServiceInit.c
* 相关文件:ServiceInit.h
* z提交日期:2012.2.1 作 者:Alex
* 版 本:0.1
* 模块描述:
* 相当于事务处理模块的构造和析构模块
* ServiceInit();
* ServiceDeInit();
* 修改记录:
* 日 期 版本 修改人 修改内容
*
*
*******************************************************************************/
#ifdef _WIN32
#define _SERVICEINIT_CPP
#include "IOCmpltThread.h"
//#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <tchar.h>
#include <direct.h>
#include "DbService.h"
#include "MessageThread.h"
#include "ServiceInit.h"
#include "debug.h"
#include "DataBuffers.h"
#include "ResponseManager.h"
#include "DBInterface.h"
//#define CTYPE_GBK 936
//#define CTYPE_UTF8 65001
CUDPMessageReceiveThread * g_pMessageReceiveThread = NULL;
CIOCmpltThread * g_pIOCmpltThread = NULL;
CDataBufferManager* g_pDataBuffers = NULL;
CResponseManager* g_pResponses = NULL;
int g_aStyleRecomList[MAX_STYLE_NUM+1];
TQNAITEM g_lstCommonQnA[200];
TNOTICEITEM g_lstPublicNotice[MAX_NOTICE_NUM];
int g_nCommonQnANum = 0, g_nPublicNoticeNum = 0;
HINSTANCE g_hDBAccessDll = NULL,
g_hParamDll = NULL;
extern MHTHREADLIST g_lstMessageHandleThreads;
TCLIENTVERSION* g_pVersionClient = NULL;
TTESTVERSION* g_pVersionClientTest = NULL;
int g_nClientTypeNum = 0,
g_nClientTestNum = 0;
HANDLE g_hEvClientCheck = NULL;
char g_strStyleFileDir[256] = "";
char g_strWebFileDir[256] = "";
char g_strMusicFileDir[256] = "";
char g_strMusicLocation[8] = "";
char g_strServiceDir[256] = "";
//UINT g_locale_ctype = 0;
/*
void UpdateStyleInfo()
{
typedef int (*CM_GetStyleTracksInfo)( int len, BYTE data[], char tracks[4][8][16][3] );
//加载ComposeModule
HINSTANCE hStyleDll = LoadLibrary( "StyleUpdate.dll" );
if( hStyleDll==NULL ){
DWORD dwRet = GetLastError();
DebugPrint( "载入风格模块失败, 程序终止! errcode=%d", dwRet );
return;
}
CM_GetStyleTracksInfo f_CM_GetStyleTracksInfo = (CM_GetStyleTracksInfo)GetProcAddress( hStyleDll, "CM_GetStyleTracksInfo" );
if( !( f_CM_GetStyleTracksInfo ) ){
DebugPrint( "获取风格模块访问函数失败, 程序终止!\n" );
return;
}
char strFileName[256];
char buf[20];
int id = 1;
while( true ){
//打开原风格文件
strcpy( strFileName, g_strStyleFileDir );
UINT nDir = ((UINT)id-1) >> 13;
sprintf( buf, "%08X\\", nDir );
strcat( strFileName, buf );
sprintf( buf, "%08X.YSF", id );
strcat( strFileName, buf );
FILE *fp = fopen( strFileName, "r+b" );
if( !fp ){
int err = GetLastError();
DebugPrint( "修改完毕,或文件读取错误err=%d\n", err );
return;
}
else{
//读取原风格信息
fseek( fp, 0, SEEK_END );
int len = ftell( fp );
int nDataSize = len - sizeof(TSTYLEINFO0);
BYTE * pData = new BYTE[nDataSize];
TMAKESTYLEINFO infoNew;
TSTYLEINFO0 infoOld;
fseek( fp, 0, SEEK_SET );
fread( &infoOld, 1, sizeof(TSTYLEINFO0), fp );
fread( pData, 1, nDataSize, fp );
//读取轨道信息
char tracks[4][8][16][3];
int size = sizeof( tracks );
memset( tracks, -1, size );
int err = f_CM_GetStyleTracksInfo( nDataSize, pData, tracks );
if( 0==err ){
//修改info
// infoNew.idStyle = id;
memcpy( infoNew.detail.type, infoOld.detail.type, sizeof(infoOld.detail.type) );
memcpy( infoNew.detail.chordRecom, infoOld.detail.chordRecom, sizeof(infoOld.detail.chordRecom) );
memcpy( infoNew.detail.aIntroBars, infoOld.detail.aIntroBars, sizeof(infoOld.detail.aIntroBars) );
memcpy( infoNew.detail.aEndingBars, infoOld.detail.aEndingBars, sizeof(infoOld.detail.aEndingBars) );
for( int s=0; s<4; s++ ){
for( int i=0; i<8; i++ ){
for( int j=0; j<16; j++ ){
infoNew.detail.tracks[s][i][j].no = tracks[s][i][j][0];
infoNew.detail.tracks[s][i][j].prog = tracks[s][i][j][1];
infoNew.detail.tracks[s][i][j].vol = tracks[s][i][j][2];
}
}
}
err = f_DB_UpdateStyle( id, &infoNew );
if( 0==err ){
fseek( fp, 0, SEEK_SET );
fwrite( &infoNew, 1, sizeof(TSTYLEINFO), fp );
fwrite( pData, 1, nDataSize, fp );
// DebugPrint( "Style %d updating OK\n", infoNew.idStyle );
}
}
if( err!=0 ){
DebugPrint( "Style %d updating failed! err=%d\n", id, err );
}
delete[] pData;
fclose( fp );
}
id++;
}
}
*/
void ModifyStyleDesc()
{
char strFileName[256];
char buf[20];
// int ids[3] = {404,418,422};
// char desc[3][120] = { "模仿周杰伦《东风破》的简单中国风,竖琴可换琵琶或古筝,鼓换电鼓",
// "模仿王菲《闷》的摇滚风格,还原前间奏,乐器协调性是美中不足",
// "麒麟谱,四不像,伪中国风。《红妆》编曲的收获,感谢花枝。" };
for( UINT i=g_iChkStyle; ; i++ ){
char strFileName[256];
char buf[20];
strcpy( strFileName, g_strStyleFileDir );
UINT nDir = (i-1) >> 13;
sprintf( buf, "%08X\\", nDir );
strcat( strFileName, buf );
sprintf( buf, "%08X.YSI", i );
strcat( strFileName, buf );
FILE *fp = fopen( strFileName, "r+b" );
if( !fp ){
int err = GetLastError();
DebugPrint( "打开风格%d失败,err=%d\n", i, err );
return;
}
else{
short len = 0;
fread( &len, 1, sizeof(short), fp );
if( len>0 ){
char* pData = new char[len];
fread( pData, 1, len, fp );
TSTYLEDETAIL detail;
int ret = StyleTrans2Detail( detail, len, (char*)pData );
if( ret<0 ){
DebugPrint( "Style %d size error\n", i );
}
else{
if( ret>0 ){
DebugPrint( "Trunc style %d %s\n", i, ret==1 ? "Author"
: ret==2 ? "AtyleName"
: "Description" );
// string ansiName;
//
// UTF8ToGBK( detail.strDescription, ansiName );
// GBKToUTF8( desc[i], ansiName);
// strcpy( detail.strDescription, ansiName.c_str() );
int size;
ret = StyleDetail2Trans( detail, size, pData );
if( ret>0 )
DebugPrint( "Trunc style %d %s\n", i, ret==1 ? "Author"
: ret==2 ? "AtyleName"
: "Description" );
len = size;
fseek( fp, 0, SEEK_SET );
fwrite( &len, 1, sizeof(short), fp );
fwrite( pData, 1, len, fp );
}
}
}
fclose( fp );
}
}
}
void CreateLog()
{
SYSTEMTIME st;
GetLocalTime(&st);
char szBufPath[MAX_PATH] = "";
sprintf( szBufPath, "%slog\\", g_strServiceDir );
if( _chdir(szBufPath) == -1)
{
_mkdir(szBufPath);
}
sprintf( szBufPath, "%s%04d-%02d-%02d.log", szBufPath, st.wYear, st.wMonth, st.wDay);
DebugModuleClose();
int iDebug = g_eDebug>0 ? g_eDebug : 1;
DebugModuleInitialize( 0xFFFF, (EDPrintDest)iDebug, szBufPath );
}
void GetStyleRecomList()
{
int tempList[MAX_STYLE_NUM+1];
memset( tempList, 0, sizeof(int)*(MAX_STYLE_NUM+1) );
int num = MAX_STYLE_NUM;
int ret = f_DB_GetRecomStyleIDs( &num, tempList );
if( ret==0 ){
tempList[MAX_STYLE_NUM] = num;
memcpy( g_aStyleRecomList, tempList, sizeof(int)*(MAX_STYLE_NUM+1) );
DebugPrint( "Recommand style num : %d\n", num );
}
else{
DebugPrint( "DB_GetRecomStyleIDs return %d\n", ret );
}
}
void GetCommonQnAList()
{
int dtUpdate = 0;
for( int i=0; i<g_nCommonQnANum; i++ ){
if( dtUpdate<g_lstCommonQnA[i].dtUpdate ){
dtUpdate = g_lstCommonQnA[i].dtUpdate;
}
}
g_nCommonQnANum = f_DB_GetCommonQnA( dtUpdate, g_nCommonQnANum, g_lstCommonQnA );
DebugPrint( "Common QnA num : %d\n", g_nCommonQnANum );
}
void GetPublicNoticeList()
{
g_nPublicNoticeNum = f_DB_GetNotice( MAX_NOTICE_NUM, g_lstPublicNotice, 0 );
DebugPrint( "Public notice num : %d\n", g_nPublicNoticeNum );
}
#define INI_FILE_NAME "DBService.ini"
#define STR_TESTVERSION_SECTION "TEST_VERSIONS"
#define STR_TESTVERSION "VERSIONS_STRING"
FILETIME g_ftIniModify;
void ReadConfigParams()
{
char szBufPath[MAX_PATH] = "";
sprintf( szBufPath, "%s%s", g_strServiceDir, INI_FILE_NAME );
HANDLE hFile = CreateFile( szBufPath, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if( hFile == INVALID_HANDLE_VALUE ){
DebugPrint( "No ini file\n" );
return;
}
int ret = -1;
FILETIME ftWrite;
ret = GetFileTime(hFile, NULL, NULL, &ftWrite);
CloseHandle( hFile );
if( !ret ){
DebugPrint( "Get ini file time error: %d\n", GetLastError());
return;
}
if( ftWrite.dwLowDateTime!=g_ftIniModify.dwLowDateTime
|| ftWrite.dwHighDateTime!=g_ftIniModify.dwHighDateTime ){
if( WAIT_OBJECT_0!=WaitForSingleObject( g_hEvClientCheck, INFINITE ) )
return;
//printf( "retrive config.\n" );
TTESTVERSION aVersion[10];
int num = 0;
char szBuf[32] = "";
ret = GetPrivateProfileString( STR_TESTVERSION_SECTION, STR_TESTVERSION, "", szBuf, 32, szBufPath );
if( ret>0 ){
char *tokenPtr=strtok( szBuf, "|" );
for( ; tokenPtr!=NULL; num++ ){
int iInner, iMaj, iMin, iMod, iBuil;
sscanf( tokenPtr, "%d,%d.%d.%d", &iInner, &iMaj, &iMin, &iMod );//, &iBuil );
aVersion[num].iClientType = iInner;
aVersion[num].version.majorVersion = iMaj;
aVersion[num].version.minorVersion = iMin;
aVersion[num].version.modifyVersion = iMod;
// aVersion[num].version.buildVersion = iBuil;
tokenPtr = strtok( NULL, "|" );
}
}
if( g_nClientTestNum>0 && g_nClientTestNum!=num ){
delete[] g_pVersionClientTest;
g_pVersionClientTest = NULL;
}
g_nClientTestNum = num;
if( num>0 ){
if( !g_pVersionClientTest ){
g_pVersionClientTest = new TTESTVERSION[num];
}
for( int i=0; i<num; i++ ){
TTESTVERSION* pVersion = &(g_pVersionClientTest[i]);
memcpy( pVersion, &aVersion[i], sizeof(TTESTVERSION) );
DebugPrint( "测试版本:%d.%d.%d\n软件内部编号:%d\n",
pVersion->version.majorVersion, pVersion->version.minorVersion,
pVersion->version.modifyVersion, //pVersion->version.buildVersion, //不设置构建版本
pVersion->iClientType );
}
}
else{
DebugPrint( "No test version.\n" );
}
SetEvent( g_hEvClientCheck );
g_ftIniModify.dwLowDateTime = ftWrite.dwLowDateTime;
g_ftIniModify.dwHighDateTime = ftWrite.dwHighDateTime;
}
else{
DebugPrint( "No config update.\n" );
}
}
void GetClientUpdateVersion()
{
if( WAIT_OBJECT_0!=WaitForSingleObject( g_hEvClientCheck, INFINITE ) ){
return;
}
int nOldTypeNum = g_nClientTypeNum;
g_nClientTypeNum = f_DB_GetClientTypeNumber();
if( nOldTypeNum>0 && g_nClientTypeNum!=nOldTypeNum ){
delete[] g_pVersionClient;
g_pVersionClient = NULL;
}
if( g_nClientTypeNum>0 ){
if( !g_pVersionClient ){
g_pVersionClient = new TCLIENTVERSION[g_nClientTypeNum];
}
if( f_DB_GetClientVersion( g_pVersionClient, g_nClientTypeNum )>=0 ){
for( int i=0; i<g_nClientTypeNum; i++ ){
TCLIENTVERSION* pVersion = &(g_pVersionClient[i]);
string ansiDescribe;
UTF8ToGBK( pVersion->swInfo.strDescribe, ansiDescribe );
DebugPrint( "软件内部编号:%d\n最新客户端版本:%d.%d.%d.%04d\n 发布时间:%d-%d-%d\n 文件大小:%dK\n 文件描述:%s\n",
pVersion->iClientType,
pVersion->swInfo.version.majorVersion, pVersion->swInfo.version.minorVersion,
pVersion->swInfo.version.modifyVersion, pVersion->swInfo.version.buildVersion,
pVersion->swInfo.tIssueDate>>16, (pVersion->swInfo.tIssueDate&0xFF00)>>8, (pVersion->swInfo.tIssueDate&0xFF),
pVersion->swInfo.nFileSize, ansiDescribe.c_str() );
}
}
else{
DebugPrint( "获取最新客户端版本信息失败!\n" );
}
}
else if( g_nClientTypeNum<0 ){
DebugPrint( "获取最新客户端类型数失败!\n" );
}
SetEvent( g_hEvClientCheck );
}
void OnTimerFunc( void *dummy )
{
CreateLog();
// GetClientUpdateVersion();
GetStyleRecomList();
GetCommonQnAList();
// GetPublicNoticeList();
DebugPrint( "OnTimerFunc exit.\n" );
}
bool ServiceInit()
{
g_hEvServiceThread = CreateEvent(
NULL, // no security attributes
TRUE, // manual reset event
FALSE, // not-signalled
NULL); // no name
g_hEvClientCheck = CreateEvent(
NULL, // no security attributes
FALSE, // auto reset event
TRUE, // signalled
NULL); // no name
if( !(g_hEvServiceThread && g_hEvClientCheck )){
return false;
}
WORD wVersionRequested;
WSADATA wsaData;
int err;
/*
//获取本地编码格式
char* locname = setlocale(LC_CTYPE, "");
char* code = strchr( locname, '.' );
//DebugPrint( "locale code: %s\n", code);
if( !strcmp(code, ".936") || !strcmp(code, ".GBK") ){
g_locale_ctype = CTYPE_GBK;
}
*/
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
// Tell the user that we could not find a usable
// WinSock DLL.
_tprintf(TEXT("CreateService failed - can't startup wsock.\n"));
if( g_hEvServiceThread ){
CloseHandle( g_hEvServiceThread );
g_hEvServiceThread = NULL;
}
return false;
}
//设置debug参数
HKEY hRootKey;
DWORD nFlag=1, dwLength=4;
if( ERROR_SUCCESS==RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\YHD\\ComposerService",
0, KEY_ALL_ACCESS, &hRootKey ) ){
if( RegQueryValueEx(hRootKey,"DebugFlag",NULL,NULL,(BYTE*)&nFlag,&dwLength)!=ERROR_SUCCESS ){
RegSetValueEx(hRootKey,"DebugFlag",0,REG_DWORD,(BYTE*)&nFlag,4 );
}
RegCloseKey( hRootKey );
}
char chTemp[2560];
GetModuleFileName( NULL, chTemp, 256 );
*(strrchr(chTemp, '\\')+1) = '\0';
strcpy( g_strServiceDir, chTemp );
//DebugModuleInitialize( 0xFFFF, (EDPrintDest)g_eDebug, NULL );
CreateLog();
//DebugPrint("DebugModuleInitialize success!\n");
//载入数据库访问模块
if( !LoadDB() ){
return FALSE;
}
// int ret = f_DB_InitDatabases("localhost", "root", "168soft.xyz");
f_DB_GetPath( g_strStyleFileDir, g_strWebFileDir, g_strMusicFileDir );
DebugPrint( "Style_dir: %s\nWeb_dir: %s\nMusic_dir: %s\n", g_strStyleFileDir, g_strWebFileDir, g_strMusicFileDir );
if( strlen(g_strMusicFileDir)>0 ){
char* pos = strstr( g_strMusicFileDir, "File" )+4;
if( pos[0]!='/' && pos[0]!='\\' ){
int num;
sscanf( pos, "%d", &num );
sprintf( g_strMusicLocation, "%d", num );
}
}
/////////////////////////////////////////////////////////////
//修改风格信息专用
//#ifdef _UPDATE
if( g_iChkStyle>0 ){
// UpdateStyleInfo();
ModifyStyleDesc();
return FALSE;
}
//#endif
/////////////////////////////////////////////////////////////
GetClientUpdateVersion();
memset( g_aStyleRecomList, 0, sizeof(int)*(MAX_STYLE_NUM+1) );
GetStyleRecomList();
g_ftIniModify.dwLowDateTime = 0;
g_ftIniModify.dwHighDateTime = 0;
ReadConfigParams();
GetCommonQnAList();
GetPublicNoticeList();
//创建数据接收
g_pDataBuffers = new CDataBufferManager;
//创建消息响应管理
g_pResponses = new CResponseManager;
//生成消息接收线程
CUDPSocket * pSocket = new CUDPSocket( 12071 );
if( pSocket && pSocket->IsOpen() ){
g_pMessageReceiveThread = new CUDPMessageReceiveThread( 3000, pSocket );
g_pMessageReceiveThread->Resume();
}
//生成消息处理线程池
for( int i=0; i<20; i++ ){
pSocket = new CUDPSocket();
if( pSocket && pSocket->IsOpen() ){
CMessageHandleThread* pThread = new CMessageHandleThread( 3000, pSocket );
g_lstMessageHandleThreads.push_back( pThread );
}
}
//生成IOComplete线程
g_pIOCmpltThread = new CIOCmpltThread(3000);
g_pIOCmpltThread->Resume();
_tprintf(TEXT("Composer Service is running...\n"));
return true;
}
void ServiceDeInit()
{
_tprintf(TEXT("Composer Service is stopping...\n"));
if( g_hEvClientCheck ){
CloseHandle( g_hEvClientCheck );
}
if( g_pVersionClient ){
delete[] g_pVersionClient;
g_pVersionClient = NULL;
}
if( g_pMessageReceiveThread ){
g_pMessageReceiveThread->Terminate();
delete g_pMessageReceiveThread;
g_pMessageReceiveThread = NULL;
}
MHTHREADLIST::iterator iMT = g_lstMessageHandleThreads.begin();
while( iMT!=g_lstMessageHandleThreads.end() ){
(*iMT)->Terminate();
delete (*iMT);
iMT = g_lstMessageHandleThreads.erase( iMT );
}
if( g_pIOCmpltThread ){
g_pIOCmpltThread->Terminate();
delete g_pIOCmpltThread;
g_pIOCmpltThread = NULL;
}
FreeDB();
if( g_pDataBuffers ){
delete g_pDataBuffers;
g_pDataBuffers = NULL;
}
if( g_pResponses ){
delete g_pResponses;
g_pResponses = NULL;
}
DebugModuleClose();
WSACleanup( );
DebugPrint( "System unloaded!" );
if( g_hEvServiceThread ){
SetEvent( g_hEvServiceThread );
}
_tprintf(TEXT("Composer Service stopped.\n"));
}
/*
#ifndef _DEBUG
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址
#endif
*/
DWORD WINAPI DBMain(void* pParam)
{
MSG msg;
if( !ServiceInit() ){
// return 1;
}
SYSTEMTIME st;
GetLocalTime(&st);
DWORD timeCount = st.wHour * 60 * 60 + st.wMinute * 60 + st.wSecond;
// timeCount = 0; //test
UINT uTimer = SetTimer( NULL, 0, 1000, NULL );
while( GetMessage(&msg, NULL, 0, 0) && msg.message!=WM_CLOSE ){
if( msg.message==WM_TIMER && msg.wParam==uTimer ){
if( g_pIOCmpltThread ){
g_pIOCmpltThread->OnTimer();
}
if( g_pDataBuffers ){
g_pDataBuffers->OnTimer();
}
if( g_pResponses ){
g_pResponses->OnTimer();
}
if( ++timeCount>=86400 ){ //00:00:00
// if( ++timeCount>=600 ){ //test 10 minutes
// timeCount = 0; //test
GetLocalTime(&st);
timeCount = st.wHour * 60 * 60 + st.wMinute * 60 + st.wSecond;
if( st.wHour==0 ){
// _beginthread( OnTimerFunc, 0, NULL );
CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)OnTimerFunc, 0, 0, 0 );
}
}
if( ( timeCount & 0x1FF )==0 ){ //512s~9m
f_DB_CleanVipLog();
}
if( ( timeCount & 0xFFF )==0 ){ //4095s~68m~1h 获取测试版本信息
ReadConfigParams();
}
if( ( timeCount & 0x1FFF )==0 ){ //8191s~136m~2h 获取发布版本信息
GetClientUpdateVersion();
}
continue;
}
try{
TranslateMessage (&msg);
DispatchMessage (&msg);
}catch (...){
_tprintf(TEXT("!!!!!!Unexpected exception in WMain()!!!!!!\n"));
}
}
KillTimer( NULL, uTimer );
IF_DEBUG_SYSMANAGER(DebugPrint("%X:In %s Line %d WMain ExitThread!\n",
TRACE_NUMBER(e_Trace_SysManager,e_Trace_Normal),
__FILE__,__LINE__))
ServiceDeInit();
_tprintf(TEXT("WMain() ExitThread!\n"));
ExitThread(0);
return 0;
}
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef ServiceInitH
#define ServiceInitH
#ifdef _SERVICEINIT_CPP
HWND g_hWnd = NULL;
HANDLE g_hEvServiceThread = NULL;
#else
extern HWND g_hWnd;
extern HANDLE g_hEvServiceThread;
#endif
bool ServiceInit();
void ServiceDeInit();
DWORD WINAPI DBMain(void* pParam);
#endif //_SERVICEINIT_H
+566
View File
@@ -0,0 +1,566 @@
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <signal.h>
#include "debug.h"
#include "ServiceThread.h"
#include "DBInterface.h"
#include "MessageThread.h"
#include "DataBuffers.h"
#include "ResponseManager.h"
#include "EpollThread.h"
#include "INIParser.h"
extern int g_eDebug;
extern int g_iChkStyle;
extern MHTHREADLIST g_lstMessageHandleThreads;
extern CSema* g_pSemaStop;
int g_iSignal = 0;
CSema* g_pSemaService = NULL;
CSema* g_pSemaClientCheck = NULL;
CSema* g_pSemaTimer = NULL;
CUDPMessageReceiveThread * g_pMessageReceiveThread = NULL;
EpollThread* g_pEpollThread = NULL;
CDataBufferManager* g_pDataBuffers = NULL;
CResponseManager* g_pResponses = NULL;
int g_aStyleRecomList[MAX_STYLE_NUM+1];
TQNAITEM g_lstCommonQnA[200];
TNOTICEITEM g_lstPublicNotice[MAX_NOTICE_NUM];
int g_nCommonQnANum = 0, g_nPublicNoticeNum = 0;
TCLIENTVERSION* g_pVersionClient = NULL;
TTESTVERSION* g_pVersionClientTest = NULL;
int g_nClientTypeNum = 0,
g_nClientTestNum = 0;
HANDLE g_hEvClientCheck = NULL;
char g_strStyleFileDir[256] = "";
char g_strWebFileDir[256] = "";
char g_strMusicFileDir[256] = "";
char g_strMusicLocation[8] = "";
char g_strServiceDir[256] = "";
void SignalHandler(int signo)
{
if(signo==SIGTERM || signo==SIGINT || signo==SIGUSR1){
DebugPrint("Terminate by signal: %d", signo);
if(signo==SIGUSR1)
g_iSignal = signo;
if(g_pSemaStop)
g_pSemaStop->ActV();
}
else if(signo==SIGALRM){
if(g_pSemaTimer)
g_pSemaTimer->ActV();
}
}
void CreateLog()
{
time_t t;
struct tm *tm;
time(&t);
tm = localtime(&t);
char szBufPath[256] = "";
sprintf( szBufPath, "%s/log/", g_strServiceDir );
// DebugPrint(szBufPath);
if( chdir(szBufPath) == -1)
mkdir(szBufPath, S_IRWXU|S_IRWXG);
sprintf( szBufPath, "%s%04d-%02d-%02d.log", szBufPath, tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
DebugModuleClose();
int iDebug = g_eDebug>0 ? g_eDebug : 1;
DebugModuleInitialize( 0xFFFF, (EDPrintDest)iDebug, szBufPath );
}
#define INI_FILE_NAME "DBService.ini"
#define STR_TESTVERSION_SECTION "TEST_VERSIONS"
#define STR_TESTVERSION "VERSIONS_STRING"
#ifdef _WIN32
#define stat _stat
#endif
time_t g_ftIniModify = 0;
void ReadConfigParams()
{
char szFileName[260] = "";
sprintf( szFileName, "%s/%s", g_strServiceDir, INI_FILE_NAME );
struct stat stFile;
if( stat( szFileName, &stFile )!=0 ){
DebugPrint( "get ini file stat error: %d", errno );
return;
}
if( g_ftIniModify!=stFile.st_mtime ){
if(g_pSemaClientCheck->ActP())
return;
//printf( "retrive config.\n" );
TTESTVERSION aVersion[10];
int num = 0;
INIParser parser;
parser.ReadINI(szFileName);
string szLine = parser.GetValue(STR_TESTVERSION_SECTION, STR_TESTVERSION);
if( !szLine.empty() ){
char szBuf[512] = "";
strcpy(szBuf, szLine.c_str());
char *tokenPtr=strtok( szBuf, "|" );
for( ; tokenPtr!=NULL; num++ ){
int iInner, iMaj, iMin, iMod, iBuil;
sscanf( tokenPtr, "%d,%d.%d.%d", &iInner, &iMaj, &iMin, &iMod );//, &iBuil );
aVersion[num].iClientType = iInner;
aVersion[num].version.majorVersion = iMaj;
aVersion[num].version.minorVersion = iMin;
aVersion[num].version.modifyVersion = iMod;
// aVersion[num].version.buildVersion = iBuil;
tokenPtr = strtok( NULL, "|" );
}
}
parser.Clear();
if( g_nClientTestNum>0 && g_nClientTestNum!=num ){
delete[] g_pVersionClientTest;
g_pVersionClientTest = NULL;
}
g_nClientTestNum = num;
if( num>0 ){
if( !g_pVersionClientTest ){
g_pVersionClientTest = new TTESTVERSION[num];
}
for( int i=0; i<num; i++ ){
TTESTVERSION* pVersion = &(g_pVersionClientTest[i]);
memcpy( pVersion, &aVersion[i], sizeof(TTESTVERSION) );
DebugPrint( "测试版本: %d.%d.%d\t软件内部编号: %d",
pVersion->version.majorVersion, pVersion->version.minorVersion,
pVersion->version.modifyVersion, //pVersion->version.buildVersion, //不设置构建版本
pVersion->iClientType );
}
}
else{
DebugPrint( "No test version." );
}
g_pSemaClientCheck->ActV();
// SetEvent( g_hEvClientCheck );
g_ftIniModify = stFile.st_mtime;
}
else{
DebugPrint( "No config update." );
}
}
void GetStyleRecomList()
{
int tempList[MAX_STYLE_NUM+1];
memset( tempList, 0, sizeof(int)*(MAX_STYLE_NUM+1) );
int num = MAX_STYLE_NUM;
int ret = f_DB_GetRecomStyleIDs( &num, tempList );
if( ret==0 ){
tempList[MAX_STYLE_NUM] = num;
memcpy( g_aStyleRecomList, tempList, sizeof(int)*(MAX_STYLE_NUM+1) );
DebugPrint( "Recommand style num : %d", num );
}
else{
DebugPrint( "DB_GetRecomStyleIDs return %d", ret );
}
}
void GetCommonQnAList()
{
// int dtUpdate = 0;
// for( int i=0; i<g_nCommonQnANum; i++ ){
// if( dtUpdate<g_lstCommonQnA[i].dtUpdate ){
// dtUpdate = g_lstCommonQnA[i].dtUpdate;
// }
// }
// g_nCommonQnANum = f_DB_GetCommonQnA( dtUpdate, g_nCommonQnANum, g_lstCommonQnA );
g_nCommonQnANum = f_DB_GetCommonQnA( 0, g_nCommonQnANum, g_lstCommonQnA );
DebugPrint( "Common QnA num : %d", g_nCommonQnANum );
}
void GetPublicNoticeList()
{
g_nPublicNoticeNum = f_DB_GetNotice( MAX_NOTICE_NUM, g_lstPublicNotice, 0 );
DebugPrint( "Public notice num : %d", g_nPublicNoticeNum );
}
void GetClientUpdateVersion()
{
if( !g_pSemaClientCheck || g_pSemaClientCheck->ActP() ){
return;
}
int nOldTypeNum = g_nClientTypeNum;
g_nClientTypeNum = f_DB_GetClientTypeNumber();
TCLIENTVERSION * pClients = NULL;
if( g_nClientTypeNum>0 ){ //有可用客户端
pClients = new TCLIENTVERSION[g_nClientTypeNum];
if( f_DB_GetClientVersion( pClients, g_nClientTypeNum )<0 ){ //获取客户端信息
delete[] pClients;
pClients = NULL;
}
}
bool bChange = true;
if( g_nClientTypeNum<0 ){
DebugPrint( "获取最新客户端类型数失败!" );
g_nClientTypeNum = nOldTypeNum; //不改变原客户端信息
bChange = false;
}
else if(g_nClientTypeNum>0 && !pClients){
DebugPrint( "获取最新客户端版本信息失败!" );
g_nClientTypeNum = nOldTypeNum; //不改变原客户端信息
bChange = false;
}
else if( g_nClientTypeNum==nOldTypeNum ){ //数量相同则比较是否有改变
bChange = false;
for( int i=0; i<g_nClientTypeNum; i++ ){
TCLIENTVERSION* pOldVersion = &(g_pVersionClient[i]);
TCLIENTVERSION* pNewVersion = &(pClients[i]);
if(memcmp(pOldVersion, pNewVersion, sizeof(TCLIENTVERSION))){
bChange = true;
break;
}
}
}
if(bChange){ //有变化
if(g_pVersionClient) //清理原内存
delete[] g_pVersionClient;
g_pVersionClient = pClients;
for( int i=0; i<g_nClientTypeNum; i++ ){ //打印信息
TCLIENTVERSION* pVersion = &(g_pVersionClient[i]);
DebugPrint( "软件内部编号: %d\n\t最新客户端版本: %d.%d.%d.%04d\n\t发布时间: %d-%d-%d",
pVersion->iClientType,
pVersion->swInfo.version.majorVersion, pVersion->swInfo.version.minorVersion,
pVersion->swInfo.version.modifyVersion, pVersion->swInfo.version.buildVersion,
pVersion->swInfo.tIssueDate>>16, (pVersion->swInfo.tIssueDate&0xFF00)>>8, (pVersion->swInfo.tIssueDate&0xFF));
}
}
else if(pClients){ //无变化清理内存
delete[] pClients;
pClients = NULL;
}
g_pSemaClientCheck->ActV();
}
bool ServiceInit()
{
g_pSemaService = new CSema(NULL, 0);
g_pSemaClientCheck = new CSema(NULL, 1);
g_pSemaTimer = new CSema(NULL, 0);
CreateLog();
//DebugPrint("DebugModuleInitialize success!\n");
//载入数据库访问模块
if( !LoadDB() ){
return FALSE;
}
f_DB_GetPath( g_strStyleFileDir, g_strWebFileDir, g_strMusicFileDir );
DebugPrint( "Style_dir: %s\n\tWeb_dir: %s\n\tMusic_dir: %s", g_strStyleFileDir, g_strWebFileDir, g_strMusicFileDir );
if( strlen(g_strMusicFileDir)>0 ){
char* pos = strstr( g_strMusicFileDir, "File" )+4;
if( pos[0]!='/' && pos[0]!='\\' ){
int num;
sscanf( pos, "%d", &num );
sprintf( g_strMusicLocation, "%d", num );
}
}
/////////////////////////////////////////////////////////////
//修改风格信息专用
if( g_iChkStyle>0 ){
// UpdateStyleInfo();
// ModifyStyleDesc();
return FALSE;
}
/////////////////////////////////////////////////////////////
GetClientUpdateVersion();
memset( g_aStyleRecomList, 0, sizeof(int)*(MAX_STYLE_NUM+1) );
GetStyleRecomList();
ReadConfigParams();
GetCommonQnAList();
GetPublicNoticeList();
//创建数据接收
g_pDataBuffers = new CDataBufferManager;
//创建消息响应管理
g_pResponses = new CResponseManager;
//生成UDP消息接收线程
CUDPSocket * pSocket = new CUDPSocket( LISTEN_PORT );
if( pSocket && pSocket->IsOpen() ){
g_pMessageReceiveThread = new CUDPMessageReceiveThread( 3000, pSocket );
g_pMessageReceiveThread->Resume();
//生成消息处理线程池
for( int i=0; i<20; i++ ){
CMessageHandleThread* pThread = new CMessageHandleThread( 3000, pSocket );
g_lstMessageHandleThreads.push_back( pThread );
}
}
//生成epoll线程
g_pEpollThread = new EpollThread();
g_pEpollThread->Resume();
printf("Composer Service is running...\n");
return true;
}
void ServiceDeInit()
{
printf("Composer Service is stopping...\n");
// if( g_hEvClientCheck ){
// CloseHandle( g_hEvClientCheck );
// }
if( g_pSemaClientCheck ){
delete g_pSemaClientCheck;
g_pSemaClientCheck = NULL;
}
if( g_pSemaTimer ){
delete g_pSemaTimer;
g_pSemaTimer = NULL;
}
if( g_pVersionClient ){
delete[] g_pVersionClient;
g_pVersionClient = NULL;
}
if( g_pMessageReceiveThread ){
g_pMessageReceiveThread->Terminate();
delete g_pMessageReceiveThread;
g_pMessageReceiveThread = NULL;
}
MHTHREADLIST::iterator iMT = g_lstMessageHandleThreads.begin();
while( iMT!=g_lstMessageHandleThreads.end() ){
(*iMT)->Terminate();
// (*iMT)->Resume();
delete (*iMT);
iMT = g_lstMessageHandleThreads.erase( iMT );
}
if( g_pEpollThread ){
g_pEpollThread->Terminate();
}
FreeDB();
if( g_pDataBuffers ){
delete g_pDataBuffers;
g_pDataBuffers = NULL;
}
if( g_pResponses ){
delete g_pResponses;
g_pResponses = NULL;
}
if( g_pEpollThread ){
delete g_pEpollThread;
g_pEpollThread = NULL;
}
DebugModuleClose();
printf( "System unloaded!\n" );
if(g_pSemaService)
g_pSemaService->ActV();
printf("Composer Service stopped.\n");
}
// void CheckProCount()
// {
// //////////////////////////////////////////////////////
// // 统计 PC pro 函数
// #include "MessageHandle.h"
// int n826(0), nOth(0);
// GetProCount(n826, nOth);
// DebugPrint("PC pro使用人数 826 : other = %d : %d", n826, nOth);
// //////////////////////////////////////////////////////
// }
void* OneDaySchedule(void* arg)
{
// CheckProCount();
CreateLog();
GetStyleRecomList();
GetCommonQnAList();
CheckMemoryUsage();
DebugPrint( "OneDaySchedule exit." );
return NULL;
}
int SetTimer(int sec)
{
itimerval value;
value.it_value.tv_sec = sec;
value.it_value.tv_usec = 0;
value.it_interval = value.it_value;
return setitimer(ITIMER_REAL, &value, NULL);
}
int GetTimeCount()
{
time_t t;
struct tm *tm;
time(&t);
tm = localtime(&t);
return tm->tm_hour * 60 * 60 + tm->tm_min * 60 + tm->tm_sec;
}
CServiceThread::CServiceThread():CThread(3000)
{
// getcwd(g_strServiceDir, 256);
if(readlink("/proc/self/exe", g_strServiceDir, 256)>0){
char* p = strrchr(g_strServiceDir,'/');
*p = 0;
}
}
void CServiceThread::Terminate()
{
CThread::Terminate();
if( g_pSemaTimer )
g_pSemaTimer->ActV();
}
void CServiceThread::Main()
{
DWORD timeCount = 0;
if( ServiceInit() ){
timeCount = GetTimeCount();
/* 设置信号的处理方式 */
signal(SIGALRM, SignalHandler);
signal(SIGTERM, SignalHandler);
signal(SIGINT, SignalHandler);
signal(SIGUSR1, SignalHandler);
/* 以系统真实的时间来计算,将送出SIGALRM信号 */
if (SetTimer(1) < 0){
/* 函数调用返回错误 */
DebugPrint("Setitimer Failed : %s", strerror(errno));
Terminate();
}
}
while(!m_bExit){
g_pSemaTimer->ActP();
// if( g_pIOCmpltThread ){
// g_pIOCmpltThread->OnTimer();
// }
if( g_pDataBuffers ){
g_pDataBuffers->OnTimer();
}
if( g_pResponses ){
g_pResponses->OnTimer();
}
if( ++timeCount>=86400 ){ //00:00:00
// if( ++timeCount>=15 ){ //test 10 minutes
// timeCount = 0; //test
timeCount = GetTimeCount();
if( timeCount<3600 ){
#ifdef _WIN32
CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)OnTimerFunc, 0, 0, 0 );
#else
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create( &tid, &attr, OneDaySchedule, NULL);
pthread_attr_destroy (&attr);
#endif
}
}
if( ( timeCount & 0x1FF )==0 ){ //0x1FF 512s~9m 定时清除VIP登录记录(10分钟内最多3个设备同时登录)
f_DB_CleanVipLog();
}
if( timeCount>0 && ( timeCount & 0xFFF )==0 //0xFFF 4095s~68m~1h 获取测试版本信息等
&& timeCount < 86000 ){ //23:53:35秒的检测跳过
ReadConfigParams();
GetClientUpdateVersion();
GetPublicNoticeList();
}
// if( ( timeCount & 0x1FFF )==0 ){ //0x1FFF 8191s~136m~2h 获取发布版本信息
// GetClientUpdateVersion();
// GetPublicNoticeList();
// }
}
SetTimer(0);
// CheckProCount();
ServiceDeInit();
DebugPrint("Service main thread exited.");
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef ServiceThreadH
#define ServiceThreadH
#include "thread.h"
void SignalHandler(int);
// CServiceThread
//
class CServiceThread : public CThread
{
private:
public:
CServiceThread();
virtual void Terminate() ;
virtual void Main();
};
#endif
+264
View File
@@ -0,0 +1,264 @@
#define _DEBUG_CPP_
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>
#include <string>
#include <iostream>
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#endif
//#include "object.h"
#include "Socket.h"
#include "debug.h"
EDPrintDest g_nDest;//表示打印的目的地
CTCPSocket * g_pNetChannel = NULL;
FILE * g_pFileChannel = NULL;
//using namespace std;
/*******************************************************
int DebugPrint(const char * fmt, ...)
功能描述:
提供类似于printf的调试打印语句
********************************************************/
int DebugPrint(const char * fmt, ...)
{
char sDebug[MAX_DEBUG_PRINT];
sDebug[0] = '\0';
/*
int nLen=strlen(sDebug);
sDebug[nLen]='@';
sDebug[nLen+1]='\0';
*/
if( g_nDest!=e_ToNet ){
time_t now;
time(&now);
strftime(sDebug, sizeof(sDebug), "[%H:%M:%S] ",localtime(&now));
}
va_list vaParams;
va_start(vaParams,fmt);
vsprintf(sDebug+strlen(sDebug),fmt,vaParams);
if( g_nDest==e_ToNet ){
int nLen=strlen(sDebug);
sDebug[nLen]='@';
sDebug[nLen+1]='\0';
}
switch (g_nDest){
case e_ToFile:
{
if( g_pFileChannel==NULL )
return 0;
fprintf(g_pFileChannel,"%s\n",sDebug);
fflush(g_pFileChannel);
break;
}
case e_ToNet:
{
if( g_pNetChannel==NULL || !g_pNetChannel->IsOpen() )
return 0;
g_pNetChannel->Send( sDebug, strlen(sDebug));
break;
}
case e_ToScreen:
{
printf( "%s\n", sDebug );
break;
}
default:
{
#ifdef _WIN32
OutputDebugString( sDebug );
#else
printf( "%s\n", sDebug );
#endif
}
}
return 1;
}
/*******************************************************
void DebugModuleInitialize(int nDebug,EDPrintDest nDest,char *sHost)
参数说明:
int nDebug
产品的名称
EDPrintDest nDest
使用什么方式打印
char *sHost
使用网络打印时用的主机地址
功能描述:
初始化调试模块
********************************************************/
void DebugModuleInitialize(int nDebug,EDPrintDest nDest,char *sHost)
{
if( nDebug==0 ) return;
g_nDebugFlag = nDebug;
g_nDest = nDest;
switch (g_nDest){
case e_ToFile:
{
g_pFileChannel = fopen( sHost, "a+" );
break;
}
case e_ToNet:
{
g_pNetChannel = new CTCPSocket( DEBUG_HOST, DEBUG_TCPPORT );
if( g_pNetChannel && !g_pNetChannel->IsOpen() ){
delete g_pNetChannel;
g_pNetChannel = NULL;
}
break;
}
}
}
/*******************************************************
void DebugModuleClose()
功能描述:
停止使用调试模块
********************************************************/
void DebugModuleClose()
{
switch (g_nDest){
case e_ToFile:
{
if( g_pFileChannel )
fclose( g_pFileChannel );
g_pFileChannel = NULL;
break;
}
case e_ToNet:
{
if( g_pNetChannel )
delete g_pNetChannel;
g_pNetChannel = NULL;
break;
}
}
}
void DllDebugModuleInitialize(int nDebug,EDPrintDest nDest,void* pChannel)
{
if( nDebug==0 ) return;
g_nDebugFlag = nDebug;
g_nDest = nDest;
switch (g_nDest){
case e_ToFile:
{
g_pFileChannel = (FILE*)pChannel;
break;
}
case e_ToNet:
{
g_pNetChannel = (CTCPSocket*)pChannel;
break;
}
}
}
void DllDebugModuleClose()
{
g_nDest = e_NoDest;
g_pFileChannel = NULL;
g_pNetChannel = NULL;
}
void GetDebugParams(int &nDebug,EDPrintDest &nDest,void **pChan)
{
nDebug = g_nDebugFlag;
nDest = g_nDest;
switch (g_nDest){
case e_ToFile:
*pChan = (void*)g_pFileChannel;
break;
case e_ToNet:
*pChan = (void*)g_pNetChannel;
break;
case e_ToScreen:
case e_ToDebug:
*pChan = NULL;
break;
}
}
long GetMemoryUsage()
{
long mem = 0L;
FILE* fp = fopen( "/proc/self/statm", "r" );
if( fp != NULL ){
long rss;
if ( fscanf( fp, "%*s%ld", &rss ) == 1 )
mem = rss << 2;
fclose( fp );
}
return mem;
}
#include <signal.h>
#include <thread.h>
#include <malloc.h>
extern char g_strServiceDir[256];
int u_nCurrMemUsedMax(0), u_nCurrMemUsedMin(0);
char u_szMemLog[256] = "";
CSema u_smMemLog("smMemLog",1);
void CheckMemoryUsage(int iParam)
{
CMutexLock lockProcess( &u_smMemLog );
int mem = (int)GetMemoryUsage();
if(mem>u_nCurrMemUsedMax){
if(u_nCurrMemUsedMax>u_nCurrMemUsedMin){ //记录波峰波谷
if(strlen(u_szMemLog)==0)
sprintf( u_szMemLog, "%s/mem.log", g_strServiceDir );
char sTime[32] = "";
time_t now;
time(&now);
strftime(sTime, 32, "%Y-%m-%d %H:%M:%S",localtime(&now));
FILE* fp = fopen( u_szMemLog, "a+" );
if(fp){
fprintf(fp, "[%s] %8d %8d\n", sTime, u_nCurrMemUsedMin, u_nCurrMemUsedMax);
fflush(fp);
fclose(fp);
}
}
u_nCurrMemUsedMax = u_nCurrMemUsedMin = mem;
DebugPrint("!!!!! Memory used: %d, msg: 0x%X", mem, iParam);
if(mem>131072 && !malloc_trim(0)){
DebugPrint("!!!!! Memory exceeded: %d", mem);
raise(SIGUSR1);
}
}
else if(mem<u_nCurrMemUsedMin){
u_nCurrMemUsedMin = mem;
DebugPrint("!!!!! Memory used: %d, msg: 0x%X", mem, iParam);
}
else if(iParam==0){
DebugPrint("!!!!! Memory used: %d, (%d - %d)", mem, u_nCurrMemUsedMin, u_nCurrMemUsedMax);
}
}
+104
View File
@@ -0,0 +1,104 @@
#ifndef DebugH
#define DebugH
#ifdef _DEBUG_CPP_
int g_nDebugFlag=0xFFFF;
#else
extern int g_nDebugFlag;
#endif
enum EDPrintDest{
e_NoDest,
e_ToFile,
e_ToNet,
e_ToScreen,
e_ToDebug
};
#ifdef __cplusplus
extern "C" {
#endif
#define DEBUG_FILE "ComposeServiceLog.txt"
#define DEBUG_HOST "127.0.0.1"
#define DEBUG_TCPPORT 2510
#define MAX_DEBUG_PRINT 10240
/*Debug代码*/
int DebugPrint(const char *fmt,...);
void DebugModuleInitialize(int nDebug,EDPrintDest nDest,char *sHost=DEBUG_HOST);
void DebugModuleClose();
void GetDebugParams( int &nDebug, EDPrintDest &nDest, void **pChan );
long GetMemoryUsage();
void CheckMemoryUsage(int iParam=0);
#ifdef _WIN32
void DllDebugModuleClose();
void __declspec(dllexport) DllDebugModuleInitialize(int nDebug,EDPrintDest nDest,void* pChannel);
typedef void (*PFDLLDEBUGINITIALIZE)(int nDebug,EDPrintDest nDest,void* pChannel);
#endif
/*条件判断语句*/
#define DEBUG_COMMON 0x0001
#define DEBUG_CLIENTAPP 0x0002
#define DEBUG_SYSMANAGER 0x0004
#define DEBUG_CLIENTMANAGER 0x0008
#define DEBUG_NODEMANAGER 0x0010
#define DEBUG_CONFMANAGER 0x0020
#define DEBUG_CONFCONTROL 0x0080
#define DEBUG_GATEKEEPER 0x0100
#define DEBUG_MCUSTACK 0x0200
#define DEBUG_NETMANAGER 0x0400
#define DEBUG_CONNECTION 0x0040
#define IF_DEBUGOUT(f) if (g_nDebugFlag & (f))
#define IF_DEBUG_COMMON(A) IF_DEBUGOUT(DEBUG_COMMON) {A;};
#define IF_DEBUG_CLIENTAPP(A) IF_DEBUGOUT(DEBUG_CLIENTAPP) {A;};
#define IF_DEBUG_SYSMANAGER(A) IF_DEBUGOUT(DEBUG_SYSMANAGER) {A;};
#define IF_DEBUG_CLIENTMANAGER(A) IF_DEBUGOUT()DEBUG_CLIENTMANAGER {A;};
#define IF_DEBUG_NODEMANAGER(A) IF_DEBUGOUT(DEBUG_NODEMANAGER) {A;};
#define IF_DEBUG_CONFMANAGER(A) IF_DEBUGOUT(DEBUG_CONFMANAGER) {A;};
#define IF_DEBUG_CONFCONTROL(A) IF_DEBUGOUT(DEBUG_CONFCONTROL) {A;};
#define IF_DEBUG_GATEKEEPER(A) IF_DEBUGOUT(DEBUG_GATEKEEPER) {A;};
#define IF_DEBUG_MCUSTACK(A) IF_DEBUGOUT(DEBUG_MCUSTACK) {A;};
#define IF_DEBUG_NETMANAGER(A) IF_DEBUGOUT(DEBUG_NETMANAGER) {A;};
#define IF_DEBUG_CONNECTION(A) IF_DEBUGOUT(DEBUG_CONNECTION) {A;}
/*跟踪消息的编号相关定义*/
#define TRACE_NUMBER(nMajor,nGrade) (nMajor<<10)|(nGrade)
#define TRACE_MAJOR(nType) (nType>>10)
#define TRACE_GRADE(nType) (nType&0x03)
enum ETraceMajorType{ // 出错的模块编号
e_Trace_Common=0x1, // 公共部分
e_Trace_ClientApp, // 客户端程序
e_Trace_SysManager, // 系统管理
e_Trace_ClientManager, // 客户端管理
e_Trace_NodeManager, // 节点管理
e_Trace_ConfManager, // 会议管理
e_Trace_TemplateManager, // 模板管理
e_Trace_ConfControl, // 会议控制
e_Trace_GateKeeper, // Gatekeeper
e_Trace_MCUStack, // MCU协议栈
e_Trace_NetManager // 网络管理
};
enum ETraceGrade{ // 错误等级
e_Trace_Severe, // 严重的错误可能引起异常
e_Trace_Major, // 断言出错,值得关注
e_Trace_Normal // 一般跟踪消息
};
/*****************************************
// Debug接口的用法示例
//
IF_DEBUG_COMMON(DebugPrint("%X:In %s Line %d 用来建立连接的地址非法\n",
TRACE_NUMBER(e_Trace_Common,e_Trace_Major),
__FILE__,__LINE__))
*****************************************/
#ifdef __cplusplus
}
#endif
#endif // DebugH