Skip to content

Latest commit

 

History

History
165 lines (121 loc) · 4.02 KB

user_defined_protocol.md

File metadata and controls

165 lines (121 loc) · 4.02 KB

lua用户自定义协议

ruci 中提供 lua用户自定义协议方式来 大大提高使用的灵活性。

方法是,用户首先在配置文件中指定 链中的一个Map为 Lua:

local config_21_lua_example1 = {
    inbounds = { {
        chain = listen_socks5http,
        tag = "listen1"
    } },
    outbounds = { {
        tag = "dial1",
        chain = { dial, tlsout, trojan_out, { Lua = { file_name = "lua_protocol_e1.lua", handshake_function = "Handshake2" } } }
    } }
}

里面指定了 具体实现协议的 lua_protocol_e1.lua 文件 以及里面的 Handshake2函数 作为 协议的握手函数

lua_protocol_e1.lua:

function Handshake(cid, behavior, addr, firstbuff, conn)
    return conn, addr, firstbuff
end

cid 为字符串, behavior 为1 表示 client, 为 2 表示 server, addr 表示 代理要连接的目标地址。 firstbuff 为数据的首包。 conn 为链中上一个Map 的连接。

上面函数的具体实现就是将内容按上一个Map的原样返回

如果要返回一个自定义的新Map,则可以返回一个 包含读、写、关、冲 四个函数的table

function Handshake(cid, behavior, addr, firstbuff, conn)
    Cid=cid
    TheConn = conn
    Behavior = behavior
     return { Read, Write, Close, Flush }, addr, firstbuff
end

上面函数把 cid, behavior, conn 保存到了全局变量中,这样就可以在 四函数中访问这些值了

其中, conn有 poll_read, poll_write, poll_close, poll_flush 四个方法。

它们都接收一个 cx 作为参数。这里不用管cx是什么,只要记住原样传递即可。

Read

Read函数除了 cx外还有一个 buf 变量。 buf 变量可以作为 conn:poll_read的参数,也可以在 Wrap_read_buf(buf) 后变为一个 lua可以访问的变量类型,其有如下方法:

put_slice
filled_len
filled_content

这种类型的变量也可以用 local b = Create_read_buf(1024) 创建。

而如果要将 lua 可以访问的buf作为 poll_read的参数,则要加一个 get_ptr:

conn:poll_read(cx, b:get_ptr())

而使用完 lua的buf后,要调用 b:drop() 来释放内存。

示例:

function Read(cx, buf)
    -- print("lua read2 called")
    local result = TheConn:poll_read(cx, buf)

    if result:is_pending() then
        return -1
    elseif result:is_err() then
        return -2
    else
        local rb = Wrap_read_buf(buf) -- 用 Wrap_read_buf 将 buf 转为 lua 可调用的 版本 (未转时仅能作 poll_read 的参数)

        local n = rb:filled_len()
        print("lua read2 got", n, Cid)

        if n > 10 then
            n = 10
        end

        local s = rb:filled_content(n)
        print("read head ", inspect(s:sub(1, 1))) --获取第一个字节的值 并打印出来

        return 0
    end
end

Write

function Write(cx, str)
    -- print("lua write2 called", str:len())
    local result = TheConn:poll_write(cx, str)

    if result:is_pending() then
        return -1
    elseif result:is_err() then
        return -2
    else
        local n = result:get_n()
        -- print("lua write2 finish", n)

        return n
    end
end

Close

function Close(cx)
    -- print("close2 called")
    local result = TheConn:poll_close(cx)

    if result:is_pending() then
        return -1
    elseif result:is_err() then
        return -2
    else
        return 0
    end
end

Flush

function Flush(cx)
    -- print("flush2 called")

    local result = TheConn:poll_flush(cx)

    if result:is_pending() then
        return -1
    elseif result:is_err() then
        return -2
    else
        return 0
    end
end

其它

ruci还在lua中注册了 Debug_print,Info_print,Warn_print 函数,可以用于向日志打印自定义输出(以debug,info,warn 级别)

还有 Load_file 函数,可以用它加载 tar 中的文件。(只在 静态链中有效)