]> jfr.im git - irc/quakenet/newserv.git/blame - lua/lib/socket.lua
Merge
[irc/quakenet/newserv.git] / lua / lib / socket.lua
CommitLineData
a098bb43
CP
1-- transparent non-blocking writes with buffers!
2
3local socket_write_raw = socket_write
4local socket_unix_connect_raw = socket_unix_connect
5local socket_unix_bind_raw = socket_unix_bind
6local socket_tcp_connect_raw = socket_tcp_connect
7local socket_tcp_bind_raw = socket_tcp_bind
8local socket_udp_connect_raw = socket_udp_connect
9local socket_udp_bind_raw = socket_udp_bind
10local socket_close_raw = socket_close
11
12local sockets = {}
13
14function socket_handler(socket, event, tag, ...)
15 if event == "flush" then
16 local buf = sockets[socket].writebuf
17 local ret = socket_write_raw(socket, buf)
18
19 if ret == -1 then
20 return -- close will be called
21 end
22
23 sockets[socket].writebuf = buf:sub(ret + 1)
24
25 if sockets[socket].closing and sockets[socket].writebuf == "" then
26 socket_close(socket)
27 end
28
29 -- no reason to tell the caller
30 return
31 elseif event == "accept" then
32 local newsocket = ...
33 socket_new(newsocket, sockets[socket].handler)
34 end
35
36 sockets[socket].handler(socket, event, tag, ...)
37
38 if event == "close" then
39 sockets[socket] = nil
40 end
41end
42
43function socket_new(socket, handler)
44 sockets[socket] = { writebuf = "", handler = handler }
45end
46
47function socket_unix_connect(path, handler, tag)
48 local connected, socket = socket_unix_connect_raw(path, socket_handler, tag)
49 if connected == nil then
50 return nil
51 end
52
53 socket_new(socket, handler)
54 if connected then
55 socket_handler(socket, "connect", tag)
56 end
57
58 return socket
59end
60
61function socket_unix_bind(path, handler, tag)
62 local socket = socket_unix_bind_raw(path, socket_handler, tag)
63 if not socket then
64 return nil
65 end
66
67 socket_new(socket, handler)
68 return socket
69end
70
71local function socket_ip_connect(fn, address, port, handler, tag)
4ce637de 72 local connected, socket = fn(address, port, handler, tag)
a098bb43
CP
73 if connected == nil then
74 return nil
75 end
76
77 socket_new(socket, handler)
78 if connected then
4ce637de 79 handler(socket, "connect", tag)
a098bb43
CP
80 end
81
82 return socket
83end
84
85local function socket_ip_bind(fn, address, port, handler, tag)
a6fa0bfb 86 local socket = fn(address, port, handler, tag)
a098bb43
CP
87 if not socket then
88 return nil
89 end
90
91 socket_new(socket, handler)
92 return socket
93end
94
95function socket_tcp_bind(address, port, handler, tag)
96 return socket_ip_bind(socket_tcp_bind_raw, address, port, handler, tag)
97end
98
99function socket_tcp_connect(address, port, handler, tag)
100 return socket_ip_connect(socket_tcp_connect_raw, address, port, handler, tag)
101end
102
103function socket_udp_bind(address, port, handler, tag)
104 return socket_ip_bind(socket_udp_bind_raw, address, port, handler, tag)
105end
106
107function socket_udp_connect(address, port, handler, tag)
108 return socket_ip_connect(socket_udp_connect_raw, address, port, handler, tag)
109end
110
111function socket_write(socket, data)
112 if sockets[socket].writebuf == "" then
113 local ret = socket_write_raw(socket, data)
114 if ret == -1 then
115 return false -- close will be called regardless
116 end
117
118 if ret == data:len() then
119 return true
120 end
121
122 -- lua strings start at 1
123 sockets[socket].writebuf = data:sub(ret + 1)
124 else
125 sockets[socket].writebuf = sockets[socket].writebuf .. data
126 end
127
128 return true
129end
130
131function socket_close(socket, flush)
132 if whenbufferempty and sockets[socket].writebuf ~= "" then
133 sockets[socket].closing = true
134 return
135 end
136
137 return socket_close_raw(socket)
138end