diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2005-08-23 05:53:14 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2005-08-23 05:53:14 +0000 |
commit | 773e35ced30fa2c03ddb2a332bf8a9aebb56aa44 (patch) | |
tree | 03e8e9a4bd64b9424006315c8e720c3f2841a751 | |
parent | 5e8ae76248ed31496dc6fef7855498a0479159ed (diff) | |
download | luasocket-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-- | TODO | 9 | ||||
-rw-r--r-- | config | 12 | ||||
-rw-r--r-- | doc/index.html | 4 | ||||
-rw-r--r-- | etc/check-links.lua | 31 | ||||
-rw-r--r-- | etc/dispatch.lua | 296 | ||||
-rw-r--r-- | etc/forward.lua | 65 | ||||
-rw-r--r-- | luasocket.sln | 2 | ||||
-rw-r--r-- | makefile | 37 | ||||
-rw-r--r-- | makefile.dist | 9 | ||||
-rw-r--r-- | mime.vcproj | 32 | ||||
-rw-r--r-- | socket.vcproj (renamed from luasocket.vcproj) | 101 | ||||
-rw-r--r-- | src/auxiliar.c | 8 | ||||
-rw-r--r-- | src/http.lua | 1 | ||||
-rw-r--r-- | src/luasocket.h | 2 | ||||
-rw-r--r-- | src/mime.c | 2 | ||||
-rw-r--r-- | src/mime.h | 2 | ||||
-rw-r--r-- | src/smtp.lua | 49 | ||||
-rw-r--r-- | src/wsocket.c | 2 | ||||
-rw-r--r-- | test/ftptest.lua | 4 | ||||
-rw-r--r-- | test/testmesg.lua | 42 |
20 files changed, 400 insertions, 310 deletions
@@ -1,10 +1,8 @@ | |||
1 | new instalation scheme??? | 1 | new instalation scheme??? |
2 | test empty socket.select no windows. | ||
3 | bug by mathew percival? | ||
4 | 2 | ||
5 | arranjar um jeito de fazer multipart/alternative | 3 | test empty socket.select no windows. |
6 | 4 | ||
7 | what the hell does __unload do? | 5 | bug by mathew percival? |
8 | 6 | ||
9 | test it on Windows!!! | 7 | test 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. | ||
@@ -8,8 +8,8 @@ | |||
8 | EXT=so | 8 | EXT=so |
9 | SOCKET_V=2.0.0 | 9 | SOCKET_V=2.0.0 |
10 | MIME_V=1.0.0 | 10 | MIME_V=1.0.0 |
11 | SOCKET_SO=socket-core.$(EXT).$(SOCKET_V) | 11 | SOCKET_SO=socket.$(EXT).$(SOCKET_V) |
12 | MIME_SO=mime-core.$(EXT).$(MIME_V) | 12 | MIME_SO=mime.$(EXT).$(MIME_V) |
13 | UNIX_SO=unix.$(EXT) | 13 | UNIX_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 | # |
30 | INSTALL_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 | ||
32 | INSTALL_TOP_LUA=share | ||
33 | INSTALL_TOP_LIB=lib | ||
31 | 34 | ||
32 | INSTALL_DATA=cp | 35 | INSTALL_DATA=cp |
33 | INSTALL_EXEC=cp | 36 | INSTALL_EXEC=cp |
34 | INSTALL_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 |
173 | parsed form; | 175 | parsed 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 |
184 | directory (ex. "socket/core.dll"). The 'l' prefix was just a bad idea; | 186 | directory (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 | ----------------------------------------------------------------------------- |
8 | local dispatch, url, http, handler | 8 | local url = require("socket.url") |
9 | local dispatch = require("dispatch") | ||
10 | local http = require("socket.http") | ||
11 | dispatch.TIMEOUT = 10 | ||
9 | 12 | ||
13 | -- make sure the user knows how to invoke us | ||
10 | arg = arg or {} | 14 | arg = arg or {} |
11 | if table.getn(arg) < 1 then | 15 | if 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() |
14 | end | 18 | end |
15 | 19 | ||
16 | if arg[1] ~= "-n" then | 20 | -- '-n' means we are running in non-blocking mode |
17 | -- if using blocking I/O, simulate dispatcher interface | 21 | if 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 | ||
27 | else | ||
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 | 25 | else |
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() | ||
35 | end | 28 | end |
36 | 29 | ||
37 | local nthreads = 0 | 30 | local 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 |
14 | TIMEOUT = 10 | 14 | TIMEOUT = 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 | 23 | local 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 |
22 | local running | 26 | function newhandler(mode) |
23 | local resume = coroutine.resume | 27 | mode = mode or "coroutine" |
24 | function coroutine.resume(co, ...) | 28 | return handlert[mode]() |
25 | running = co | ||
26 | return resume(co, unpack(arg)) | ||
27 | end | 29 | end |
28 | 30 | ||
29 | function coroutine.running() | 31 | local function seqstart(self, func) |
30 | return running | 32 | return func() |
33 | end | ||
34 | |||
35 | -- sequential handler simply calls the functions and doesn't wrap I/O | ||
36 | function handlert.sequential() | ||
37 | return { | ||
38 | tcp = socket.tcp, | ||
39 | start = seqstart | ||
40 | } | ||
31 | end | 41 | end |
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 |
39 | function socket.protect(f) | 49 | function socket.protect(f) |
40 | return f | ||
41 | end | ||
42 | |||
43 | function 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) | |||
61 | end | 67 | end |
62 | 68 | ||
63 | ----------------------------------------------------------------------------- | 69 | ----------------------------------------------------------------------------- |
64 | -- socket.tcp() replacement for non-blocking I/O | 70 | -- Simple set data structure. O(1) everything. |
71 | ----------------------------------------------------------------------------- | ||
72 | local 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 | }}) | ||
94 | end | ||
95 | |||
96 | ----------------------------------------------------------------------------- | ||
97 | -- socket.tcp() wrapper for the coroutine dispatcher | ||
65 | ----------------------------------------------------------------------------- | 98 | ----------------------------------------------------------------------------- |
66 | local function newtrap(dispatcher) | 99 | local 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) | ||
187 | end | 206 | end |
188 | 207 | ||
208 | |||
189 | ----------------------------------------------------------------------------- | 209 | ----------------------------------------------------------------------------- |
190 | -- Our set data structure | 210 | -- Our coroutine dispatcher |
191 | ----------------------------------------------------------------------------- | 211 | ----------------------------------------------------------------------------- |
192 | local function newset() | 212 | local cometat = { __index = {} } |
193 | local reverse = {} | 213 | |
194 | local set = {} | 214 | function 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 |
214 | end | 222 | end |
215 | 223 | ||
216 | ----------------------------------------------------------------------------- | 224 | function kick(operation, tcp) |
217 | -- Our dispatcher API. | 225 | operation.cortn[tcp] = nil |
218 | ----------------------------------------------------------------------------- | 226 | operation.set:remove(tcp) |
219 | local metat = { __index = {} } | 227 | end |
220 | 228 | ||
221 | function metat.__index:start(func) | 229 | function 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 | ||
224 | end | 239 | end |
225 | 240 | ||
226 | function newhandler() | 241 | function 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) | ||
236 | end | 247 | end |
237 | 248 | ||
238 | -- step through all active threads | 249 | -- step through all active cortns |
239 | function metat.__index:step() | 250 | function 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 |
267 | end | 272 | end |
273 | |||
274 | function cometat.__index:start(func) | ||
275 | local cortn = coroutine.create(func) | ||
276 | schedule(cortn, coroutine.resume(cortn)) | ||
277 | end | ||
278 | |||
279 | function 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) | ||
300 | end | ||
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 | ||
2 | local dispatch = require("dispatch") | ||
3 | local handler = dispatch.newhandler() | ||
4 | |||
5 | -- make sure the user knows how to invoke us | ||
6 | if table.getn(arg) < 1 then | ||
7 | print("Usage") | ||
8 | print(" lua forward.lua <iport:ohost:oport> ...") | ||
9 | os.exit(1) | ||
10 | end | ||
11 | |||
12 | -- function to move data from one socket to the other | ||
13 | local 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 | ||
26 | end | ||
27 | |||
28 | -- for each tunnel, start a new server | ||
29 | for 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) | ||
60 | end | ||
61 | |||
62 | -- simply loop stepping the server | ||
63 | while 1 do | ||
64 | handler:step() | ||
65 | end | ||
diff --git a/luasocket.sln b/luasocket.sln index 6a1d0b8..006b7f0 100644 --- a/luasocket.sln +++ b/luasocket.sln | |||
@@ -1,5 +1,5 @@ | |||
1 | Microsoft Visual Studio Solution File, Format Version 8.00 | 1 | Microsoft Visual Studio Solution File, Format Version 8.00 |
2 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luasocket", "luasocket.vcproj", "{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}" | 2 | Project("{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 |
5 | EndProject | 5 | EndProject |
@@ -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 | # |
9 | INSTALL_SOCKET=$(INSTALL_TOP)/socket | 9 | INSTALL_SOCKET_LUA=$(INSTALL_TOP_LUA)/socket |
10 | INSTALL_MIME=$(INSTALL_TOP)/mime | 10 | INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket |
11 | INSTALL_MIME_LUA=$(INSTALL_TOP_LUA)/mime | ||
12 | INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime | ||
11 | 13 | ||
12 | all clean: | 14 | all 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 | # |
18 | TO_SOCKET:= \ | 20 | TO_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 | ||
26 | TO_TOP:= \ | 28 | TO_TOP_LUA:= \ |
27 | ltn12.lua | 29 | ltn12.lua |
28 | 30 | ||
29 | TO_MIME:= \ | 31 | TO_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 | # |
36 | install: all | 37 | install: 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 | ||
5 | DIST = luasocket-2.0-beta3 | 5 | DIST = luasocket-2.0 |
6 | 6 | ||
7 | COMPAT = compat-5.1r2 | 7 | COMPAT = compat-5.1r4 |
8 | 8 | ||
9 | LUA = \ | 9 | LUA = \ |
10 | ftp.lua \ | 10 | ftp.lua \ |
@@ -37,6 +37,7 @@ EXAMPLES = \ | |||
37 | 37 | ||
38 | ETC = \ | 38 | ETC = \ |
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 | ||
78 | MAKE = \ | 79 | MAKE = \ |
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 | \*-------------------------------------------------------------------------*/ |
129 | void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx) { | 129 | void *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 | \*-------------------------------------------------------------------------*/ |
147 | void *aux_getclassudata(lua_State *L, const char *classname, int objidx) { | 151 | void *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 |
327 | end) | 327 | end) |
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 | \*-------------------------------------------------------------------------*/ |
30 | LUASOCKET_API int luaopen_socketcore(lua_State *L); | 30 | LUASOCKET_API int luaopen_socket_core(lua_State *L); |
31 | 31 | ||
32 | #endif /* LUASOCKET_H */ | 32 | #endif /* LUASOCKET_H */ |
@@ -78,7 +78,7 @@ static UC b64unbase[256]; | |||
78 | /*-------------------------------------------------------------------------*\ | 78 | /*-------------------------------------------------------------------------*\ |
79 | * Initializes module | 79 | * Initializes module |
80 | \*-------------------------------------------------------------------------*/ | 80 | \*-------------------------------------------------------------------------*/ |
81 | MIME_API int luaopen_mimecore(lua_State *L) | 81 | MIME_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 */ |
@@ -19,6 +19,6 @@ | |||
19 | #define MIME_API extern | 19 | #define MIME_API extern |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | MIME_API int luaopen_mimecore(lua_State *L); | 22 | MIME_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 |
138 | local send_message | 138 | local send_message |
139 | 139 | ||
140 | -- yield the headers all at once, it's faster | ||
141 | local 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) | ||
147 | end | ||
148 | |||
140 | -- yield multipart message body from a multipart message table | 149 | -- yield multipart message body from a multipart message table |
141 | local function send_multipart(mesgt) | 150 | local 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 |
166 | local function send_source(mesgt) | 178 | local 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 |
182 | local function send_string(mesgt) | 194 | local 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) |
189 | end | 202 | end |
190 | 203 | ||
191 | -- yield the headers all at once | ||
192 | local 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 | ||
200 | end | ||
201 | |||
202 | -- message source | 204 | -- message source |
203 | function send_message(mesgt) | 205 | function 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 | ||
13 | local t = socket.gettime() | 13 | local t = socket.gettime() |
14 | 14 | ||
15 | host = host or "diego.student.princeton.edu" | 15 | host = host or "localhost" |
16 | index_file = "test/index.html" | 16 | index_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") | |||
3 | local mime = require("mime") | 3 | local mime = require("mime") |
4 | local ltn12 = require("ltn12") | 4 | local ltn12 = require("ltn12") |
5 | 5 | ||
6 | function filter(s) | ||
7 | if s then io.write(s) end | ||
8 | return s | ||
9 | end | ||
10 | |||
11 | source = 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 | |||
25 | r, 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 | |||
36 | os.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. |
8 | source = smtp.message{ | 44 | source = smtp.message{ |
@@ -48,10 +84,6 @@ source = smtp.message{ | |||
48 | } | 84 | } |
49 | } | 85 | } |
50 | 86 | ||
51 | function filter(s) | ||
52 | if s then io.write(s) end | ||
53 | return s | ||
54 | end | ||
55 | 87 | ||
56 | r, e = smtp.send{ | 88 | r, 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 | ||
66 | print(r, e) | 98 | print(r, e) |
99 | |||
100 | |||