A DNS Server 源碼分析(待續)

                                                A DNS Server 源碼分析html

備用知識git

1.Lua BIT庫,在LUA 5.1/5.2下面的C擴展模塊。網址:http://bitop.luajit.org/index.htmlgithub

介紹BitOp庫可能會用到的一些函數數據庫

1.bit.tohex()全部32位平臺的16進制數,第一個參數爲十六進制字符串轉換。十六進制數字的數量由可選的第二個參數的絕對值給出。1和8之間的正數生成小寫十六進制數字。負數生成大寫十六進制數字。只有最低的顯著4 * | N | 位被使用。默認值是產生8小寫十六進制數字。session

print(bit.tohex(1))              --> 00000001
print(bit.tohex(-1))             --> ffffffff
print(bit.tohex(0xffffffff))     --> ffffffff
print(bit.tohex(-1, -8))         --> FFFFFFFF
print(bit.tohex(0x21, 4))        --> 0021
print(bit.tohex(0x87654321, 4))  --> 4321

2.bit.tobit()位運算,函數

print(0xffffffff)                --> 4294967295 (*)
print(bit.tobit(0xffffffff))     --> -1  (若是你的Lua安裝使用double型)
printx(bit.tobit(0xffffffff))    --> 0xffffffff
print(bit.tobit(0xffffffff + 1)) --> 0
print(bit.tobit(2^40 + 1234))    --> 1234

3.bit.bnot()取反源碼分析

print(bit.bnot(0))            --> -1
printx(bit.bnot(0))           --> 0xffffffff
print(bit.bnot(-1))           --> 0
print(bit.bnot(0xffffffff))   --> 0
printx(bit.bnot(0x12345678))  --> 0xedcba987

4.y = bit.bor(x1 [,x2...]) 或運算,y = bit.band(x1 [,x2...]) 與運算,y = bit.bxor(x1 [,x2...]) 異或運算學習

print(bit.bor(1, 2, 4, 8))                --> 15
printx(bit.band(0x12345678, 0xff))        --> 0x00000078
printx(bit.bxor(0xa5a5f0f0, 0xaa55ff00))  --> 0x0ff00ff0

5.Y = bit.lshift(X,N),Y = bit.rshift(X,N),Y = bit.arshift(X,N)分別對應按位邏輯左移,按位邏輯右移,或按位算術右移ui

print(bit.lshift(1, 0))              --> 1
print(bit.lshift(1, 8))              --> 256
print(bit.lshift(1, 40))             --> 256
print(bit.rshift(256, 8))            --> 1
print(bit.rshift(-256, 8))           --> 16777215
print(bit.arshift(256, 8))           --> 1
print(bit.arshift(-256, 8))          --> -1
printx(bit.lshift(0x87654321, 12))   --> 0x54321000
printx(bit.rshift(0x87654321, 12))   --> 0x00087654
printx(bit.arshift(0x87654321, 12))  --> 0xfff87654

6.Y = bit.bswap(X)編碼

交換其參數的字節數,並返回它。這可用於小端的32位數字轉換成大端32位數字或反之亦然。

printx(bit.bswap(爲0x12345678)) - > 0x78563412
printx(bit.bswap(0x78563412)) - >爲0x12345678

7.Y = bit.rol(X,N),Y = bit.ror(X,N)

返回要麼按位左旋轉或按位右旋轉由第二個參數給出的位數的第一個參數。比特移出在一側在移回上的另外一側。
只有旋轉計數的低5位(減少到範圍[0..31])。

printx(bit.rol(爲0x12345678,12)) - > 0x45678123
printx(bit.ror(爲0x12345678,12)) - > 0x67812345

2.lua-resty-limit-req庫   github地址:https://github.com/timebug/lua-resty-limit-req/

 用於限制NGINX多個實例之間的請求處理率,具體實現查看github裏面的內容。

3.FFI Library   介紹網址http://luajit.org/ext_ffi.html

待完善總結,須要一篇完整的博客進行來總結

                                                        正式閱讀源碼

初始化,限制請求的庫

local limiter
do
    local limit_req_module = require "resty.limit.req"

    -- local rate = 2000000
    local rate = 20

    -- local burst = 1000
    local burst = 20
    local err
    limiter, err = limit_req_module.new("limit_req_zone", rate, burst)
    if not limiter then
        return error("failed to instantiate a resty.limit.req object: "
                     .. (err or ""))
    end
end

 函數 function get_binary_remote_addr()

關鍵點:獲取環境變量,getfenv方法,學習博客

http://blog.csdn.net/jayson520/article/details/51498848

C.ngx_stream_lua_get_binary_remote_addr(s, ccbuf, sizep)方法的調用依賴於ffi模塊代碼以下:

ffi.cdef[[
int ngx_stream_lua_mmdb_lookup(void *s, char **country_code,
    size_t *country_code_size);

int ngx_stream_lua_get_binary_remote_addr(void *s, char **country_code,
    size_t *country_code_size);
]]

,經過該函數獲取真正的二進制地址。

local function get_binary_remote_addr()
    local s = getfenv(0).__ngx_sess  #getfenv(f)函數查看函數所處的環境,一般和setfenv結合起來用,解決命名衝突等
    if not s then
        return error("no session found")
    end

    local rc = C.ngx_stream_lua_get_binary_remote_addr(s, ccbuf, sizep)
    if rc ~= 0 then
        -- ngx.log(ngx.ERR, "error: ", rc)
        return nil
    end

    return ffi_str(ccbuf[0], sizep[0])
end

函數local function get_country_code()

獲取國家編碼:骨架和樓上類似,關鍵函數依賴於 C.ngx_stream_lua_mmdb_lookup(s, ccbuf, sizep)

從命名能夠看出是從mmdb數據庫中來查詢,更深刻部分只能研究C代碼是如何嵌入。

local function get_country_code()
    local s = getfenv(0).__ngx_sess
    if not s then
        return error("no session found")
    end

    local rc = C.ngx_stream_lua_mmdb_lookup(s, ccbuf, sizep)
    if rc ~= 0 then
        -- ngx.log(ngx.ERR, "error: ", rc)
        return nil
    end

    return ffi_str(ccbuf[0], sizep[0])
end

函數 function _decode_name(buf, pos) 

在while循環內部 第一行就是  local fst = byte(buf, p),這個byte函數是string.byte函數的別名。

他的做用主要是對指定字符求ascii編碼,第一個參數是求解字符串,第二個參數是字符的位置,若是是""字符串,就會返回nil,因此在作後續的計算時作了一個if的判斷,注意這裏必需要提一下,在lua中只有false,nil是false,因此直接判斷 not fst,接下來對各個ascii碼進行處理。(這裏的ascii碼指的是擴展後的ascii編碼,能夠使用到255)

if fst==0 是爲判斷若是是空格符,就右移一位。

接下來是對fst和 十六進制的0xc0進行與預算,咱們很容易知道0xc0的十進制是192,查詢擴展ascii碼下咱們能夠知道的是:

 

local function _decode_name(buf, pos)
    clear_tb(labels)

    local nptrs = 0
    local p = pos
    while nptrs < 128 do
        local fst = byte(buf, p)

        if not fst then
            return nil, 'truncated';
        end

        -- print("fst at ", p, ": ", fst)

        if fst == 0 then
            if nptrs == 0 then
                pos = pos + 1
            end
            break
        end

        if band(fst, 0xc0) ~= 0 then
            -- being a pointer
            if nptrs == 0 then
                pos = pos + 2
            end

            nptrs = nptrs + 1

            local snd = byte(buf, p + 1)
            if not snd then
                return nil, 'truncated'
            end

            p = lshift(band(fst, 0x3f), 8) + snd + 1

            -- print("resolving ptr ", p, ": ", byte(buf, p))

        else
            -- being a label
            local label = sub(buf, p + 1, p + fst)
            insert(labels, label)

            -- print("resolved label ", label)

            p = p + fst + 1

            if nptrs == 0 then
                pos = p
            end
        end
    end

    return concat(labels, "."), pos
end
第149行

待續

相關文章
相關標籤/搜索