760ec8f820b7685a278154722c77bb971033ebd1
[project/luci.git] / libs / nixio / lua / nixio / util.lua
1 --[[
2 nixio - Linux I/O library for lua
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13 ]]--
14
15 local table = require "table"
16 local nixio = require "nixio"
17 local getmetatable, assert = getmetatable, assert
18
19 module "nixio.util"
20
21 local BUFFERSIZE = 8096
22 local socket = nixio.socket_meta
23 local tls_socket = nixio.tls_socket_meta
24
25 function socket.is_socket(self)
26         return (getmetatable(self) == socket)
27 end
28 tls_socket.is_socket = socket.is_socket
29
30 function socket.is_tls_socket(self)
31         return (getmetatable(self) == tls_socket)
32 end
33 tls_socket.is_tls_socket = socket.is_tls_socket
34
35 function socket.recvall(self, len)
36         local block, code, msg = self:recv(len)
37
38         if not block then
39                 return "", code, msg, len
40         elseif #block == 0 then
41                 return "", nil, nil, len
42         end
43
44         local data, total = {block}, #block
45
46         while len > total do
47                 block, code, msg = self:recv(len - total)
48
49                 if not block then
50                         return data, code, msg, len - #data
51                 elseif #block == 0 then
52                         return data, nil, nil, len - #data
53                 end
54
55                 data[#data+1], total = block, total + #block
56         end
57
58         return (#data > 1 and table.concat(data) or data[1]), nil, nil, 0
59 end
60 tls_socket.recvall = socket.recvall
61
62 function socket.sendall(self, data)
63         local total, block = 0
64         local sent, code, msg = self:send(data)
65
66         if not sent then
67                 return total, code, msg, data
68         end
69
70         while sent < #data do
71                 block, total = data:sub(sent + 1), total + sent
72                 sent, code, msg = self:send(block)
73                 
74                 if not sent then
75                         return total, code, msg, block
76                 end
77         end
78         
79         return total + sent, nil, nil, ""
80 end
81 tls_socket.sendall = socket.sendall
82
83 function socket.linesource(self, limit)
84         limit = limit or BUFFERSIZE
85         local buffer = ""
86         local bpos = 0
87         return function(flush)
88                 local line, endp, _
89                 
90                 if flush then
91                         line = buffer:sub(bpos + 1)
92                         buffer = ""
93                         bpos = 0
94                         return line
95                 end
96
97                 while not line do
98                         _, endp, line = buffer:find("(.-)\r?\n", bpos + 1)
99                         if line then
100                                 bpos = endp
101                                 return line
102                         elseif #buffer < limit + bpos then
103                                 local newblock, code = self:recv(limit + bpos - #buffer)
104                                 if not newblock then
105                                         return nil, code
106                                 elseif #newblock == 0 then
107                                         return nil
108                                 end
109                                 buffer = buffer:sub(bpos + 1) .. newblock
110                                 bpos = 0
111                         else
112                                 return nil, 0
113                         end
114                 end
115         end
116 end
117 tls_socket.linesource = socket.linesource
118
119 function socket.blocksource(self, bs, limit)
120         bs = bs or BUFFERSIZE
121         return function()
122                 local toread = bs
123                 if limit then
124                         if limit < 1 then
125                                 return nil
126                         elseif limit < toread then
127                                 toread = limit
128                         end
129                 end
130
131                 local block, code, msg = self:recv(toread)
132
133                 if not block then
134                         return nil, code
135                 elseif #block == 0 then
136                         return nil
137                 else
138                         if limit then
139                                 limit = limit - #block
140                         end
141
142                         return block
143                 end
144         end
145 end
146 tls_socket.blocksource = socket.blocksource
147
148 function tls_socket.close(self)
149         self:shutdown()
150         return self.socket:close()
151 end