summaryrefslogtreecommitdiffstats
path: root/src/output/tcpcli.lua
blob: d57de8883ff01878abc53e3b2f6a7992afde4043 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
-- Copyright (c) 2018-2021, OARC, Inc.
-- All rights reserved.
--
-- This file is part of dnsjit.
--
-- dnsjit is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- dnsjit is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with dnsjit.  If not, see <http://www.gnu.org/licenses/>.

-- dnsjit.output.tcpcli
-- Simple, length aware, TCP client
--   local output = require("dnsjit.output.tcpcli").new("127.0.0.1", "53")
--
-- Simple TCP client that takes any payload you give it, sends the length of
-- the payload as an unsigned 16 bit integer and then sends the payload.
-- When receiving it will first retrieve the length of the payload as an
-- unsigned 16 bit integer and it will stall until it gets, even if
-- nonblocking mode is used.
-- Then it will retrieve at least that amount of bytes, if nonblocking mode
-- is used here then it will return a payload object with length zero if
-- there was nothing to receive or if the full payload have not been received
-- yet.
-- Additional calls will continue retrieving the payload.
-- .SS Attributes
-- .TP
-- timeout
-- A
-- .I core.timespec
-- that is used when producing objects.
module(...,package.seeall)

require("dnsjit.output.tcpcli_h")
local ffi = require("ffi")
local C = ffi.C

local t_name = "output_tcpcli_t"
local output_tcpcli_t = ffi.typeof(t_name)
local Tcpcli = {}

-- Create a new Tcpcli output.
function Tcpcli.new()
    local self = {
        obj = output_tcpcli_t(),
    }
    C.output_tcpcli_init(self.obj)
    ffi.gc(self.obj, C.output_tcpcli_destroy)
    return setmetatable(self, { __index = Tcpcli })
end

-- Set the timeout when producing objects.
function Tcpcli:timeout(seconds, nanoseconds)
    self.obj.timeout.sec = seconds
    self.obj.timeout.nsec = nanoseconds
end

-- Connect to the
-- .I host
-- and
-- .I port
-- and return 0 if successful.
function Tcpcli:connect(host, port)
    return C.output_tcpcli_connect(self.obj, host, port)
end

-- Enable (true) or disable (false) nonblocking mode and
-- return 0 if successful, if
-- .I bool
-- is not specified then return if nonblocking mode is on (true) or off (false).
function Tcpcli:nonblocking(bool)
    if bool == nil then
        if C.output_tcpcli_nonblocking(self.obj) == 1 then
            return true
        end
        return false
    elseif bool == true then
        return C.output_tcpcli_set_nonblocking(self.obj, 1)
    else
        return C.output_tcpcli_set_nonblocking(self.obj, 0)
    end
end

-- Return the C functions and context for receiving objects, these objects
-- will be sent.
function Tcpcli:receive()
    return C.output_tcpcli_receiver(self.obj), self.obj
end

-- Return the C functions and context for producing objects, these objects
-- are received.
-- If nonblocking mode is enabled the producer will return a payload object
-- with length zero if there was nothing to receive or if the full payload
-- have not been received yet.
-- If nonblocking mode is disabled the producer will wait for data and if
-- timed out (see
-- .IR timeout )
-- it will return a payload object with length zero.
-- If a timeout happens during during the first stage, getting the length, it
-- will fail and return nil.
-- Additional calls will continue retrieving the payload.
-- The producer returns nil on error.
function Tcpcli:produce()
    return C.output_tcpcli_producer(self.obj), self.obj
end

-- Return the number of "packets" sent, actually the number of completely sent
-- payloads.
function Tcpcli:packets()
    return tonumber(self.obj.pkts)
end

-- Return the number of "packets" received, actually the number of completely
-- received DNS messages.
function Tcpcli:received()
    return tonumber(self.obj.pkts_recv)
end

-- Return the number of errors when sending.
function Tcpcli:errors()
    return tonumber(self.obj.errs)
end

return Tcpcli