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行
待續