aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2005-08-23 05:53:14 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2005-08-23 05:53:14 +0000
commit773e35ced30fa2c03ddb2a332bf8a9aebb56aa44 (patch)
tree03e8e9a4bd64b9424006315c8e720c3f2841a751
parent5e8ae76248ed31496dc6fef7855498a0479159ed (diff)
downloadluasocket-773e35ced30fa2c03ddb2a332bf8a9aebb56aa44.tar.gz
luasocket-773e35ced30fa2c03ddb2a332bf8a9aebb56aa44.tar.bz2
luasocket-773e35ced30fa2c03ddb2a332bf8a9aebb56aa44.zip
Compiled on Windows. Fixed a bunch of stuff. Almost ready to release.
Implemented a nice dispatcher! Non-blocking check-links and forward server use the dispatcher.
-rw-r--r--TODO9
-rw-r--r--config12
-rw-r--r--doc/index.html4
-rw-r--r--etc/check-links.lua31
-rw-r--r--etc/dispatch.lua296
-rw-r--r--etc/forward.lua65
-rw-r--r--luasocket.sln2
-rw-r--r--makefile37
-rw-r--r--makefile.dist9
-rw-r--r--mime.vcproj32
-rw-r--r--socket.vcproj (renamed from luasocket.vcproj)101
-rw-r--r--src/auxiliar.c8
-rw-r--r--src/http.lua1
-rw-r--r--src/luasocket.h2
-rw-r--r--src/mime.c2
-rw-r--r--src/mime.h2
-rw-r--r--src/smtp.lua49
-rw-r--r--src/wsocket.c2
-rw-r--r--test/ftptest.lua4
-rw-r--r--test/testmesg.lua42
20 files changed, 400 insertions, 310 deletions
diff --git a/TODO b/TODO
index b2a167e..bd60aaa 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,8 @@
1new instalation scheme??? 1new instalation scheme???
2test empty socket.select no windows.
3bug by mathew percival?
4 2
5arranjar um jeito de fazer multipart/alternative 3test empty socket.select no windows.
6 4
7what the hell does __unload do? 5bug by mathew percival?
8 6
9test it on Windows!!! 7test it on Windows!!!
10 8
@@ -45,3 +43,6 @@ testar os options!
45 * received connections 43 * received connections
46 * - this function is invoked with the client socket 44 * - this function is invoked with the client socket
47 * - it calls special send and receive functions that yield on timeout 45 * - it calls special send and receive functions that yield on timeout
46* arranjar um jeito de fazer multipart/alternative
47* what the hell does __unload do?
48 * it's there just in case someone wants to use it.
diff --git a/config b/config
index da9fdf4..a85e8e6 100644
--- a/config
+++ b/config
@@ -8,8 +8,8 @@
8EXT=so 8EXT=so
9SOCKET_V=2.0.0 9SOCKET_V=2.0.0
10MIME_V=1.0.0 10MIME_V=1.0.0
11SOCKET_SO=socket-core.$(EXT).$(SOCKET_V) 11SOCKET_SO=socket.$(EXT).$(SOCKET_V)
12MIME_SO=mime-core.$(EXT).$(MIME_V) 12MIME_SO=mime.$(EXT).$(MIME_V)
13UNIX_SO=unix.$(EXT) 13UNIX_SO=unix.$(EXT)
14 14
15#------ 15#------
@@ -25,13 +25,15 @@ COMPAT=compat-5.1r4
25 25
26#------ 26#------
27# Top of your Lua installation 27# Top of your Lua installation
28# Relative paths will be inside src tree 28# Relative paths will be inside the src tree
29# 29#
30INSTALL_TOP=/usr/local/share/lua/5.0 30#INSTALL_TOP_LUA=/usr/local/share/lua/5.0
31#INSTALL_TOP_LIB=/usr/local/lib/lua/5.0
32INSTALL_TOP_LUA=share
33INSTALL_TOP_LIB=lib
31 34
32INSTALL_DATA=cp 35INSTALL_DATA=cp
33INSTALL_EXEC=cp 36INSTALL_EXEC=cp
34INSTALL_LINK=ln
35 37
36#------ 38#------
37# Compiler and linker settings 39# Compiler and linker settings
diff --git a/doc/index.html b/doc/index.html
index e596f8e..3d5acb3 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -168,6 +168,8 @@ support.
168<li> Improved: <tt>tcp:send(data, i, j)</tt> to return <tt>(i+sent-1)</tt>. This is great for non-blocking I/O, but might break some code; 168<li> Improved: <tt>tcp:send(data, i, j)</tt> to return <tt>(i+sent-1)</tt>. This is great for non-blocking I/O, but might break some code;
169<li> Improved: HTTP, SMTP, and FTP functions to accept a new field 169<li> Improved: HTTP, SMTP, and FTP functions to accept a new field
170<tt>create</tt> that overrides the function used to create socket objects; 170<tt>create</tt> that overrides the function used to create socket objects;
171<li> Improved: <tt>smtp.message</tt> now supports multipart/alternative
172(for the HTML messages we all love so much);
171<li> Fixed: <tt>smtp.send</tt> was hanging on errors returned by LTN12 sources; 173<li> Fixed: <tt>smtp.send</tt> was hanging on errors returned by LTN12 sources;
172<li> Fixed: <tt>url.absolute()</tt> to work when <tt>base_url</tt> is in 174<li> Fixed: <tt>url.absolute()</tt> to work when <tt>base_url</tt> is in
173parsed form; 175parsed form;
@@ -183,7 +185,7 @@ group;
183<li> Improved: Socket and MIME binaries are called 'core' each inside their 185<li> Improved: Socket and MIME binaries are called 'core' each inside their
184directory (ex. "socket/core.dll"). The 'l' prefix was just a bad idea; 186directory (ex. "socket/core.dll"). The 'l' prefix was just a bad idea;
185<li> Improved: Using bundles in Mac OS X, instead of dylibs; 187<li> Improved: Using bundles in Mac OS X, instead of dylibs;
186<li> Fixed: <tt>luasocket.h</tt> to export <tt>luaopen_socketcore</tt>; 188<li> Fixed: <tt>luasocket.h</tt> to export <tt>luaopen_socket_core</tt>;
187<li> Fixed: <tt>udp:setpeername()</tt> so you can "disconnect" an 189<li> Fixed: <tt>udp:setpeername()</tt> so you can "disconnect" an
188<tt>UDP</tt> socket; 190<tt>UDP</tt> socket;
189<li> Fixed: A weird bug in HTTP support that caused some requests to 191<li> Fixed: A weird bug in HTTP support that caused some requests to
diff --git a/etc/check-links.lua b/etc/check-links.lua
index e06cc91..725cd2a 100644
--- a/etc/check-links.lua
+++ b/etc/check-links.lua
@@ -5,33 +5,26 @@
5-- Author: Diego Nehab 5-- Author: Diego Nehab
6-- RCS ID: $$ 6-- RCS ID: $$
7----------------------------------------------------------------------------- 7-----------------------------------------------------------------------------
8local dispatch, url, http, handler 8local url = require("socket.url")
9local dispatch = require("dispatch")
10local http = require("socket.http")
11dispatch.TIMEOUT = 10
9 12
13-- make sure the user knows how to invoke us
10arg = arg or {} 14arg = arg or {}
11if table.getn(arg) < 1 then 15if table.getn(arg) < 1 then
12 print("Usage:\n luasocket check-links.lua [-n] {<url>}") 16 print("Usage:\n luasocket check-links.lua [-n] {<url>}")
13 exit() 17 exit()
14end 18end
15 19
16if arg[1] ~= "-n" then 20-- '-n' means we are running in non-blocking mode
17 -- if using blocking I/O, simulate dispatcher interface 21if arg[1] == "-n" then
18 url = require("socket.url") 22 -- if non-blocking I/O was requested, use real dispatcher interface
19 http = require("socket.http")
20 handler = {
21 start = function(self, f)
22 f()
23 end,
24 tcp = socket.tcp
25 }
26 http.TIMEOUT = 10
27else
28 -- if non-blocking I/O was requested, disable dispatcher
29 table.remove(arg, 1) 23 table.remove(arg, 1)
30 dispatch = require("dispatch") 24 handler = dispatch.newhandler("coroutine")
31 dispatch.TIMEOUT = 10 25else
32 url = require("socket.url") 26 -- if using blocking I/O, use fake dispatcher interface
33 http = require("socket.http") 27 handler = dispatch.newhandler("sequential")
34 handler = dispatch.newhandler()
35end 28end
36 29
37local nthreads = 0 30local nthreads = 0
diff --git a/etc/dispatch.lua b/etc/dispatch.lua
index e6c14a6..98fa8a8 100644
--- a/etc/dispatch.lua
+++ b/etc/dispatch.lua
@@ -11,23 +11,33 @@ module("dispatch")
11 11
12-- if too much time goes by without any activity in one of our sockets, we 12-- if too much time goes by without any activity in one of our sockets, we
13-- just kill it 13-- just kill it
14TIMEOUT = 10 14TIMEOUT = 60
15 15
16----------------------------------------------------------------------------- 16-----------------------------------------------------------------------------
17-- Mega hack. Don't try to do this at home. 17-- We implement 3 types of dispatchers:
18-- sequential
19-- coroutine
20-- threaded
21-- The user can choose whatever one is needed
18----------------------------------------------------------------------------- 22-----------------------------------------------------------------------------
19-- Lua 5.1 has coroutine.running(). We need it here, so we use this terrible 23local handlert = {}
20-- hack to emulate it in Lua itself 24
21-- This is very inefficient, but is very good for debugging. 25-- default handler is coroutine
22local running 26function newhandler(mode)
23local resume = coroutine.resume 27 mode = mode or "coroutine"
24function coroutine.resume(co, ...) 28 return handlert[mode]()
25 running = co
26 return resume(co, unpack(arg))
27end 29end
28 30
29function coroutine.running() 31local function seqstart(self, func)
30 return running 32 return func()
33end
34
35-- sequential handler simply calls the functions and doesn't wrap I/O
36function handlert.sequential()
37 return {
38 tcp = socket.tcp,
39 start = seqstart
40 }
31end 41end
32 42
33----------------------------------------------------------------------------- 43-----------------------------------------------------------------------------
@@ -37,14 +47,10 @@ end
37-- make sure you don't require any module that uses socket.protect before 47-- make sure you don't require any module that uses socket.protect before
38-- loading our hack 48-- loading our hack
39function socket.protect(f) 49function socket.protect(f)
40 return f
41end
42
43function socket.protect(f)
44 return function(...) 50 return function(...)
45 local co = coroutine.create(f) 51 local co = coroutine.create(f)
46 while true do 52 while true do
47 local results = {resume(co, unpack(arg))} 53 local results = {coroutine.resume(co, unpack(arg))}
48 local status = table.remove(results, 1) 54 local status = table.remove(results, 1)
49 if not status then 55 if not status then
50 if type(results[1]) == 'table' then 56 if type(results[1]) == 'table' then
@@ -61,48 +67,68 @@ function socket.protect(f)
61end 67end
62 68
63----------------------------------------------------------------------------- 69-----------------------------------------------------------------------------
64-- socket.tcp() replacement for non-blocking I/O 70-- Simple set data structure. O(1) everything.
71-----------------------------------------------------------------------------
72local function newset()
73 local reverse = {}
74 local set = {}
75 return setmetatable(set, {__index = {
76 insert = function(set, value)
77 if not reverse[value] then
78 table.insert(set, value)
79 reverse[value] = table.getn(set)
80 end
81 end,
82 remove = function(set, value)
83 local index = reverse[value]
84 if index then
85 reverse[value] = nil
86 local top = table.remove(set)
87 if top ~= value then
88 reverse[top] = index
89 set[index] = top
90 end
91 end
92 end
93 }})
94end
95
96-----------------------------------------------------------------------------
97-- socket.tcp() wrapper for the coroutine dispatcher
65----------------------------------------------------------------------------- 98-----------------------------------------------------------------------------
66local function newtrap(dispatcher) 99local function cowrap(dispatcher, tcp, error)
67 -- try to create underlying socket
68 local tcp, error = socket.tcp()
69 if not tcp then return nil, error end 100 if not tcp then return nil, error end
70 -- put it in non-blocking mode right away 101 -- put it in non-blocking mode right away
71 tcp:settimeout(0) 102 tcp:settimeout(0)
72 -- metatable for trap produces new methods on demand for those that we 103 -- metatable for wrap produces new methods on demand for those that we
73 -- don't override explicitly. 104 -- don't override explicitly.
74 local metat = { __index = function(table, key) 105 local metat = { __index = function(table, key)
75 table[key] = function(...) 106 table[key] = function(...)
76 return tcp[key](tcp, unpack(arg)) 107 arg[1] = tcp
108 return tcp[key](unpack(arg))
77 end 109 end
110 return table[key]
78 end} 111 end}
79 -- does user want to do his own non-blocking I/O? 112 -- does our user want to do his own non-blocking I/O?
80 local zero = false 113 local zero = false
81 -- create a trap object that will behave just like a real socket object 114 -- create a wrap object that will behave just like a real socket object
82 local trap = { } 115 local wrap = { }
83 -- we ignore settimeout to preserve our 0 timeout, but record whether 116 -- we ignore settimeout to preserve our 0 timeout, but record whether
84 -- the user wants to do his own non-blocking I/O 117 -- the user wants to do his own non-blocking I/O
85 function trap:settimeout(mode, value) 118 function wrap:settimeout(value, mode)
86 if value == 0 then 119 if value == 0 then zero = true
87 zero = true 120 else zero = false end
88 else
89 zero = false
90 end
91 return 1 121 return 1
92 end 122 end
93 -- send in non-blocking mode and yield on timeout 123 -- send in non-blocking mode and yield on timeout
94 function trap:send(data, first, last) 124 function wrap:send(data, first, last)
95 first = (first or 1) - 1 125 first = (first or 1) - 1
96 local result, error 126 local result, error
97 while true do 127 while true do
98 -- tell dispatcher we want to keep sending before we yield 128 -- return control to dispatcher and tell it we want to send
99 dispatcher.sending:insert(tcp)
100 -- mark time we started waiting
101 dispatcher.context[tcp].last = socket.gettime()
102 -- return control to dispatcher
103 -- if upon return the dispatcher tells us we timed out, 129 -- if upon return the dispatcher tells us we timed out,
104 -- return an error to whoever called us 130 -- return an error to whoever called us
105 if coroutine.yield() == "timeout" then 131 if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
106 return nil, "timeout" 132 return nil, "timeout"
107 end 133 end
108 -- try sending 134 -- try sending
@@ -114,41 +140,35 @@ local function newtrap(dispatcher)
114 end 140 end
115 -- receive in non-blocking mode and yield on timeout 141 -- receive in non-blocking mode and yield on timeout
116 -- or simply return partial read, if user requested timeout = 0 142 -- or simply return partial read, if user requested timeout = 0
117 function trap:receive(pattern, partial) 143 function wrap:receive(pattern, partial)
118 local error = "timeout" 144 local error = "timeout"
119 local value 145 local value
120 while true do 146 while true do
121 -- tell dispatcher we want to keep receiving before we yield 147 -- return control to dispatcher and tell it we want to receive
122 dispatcher.receiving:insert(tcp)
123 -- mark time we started waiting
124 dispatcher.context[tcp].last = socket.gettime()
125 -- return control to dispatcher
126 -- if upon return the dispatcher tells us we timed out, 148 -- if upon return the dispatcher tells us we timed out,
127 -- return an error to whoever called us 149 -- return an error to whoever called us
128 if coroutine.yield() == "timeout" then 150 if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
129 return nil, "timeout" 151 return nil, "timeout"
130 end 152 end
131 -- try receiving 153 -- try receiving
132 value, error, partial = tcp:receive(pattern, partial) 154 value, error, partial = tcp:receive(pattern, partial)
133 -- if we are done, or there was an unexpected error, 155 -- if we are done, or there was an unexpected error,
134 -- break away from loop 156 -- break away from loop. also, if the user requested
157 -- zero timeout, return all we got
135 if (error ~= "timeout") or zero then 158 if (error ~= "timeout") or zero then
136 return value, error, partial 159 return value, error, partial
137 end 160 end
138 end 161 end
139 end 162 end
140 -- connect in non-blocking mode and yield on timeout 163 -- connect in non-blocking mode and yield on timeout
141 function trap:connect(host, port) 164 function wrap:connect(host, port)
142 local result, error = tcp:connect(host, port) 165 local result, error = tcp:connect(host, port)
143 -- mark time we started waiting
144 dispatcher.context[tcp].last = socket.gettime()
145 if error == "timeout" then 166 if error == "timeout" then
146 -- tell dispatcher we will be able to write uppon connection 167 -- return control to dispatcher. we will be writable when
147 dispatcher.sending:insert(tcp) 168 -- connection succeeds.
148 -- return control to dispatcher
149 -- if upon return the dispatcher tells us we have a 169 -- if upon return the dispatcher tells us we have a
150 -- timeout, just abort 170 -- timeout, just abort
151 if coroutine.yield() == "timeout" then 171 if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
152 return nil, "timeout" 172 return nil, "timeout"
153 end 173 end
154 -- when we come back, check if connection was successful 174 -- when we come back, check if connection was successful
@@ -158,110 +178,124 @@ local function newtrap(dispatcher)
158 else return result, error end 178 else return result, error end
159 end 179 end
160 -- accept in non-blocking mode and yield on timeout 180 -- accept in non-blocking mode and yield on timeout
161 function trap:accept() 181 function wrap:accept()
162 local result, error = tcp:accept() 182 while 1 do
163 while error == "timeout" do 183 -- return control to dispatcher. we will be readable when a
164 -- mark time we started waiting 184 -- connection arrives.
165 dispatcher.context[tcp].last = socket.gettime()
166 -- tell dispatcher we will be able to read uppon connection
167 dispatcher.receiving:insert(tcp)
168 -- return control to dispatcher
169 -- if upon return the dispatcher tells us we have a 185 -- if upon return the dispatcher tells us we have a
170 -- timeout, just abort 186 -- timeout, just abort
171 if coroutine.yield() == "timeout" then 187 if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
172 return nil, "timeout" 188 return nil, "timeout"
173 end 189 end
190 local client, error = tcp:accept()
191 if error ~= "timeout" then
192 return cowrap(dispatcher, client, error)
193 end
174 end 194 end
175 return result, error
176 end 195 end
177 -- remove thread from context 196 -- remove cortn from context
178 function trap:close() 197 function wrap:close()
179 dispatcher.context[tcp] = nil 198 dispatcher.stamp[tcp] = nil
199 dispatcher.sending.set:remove(tcp)
200 dispatcher.sending.cortn[tcp] = nil
201 dispatcher.receiving.set:remove(tcp)
202 dispatcher.receiving.cortn[tcp] = nil
180 return tcp:close() 203 return tcp:close()
181 end 204 end
182 -- add newly created socket to context 205 return setmetatable(wrap, metat)
183 dispatcher.context[tcp] = {
184 thread = coroutine.running()
185 }
186 return setmetatable(trap, metat)
187end 206end
188 207
208
189----------------------------------------------------------------------------- 209-----------------------------------------------------------------------------
190-- Our set data structure 210-- Our coroutine dispatcher
191----------------------------------------------------------------------------- 211-----------------------------------------------------------------------------
192local function newset() 212local cometat = { __index = {} }
193 local reverse = {} 213
194 local set = {} 214function schedule(cortn, status, operation, tcp)
195 return setmetatable(set, {__index = { 215 if status then
196 insert = function(set, value) 216 if cortn and operation then
197 if not reverse[value] then 217 operation.set:insert(tcp)
198 table.insert(set, value) 218 operation.cortn[tcp] = cortn
199 reverse[value] = table.getn(set) 219 operation.stamp[tcp] = socket.gettime()
200 end
201 end,
202 remove = function(set, value)
203 local index = reverse[value]
204 if index then
205 reverse[value] = nil
206 local top = table.remove(set)
207 if top ~= value then
208 reverse[top] = index
209 set[index] = top
210 end
211 end
212 end 220 end
213 }}) 221 else error(operation) end
214end 222end
215 223
216----------------------------------------------------------------------------- 224function kick(operation, tcp)
217-- Our dispatcher API. 225 operation.cortn[tcp] = nil
218----------------------------------------------------------------------------- 226 operation.set:remove(tcp)
219local metat = { __index = {} } 227end
220 228
221function metat.__index:start(func) 229function wakeup(operation, tcp)
222 local co = coroutine.create(func) 230 local cortn = operation.cortn[tcp]
223 assert(coroutine.resume(co)) 231 -- if cortn is still valid, wake it up
232 if cortn then
233 kick(operation, tcp)
234 return cortn, coroutine.resume(cortn)
235 -- othrewise, just get scheduler not to do anything
236 else
237 return nil, true
238 end
224end 239end
225 240
226function newhandler() 241function abort(operation, tcp)
227 local dispatcher = { 242 local cortn = operation.cortn[tcp]
228 context = {}, 243 if cortn then
229 sending = newset(), 244 kick(operation, tcp)
230 receiving = newset() 245 coroutine.resume(cortn, "timeout")
231 }
232 function dispatcher.tcp()
233 return newtrap(dispatcher)
234 end 246 end
235 return setmetatable(dispatcher, metat)
236end 247end
237 248
238-- step through all active threads 249-- step through all active cortns
239function metat.__index:step() 250function cometat.__index:step()
240 -- check which sockets are interesting and act on them 251 -- check which sockets are interesting and act on them
241 local readable, writable = socket.select(self.receiving, 252 local readable, writable = socket.select(self.receiving.set,
242 self.sending, 1) 253 self.sending.set, 1)
243 -- for all readable connections, resume their threads 254 -- for all readable connections, resume their cortns and reschedule
244 for _, who in ipairs(readable) do 255 -- when they yield back to us
245 if self.context[who] then 256 for _, tcp in ipairs(readable) do
246 self.receiving:remove(who) 257 schedule(wakeup(self.receiving, tcp))
247 assert(coroutine.resume(self.context[who].thread))
248 end
249 end 258 end
250 -- for all writable connections, do the same 259 -- for all writable connections, do the same
251 for _, who in ipairs(writable) do 260 for _, tcp in ipairs(writable) do
252 if self.context[who] then 261 schedule(wakeup(self.sending, tcp))
253 self.sending:remove(who)
254 assert(coroutine.resume(self.context[who].thread))
255 end
256 end 262 end
257 -- politely ask replacement I/O functions in idle threads to 263 -- politely ask replacement I/O functions in idle cortns to
258 -- return reporting a timeout 264 -- return reporting a timeout
259 local now = socket.gettime() 265 local now = socket.gettime()
260 for who, data in pairs(self.context) do 266 for tcp, stamp in pairs(self.stamp) do
261 if data.last and now - data.last > TIMEOUT then 267 if tcp.class == "tcp{client}" and now - stamp > TIMEOUT then
262 self.sending:remove(who) 268 abort(self.sending, tcp)
263 self.receiving:remove(who) 269 abort(self.receiving, tcp)
264 assert(coroutine.resume(self.context[who].thread, "timeout"))
265 end 270 end
266 end 271 end
267end 272end
273
274function cometat.__index:start(func)
275 local cortn = coroutine.create(func)
276 schedule(cortn, coroutine.resume(cortn))
277end
278
279function handlert.coroutine()
280 local stamp = {}
281 local dispatcher = {
282 stamp = stamp,
283 sending = {
284 name = "sending",
285 set = newset(),
286 cortn = {},
287 stamp = stamp
288 },
289 receiving = {
290 name = "receiving",
291 set = newset(),
292 cortn = {},
293 stamp = stamp
294 },
295 }
296 function dispatcher.tcp()
297 return cowrap(dispatcher, socket.tcp())
298 end
299 return setmetatable(dispatcher, cometat)
300end
301
diff --git a/etc/forward.lua b/etc/forward.lua
new file mode 100644
index 0000000..eac98ae
--- /dev/null
+++ b/etc/forward.lua
@@ -0,0 +1,65 @@
1-- load our favourite library
2local dispatch = require("dispatch")
3local handler = dispatch.newhandler()
4
5-- make sure the user knows how to invoke us
6if table.getn(arg) < 1 then
7 print("Usage")
8 print(" lua forward.lua <iport:ohost:oport> ...")
9 os.exit(1)
10end
11
12-- function to move data from one socket to the other
13local function move(foo, bar)
14 local live
15 while 1 do
16 local data, error, partial = foo:receive(2048)
17 live = data or error == "timeout"
18 data = data or partial
19 local result, error = bar:send(data)
20 if not live or not result then
21 foo:close()
22 bar:close()
23 break
24 end
25 end
26end
27
28-- for each tunnel, start a new server
29for i, v in ipairs(arg) do
30 -- capture forwarding parameters
31 local _, _, iport, ohost, oport = string.find(v, "([^:]+):([^:]+):([^:]+)")
32 assert(iport, "invalid arguments")
33 -- create our server socket
34 local server = assert(handler.tcp())
35 assert(server:setoption("reuseaddr", true))
36 assert(server:bind("*", iport))
37 assert(server:listen(32))
38 -- handler for the server object loops accepting new connections
39 handler:start(function()
40 while 1 do
41 local client = assert(server:accept())
42 assert(client:settimeout(0))
43 -- for each new connection, start a new client handler
44 handler:start(function()
45 -- handler tries to connect to peer
46 local peer = assert(handler.tcp())
47 assert(peer:settimeout(0))
48 assert(peer:connect(ohost, oport))
49 -- if sucessful, starts a new handler to send data from
50 -- client to peer
51 handler:start(function()
52 move(client, peer)
53 end)
54 -- afte starting new handler, enter in loop sending data from
55 -- peer to client
56 move(peer, client)
57 end)
58 end
59 end)
60end
61
62-- simply loop stepping the server
63while 1 do
64 handler:step()
65end
diff --git a/luasocket.sln b/luasocket.sln
index 6a1d0b8..006b7f0 100644
--- a/luasocket.sln
+++ b/luasocket.sln
@@ -1,5 +1,5 @@
1Microsoft Visual Studio Solution File, Format Version 8.00 1Microsoft Visual Studio Solution File, Format Version 8.00
2Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luasocket", "luasocket.vcproj", "{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}" 2Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "socket", "socket.vcproj", "{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}"
3 ProjectSection(ProjectDependencies) = postProject 3 ProjectSection(ProjectDependencies) = postProject
4 EndProjectSection 4 EndProjectSection
5EndProject 5EndProject
diff --git a/makefile b/makefile
index 234e162..c84ef10 100644
--- a/makefile
+++ b/makefile
@@ -6,8 +6,10 @@ include config
6#------ 6#------
7# Hopefully no need to change anything below this line 7# Hopefully no need to change anything below this line
8# 8#
9INSTALL_SOCKET=$(INSTALL_TOP)/socket 9INSTALL_SOCKET_LUA=$(INSTALL_TOP_LUA)/socket
10INSTALL_MIME=$(INSTALL_TOP)/mime 10INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket
11INSTALL_MIME_LUA=$(INSTALL_TOP_LUA)/mime
12INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
11 13
12all clean: 14all clean:
13 cd src; $(MAKE) $@ 15 cd src; $(MAKE) $@
@@ -15,7 +17,7 @@ all clean:
15#------ 17#------
16# Files to install 18# Files to install
17# 19#
18TO_SOCKET:= \ 20TO_SOCKET_LUA:= \
19 socket.lua \ 21 socket.lua \
20 http.lua \ 22 http.lua \
21 url.lua \ 23 url.lua \
@@ -23,29 +25,28 @@ TO_SOCKET:= \
23 ftp.lua \ 25 ftp.lua \
24 smtp.lua 26 smtp.lua
25 27
26TO_TOP:= \ 28TO_TOP_LUA:= \
27 ltn12.lua 29 ltn12.lua
28 30
29TO_MIME:= \ 31TO_MIME_LUA:= \
30 $(MIME_SO) \
31 mime.lua 32 mime.lua
32 33
33#------ 34#------
34# Install LuaSocket according to recommendation 35# Install LuaSocket according to recommendation
35# 36#
36install: all 37install: all
37 cd src; mkdir -p $(INSTALL_TOP) 38 cd src; mkdir -p $(INSTALL_TOP_LUA)
38 cd src; $(INSTALL_DATA) $(COMPAT)/compat-5.1.lua $(INSTALL_TOP) 39 cd src; mkdir -p $(INSTALL_TOP_LIB)
39 cd src; $(INSTALL_DATA) ltn12.lua $(INSTALL_TOP) 40 cd src; $(INSTALL_DATA) $(COMPAT)/compat-5.1.lua $(INSTALL_TOP_LUA)
40 cd src; mkdir -p $(INSTALL_SOCKET) 41 cd src; $(INSTALL_DATA) ltn12.lua $(INSTALL_TOP_LUA)
41 cd src; $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET) 42 cd src; mkdir -p $(INSTALL_SOCKET_LUA)
42 cd src; $(INSTALL_DATA) $(TO_SOCKET) $(INSTALL_SOCKET) 43 cd src; mkdir -p $(INSTALL_SOCKET_LIB)
43 cd src; cd $(INSTALL_SOCKET); $(INSTALL_LINK) -s $(SOCKET_SO) core.$(EXT) 44 cd src; $(INSTALL_DATA) $(TO_SOCKET_LUA) $(INSTALL_SOCKET_LUA)
44 cd src; cd $(INSTALL_SOCKET); $(INSTALL_LINK) -s socket.lua init.lua 45 cd src; $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT)
45 cd src; mkdir -p $(INSTALL_MIME) 46 cd src; mkdir -p $(INSTALL_MIME_LUA)
46 cd src; $(INSTALL_DATA) $(TO_MIME) $(INSTALL_MIME) 47 cd src; mkdir -p $(INSTALL_MIME_LIB)
47 cd src; cd $(INSTALL_MIME); $(INSTALL_LINK) -s $(MIME_SO) core.$(EXT) 48 cd src; $(INSTALL_DATA) $(TO_MIME_LUA) $(INSTALL_MIME_LUA)
48 cd src; cd $(INSTALL_MIME); $(INSTALL_LINK) -s mime.lua init.lua 49 cd src; $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT)
49 50
50#------ 51#------
51# End of makefile 52# End of makefile
diff --git a/makefile.dist b/makefile.dist
index 4ccddbc..8b79653 100644
--- a/makefile.dist
+++ b/makefile.dist
@@ -2,9 +2,9 @@
2# Distribution makefile 2# Distribution makefile
3#-------------------------------------------------------------------------- 3#--------------------------------------------------------------------------
4 4
5DIST = luasocket-2.0-beta3 5DIST = luasocket-2.0
6 6
7COMPAT = compat-5.1r2 7COMPAT = compat-5.1r4
8 8
9LUA = \ 9LUA = \
10 ftp.lua \ 10 ftp.lua \
@@ -37,6 +37,7 @@ EXAMPLES = \
37 37
38ETC = \ 38ETC = \
39 check-links.lua \ 39 check-links.lua \
40 check-links-nb.lua \
40 dict.lua \ 41 dict.lua \
41 get.lua \ 42 get.lua \
42 unix.c \ 43 unix.c \
@@ -76,8 +77,8 @@ CORE = \
76 wsocket.h 77 wsocket.h
77 78
78MAKE = \ 79MAKE = \
79 makefile.Darwin \ 80 makefile \
80 makefile.Linux \ 81 config \
81 luasocket.sln \ 82 luasocket.sln \
82 luasocket.vcproj \ 83 luasocket.vcproj \
83 mime.vcproj 84 mime.vcproj
diff --git a/mime.vcproj b/mime.vcproj
index 43d289a..c4e328f 100644
--- a/mime.vcproj
+++ b/mime.vcproj
@@ -12,18 +12,18 @@
12 <Configurations> 12 <Configurations>
13 <Configuration 13 <Configuration
14 Name="Debug|Win32" 14 Name="Debug|Win32"
15 OutputDirectory=".\" 15 OutputDirectory="src"
16 IntermediateDirectory=".\" 16 IntermediateDirectory="src"
17 ConfigurationType="2" 17 ConfigurationType="2"
18 CharacterSet="2"> 18 CharacterSet="2">
19 <Tool 19 <Tool
20 Name="VCCLCompilerTool" 20 Name="VCCLCompilerTool"
21 Optimization="0" 21 Optimization="0"
22 AdditionalIncludeDirectories="..\..\include, compat-5.1r2" 22 AdditionalIncludeDirectories="src\compat-5.1r4, ..\lua-5.0.2\include"
23 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS;MIME_API=__declspec(dllexport)" 23 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS;MIME_API=__declspec(dllexport)"
24 MinimalRebuild="TRUE" 24 MinimalRebuild="TRUE"
25 BasicRuntimeChecks="3" 25 BasicRuntimeChecks="3"
26 RuntimeLibrary="5" 26 RuntimeLibrary="3"
27 UsePrecompiledHeader="0" 27 UsePrecompiledHeader="0"
28 WarningLevel="3" 28 WarningLevel="3"
29 Detect64BitPortabilityProblems="TRUE" 29 Detect64BitPortabilityProblems="TRUE"
@@ -32,7 +32,7 @@
32 Name="VCCustomBuildTool"/> 32 Name="VCCustomBuildTool"/>
33 <Tool 33 <Tool
34 Name="VCLinkerTool" 34 Name="VCLinkerTool"
35 OutputFile="$(OutDir)/cmime.dll" 35 OutputFile="$(OutDir)/mime.dll"
36 LinkIncremental="2" 36 LinkIncremental="2"
37 GenerateDebugInformation="TRUE" 37 GenerateDebugInformation="TRUE"
38 ProgramDatabaseFile="$(OutDir)/mime.pdb" 38 ProgramDatabaseFile="$(OutDir)/mime.pdb"
@@ -62,15 +62,15 @@
62 </Configuration> 62 </Configuration>
63 <Configuration 63 <Configuration
64 Name="Release|Win32" 64 Name="Release|Win32"
65 OutputDirectory="." 65 OutputDirectory="src"
66 IntermediateDirectory="." 66 IntermediateDirectory="src"
67 ConfigurationType="2" 67 ConfigurationType="2"
68 CharacterSet="2"> 68 CharacterSet="2">
69 <Tool 69 <Tool
70 Name="VCCLCompilerTool" 70 Name="VCCLCompilerTool"
71 AdditionalIncludeDirectories="../../include, compat-5.1r2" 71 AdditionalIncludeDirectories="src\compat-5.1r4, ..\lua-5.0.2\include"
72 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS; MIME_API=__declspec(dllexport)" 72 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MIME_EXPORTS; MIME_API=__declspec(dllexport)"
73 RuntimeLibrary="4" 73 RuntimeLibrary="2"
74 UsePrecompiledHeader="0" 74 UsePrecompiledHeader="0"
75 WarningLevel="3" 75 WarningLevel="3"
76 Detect64BitPortabilityProblems="TRUE" 76 Detect64BitPortabilityProblems="TRUE"
@@ -79,7 +79,7 @@
79 Name="VCCustomBuildTool"/> 79 Name="VCCustomBuildTool"/>
80 <Tool 80 <Tool
81 Name="VCLinkerTool" 81 Name="VCLinkerTool"
82 OutputFile="$(OutDir)/cmime.dll" 82 OutputFile="$(OutDir)/mime.dll"
83 LinkIncremental="1" 83 LinkIncremental="1"
84 GenerateDebugInformation="TRUE" 84 GenerateDebugInformation="TRUE"
85 SubSystem="2" 85 SubSystem="2"
@@ -117,19 +117,16 @@
117 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" 117 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
118 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> 118 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
119 <File 119 <File
120 RelativePath=".\compat-5.1r2\compat-5.1.c"> 120 RelativePath="src\compat-5.1r4\compat-5.1.c">
121 </File> 121 </File>
122 <File 122 <File
123 RelativePath=".\mime.c"> 123 RelativePath="src\mime.c">
124 </File> 124 </File>
125 </Filter> 125 </Filter>
126 <Filter 126 <Filter
127 Name="Header Files" 127 Name="Header Files"
128 Filter="h;hpp;hxx;hm;inl;inc;xsd" 128 Filter="h;hpp;hxx;hm;inl;inc;xsd"
129 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> 129 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
130 <File
131 RelativePath=".\mime.h">
132 </File>
133 </Filter> 130 </Filter>
134 <Filter 131 <Filter
135 Name="Resource Files" 132 Name="Resource Files"
@@ -137,10 +134,7 @@
137 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> 134 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
138 </Filter> 135 </Filter>
139 <File 136 <File
140 RelativePath="..\..\lib\liblua.lib"> 137 RelativePath="..\lua-5.0.2\lib\lua50.lib">
141 </File>
142 <File
143 RelativePath="..\..\lib\liblualib.lib">
144 </File> 138 </File>
145 </Files> 139 </Files>
146 <Globals> 140 <Globals>
diff --git a/luasocket.vcproj b/socket.vcproj
index 71486d6..ddfb46e 100644
--- a/luasocket.vcproj
+++ b/socket.vcproj
@@ -2,7 +2,7 @@
2<VisualStudioProject 2<VisualStudioProject
3 ProjectType="Visual C++" 3 ProjectType="Visual C++"
4 Version="7.10" 4 Version="7.10"
5 Name="luasocket" 5 Name="socket"
6 ProjectGUID="{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}" 6 ProjectGUID="{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}"
7 Keyword="Win32Proj"> 7 Keyword="Win32Proj">
8 <Platforms> 8 <Platforms>
@@ -12,18 +12,18 @@
12 <Configurations> 12 <Configurations>
13 <Configuration 13 <Configuration
14 Name="Debug|Win32" 14 Name="Debug|Win32"
15 OutputDirectory=".\" 15 OutputDirectory="src"
16 IntermediateDirectory=".\" 16 IntermediateDirectory="src"
17 ConfigurationType="2" 17 ConfigurationType="2"
18 CharacterSet="2"> 18 CharacterSet="2">
19 <Tool 19 <Tool
20 Name="VCCLCompilerTool" 20 Name="VCCLCompilerTool"
21 Optimization="0" 21 Optimization="0"
22 AdditionalIncludeDirectories="..\..\include, compat-5.1r2" 22 AdditionalIncludeDirectories="src\compat-5.1r4, ..\lua-5.0.2\include, src"
23 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport)" 23 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport)"
24 MinimalRebuild="TRUE" 24 MinimalRebuild="TRUE"
25 BasicRuntimeChecks="3" 25 BasicRuntimeChecks="3"
26 RuntimeLibrary="5" 26 RuntimeLibrary="3"
27 UsePrecompiledHeader="0" 27 UsePrecompiledHeader="0"
28 WarningLevel="3" 28 WarningLevel="3"
29 Detect64BitPortabilityProblems="TRUE" 29 Detect64BitPortabilityProblems="TRUE"
@@ -33,12 +33,12 @@
33 <Tool 33 <Tool
34 Name="VCLinkerTool" 34 Name="VCLinkerTool"
35 AdditionalDependencies="ws2_32.lib" 35 AdditionalDependencies="ws2_32.lib"
36 OutputFile="$(OutDir)/csocket.dll" 36 OutputFile="$(OutDir)/socket.dll"
37 LinkIncremental="2" 37 LinkIncremental="2"
38 GenerateDebugInformation="TRUE" 38 GenerateDebugInformation="TRUE"
39 ProgramDatabaseFile="$(OutDir)/luasocket.pdb" 39 ProgramDatabaseFile="$(OutDir)/socket.pdb"
40 SubSystem="2" 40 SubSystem="2"
41 ImportLibrary="$(OutDir)/luasocket.lib" 41 ImportLibrary="$(OutDir)/socket.lib"
42 TargetMachine="1"/> 42 TargetMachine="1"/>
43 <Tool 43 <Tool
44 Name="VCMIDLTool"/> 44 Name="VCMIDLTool"/>
@@ -63,15 +63,15 @@
63 </Configuration> 63 </Configuration>
64 <Configuration 64 <Configuration
65 Name="Release|Win32" 65 Name="Release|Win32"
66 OutputDirectory="." 66 OutputDirectory="./src"
67 IntermediateDirectory="." 67 IntermediateDirectory="./src"
68 ConfigurationType="2" 68 ConfigurationType="2"
69 CharacterSet="2"> 69 CharacterSet="2">
70 <Tool 70 <Tool
71 Name="VCCLCompilerTool" 71 Name="VCCLCompilerTool"
72 AdditionalIncludeDirectories="../../include, compat-5.1r2" 72 AdditionalIncludeDirectories="src\compat-5.1r4, ..\lua-5.0.2\include"
73 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport); LUASOCKET_DEBUG" 73 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LUASOCKET_EXPORTS;LUASOCKET_API=__declspec(dllexport); LUASOCKET_DEBUG"
74 RuntimeLibrary="4" 74 RuntimeLibrary="2"
75 UsePrecompiledHeader="0" 75 UsePrecompiledHeader="0"
76 WarningLevel="3" 76 WarningLevel="3"
77 Detect64BitPortabilityProblems="TRUE" 77 Detect64BitPortabilityProblems="TRUE"
@@ -81,13 +81,13 @@
81 <Tool 81 <Tool
82 Name="VCLinkerTool" 82 Name="VCLinkerTool"
83 AdditionalDependencies="ws2_32.lib" 83 AdditionalDependencies="ws2_32.lib"
84 OutputFile="$(OutDir)/csocket.dll" 84 OutputFile="$(OutDir)/socket.dll"
85 LinkIncremental="1" 85 LinkIncremental="1"
86 GenerateDebugInformation="TRUE" 86 GenerateDebugInformation="TRUE"
87 SubSystem="2" 87 SubSystem="2"
88 OptimizeReferences="2" 88 OptimizeReferences="2"
89 EnableCOMDATFolding="2" 89 EnableCOMDATFolding="2"
90 ImportLibrary="$(OutDir)/luasocket.lib" 90 ImportLibrary="$(OutDir)/socket.lib"
91 TargetMachine="1"/> 91 TargetMachine="1"/>
92 <Tool 92 <Tool
93 Name="VCMIDLTool"/> 93 Name="VCMIDLTool"/>
@@ -119,91 +119,49 @@
119 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" 119 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
120 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> 120 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
121 <File 121 <File
122 RelativePath=".\auxiliar.c"> 122 RelativePath="src\auxiliar.c">
123 </File> 123 </File>
124 <File 124 <File
125 RelativePath=".\buffer.c"> 125 RelativePath="src\buffer.c">
126 </File> 126 </File>
127 <File 127 <File
128 RelativePath=".\compat-5.1r2\compat-5.1.c"> 128 RelativePath="src\compat-5.1r4\compat-5.1.c">
129 </File> 129 </File>
130 <File 130 <File
131 RelativePath=".\except.c"> 131 RelativePath="src\except.c">
132 </File> 132 </File>
133 <File 133 <File
134 RelativePath=".\inet.c"> 134 RelativePath="src\inet.c">
135 </File> 135 </File>
136 <File 136 <File
137 RelativePath=".\io.c"> 137 RelativePath="src\io.c">
138 </File> 138 </File>
139 <File 139 <File
140 RelativePath=".\luasocket.c"> 140 RelativePath="src\luasocket.c">
141 </File> 141 </File>
142 <File 142 <File
143 RelativePath=".\options.c"> 143 RelativePath="src\options.c">
144 </File> 144 </File>
145 <File 145 <File
146 RelativePath=".\select.c"> 146 RelativePath="src\select.c">
147 </File> 147 </File>
148 <File 148 <File
149 RelativePath=".\tcp.c"> 149 RelativePath="src\tcp.c">
150 </File> 150 </File>
151 <File 151 <File
152 RelativePath=".\timeout.c"> 152 RelativePath="src\timeout.c">
153 </File> 153 </File>
154 <File 154 <File
155 RelativePath=".\udp.c"> 155 RelativePath="src\udp.c">
156 </File> 156 </File>
157 <File 157 <File
158 RelativePath=".\wsocket.c"> 158 RelativePath="src\wsocket.c">
159 </File> 159 </File>
160 </Filter> 160 </Filter>
161 <Filter 161 <Filter
162 Name="Header Files" 162 Name="Header Files"
163 Filter="h;hpp;hxx;hm;inl;inc;xsd" 163 Filter="h;hpp;hxx;hm;inl;inc;xsd"
164 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> 164 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
165 <File
166 RelativePath=".\auxiliar.h">
167 </File>
168 <File
169 RelativePath=".\base.h">
170 </File>
171 <File
172 RelativePath=".\buffer.h">
173 </File>
174 <File
175 RelativePath=".\inet.h">
176 </File>
177 <File
178 RelativePath=".\io.h">
179 </File>
180 <File
181 RelativePath=".\luasocket.h">
182 </File>
183 <File
184 RelativePath=".\options.h">
185 </File>
186 <File
187 RelativePath=".\select.h">
188 </File>
189 <File
190 RelativePath=".\smtp.h">
191 </File>
192 <File
193 RelativePath=".\socket.h">
194 </File>
195 <File
196 RelativePath=".\tcp.h">
197 </File>
198 <File
199 RelativePath=".\timeout.h">
200 </File>
201 <File
202 RelativePath=".\udp.h">
203 </File>
204 <File
205 RelativePath=".\wsocket.h">
206 </File>
207 </Filter> 165 </Filter>
208 <Filter 166 <Filter
209 Name="Resource Files" 167 Name="Resource Files"
@@ -211,10 +169,7 @@
211 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> 169 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
212 </Filter> 170 </Filter>
213 <File 171 <File
214 RelativePath="..\..\lib\liblua.lib"> 172 RelativePath="..\lua-5.0.2\lib\lua50.lib">
215 </File>
216 <File
217 RelativePath="..\..\lib\liblualib.lib">
218 </File> 173 </File>
219 </Files> 174 </Files>
220 <Globals> 175 <Globals>
diff --git a/src/auxiliar.c b/src/auxiliar.c
index 2ebcdd6..b228785 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -127,6 +127,9 @@ void aux_setclass(lua_State *L, const char *classname, int objidx) {
127* otherwise 127* otherwise
128\*-------------------------------------------------------------------------*/ 128\*-------------------------------------------------------------------------*/
129void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx) { 129void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx) {
130#if 0
131 return lua_touserdata(L, objidx);
132#else
130 if (!lua_getmetatable(L, objidx)) 133 if (!lua_getmetatable(L, objidx))
131 return NULL; 134 return NULL;
132 lua_pushstring(L, groupname); 135 lua_pushstring(L, groupname);
@@ -138,6 +141,7 @@ void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx) {
138 lua_pop(L, 2); 141 lua_pop(L, 2);
139 return lua_touserdata(L, objidx); 142 return lua_touserdata(L, objidx);
140 } 143 }
144#endif
141} 145}
142 146
143/*-------------------------------------------------------------------------*\ 147/*-------------------------------------------------------------------------*\
@@ -145,5 +149,9 @@ void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx) {
145* otherwise 149* otherwise
146\*-------------------------------------------------------------------------*/ 150\*-------------------------------------------------------------------------*/
147void *aux_getclassudata(lua_State *L, const char *classname, int objidx) { 151void *aux_getclassudata(lua_State *L, const char *classname, int objidx) {
152#if 0
153 return lua_touserdata(L, objidx);
154#else
148 return luaL_checkudata(L, objidx, classname); 155 return luaL_checkudata(L, objidx, classname);
156#endif
149} 157}
diff --git a/src/http.lua b/src/http.lua
index 9434d97..fe779a3 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -325,4 +325,3 @@ request = socket.protect(function(reqt, body)
325 if base.type(reqt) == "string" then return srequest(reqt, body) 325 if base.type(reqt) == "string" then return srequest(reqt, body)
326 else return trequest(reqt) end 326 else return trequest(reqt) end
327end) 327end)
328
diff --git a/src/luasocket.h b/src/luasocket.h
index 34a7693..c7d09d8 100644
--- a/src/luasocket.h
+++ b/src/luasocket.h
@@ -27,6 +27,6 @@
27/*-------------------------------------------------------------------------*\ 27/*-------------------------------------------------------------------------*\
28* Initializes the library. 28* Initializes the library.
29\*-------------------------------------------------------------------------*/ 29\*-------------------------------------------------------------------------*/
30LUASOCKET_API int luaopen_socketcore(lua_State *L); 30LUASOCKET_API int luaopen_socket_core(lua_State *L);
31 31
32#endif /* LUASOCKET_H */ 32#endif /* LUASOCKET_H */
diff --git a/src/mime.c b/src/mime.c
index 70e0db9..4539e2c 100644
--- a/src/mime.c
+++ b/src/mime.c
@@ -78,7 +78,7 @@ static UC b64unbase[256];
78/*-------------------------------------------------------------------------*\ 78/*-------------------------------------------------------------------------*\
79* Initializes module 79* Initializes module
80\*-------------------------------------------------------------------------*/ 80\*-------------------------------------------------------------------------*/
81MIME_API int luaopen_mimecore(lua_State *L) 81MIME_API int luaopen_mime_core(lua_State *L)
82{ 82{
83 luaL_openlib(L, "mime", func, 0); 83 luaL_openlib(L, "mime", func, 0);
84 /* initialize lookup tables */ 84 /* initialize lookup tables */
diff --git a/src/mime.h b/src/mime.h
index 34031a1..eda0898 100644
--- a/src/mime.h
+++ b/src/mime.h
@@ -19,6 +19,6 @@
19#define MIME_API extern 19#define MIME_API extern
20#endif 20#endif
21 21
22MIME_API int luaopen_mimecore(lua_State *L); 22MIME_API int luaopen_mime_core(lua_State *L);
23 23
24#endif /* MIME_H */ 24#endif /* MIME_H */
diff --git a/src/smtp.lua b/src/smtp.lua
index 46df1ab..5c485c2 100644
--- a/src/smtp.lua
+++ b/src/smtp.lua
@@ -137,12 +137,24 @@ end
137-- send_message forward declaration 137-- send_message forward declaration
138local send_message 138local send_message
139 139
140-- yield the headers all at once, it's faster
141local function send_headers(headers)
142 local h = "\r\n"
143 for i,v in base.pairs(headers) do
144 h = i .. ': ' .. v .. "\r\n" .. h
145 end
146 coroutine.yield(h)
147end
148
140-- yield multipart message body from a multipart message table 149-- yield multipart message body from a multipart message table
141local function send_multipart(mesgt) 150local function send_multipart(mesgt)
151 -- make sure we have our boundary and send headers
142 local bd = newboundary() 152 local bd = newboundary()
143 -- define boundary and finish headers 153 local headers = mesgt.headers or {}
144 coroutine.yield('content-type: multipart/mixed; boundary="' .. 154 headers['content-type'] = headers['content-type'] or 'multipart/mixed'
145 bd .. '"\r\n\r\n') 155 headers['content-type'] = headers['content-type'] ..
156 '; boundary="' .. bd .. '"'
157 send_headers(headers)
146 -- send preamble 158 -- send preamble
147 if mesgt.body.preamble then 159 if mesgt.body.preamble then
148 coroutine.yield(mesgt.body.preamble) 160 coroutine.yield(mesgt.body.preamble)
@@ -164,11 +176,11 @@ end
164 176
165-- yield message body from a source 177-- yield message body from a source
166local function send_source(mesgt) 178local function send_source(mesgt)
167 -- set content-type if user didn't override 179 -- make sure we have a content-type
168 if not mesgt.headers or not mesgt.headers["content-type"] then 180 local headers = mesgt.headers or {}
169 coroutine.yield('content-type: text/plain; charset="iso-8859-1"\r\n\r\n') 181 headers['content-type'] = headers['content-type'] or
170 else coroutine.yield("\r\n") end 182 'text/plain; charset="iso-8859-1"'
171 -- finish headers 183 send_headers(headers)
172 -- send body from source 184 -- send body from source
173 while true do 185 while true do
174 local chunk, err = mesgt.body() 186 local chunk, err = mesgt.body()
@@ -180,28 +192,17 @@ end
180 192
181-- yield message body from a string 193-- yield message body from a string
182local function send_string(mesgt) 194local function send_string(mesgt)
183 -- set content-type if user didn't override 195 -- make sure we have a content-type
184 if not mesgt.headers or not mesgt.headers["content-type"] then 196 local headers = mesgt.headers or {}
185 coroutine.yield('content-type: text/plain; charset="iso-8859-1"\r\n\r\n') 197 headers['content-type'] = headers['content-type'] or
186 else coroutine.yield("\r\n") end 198 'text/plain; charset="iso-8859-1"'
199 send_headers(headers)
187 -- send body from string 200 -- send body from string
188 coroutine.yield(mesgt.body) 201 coroutine.yield(mesgt.body)
189end 202end
190 203
191-- yield the headers all at once
192local function send_headers(mesgt)
193 if mesgt.headers then
194 local h = ""
195 for i,v in base.pairs(mesgt.headers) do
196 h = i .. ': ' .. v .. "\r\n" .. h
197 end
198 coroutine.yield(h)
199 end
200end
201
202-- message source 204-- message source
203function send_message(mesgt) 205function send_message(mesgt)
204 send_headers(mesgt)
205 if base.type(mesgt.body) == "table" then send_multipart(mesgt) 206 if base.type(mesgt.body) == "table" then send_multipart(mesgt)
206 elseif base.type(mesgt.body) == "function" then send_source(mesgt) 207 elseif base.type(mesgt.body) == "function" then send_source(mesgt)
207 else send_string(mesgt) end 208 else send_string(mesgt) end
diff --git a/src/wsocket.c b/src/wsocket.c
index c4c51b4..0f6005f 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -75,7 +75,7 @@ int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm) {
75 tv.tv_sec = (int) t; 75 tv.tv_sec = (int) t;
76 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); 76 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
77 if (n <= 0) { 77 if (n <= 0) {
78 Sleep(1000*t); 78 Sleep((DWORD) (1000*t));
79 return 0; 79 return 0;
80 } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL); 80 } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL);
81} 81}
diff --git a/test/ftptest.lua b/test/ftptest.lua
index ef1bf0f..63d20e6 100644
--- a/test/ftptest.lua
+++ b/test/ftptest.lua
@@ -12,8 +12,8 @@ local host, port, index_file, index, back, err, ret
12 12
13local t = socket.gettime() 13local t = socket.gettime()
14 14
15host = host or "diego.student.princeton.edu" 15host = host or "localhost"
16index_file = "test/index.html" 16index_file = "index.html"
17 17
18 18
19-- a function that returns a directory listing 19-- a function that returns a directory listing
diff --git a/test/testmesg.lua b/test/testmesg.lua
index 37e8c11..1dd9a97 100644
--- a/test/testmesg.lua
+++ b/test/testmesg.lua
@@ -3,6 +3,42 @@ local smtp = require("socket.smtp")
3local mime = require("mime") 3local mime = require("mime")
4local ltn12 = require("ltn12") 4local ltn12 = require("ltn12")
5 5
6function filter(s)
7 if s then io.write(s) end
8 return s
9end
10
11source = smtp.message {
12 headers = { ['content-type'] = 'multipart/alternative' },
13 body = {
14 [1] = {
15 headers = { ['content-type'] = 'text/html' },
16 body = "<html> <body> Hi, <b>there</b>...</body> </html>"
17 },
18 [2] = {
19 headers = { ['content-type'] = 'text/plain' },
20 body = "Hi, there..."
21 }
22 }
23}
24
25r, e = smtp.send{
26 rcpt = {"<diego@tecgraf.puc-rio.br>",
27 "<diego@princeton.edu>" },
28 from = "<diego@princeton.edu>",
29 source = ltn12.source.chain(source, filter),
30 --server = "mail.cs.princeton.edu"
31 server = "localhost",
32 port = 2525
33}
34
35
36os.exit()
37
38
39
40
41
6-- creates a source to send a message with two parts. The first part is 42-- creates a source to send a message with two parts. The first part is
7-- plain text, the second part is a PNG image, encoded as base64. 43-- plain text, the second part is a PNG image, encoded as base64.
8source = smtp.message{ 44source = smtp.message{
@@ -48,10 +84,6 @@ source = smtp.message{
48 } 84 }
49} 85}
50 86
51function filter(s)
52 if s then io.write(s) end
53 return s
54end
55 87
56r, e = smtp.send{ 88r, e = smtp.send{
57 rcpt = {"<diego@tecgraf.puc-rio.br>", 89 rcpt = {"<diego@tecgraf.puc-rio.br>",
@@ -64,3 +96,5 @@ r, e = smtp.send{
64} 96}
65 97
66print(r, e) 98print(r, e)
99
100