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 | |||
