aboutsummaryrefslogtreecommitdiff
path: root/src/udp.c
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-05-25 01:54:13 +0000
commit0f6c8d50a99997ac7829864b1c93362b50f1bbf3 (patch)
treed0cefe3a05484e65b7b7e79d8cae4a1d2e6d19fb /src/udp.c
parentc1ef3e7103cc652d2004ef1ddc9409b946207f33 (diff)
downloadluasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.gz
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.bz2
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.zip
Porting to LUA 5.0 final
Diffstat (limited to 'src/udp.c')
-rw-r--r--src/udp.c404
1 files changed, 184 insertions, 220 deletions
diff --git a/src/udp.c b/src/udp.c
index 361816c..1701d1b 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -1,299 +1,263 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* UDP class: inherits from Socked and Internet domain classes and provides 2* UDP object
3* all the functionality for UDP objects.
4* Lua methods:
5* send: using compat module
6* sendto: using compat module
7* receive: using compat module
8* receivefrom: using compat module
9* setpeername: using internet module
10* setsockname: using internet module
11* Global Lua functions:
12* udp: creates the udp object
13* 3*
14* RCS ID: $Id$ 4* RCS ID: $Id$
15\*=========================================================================*/ 5\*=========================================================================*/
16#include <string.h> 6#include <string.h>
17 7
18#include <lua.h> 8#include <lua.h>
19#include <lauxlib.h> 9#include <lauxlib.h>
20 10
21#include "lsinet.h" 11#include "luasocket.h"
22#include "lsudp.h" 12
23#include "lscompat.h" 13#include "aux.h"
24#include "lsselect.h" 14#include "inet.h"
15#include "udp.h"
25 16
26/*=========================================================================*\ 17/*=========================================================================*\
27* Internal function prototypes. 18* Internal function prototypes
28\*=========================================================================*/ 19\*=========================================================================*/
29static int udp_lua_send(lua_State *L); 20static int udp_global_create(lua_State *L);
30static int udp_lua_sendto(lua_State *L); 21static int udp_meth_send(lua_State *L);
31static int udp_lua_receive(lua_State *L); 22static int udp_meth_sendto(lua_State *L);
32static int udp_lua_receivefrom(lua_State *L); 23static int udp_meth_receive(lua_State *L);
33static int udp_lua_setpeername(lua_State *L); 24static int udp_meth_receivefrom(lua_State *L);
34static int udp_lua_setsockname(lua_State *L); 25static int udp_meth_getsockname(lua_State *L);
26static int udp_meth_getpeername(lua_State *L);
27static int udp_meth_setsockname(lua_State *L);
28static int udp_meth_setpeername(lua_State *L);
29static int udp_meth_close(lua_State *L);
30static int udp_meth_timeout(lua_State *L);
35 31
36static int udp_global_udp(lua_State *L); 32/* udp object methods */
33static luaL_reg udp[] = {
34 {"setpeername", udp_meth_setpeername},
35 {"setsockname", udp_meth_setsockname},
36 {"getsockname", udp_meth_getsockname},
37 {"getpeername", udp_meth_getpeername},
38 {"send", udp_meth_send},
39 {"sendto", udp_meth_sendto},
40 {"receive", udp_meth_receive},
41 {"receivefrom", udp_meth_receivefrom},
42 {"timeout", udp_meth_timeout},
43 {"close", udp_meth_close},
44 {NULL, NULL}
45};
37 46
38static struct luaL_reg funcs[] = { 47/* functions in library namespace */
39 {"send", udp_lua_send}, 48static luaL_reg func[] = {
40 {"sendto", udp_lua_sendto}, 49 {"udp", udp_global_create},
41 {"receive", udp_lua_receive}, 50 {NULL, NULL}
42 {"receivefrom", udp_lua_receivefrom},
43 {"setpeername", udp_lua_setpeername},
44 {"setsockname", udp_lua_setsockname},
45}; 51};
46 52
47/*=========================================================================*\
48* Exported functions
49\*=========================================================================*/
50/*-------------------------------------------------------------------------*\ 53/*-------------------------------------------------------------------------*\
51* Initializes module 54* Initializes module
52\*-------------------------------------------------------------------------*/ 55\*-------------------------------------------------------------------------*/
53void udp_open(lua_State *L) 56void udp_open(lua_State *L)
54{ 57{
55 unsigned int i; 58 /* create classes */
56 priv_newclass(L, UDP_CLASS); 59 aux_newclass(L, "udp{connected}", udp);
57 udp_inherit(L, UDP_CLASS); 60 aux_newclass(L, "udp{unconnected}", udp);
58 /* declare global functions */ 61 /* create class groups */
59 lua_pushcfunction(L, udp_global_udp); 62 aux_add2group(L, "udp{connected}", "udp{any}");
60 priv_newglobal(L, "udp"); 63 aux_add2group(L, "udp{unconnected}", "udp{any}");
61 for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) 64 /* define library functions */
62 priv_newglobalmethod(L, funcs[i].name); 65 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
63 /* make class selectable */ 66 lua_pop(L, 1);
64 select_addclass(L, UDP_CLASS);
65}
66
67/*-------------------------------------------------------------------------*\
68* Hook object methods to methods table.
69\*-------------------------------------------------------------------------*/
70void udp_inherit(lua_State *L, cchar *lsclass)
71{
72 unsigned int i;
73 inet_inherit(L, lsclass);
74 for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) {
75 lua_pushcfunction(L, funcs[i].func);
76 priv_setmethod(L, lsclass, funcs[i].name);
77 }
78} 67}
79 68
69/*=========================================================================*\
70* Lua methods
71\*=========================================================================*/
80/*-------------------------------------------------------------------------*\ 72/*-------------------------------------------------------------------------*\
81* Initializes socket structure 73* Send data through connected udp socket
82\*-------------------------------------------------------------------------*/ 74\*-------------------------------------------------------------------------*/
83void udp_construct(lua_State *L, p_udp udp) 75static int udp_meth_send(lua_State *L)
84{ 76{
85 inet_construct(L, (p_inet) udp); 77 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
86 udp->udp_connected = 0; 78 p_tm tm = &udp->tm;
79 size_t count, sent = 0;
80 int err;
81 const char *data = luaL_checklstring(L, 2, &count);
82 tm_markstart(tm);
83 err = sock_send(&udp->sock, data, count, &sent, tm_get(tm));
84 if (err == IO_DONE) lua_pushnumber(L, sent);
85 else lua_pushnil(L);
86 error_push(L, err);
87 return 2;
87} 88}
88 89
89/*-------------------------------------------------------------------------*\ 90/*-------------------------------------------------------------------------*\
90* Creates a socket structure and initializes it. A socket object is 91* Send data through unconnected udp socket
91* left in the Lua stack.
92* Returns
93* pointer to allocated structure
94\*-------------------------------------------------------------------------*/ 92\*-------------------------------------------------------------------------*/
95p_udp udp_push(lua_State *L) 93static int udp_meth_sendto(lua_State *L)
96{ 94{
97 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); 95 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
98 priv_setclass(L, UDP_CLASS); 96 size_t count, sent = 0;
99 udp_construct(L, udp); 97 const char *data = luaL_checklstring(L, 2, &count);
100 return udp; 98 const char *ip = luaL_checkstring(L, 3);
99 ushort port = (ushort) luaL_checknumber(L, 4);
100 p_tm tm = &udp->tm;
101 struct sockaddr_in addr;
102 int err;
103 memset(&addr, 0, sizeof(addr));
104 if (!inet_aton(ip, &addr.sin_addr))
105 luaL_argerror(L, 3, "invalid ip address");
106 addr.sin_family = AF_INET;
107 addr.sin_port = htons(port);
108 tm_markstart(tm);
109 err = sock_sendto(&udp->sock, data, count, &sent,
110 (SA *) &addr, sizeof(addr), tm_get(tm));
111 if (err == IO_DONE) lua_pushnumber(L, sent);
112 else lua_pushnil(L);
113 error_push(L, err == IO_CLOSED ? IO_REFUSED : err);
114 return 2;
101} 115}
102 116
103/*=========================================================================*\
104* Socket table constructors
105\*=========================================================================*/
106/*-------------------------------------------------------------------------*\
107* Creates a udp socket object and returns it to the Lua script.
108* Lua Input: [options]
109* options: socket options table
110* Lua Returns
111* On success: udp socket
112* On error: nil, followed by an error message
113\*-------------------------------------------------------------------------*/
114static int udp_global_udp(lua_State *L)
115{
116 int oldtop = lua_gettop(L);
117 p_udp udp = udp_push(L);
118 cchar *err = inet_trysocket((p_inet) udp, SOCK_DGRAM);
119 if (err) {
120 lua_pushnil(L);
121 lua_pushstring(L, err);
122 return 2;
123 }
124 if (oldtop < 1) return 1;
125 err = compat_trysetoptions(L, udp->fd);
126 if (err) {
127 lua_pushnil(L);
128 lua_pushstring(L, err);
129 return 2;
130 }
131 return 1;
132}
133
134/*=========================================================================*\
135* Socket table methods
136\*=========================================================================*/
137/*-------------------------------------------------------------------------*\ 117/*-------------------------------------------------------------------------*\
138* Receives data from a UDP socket 118* Receives data from a UDP socket
139* Lua Input: sock [, wanted]
140* sock: client socket created by the connect function
141* wanted: the number of bytes expected (default: LUASOCKET_UDPBUFFERSIZE)
142* Lua Returns
143* On success: datagram received
144* On error: nil, followed by an error message
145\*-------------------------------------------------------------------------*/ 119\*-------------------------------------------------------------------------*/
146static int udp_lua_receive(lua_State *L) 120static int udp_meth_receive(lua_State *L)
147{ 121{
148 p_udp udp = (p_udp) lua_touserdata(L, 1); 122 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
149 char buffer[UDP_DATAGRAMSIZE]; 123 char buffer[UDP_DATAGRAMSIZE];
150 size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 124 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
151 int err; 125 int err;
152 p_tm tm = &udp->base_tm; 126 p_tm tm = &udp->tm;
153 wanted = MIN(wanted, sizeof(buffer)); 127 count = MIN(count, sizeof(buffer));
154 tm_markstart(tm); 128 tm_markstart(tm);
155 err = compat_recv(udp->fd, buffer, wanted, &got, tm_getremaining(tm)); 129 err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm));
156 if (err == PRIV_CLOSED) err = PRIV_REFUSED; 130 if (err == IO_DONE) lua_pushlstring(L, buffer, got);
157 if (err != PRIV_DONE) lua_pushnil(L); 131 else lua_pushnil(L);
158 else lua_pushlstring(L, buffer, got); 132 error_push(L, err);
159 priv_pusherror(L, err);
160 return 2; 133 return 2;
161} 134}
162 135
163/*-------------------------------------------------------------------------*\ 136/*-------------------------------------------------------------------------*\
164* Receives a datagram from a UDP socket 137* Receives data and sender from a UDP socket
165* Lua Input: sock [, wanted]
166* sock: client socket created by the connect function
167* wanted: the number of bytes expected (default: LUASOCKET_UDPBUFFERSIZE)
168* Lua Returns
169* On success: datagram received, ip and port of sender
170* On error: nil, followed by an error message
171\*-------------------------------------------------------------------------*/ 138\*-------------------------------------------------------------------------*/
172static int udp_lua_receivefrom(lua_State *L) 139static int udp_meth_receivefrom(lua_State *L)
173{ 140{
174 p_udp udp = (p_udp) lua_touserdata(L, 1); 141 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
175 p_tm tm = &udp->base_tm; 142 struct sockaddr_in addr;
176 struct sockaddr_in peer; 143 size_t addr_len = sizeof(addr);
177 size_t peer_len = sizeof(peer);
178 char buffer[UDP_DATAGRAMSIZE]; 144 char buffer[UDP_DATAGRAMSIZE];
179 size_t wanted = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 145 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
180 size_t got;
181 int err; 146 int err;
182 if (udp->udp_connected) luaL_error(L, "receivefrom on connected socket"); 147 p_tm tm = &udp->tm;
183 tm_markstart(tm); 148 tm_markstart(tm);
184 wanted = MIN(wanted, sizeof(buffer)); 149 count = MIN(count, sizeof(buffer));
185 err = compat_recvfrom(udp->fd, buffer, wanted, &got, tm_getremaining(tm), 150 err = sock_recvfrom(&udp->sock, buffer, count, &got,
186 (SA *) &peer, &peer_len); 151 (SA *) &addr, &addr_len, tm_get(tm));
187 if (err == PRIV_CLOSED) err = PRIV_REFUSED; 152 if (err == IO_DONE) {
188 if (err == PRIV_DONE) {
189 lua_pushlstring(L, buffer, got); 153 lua_pushlstring(L, buffer, got);
190 lua_pushstring(L, inet_ntoa(peer.sin_addr)); 154 lua_pushstring(L, inet_ntoa(addr.sin_addr));
191 lua_pushnumber(L, ntohs(peer.sin_port)); 155 lua_pushnumber(L, ntohs(addr.sin_port));
192 return 3; 156 return 3;
193 } else { 157 } else {
194 lua_pushnil(L); 158 lua_pushnil(L);
195 priv_pusherror(L, err); 159 error_push(L, err);
196 return 2; 160 return 2;
197 } 161 }
198} 162}
199 163
200/*-------------------------------------------------------------------------*\ 164/*-------------------------------------------------------------------------*\
201* Send data through a connected UDP socket 165* Just call inet methods
202* Lua Input: sock, data
203* sock: udp socket
204* data: data to be sent
205* Lua Returns
206* On success: nil, followed by the total number of bytes sent
207* On error: error message
208\*-------------------------------------------------------------------------*/ 166\*-------------------------------------------------------------------------*/
209static int udp_lua_send(lua_State *L) 167static int udp_meth_getpeername(lua_State *L)
210{ 168{
211 p_udp udp = (p_udp) lua_touserdata(L, 1); 169 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
212 p_tm tm = &udp->base_tm; 170 return inet_meth_getpeername(L, &udp->sock);
213 size_t wanted, sent = 0; 171}
214 int err; 172
215 cchar *data = luaL_checklstring(L, 2, &wanted); 173static int udp_meth_getsockname(lua_State *L)
216 if (!udp->udp_connected) luaL_error(L, "send on unconnected socket"); 174{
217 tm_markstart(tm); 175 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
218 err = compat_send(udp->fd, data, wanted, &sent, tm_getremaining(tm)); 176 return inet_meth_getsockname(L, &udp->sock);
219 priv_pusherror(L, err == PRIV_CLOSED ? PRIV_REFUSED : err);
220 lua_pushnumber(L, sent);
221 return 2;
222} 177}
223 178
224/*-------------------------------------------------------------------------*\ 179/*-------------------------------------------------------------------------*\
225* Send data through a unconnected UDP socket 180* Just call tm methods
226* Lua Input: sock, data, ip, port
227* sock: udp socket
228* data: data to be sent
229* ip: ip address of target
230* port: port in target
231* Lua Returns
232* On success: nil, followed by the total number of bytes sent
233* On error: error message
234\*-------------------------------------------------------------------------*/ 181\*-------------------------------------------------------------------------*/
235static int udp_lua_sendto(lua_State *L) 182static int udp_meth_timeout(lua_State *L)
236{ 183{
237 p_udp udp = (p_udp) lua_touserdata(L, 1); 184 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
238 size_t wanted, sent = 0; 185 return tm_meth_timeout(L, &udp->tm);
239 cchar *data = luaL_checklstring(L, 2, &wanted);
240 cchar *ip = luaL_checkstring(L, 3);
241 ushort port = (ushort) luaL_checknumber(L, 4);
242 p_tm tm = &udp->base_tm;
243 struct sockaddr_in peer;
244 int err;
245 if (udp->udp_connected) luaL_error(L, "sendto on connected socket");
246 memset(&peer, 0, sizeof(peer));
247 if (!inet_aton(ip, &peer.sin_addr)) luaL_error(L, "invalid ip address");
248 peer.sin_family = AF_INET;
249 peer.sin_port = htons(port);
250 tm_markstart(tm);
251 err = compat_sendto(udp->fd, data, wanted, &sent, tm_getremaining(tm),
252 (SA *) &peer, sizeof(peer));
253 priv_pusherror(L, err == PRIV_CLOSED ? PRIV_REFUSED : err);
254 lua_pushnumber(L, sent);
255 return 2;
256} 186}
257 187
258/*-------------------------------------------------------------------------*\ 188/*-------------------------------------------------------------------------*\
259* Associates a local address to an UDP socket 189* Turns a master udp object into a client object.
260* Lua Input: address, port
261* address: host name or ip address to bind to
262* port: port to bind to
263* Lua Returns
264* On success: nil
265* On error: error message
266\*-------------------------------------------------------------------------*/ 190\*-------------------------------------------------------------------------*/
267static int udp_lua_setsockname(lua_State * L) 191static int udp_meth_setpeername(lua_State *L)
268{ 192{
269 p_udp udp = (p_udp) lua_touserdata(L, 1); 193 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
270 cchar *address = luaL_checkstring(L, 2); 194 const char *address = luaL_checkstring(L, 2);
271 ushort port = (ushort) luaL_checknumber(L, 3); 195 int connecting = strcmp(address, "*");
272 cchar *err = inet_trybind((p_inet) udp, address, port); 196 unsigned short port = connecting ?
273 if (err) lua_pushstring(L, err); 197 (ushort) luaL_checknumber(L, 3) : (ushort) luaL_optnumber(L, 3, 0);
274 else lua_pushnil(L); 198 const char *err = inet_tryconnect(&udp->sock, address, port);
199 if (err) {
200 lua_pushnil(L);
201 lua_pushstring(L, err);
202 return 2;
203 }
204 /* change class to connected or unconnected depending on address */
205 if (connecting) aux_setclass(L, "udp{connected}", 1);
206 else aux_setclass(L, "udp{unconnected}", 1);
207 lua_pushnumber(L, 1);
275 return 1; 208 return 1;
276} 209}
277 210
278/*-------------------------------------------------------------------------*\ 211/*-------------------------------------------------------------------------*\
279* Sets a peer for a UDP socket 212* Closes socket used by object
280* Lua Input: address, port 213\*-------------------------------------------------------------------------*/
281* address: remote host name 214static int udp_meth_close(lua_State *L)
282* port: remote host port 215{
283* Lua Returns 216 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
284* On success: nil 217 sock_destroy(&udp->sock);
285* On error: error message 218 return 0;
219}
220
221/*-------------------------------------------------------------------------*\
222* Turns a master object into a server object
286\*-------------------------------------------------------------------------*/ 223\*-------------------------------------------------------------------------*/
287static int udp_lua_setpeername(lua_State *L) 224static int udp_meth_setsockname(lua_State *L)
288{ 225{
289 p_udp udp = (p_udp) lua_touserdata(L, 1); 226 p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1);
290 cchar *address = luaL_checkstring(L, 2); 227 const char *address = luaL_checkstring(L, 2);
291 ushort port = (ushort) luaL_checknumber(L, 3); 228 unsigned short port = (ushort) luaL_checknumber(L, 3);
292 cchar *err = inet_tryconnect((p_inet) udp, address, port); 229 const char *err = inet_trybind(&udp->sock, address, port, -1);
293 if (!err) { 230 if (err) {
294 udp->udp_connected = 1;
295 lua_pushnil(L); 231 lua_pushnil(L);
296 } else lua_pushstring(L, err); 232 lua_pushstring(L, err);
233 return 2;
234 }
235 lua_pushnumber(L, 1);
297 return 1; 236 return 1;
298} 237}
299 238
239/*=========================================================================*\
240* Library functions
241\*=========================================================================*/
242/*-------------------------------------------------------------------------*\
243* Creates a master udp object
244\*-------------------------------------------------------------------------*/
245int udp_global_create(lua_State *L)
246{
247 /* allocate udp object */
248 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
249 /* set its type as master object */
250 aux_setclass(L, "udp{unconnected}", -1);
251 /* try to allocate a system socket */
252 const char *err = inet_trycreate(&udp->sock, SOCK_DGRAM);
253 if (err) {
254 /* get rid of object on stack and push error */
255 lua_pop(L, 1);
256 lua_pushnil(L);
257 lua_pushstring(L, err);
258 return 2;
259 }
260 /* initialize timeout management */
261 tm_init(&udp->tm, -1, -1);
262 return 1;
263}