Sun, 10 Jun 2007 16:52:55 +0000
* Adjusted licensing and added README.
1
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
1 | --[[ |
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
2 | LuaEvent - Copyright (C) 2007 Thomas Harning <harningt@gmail.com> |
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
3 | Licensed as LGPL - See doc/COPYING for details. |
31c782cfe7fe
* Adjusted licensing and added README.
Thomas Harning Jr <harningt@gmail.com>
parents:
0
diff
changeset
|
4 | ]] |
0 | 5 | module("luaevent", package.seeall) |
6 | require("luaevent.core") | |
7 | ||
8 | local EV_READ = luaevent.core.EV_READ | |
9 | local EV_WRITE = luaevent.core.EV_WRITE | |
10 | local fair = false | |
11 | ||
12 | -- Weak keys.. the keys are the client sockets | |
13 | local clientTable = {} or setmetatable({}, {'__mode', 'k'}) | |
14 | ||
15 | local function getWrapper() | |
16 | local running = coroutine.running() | |
17 | return function(...) | |
18 | print(coroutine.running(), running) | |
19 | print(debug.traceback()) | |
20 | if coroutine.running() == running then return end | |
21 | return select(2, coroutine.resume(running, ...)) | |
22 | end | |
23 | end | |
24 | ||
25 | function send(sock, data, start, stop) | |
26 | local s, err | |
27 | local from = start or 1 | |
28 | local sent = 0 | |
29 | repeat | |
30 | from = from + sent | |
31 | s, err, sent = sock:send(data, from, stop) | |
32 | -- Add extra coro swap for fairness | |
33 | -- CURRENTLY DISABLED FOR TESTING...... | |
34 | if fair and math.random(100) > 90 then | |
35 | coroutine.yield(EV_WRITE) | |
36 | end | |
37 | if s or err ~= "timeout" then return s, err, sent end | |
38 | if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end | |
39 | coroutine.yield(EV_WRITE) | |
40 | until false | |
41 | end | |
42 | function receive(sock, pattern, part) | |
43 | local s, err | |
44 | pattern = pattern or '*l' | |
45 | repeat | |
46 | s, err, part = sock:receive(pattern, part) | |
47 | if s or err ~= "timeout" then return s, err, part end | |
48 | if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end | |
49 | coroutine.yield(EV_READ) | |
50 | until false | |
51 | end | |
52 | -- same as above but with special treatment when reading chunks, | |
53 | -- unblocks on any data received. | |
54 | function receivePartial(client, pattern) | |
55 | local s, err, part | |
56 | pattern = pattern or "*l" | |
57 | repeat | |
58 | s, err, part = client:receive(pattern) | |
59 | if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or | |
60 | err ~= "timeout" then return s, err, part end | |
61 | if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_READ, getWrapper()) end | |
62 | coroutine.yield(EV_READ) | |
63 | until false | |
64 | end | |
65 | function connect(sock, ...) | |
66 | sock:settimeout(0) | |
67 | local ret, err = sock:connect(...) | |
68 | if ret or err ~= "timeout" then return ret, err end | |
69 | if not clientTable[sock] then clientTable[sock] = luaevent.core.addevent(sock, EV_WRITE, getWrapper()) end | |
70 | coroutine.yield(EV_WRITE) | |
71 | ret, err = sock:connect(...) | |
72 | if err == "already connected" then | |
73 | return 1 | |
74 | end | |
75 | return ret, err | |
76 | end | |
77 | -- Deprecated.. | |
78 | function flush(sock) | |
79 | end | |
80 | local function clientCoroutine(sock, handler) | |
81 | -- Figure out what to do ...... | |
82 | return handler(sock) | |
83 | end | |
84 | local function handleClient(co, client, handler) | |
85 | local ok, res, event = coroutine.resume(co, client, handler) | |
86 | end | |
87 | local function serverCoroutine(sock, callback) | |
88 | local listenItem = luaevent.core.addevent(sock, EV_READ, getWrapper()) | |
89 | repeat | |
90 | local event = coroutine.yield(EV_READ) | |
91 | -- Get new socket | |
92 | local client = sock:accept() | |
93 | if client then | |
94 | client:settimeout(0) | |
95 | local co = coroutine.create(clientCoroutine) | |
96 | handleClient(co, client, callback) | |
97 | end | |
98 | until false | |
99 | end | |
100 | function addserver(sock, callback) | |
101 | local coro = coroutine.create(serverCoroutine) | |
102 | assert(coroutine.resume(coro, sock, callback)) | |
103 | end | |
104 | function addthread(func, ...) | |
105 | return coroutine.resume(coroutine.create(func), ...) | |
106 | end | |
107 | local _skt_mt = {__index = { | |
108 | connect = function(self, ...) | |
109 | return connect(self.socket, ...) | |
110 | end, | |
111 | send = function (self, data) | |
112 | return send (self.socket, data) | |
113 | end, | |
114 | ||
115 | receive = function (self, pattern) | |
116 | if (self.timeout==0) then | |
117 | return receivePartial(self.socket, pattern) | |
118 | end | |
119 | return receive (self.socket, pattern) | |
120 | end, | |
121 | ||
122 | flush = function (self) | |
123 | return flush (self.socket) | |
124 | end, | |
125 | ||
126 | settimeout = function (self,time) | |
127 | self.timeout=time | |
128 | return | |
129 | end, | |
130 | }} | |
131 | function wrap(sock) | |
132 | return setmetatable({socket = sock}, _skt_mt) | |
133 | end | |
134 | loop = luaevent.core.loop |