chapter 10-04

Session 的存取 (用戶端)

此章節說明用戶端程式如何存取 session 資料.


登入的使用者的 session 資料是放在共享記憶體, 其他用戶端程式可以存取這些資料.

Makefile 的編譯參數 :
# 路徑設定.
MAAM_PATH       = mint_cm/http_server/mini_httpd/last/mint_aam
MAAM_LULIB_PATH = $(MAAM_PATH)/maam_lib/maam_lulib

# 標頭檔路徑.
INCLUDE_PATH = -I$(MAAM_PATH)
# 函式庫路徑.
LIBRARY_PATH = -L$(MAAM_LULIB_PATH)

# 使用靜態鏈結或動態鏈結的鏈結參數.
USE_STATIC_MAAM_LIB = YES
ifeq (${USE_STATIC_MAAM_LIB}, YES)
LIBRARY_FILE = $(MAAM_LULIB_PATH)/maam_lulib_api.a
else
LIBRARY_FILE = -lmaam_lulib_api
endif

MintAAM 的用戶端函式庫在 mint_cm/http_server/mini_httpd/last/mint_aam/maam_lib/maam_lulib.
使用動態鏈結必須將 libmaam_lulib_api.so 複製到系統的 lib 目錄.

需要的標頭檔 :
#include "maam_lib/maam_lulib/maam_lulib_api.h"



變數格式的說明

[struct maam_session_t]
紀錄每筆 session 的資料的結構, 結構成員
usockaddr
client_addr
客戶端的位址
char
account_name[MAAM_BSIZE_ACCOUNT_NAME]
帳號的名稱
int
account_permission
帳號的權限
char
session_key[MAAM_BSIZE_SESSION_KEY]
session 的 key 值
long
idle_timeout
閒置超時時間
long
create_uptime
登入的時間 (系統開機後的經過時間) [!]
long
last_access_uptime
最後活動的時間 (系統開機後的經過時間) [!]
int
session_index
內部鏈結串列使用, 紀錄此節點的編號 [!]
int
prev_session
內部鏈結串列使用, 紀錄串列上前一個節點的編號 [!]
int
next_session
內部鏈結串列使用, 紀錄串列上後一個節點的編號 [!]
int
empty_session
內部鏈結串列使用, 紀錄下一個沒被使用的節點的編號 [!]
有 [!] 表示其他程式存取時不要修改這些資料, 會造成無法預期的錯誤.
每筆 session 資料之間使用雙向鍊結串列排列.


[struct maam_auth_sys_t]
session 資料以及其他全部資料的結構, 結構成員
int
max_uptime
系統的 uptime 能記錄的最大值 [!]
int
session_count
目前的 session 數目 [!]
int
session_head
內部鏈結串列使用, 紀錄串列上第一個節點的編號 [!]
int
session_tail
內部鏈結串列使用, 紀錄串列上第一個沒被使用的節點的編號 [!]
struct maam_session_t
session_info[MAAM_MAX_SESSION]
每筆 session 的資料 [詳細]
有 [!] 表示其他程式存取時不要修改這些資料, 會造成無法預期的錯誤.


[struct maam_lulib_t]
用來儲存 libmaam_lulib_api.so 使用時需要的資訊.
會用到的結構成員 :
[key_t sm_key]
session 資料的共享記憶體的 key 值.
使用 MAAM_SHARE_MEMORY_KEY
[char *sm_mutex_path]
存取 session 資料的檔案互斥鎖的路徑.
使用 MAAM_MUTEX_PATH
[int sm_id]
紀錄使用 shmget() 開啟共享記憶體的 id.
[int sm_mutex_fd]
紀錄使用 open() 開啟檔案互斥鎖的 fd.
[struct maam_auth_sys_t *auth_sys]
紀錄 session 資料的記憶體位址. [詳細]


可用的函式

maam_lulib_init
初始化, 開啟存取內部資料.
參數 說明
struct maam_lulib_t *
maam_lulib_info
紀錄 maam_lulib_api 所需要的資料 [詳細]
需要先設定好會用到的結構成員 :
sm_key [詳細]
sm_mutex_path [詳細]
回傳 說明
>= MAAM_RCODE_PASS 成功
 < MAAM_RCODE_PASS 錯誤

注意事項 :
01.  函式內會使用 flock(LOCK_EX) 鎖定佔有.

範例 :
#include <stdio.h>
#include <string.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    //  session 資料存取.
    // ...

FREE_01:
    return 0;
}

maam_lulib_exit
使用完畢, 釋放使用權.
參數 說明
struct maam_lulib_t *
maam_lulib_info
紀錄 maam_lulib_api 所需要的資料 [詳細]
回傳 說明
>= MAAM_RCODE_PASS 成功

注意事項 :
01.  函式會先使用 flock(LOCK_EX) 解除占有後才關閉相關資源.

範例 :
#include <stdio.h>
#include <string.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    //  session 資料存取.
    // ...

    maam_lulib_exit(&self_maam_lulib);
FREE_01:
    return 0;
}

MAAM_LULIB_HEAD_SESSION
巨集, 找到串列上開頭的那筆 session 資料.
參數 說明
struct maam_auth_sys_t *
auth_sys_info
session 資料以及其他全部資料 [詳細]
回傳 說明
!= NULL 有該筆資料
== NULL 無該筆資料

範例 :
#include <stdio.h>
#include <string.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;
    struct maam_session_t *each_session;

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    // 開頭的 session 資料.
    each_session = MAAM_LULIB_HEAD_SESSION(self_maam_lulib.auth_sys);
    if(each_session != NULL)
    {
        DMSG("head session [%s][%s]",
             each_session->account_name, each_session->session_key);
    }
    else
    {
        DMSG("no any session");
    }

    maam_lulib_exit(&self_maam_lulib);
FREE_01:
    return 0;
}

MAAM_LULIB_TAIL_SESSION
巨集, 找到串列上結尾的那筆 session 資料.
參數 說明
struct maam_auth_sys_t *
auth_sys_info
session 資料以及其他全部資料 [詳細]
回傳 說明
!= NULL 有該筆資料
== NULL 無該筆資料

範例 :
#include <stdio.h>
#include <string.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;
    struct maam_session_t *each_session;

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    // 結尾的 session 資料.
    each_session = MAAM_LULIB_TAIL_SESSION(self_maam_lulib.auth_sys);
    if(each_session != NULL)
    {
        DMSG("tail session [%s][%s]",
             each_session->account_name, each_session->session_key);
    }
    else
    {
        DMSG("no any session");
    }

    maam_lulib_exit(&self_maam_lulib);
FREE_01:
    return 0;
}

MAAM_LULIB_NEXT_SESSION
巨集, 找到串列上目前這筆 session 資料的後一筆.
參數 說明
struct maam_auth_sys_t *
auth_sys_info
session 資料以及其他全部資料 [詳細]
struct maam_session_t *
link_session
目前的 session 資料 [詳細]
回傳 說明
!= NULL 有該筆資料
== NULL 無該筆資料

範例 :
#include <stdio.h>
#include <string.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;
    struct maam_session_t *each_session;

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    // 從開頭到結尾.
    for(each_session = MAAM_LULIB_HEAD_SESSION(self_maam_lulib.auth_sys);
        each_session != NULL;
        each_session = MAAM_LULIB_NEXT_SESSION(self_maam_lulib.auth_sys, each_session))
    {
        DMSG("session [%s][%s]",
             each_session->account_name, each_session->session_key);
    }

    maam_lulib_exit(&self_maam_lulib);
FREE_01:
    return 0;
}

MAAM_LULIB_PREV_SESSION
巨集, 找到串列上目前這筆 session 資料的前一筆.
參數 說明
struct maam_auth_sys_t *
auth_sys_info
session 資料以及其他全部資料 [詳細]
struct maam_session_t *
link_session
目前的 session 資料 [詳細]
回傳 說明
!= NULL 有該筆資料
== NULL 無該筆資料

範例 :
#include <stdio.h>
#include <string.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;
    struct maam_session_t *each_session;

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    // 從結尾到開頭.
    for(each_session = MAAM_LULIB_TAIL_SESSION(self_maam_lulib.auth_sys);
        each_session != NULL;
        each_session = MAAM_LULIB_PREV_SESSION(self_maam_lulib.auth_sys, each_session))
    {
        DMSG("session [%s][%s]",
             each_session->account_name, each_session->session_key);
    }

    maam_lulib_exit(&self_maam_lulib);
FREE_01:
    return 0;
}

MAAM_LULIB_IP_NTOH
巨集, 將網路格式的位址轉為字串格式.
參數 說明
usockaddr
usockaddr_info
網路格式的位址資料
char *
host_buf
紀錄字串格式位址的緩衝
size_t
host_size
紀錄字串格式位址的緩衝的大小

注意事項 :
01.  需要引用 <sys/types.h> <sys/socket.h> <arpa/inet.h> 這幾個標頭檔.

範例 :
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;
    struct maam_session_t *each_session;
    char client_haddr[64];

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    for(each_session = MAAM_LULIB_HEAD_SESSION(self_maam_lulib.auth_sys);
        each_session != NULL;
        each_session = MAAM_LULIB_NEXT_SESSION(self_maam_lulib.auth_sys, each_session))
    {
        // 轉換位址.
        MAAM_LULIB_IP_NTOH(each_session->client_addr, client_haddr, sizeof(client_haddr));

        DMSG("session [%s][%s][%s]",
             each_session->account_name, each_session->session_key, client_haddr);
    }

    maam_lulib_exit(&self_maam_lulib);
FREE_01:
    return 0;
}

maam_lulib_kick_session
踢掉該使用者 (移除該筆 session 資料)
參數 說明
struct maam_auth_sys_t *
auth_sys_info
session 資料以及其他全部資料 [詳細]
struct maam_session_t *
session_info
要移除的 session 資料 [詳細]
回傳 說明
>= MAAM_RCODE_PASS 成功

範例 :
#include <stdio.h>
#include <string.h>
#include "maam_lib/maam_lulib/maam_lulib_api.h"

#define DMSG(msg_fmt, msgs...) printf("%s(%04u): " msg_fmt "\n", __FILE__, __LINE__, ##msgs)

int main(
    int argc,
    char **argv)
{
    struct maam_lulib_t self_maam_lulib;
    struct maam_session_t *each_session, *next_session;

    self_maam_lulib.sm_key = MAAM_SHARE_MEMORY_KEY;
    self_maam_lulib.sm_mutex_path = MAAM_MUTEX_PATH;
    if(maam_lulib_init(&self_maam_lulib) < MAAM_RCODE_PASS)
    {
        DMSG("call maam_lulib_init() fail");
        goto FREE_01;
    }

    // 移除所有的 session 資料.
    for(each_session = MAAM_LULIB_HEAD_SESSION(self_maam_lulib.auth_sys);
        each_session != NULL;
        each_session = next_session)
    {
        next_session = MAAM_LULIB_NEXT_SESSION(self_maam_lulib.auth_sys, each_session);

        DMSG("kick session [%s][%s]",
             each_session->account_name, each_session->session_key);

        maam_lulib_kick_session(self_maam_lulib.auth_sys, each_session);
    }

    maam_lulib_exit(&self_maam_lulib);
FREE_01:
    return 0;
}


範例程式的使用

01.  範例程式目錄在 mint_cm/usage/example/1004.


02.  下面關於 make 的操作沒有特別註明的話都是在 mint_cm 目錄.


03.  第一次使用, 使用 make example_add KEY=1004 載入範例並編譯.


04.  web_app 是範例程式.

範例項目 :
case-01 測試帳號的增加/刪除/修改
case-02 測試 session 的取得和踢除


05.  先執行 mcm_daemon 和 mini_httpd 才可測試.


06.  瀏覽器連至 http://<server-address> 會自動導到登入頁面.


07.  測試完畢不使用後, 使用 make example_del KEY=1004 將範例移除.


08.  範例程式目錄下的檔案在做完 make example_add 後會複製到真正使用的位置, 要修改做測試的話要改在複製後的.
來源 profile/mcm_data_profile_1004.xml
目地 mint_cm/mcm_build/mcm_data_profile.xml
資料模型範例
有修改要使用 make all 重新編譯
來源 profile/mcm_store_profile_default_1004.txt
目地 mint_cm/mcm_build/mcm_store_profile_default.txt
資料預設值範例
使用 make all 後會再複製到 mint_cm/run
來源 web_app
目地 mint_cm/run/web
網頁程式範例
來源 module/mcm_module_1004.c
目地 mint_cm/mcm_daemon/mcm_module
內部模組範例
有修改要使用 make all 重新編譯
來源 module/Makefile
目地 mint_cm/mcm_daemon/mcm_module
內部模組的 Makefile, 主要是加入使用 MintAAM 函式庫的連結
有修改要使用 make all 重新編譯
來源 maam_buildin
目地 http_server/mini_httpd/last/mint_aam/maam_buildin
MintAAM 端範例範例
有修改要使用 make all 重新編譯
來源 mini_httpd/Makefile
目地 http_server/mini_httpd/last
mini_httpd 的 Makefile, 主要是加入使用 MintCM 函式庫的連結
有修改要使用 make all 重新編譯