使用goahead搭建https服務器的實例

                                                   

webcomm與前端的通訊-goahead服務器流程圖 

#ifndef __CET_WEBCOMM_H__
#define __CET_WEBCOMM_H__

// 0x0000FFFF
typedef enum eWebSubOptionType
{
	WSOT_DASHBOARD			= 0X00000001,
	WSOT_INTERFACE			= 0X00000002,	
	WSOT_CONNECTION 		= 0X00000004,	
	WSOT_NETWORK			= 0X00000008,
	WSOT_WLAN				= 0X00000010,
	WSOT_PARAMETERS 		= 0X00000020,
	WSOT_EXPORT 			= 0X00000040,
	WSOT_RESET				= 0X00000080,
	WSOT_FW_UPDATE			= 0X00000100,
	WSOT_DEBUG				= 0X00000200,
	WSOT_LOGS				= 0X00000400,
	WSOT_USERS				= 0X00000800,
	WSOT_DATE_AND_TIME		= 0X00001000,
	WSOT_LOAD_CERT			= 0X00002000,
	WSOT_IPFILTER			= 0X00004000,
	WSOT_ABOUT				= 0X00008000,
	WSOT_MUST_SUPPORT		= 0XFFFFFFFF,
	
} WebSubOptionType_t;

#ifndef WEBCOMM_ACCOUNT_PERMISSION_CHECK
#define WEBCOMM_ACCOUNT_PERMISSION_CHECK	( 1 )
#endif

#ifndef WEBCOMM_ACCOUNT_MAX_NUM
#define WEBCOMM_ACCOUNT_MAX_NUM				( 16 )
#endif

typedef void * WEBHANDLE;

typedef BYTE WebcommResult_t;
enum eWebcommResult
{	
	WEBERR_RSN_OK = 0,						/**< 操作成功 */
	WEBERR_RSN_OK_NOTRSP = 1,				/**< 操作成功但無回覆 */

	WEBERR_RSN_ACCOUNT_PASSWORD_ERROR = 11,		/**< 賬號或密碼錯誤 */
	WEBERR_RSN_ACCOUNT_LOGIN_TIMEOUT = 12,		/**< 賬號登入超時 */
	WEBERR_RSN_ACCOUNT_DISABLE = 13,			/**< 賬號被禁用 */
	WEBERR_RSN_ACCOUNT_OUT_NUMBER = 14,			/**< 賬號數量超出最大值(默認最大16個) */
	WEBERR_RSN_ACCOUNT_NOT_PERISSION = 15,		/**< 賬號沒有訪問權限 */
	WEBERR_RSN_ACCOUNT_ALREADY_EXIST = 16,		/**< 賬號已存在 */
	WEBERR_RSN_ACCOUNT_PASSWORD_SAME = 17,		/**< 賬號和密碼一樣 */
	WEBERR_RSN_FILES_NOT_EXIST = 18,			/**< 文件不存在 */	
	WEBERR_RSN_FILES_CANNOT_OPEN = 19,			/**< 文件不能被打開 */	
	WEBERR_RSN_FILES_FORMAT_ERROR = 20, 		/**< 文件格式錯誤 */
	WEBERR_RSN_FILES_CHECKSUM_FAIL = 21,		/**< 文件校驗失敗 */
	WEBERR_RSN_DATABASE_OPERATE_FAIL = 22,		/**< 數據庫操作失敗 */
	WEBERR_RSN_NOT_FLASH_SPACE = 23,			/**< FLASH空間不足 */
	WEBERR_RSN_HUB_COMM_FAIL = 24,				/**< HUB通信失敗 */
	WEBERR_RSN_PARAMETER_MISSING = 25,			/**< 請求的參數缺失 */
	WEBERR_RSN_PARAMETER_VALUE_OUTOFRANGE = 26,	/**< 請求的參數值超出範圍 */
	WEBERR_RSN_MEMORY_ALLOCATION_FAIL = 27, 	/**< 內存分配失敗 */
	WEBERR_RSN_URL_NOT_SUPPORT = 28,			/**< URL請求路徑不支持 */
	WEBERR_RSN_REQUEST_NOT_METHOD = 29, 		/**< 請求不支持該方法 */
	WEBERR_RSN_PORT_ALREADY_OCCUPIED = 30, 		/**< 端口已被佔用 */
	
	WEBERR_RSN_UNKNOWN = 60,				/**< 未知錯誤 */
};

typedef struct sReasonInfo
{
	WebcommResult_t	code;		/**< 錯誤的原因編號 */
	const char		*message;	/**< 編號的字符串形式 */
	
} GCC_PACKED ReasonInfo_t;

// Webcomm Result Response
#define WEBRES_CODE					"code"
#define WEBRES_MESSAGE				"message"
#define WEBRES_DATA					"data"

#define WEBCOMM_METHOD					"method"
#define WEBCOMM_LOGIN_USER				"username"
#define WEBCOMM_LOGIN_PASS				"password"
#define WEBCOMM_LOGIN_LAST				"last_time"
#define WEBCOMM_TOKEN_ACCESS 			"access_token"

#define WEBMETHOD_POST			"POST"	// 創建(更新,刪除)
#define WEBMETHOD_GET			"GET"	// 讀取

#define POSTMETHOD_CREATE		"create"	// 創建
#define POSTMETHOD_UPDATE		"update"	// 更新
#define POSTMETHOD_DELETE		"delete"	// 刪除
#define POSTMETHOD_IMPORT		"import"	// 導入
#define POSTMETHOD_EXPORT		"export"	// 導出
#define POSTMETHOD_LOAD			"load"		// 加載
#define POSTMETHOD_EXECUTE		"execute"	// 執行

typedef WebcommResult_t (*fHandler_t)(WEBHANDLE webHandle, const char *uriPath, Webs *wp);

// create webcomm object
WEBHANDLE WebcommCreate(void);

// destroy webcomm object
void WebcommDestroy(WEBHANDLE webHandle);

// send result from webcomm data
int WebcommSendResult(WEBHANDLE webHandle, Webs *wp);

// check User account and password
WebcommResult_t WebcommLoginCheck(WEBHANDLE webHandle, int alreaylogin, const char *cname, const char *cpasswd);

// New Session
WebcommResult_t WebcommNewSession(WEBHANDLE webHandle, Webs *wp, const char *cname, const char *cvalue);

WebcommResult_t WebcommGetSession(WEBHANDLE webHandle, Webs *wp, const char *cname);

WebcommResult_t WebcommDeleteSession(WEBHANDLE webHandle, Webs *wp, const char *cname);

WebcommResult_t WebcommExecuteHandler(WEBHANDLE webHandle, Webs *wp, const char *cname);

const char *ReasonInfo(WebcommResult_t code);

///////////////////////////////////////////////////////////////////////////////////////

#endif /* __CET_WEBCOMM_H__ */

/*
 * File name	: webcommsdk.c
 *
 * Created on	: 2020年3月12日09:35:10
 * Author		: Firmware of xiyuan255
 * Version		: 1.0
 * Language		: C
 * Copyright	: Copyright (C) 2019, xiyuan255 Inc.
 *
 */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <pthread.h>
#include "goahead.h"
#include "cetwebcomm.h"

/////////////////////////////////////////////////////////////////////////

typedef struct sWebHandler
{
	HANDLE				dbHandle;				/**< 數據庫操作是句柄 */
	ReasonInfo_t		rsi;
	cJSON				*pData; 				/**< data數據塊的指針 */
	
} WebHandler_t;

typedef struct sCallbackSet
{
	const char *wpMethod; // POST or GET
	union 
	{
		/* POST方法的函數映射 */
		struct
		{
			const char *method; // execute import ...
			WebcommResult_t (*callback)(WEBHANDLE, const char *, Webs *);
		} post;

		/* GET方法的函數映射 */
		WebcommResult_t (*callback)(WEBHANDLE, const char *, Webs *);
		
	} symbol;
	
} CallbackSet_t;

#define CALLBACKSET_END(METHOD, name)	\
	{ METHOD, { .callback = name }, }

#define CALLBACKSET_INIT(WMETHOD, name)	\
	{ WEBMETHOD_##WMETHOD, { .callback = WEB##WMETHOD##_##name }, }

#define CALLBACKSET_POSTINIT(PMETHOD, name)	\
	{ WEBMETHOD_POST, { { .method = POSTMETHOD_##PMETHOD, .callback = WEB##PMETHOD##_##name } }, }

#define CALLBACKSET_NAME(cstring) sg_callbackset_##cstring

#define WEBCOMM_FRAME_WITH_SUB(OPTION, WSOT, cstring, csubstring)	\
	{ OPTION, 	WSOT,	#cstring"/"#csubstring, CALLBACKSET_NAME(cstring##_##csubstring) }

#define WEBCOMM_FRAME(OPTION, WSOT, cstring)	\
	{ OPTION, 	WSOT,	#cstring, CALLBACKSET_NAME(cstring) }

#define DEFINE_STATIC_GLBVAR(type, name) static type name

typedef struct sWebcommFrame
{
	const char			*options;	
	WebSubOptionType_t	suboptions;
	const char			*uriLabel;		/**< url的路徑 */
	CallbackSet_t		*callbackSet;	/**< 對應的回調集合 */
	
} GCC_PACKED WebcommFrame_t;

typedef struct sWebOptionMap
{
	const char			*webOption;		/**< web的主選項 */
	const char			*webSubOption;	/**< web的子選項 */
	WebSubOptionType_t	subOption;
	
} GCC_PACKED WebOptionMap_t;

#define CHECK_WEBHANDLE_DATA_OBJECT(pWebHandler) \
	do { \
		if (NULL == (pWebHandler)->pData) { \
			(pWebHandler)->pData = cJSON_CreateObject(); \
		} \
		if (NULL == (pWebHandler)->pData) { \
			return WebErrReason(pWebHandler, WEBERR_RSN_MEMORY_ALLOCATION_FAIL); \
		} \
	} while (0)

static const ReasonInfo_t sg_WebRsnInfo[] = 
{
	{WEBERR_RSN_OK,							"success"},
	{WEBERR_RSN_ACCOUNT_PASSWORD_ERROR,		"account or password error"},
	{WEBERR_RSN_ACCOUNT_LOGIN_TIMEOUT,		"account login timeout"},
	{WEBERR_RSN_ACCOUNT_DISABLE,			"account is disabled"},
	{WEBERR_RSN_ACCOUNT_OUT_NUMBER,			"number of accounts exceeds"},
	{WEBERR_RSN_ACCOUNT_NOT_PERISSION,		"account has no access rights"},
	{WEBERR_RSN_ACCOUNT_ALREADY_EXIST,		"account already exists"},
	{WEBERR_RSN_ACCOUNT_PASSWORD_SAME,		"account is the same as the password"},
	{WEBERR_RSN_FILES_NOT_EXIST,			"file does not exist"},
	{WEBERR_RSN_FILES_CANNOT_OPEN,			"file cannot be opened"},
	{WEBERR_RSN_FILES_FORMAT_ERROR,			"file format error"},
	{WEBERR_RSN_FILES_CHECKSUM_FAIL,		"file validation failed"},
	{WEBERR_RSN_DATABASE_OPERATE_FAIL,		"database operation failed"},
	{WEBERR_RSN_NOT_FLASH_SPACE,			"not flash space"},
	{WEBERR_RSN_HUB_COMM_FAIL,				"hub communication failure"},
	{WEBERR_RSN_PARAMETER_MISSING,			"request parameter exception"},
	{WEBERR_RSN_PARAMETER_VALUE_OUTOFRANGE,	"request parameter values are out of range"},
	{WEBERR_RSN_MEMORY_ALLOCATION_FAIL,		"memory allocation failure"},
	{WEBERR_RSN_URL_NOT_SUPPORT,			"url request path is not supported"},
	{WEBERR_RSN_REQUEST_NOT_METHOD,			"request does not support the method"},
	{WEBERR_RSN_PORT_ALREADY_OCCUPIED,		"the port is already occupied"},
	
	{WEBERR_RSN_UNKNOWN,				     "unknown error"},	
};

static WebOptionMap_t sg_WebOptionMap[] = 
{
	{WEBOVERIVEW_OPTION, 		SUBOPTION_DASHBOARD, 				WSOT_DASHBOARD},
	{WEBOVERIVEW_OPTION, 		SUBOPTION_INTERFACE,		 		WSOT_INTERFACE},
	{WEBCONNECTIVITY_OPTION,	SUBOPTION_CONNECTION, 				WSOT_CONNECTION},
	{WEBCONNECTIVITY_OPTION,	SUBOPTION_NETWORK, 					WSOT_NETWORK},	
	{WEBCONNECTIVITY_OPTION,	SUBOPTION_WLAN, 					WSOT_WLAN},
	{WEBCONNECTIVITY_OPTION,	SUBOPTION_PARAMETERS,				WSOT_PARAMETERS},
	{WEBMAINTENANCE_OPTION,		SUBOPTION_EXPORT, 					WSOT_EXPORT},
	{WEBMAINTENANCE_OPTION,		SUBOPTION_RESET, 					WSOT_RESET},
	{WEBMAINTENANCE_OPTION,		SUBOPTION_FIRMWARE_UPDATE, 			WSOT_FW_UPDATE},
	{WEBMAINTENANCE_OPTION, 	SUBOPTION_DEBUG, 					WSOT_DEBUG},
	{WEBMAINTENANCE_OPTION, 	SUBOPTION_LOGS, 					WSOT_LOGS},
	{WEBSYSTEM_OPTION,			SUBOPTION_USERS,					WSOT_USERS},
	{WEBSYSTEM_OPTION, 			SUBOPTION_DATE_AND_TIME,			WSOT_DATE_AND_TIME},
	{WEBSYSTEM_OPTION, 			SUBOPTION_LOAD_CERTIFICATE, 		WSOT_LOAD_CERT},	
	{WEBSYSTEM_OPTION, 			SUBOPTION_IPFILTER, 				WSOT_IPFILTER},
	{WEBSYSTEM_OPTION, 			SUBOPTION_ABOUT, 					WSOT_ABOUT},
	{NULL,						NULL,								0},
};

const char *ReasonInfo(WebcommResult_t code)
{
	int	idx = 0;
	int length = 0;

	length = sizeof(sg_WebRsnInfo)/sizeof(sg_WebRsnInfo[0]);
	
	for (idx = 0; idx < length; idx++)
	{
		if (sg_WebRsnInfo[idx].code == code) {			
			return sg_WebRsnInfo[idx].message;
		}
	}

	return NULL;
}

static inline int WebErrReason(WebHandler_t *pWebHandler, WebcommResult_t code)
{
	pWebHandler->rsi.code = code;
	pWebHandler->rsi.message = ReasonInfo(code);

	return code;
}

inline void *GetCallback(CallbackSet_t CallbackSet[], const char *wpMethod, const char *method)
{
	void 			*callback = NULL;
	CallbackSet_t	*pCbSet = NULL;
	
	for (pCbSet = CallbackSet; (pCbSet && pCbSet->wpMethod); pCbSet++)
	{	
		// 校驗HTTP方法是否匹配
		if (0 != strcmp1(wpMethod, pCbSet->wpMethod)) {
			continue;
		}

		if (0 == strcmp1(WEBMETHOD_POST, pCbSet->wpMethod))
		{			
			// 校驗POST方法的method字段是否匹配
			if (0 == strcmp1(method, pCbSet->symbol.post.method)) {
				callback = (void *)pCbSet->symbol.post.callback;
				break;
			}
		}
		else if (0 == strcmp1(WEBMETHOD_GET, pCbSet->wpMethod))
		{
			callback = (void *)pCbSet->symbol.callback;
			break;
		}
	}

	return callback;
}

void WebsResponseHeadSafePolicy(Webs *wp)
{	
    websWriteHeader(wp, "Pragma", "no-cache");
    websWriteHeader(wp, "Cache-Control", "no-store");
	websWriteHeader(wp, "X-Content-Type-Options", "nosniff");
	websWriteHeader(wp, "X-XSS-Protection", "%d; mode=block", 1);
	websWriteHeader(wp, "Content-Security-Policy", "default-src 'self'; frame-ancestors 'self'");
	websWriteHeader(wp, "Content-Type", "application/json; charset=utf-8");
	websWriteHeader(wp, "Strict-Transport-Security", "max-age=%d; includeSubDomains", 31536000);
}

static int WebSetParam(void *arg, cJSON *mJson, cJSON *childJson)
{		
	Webs 		*wp = NULL;
    cchar       *prior = NULL;
    WebsKey     *sp = NULL;	
    char        *keyword = NULL;
	char		value[MAX_LEN_1024] = {0};
		
    assert(arg);
	assert(mJson);
	assert(childJson);
	
	keyword = childJson->string? childJson->string : mJson->string;
	if (cJSON_Number == childJson->type) {
		snprintf(value, MAX_LEN_1024, "%d", childJson->valueint);
	} else if (cJSON_String == childJson->type) {			
		snprintf(value, MAX_LEN_1024, "%s", childJson->valuestring);
	}
	wp = (Webs *)arg;
	if (*keyword) {
        /*
            If keyword has already been set, append the new value to what has been stored.
         */
        if ((prior = websGetVar(wp, keyword, NULL)) != 0) {
            sp = websSetVarFmt(wp, keyword, "%s,%s", prior, value);
        } else {
            sp = websSetVar(wp, keyword, value);
        }
        /* Flag as untrusted keyword by setting arg to 1. This is used by CGI to prefix this keyword */
        sp->arg = 0;

		return 0;
    }

	return -1;
}

static int WebReplaceKey(void *arg, cJSON *mJson, cJSON *childJson)
{	
	char *temp = NULL;
	struct sKey {
		const char *oldkey;
		const char *newkey;
	};

	struct sKey *pKey = (struct sKey *)arg;
		
    assert(arg);
	assert(mJson);
	assert(childJson);

	if (mJson->string && 0 == strcmp(mJson->string, pKey->oldkey)) {
		temp = calloc(sizeof(char), strlen(pKey->newkey) + 1);
		if (NULL == temp)
			return -1;
		free(mJson->string);
		mJson->string = temp;
		strcpy(mJson->string, pKey->newkey);
		return 0;
	}
	
	return -1;
}

/**
	遞歸遍歷json串的數據
*/
static void RecursiveTraversal(int isBreak, void *arg, cJSON *mJson, cJSON *childJson, 
		int (*callback)(void *arg, cJSON *mJson, cJSON *childJson))
{	
	int ret = -1;
	
	while (childJson)
	{
		if ((cJSON_Number == childJson->type)||(cJSON_String == childJson->type)) {			
			if (NULL != callback) {
				ret = callback(arg, mJson, childJson);
				if (0 == ret && isBreak)
					return;
			}
		} else if ((cJSON_Array == childJson->type)||(cJSON_Object == childJson->type)) {
			RecursiveTraversal(isBreak, arg, childJson, childJson->child, callback);
		}
		
		childJson = childJson->next;
	}
}

/**
	KEY相同的VALUE會以空格間隔的形式被放在一起,也是因爲這樣,
	要避免出現的不同對象中定義相同的KEY的情況,造成VALUE存在到一起
*/
int WebcommAddJsonVars(Webs *wp, char *vars)
{	
    cJSON 	*cJson = NULL;
	char 	*strData = NULL;

    assert(wp);
    assert(vars);

	if (NULL != (cJson = cJSON_Parse(vars)))
	{		
		strData = cJSON_Print(cJson);
		//cJSON_Minify(strData);
		PrintInfo("JsonVars=%s", strData);
		RecursiveTraversal(0, wp, cJson, cJson->child, WebSetParam);
		
		cJSON_Delete(cJson);
		free(strData);

		return 0;
	}

	return -1;
}

/**
	使用新key替換json中的key=value形式的舊key
*/
int WebcommReplaceJsonKey(cJSON *cJson, const char *oldkey, const char *newkey)
{	
	struct sKey {
		const char *oldkey;
		const char *newkey;
	};

	char 	*strData = NULL;
	struct sKey Key;

    assert(cJson);
    assert(oldkey);
    assert(newkey);

	strData = cJSON_Print(cJson);
	cJSON_Minify(strData);
	PrintInfo("JsonVars=%s", strData);
	Key.oldkey = oldkey;
	Key.newkey = newkey;
	RecursiveTraversal(1, &Key, cJson, cJson->child, WebReplaceKey);
	
	free(strData);

	return 0;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static WebcommResult_t WEBGET_DeviceUseSituation(WEBHANDLE webHandle, const char *uriPath, Webs *wp)
{
	WebHandler_t	*pWebHandler = NULL;

	assert(webHandle);
	assert(uriPath);
	assert(wp);

	pWebHandler = (WebHandler_t *)webHandle;
	JsonGetDeviceUseSituation(pWebHandler->pData, pWebHandler->dbHandle, 0);
	
	return WebErrReason(pWebHandler, WEBERR_RSN_OK);
}

DEFINE_STATIC_GLBVAR(CallbackSet_t, CALLBACKSET_NAME(use_situation))[] = {
	CALLBACKSET_INIT(GET, DeviceUseSituation),
	CALLBACKSET_END(NULL, NULL),
};

DEFINE_STATIC_GLBVAR(WebcommFrame_t, sg_WebAssemble)[] = 
{
	// 資源對象的回調函數 可在此添加
	WEBCOMM_FRAME(WEBOVERIVEW_OPTION, WSOT_DASHBOARD, use_situation),
	{NULL,	0,	NULL,	NULL},
};

WEBHANDLE WebcommCreate(void)
{
	WebHandler_t	*pWebHandler = NULL;	

	pWebHandler = (WebHandler_t *)calloc(sizeof(char), sizeof(WebHandler_t));
	
	return (WEBHANDLE)pWebHandler;
}

void WebcommDestroy(WEBHANDLE webHandle)
{	
	WebHandler_t *pWebHandler = NULL;

	pWebHandler = (WebHandler_t *)webHandle;
	if (NULL != pWebHandler) {
		if (NULL != pWebHandler->pData) {
			cJSON_Delete(pWebHandler->pData);
		}
		free(pWebHandler);
	}
}

// send result from webcomm data
int WebcommSendResult(WEBHANDLE webHandle, Webs *wp)
{	
	int 	code = 0;
	int		payloadLen = 0;
	char	*payload = NULL;
	cJSON 	*resJson = NULL;
	WebHandler_t *pWebHandler = NULL;

	assert(webHandle);
	assert(wp);
	
	pWebHandler = (WebHandler_t *)webHandle;
	if (WEBERR_RSN_OK_NOTRSP == pWebHandler->rsi.code) {
		if (NULL != pWebHandler->pData) {
			cJSON_Delete(pWebHandler->pData);
			pWebHandler->pData = NULL;
		}
		WebErrReason(pWebHandler, WEBERR_RSN_UNKNOWN);
		return 0;
	}

	switch (pWebHandler->rsi.code)
	{
		case WEBERR_RSN_OK:
		case WEBERR_RSN_PARAMETER_VALUE_OUTOFRANGE:
			code = HTTP_CODE_OK;
			break;
		case WEBERR_RSN_URL_NOT_SUPPORT:
		case WEBERR_RSN_PARAMETER_MISSING:
			code = HTTP_CODE_BAD_REQUEST;
			break;
		case WEBERR_RSN_ACCOUNT_PASSWORD_ERROR:
			code = HTTP_CODE_UNAUTHORIZED;
			break;
		case WEBERR_RSN_REQUEST_NOT_METHOD:
			code = HTTP_CODE_BAD_METHOD;
			break;
		default:
			code = HTTP_CODE_INTERNAL_SERVER_ERROR;
			break;
	}
	
	resJson = cJSON_CreateObject();
	cJSON_AddNumberToObject(resJson, WEBRES_CODE, pWebHandler->rsi.code);
	cJSON_AddStringToObject(resJson, WEBRES_MESSAGE, pWebHandler->rsi.message);
	cJSON_AddItemToObject(resJson, WEBRES_DATA, pWebHandler->pData);

	if (NULL == (payload = cJSON_Print(resJson))) {
		return -1;
	}

	payloadLen = strlen(payload);
	PrintInfo("[WebcommSendResult:%d] %s ", pWebHandler->rsi.code, payload);
	
	websSetStatus(wp, code);
	websWriteHeaders(wp, payloadLen, 0);
	WebsResponseHeadSafePolicy(wp);
	websWriteEndHeaders(wp);
	websWriteBlock(wp, payload, payloadLen);
    websWriteBlock(wp, "\r\n", 2);
	websDone(wp);
	
	cJSON_Delete(resJson);
	free(payload);
	pWebHandler->pData = NULL;
	WebErrReason(pWebHandler, WEBERR_RSN_UNKNOWN);
	
	return 0;
}

WebcommResult_t WebcommLoginCheck(WEBHANDLE webHandle, int alreaylogin, const char *cname, const char *cpasswd)
{	
	WebPermitUser_t	*pPermitUser = NULL;
	WebcommResult_t webResult = WEBERR_RSN_ACCOUNT_PASSWORD_ERROR;

	assert(webHandle);
	assert(cname);
	assert(cpasswd);
	
	if (NULL != (pPermitUser = WebsGetPermitUser(cname))) {
		if (0 == pPermitUser->state) { // 賬戶是否被禁用
			webResult = WEBERR_RSN_ACCOUNT_DISABLE;
		} else  {
			webResult = (0 == strcmp1(pPermitUser->password, cpasswd)) ?
						 WEBERR_RSN_OK : WEBERR_RSN_ACCOUNT_PASSWORD_ERROR;
		}
	} else if (alreaylogin) { // 登入過,獲取不到,說明超時,已被刪除
		webResult = WEBERR_RSN_ACCOUNT_LOGIN_TIMEOUT;
	}

	return WebErrReason((WebHandler_t *)webHandle, webResult);
}

// New Session
WebcommResult_t WebcommNewSession(WEBHANDLE webHandle, Webs *wp, const char *cname, const char *cvalue)
{		
	WebHandler_t 	*pWebHandler = NULL;	
	WebPermitUser_t *pPermitUser = NULL;
	char			currenttime[MAX_LEN_256] = {0};
				
	assert(wp);
	assert(webHandle);
	
	wfree(wp->username);
	wp->username = sclone(cname);
	wfree(wp->password);
	wp->password = sclone(cvalue);
		
	pWebHandler = (WebHandler_t *)webHandle;
	
	CHECK_WEBHANDLE_DATA_OBJECT(pWebHandler);
	
	websCreateSession(wp);
	websSetSessionVar(wp, WEBCOMM_LOGIN_USER, wp->username);
	websSetSessionVar(wp, WEBCOMM_LOGIN_PASS, wp->password);
	websSetSessionVar(wp, WEBCOMM_LOGIN_LAST, GetCurrentTime(currenttime, MAX_LEN_256));

	if (NULL != (pPermitUser = WebsGetPermitUser(wp->username))) {
		/* 同一個賬號新登入的session會將之前的會話替換掉 */
		if (wp->session && 0 != strcmp(pPermitUser->cookieId, wp->session->id)) {
			if (*pPermitUser->cookieId) {
				websDeleteSessionByCookie(pPermitUser->cookieId);
			}
			strcpy(pPermitUser->cookieId, wp->session->id);
		}
	}

	cJSON_AddStringToObject(pWebHandler->pData, WEBCOMM_TOKEN_ACCESS, pPermitUser->cookieId);
		
	return WebErrReason(pWebHandler, WEBERR_RSN_OK);
}

WebcommResult_t WebcommGetSession(WEBHANDLE webHandle, Webs *wp, const char *cname)
{		
	const char		*lasttime = NULL;
	WebHandler_t	*pWebHandler = NULL;
	
	assert(webHandle);
	assert(wp);
	
	wfree(wp->username);
	wp->username = sclone(cname);

	pWebHandler = (WebHandler_t *)webHandle;

	CHECK_WEBHANDLE_DATA_OBJECT(pWebHandler);
		
	lasttime = websGetTokenSessionVar(wp, WEBCOMM_LOGIN_LAST, "");

	cJSON_AddStringToObject(pWebHandler->pData, WEBCOMM_LOGIN_USER, cname);
	cJSON_AddStringToObject(pWebHandler->pData, WEBCOMM_LOGIN_LAST, lasttime);
	
	return WebErrReason(pWebHandler, WEBERR_RSN_OK);
}

WebcommResult_t WebcommDeleteSession(WEBHANDLE webHandle, Webs *wp, const char *cname)
{
	assert(webHandle);
	assert(wp);
	
	wfree(wp->username);
	wp->username = sclone(cname);
	
	OPLOGS_OPTION_PREFIX(webHandle, wp->username, NULL, "logout");			
	OPLOGS_OPTION_STRSAVE("", NULL, "", 1);

	websRemoveSessionVar(wp, WEBCOMM_LOGIN_USER);
	websRemoveSessionVar(wp, WEBCOMM_LOGIN_PASS);
	websRemoveSessionVar(wp, WEBCOMM_LOGIN_LAST);
	websDestroySession(wp);
	
	return WebErrReason((WebHandler_t *)webHandle, WEBERR_RSN_OK);
}

WebcommResult_t WebcommExecuteHandler(WEBHANDLE webHandle, Webs *wp, const char *cname)
{
	void 			*callback = NULL;
	const char		*method = NULL;
	char			option[MAX_LEN_64] = {0};
	char			uriPath[MAX_LEN_2048] = {0};
	WebHandler_t	*pWebHandler = NULL;
	WebPermitUser_t *pPermitUser = NULL;
	WebcommFrame_t	*pAssemble = NULL;
	
	assert(webHandle);
	assert(wp);
	
	wfree(wp->username);
	wp->username = sclone(cname);
	
	pWebHandler = (WebHandler_t *)webHandle;
	
	CHECK_WEBHANDLE_DATA_OBJECT(pWebHandler);
	
#if (1 == WEBCOMM_ACCOUNT_PERMISSION_CHECK)
	/* 獲取當前用戶的權限mask */	
	if (NULL != (pPermitUser = WebsGetPermitUser(wp->username))) {
		// ....
	}
#endif

	sscanf(wp->url, "/web/app/%[^/]%*c%[^?]", option, uriPath);
	for (pAssemble = sg_WebAssemble; pAssemble->options; pAssemble++) {
		// 校驗option的是否匹配
		if (0 != strcmp1(option, pAssemble->options)) {
			continue;
		}

		// 校驗請求路徑的是否匹配
		if (0 != strncmp(uriPath, pAssemble->uriLabel, strlen(pAssemble->uriLabel))) {
			continue;
		}

#if (1 == WEBCOMM_ACCOUNT_PERMISSION_CHECK)
		// 檢查當前用戶是否具體該 suboptions 權限
		if (NULL == pPermitUser || !(pPermitUser->permitMask & pAssemble->suboptions)) {
			return WebErrReason(pWebHandler, WEBERR_RSN_ACCOUNT_NOT_PERISSION);
		}
#endif
		// 獲取BODY中method的值		
		method	= websGetVar(wp, WEBCOMM_METHOD, "");
		if (NULL != (callback = GetCallback(pAssemble->callbackSet, wp->method, method))) {					
			return ((WebcommResult_t (*)(WEBHANDLE, cchar *, Webs *))callback)(webHandle, uriPath, wp);
		} else {
			return WebErrReason(pWebHandler, WEBERR_RSN_REQUEST_NOT_METHOD);
		}
	}
	
	return WebErrReason(pWebHandler,  WEBERR_RSN_URL_NOT_SUPPORT);
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章