aboutsummaryrefslogtreecommitdiff
path: root/src/tcp.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/tcp.c
parentc1ef3e7103cc652d2004ef1ddc9409b946207f33 (diff)
downloadluasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.gz
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.tar.bz2
luasocket-0f6c8d50a99997ac7829864b1c93362b50f1bbf3.zip
Porting to LUA 5.0 final
Diffstat (limited to 'src/tcp.c')
-rw-r--r--src/tcp.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/tcp.c b/src/tcp.c
new file mode 100644
index 0000000..db6a38e
--- /dev/null
+++ b/src/tcp.c
@@ -0,0 +1,222 @@
1/*=========================================================================*\
2* TCP object
3*
4* RCS ID: $Id$
5\*=========================================================================*/
6#include <string.h>
7
8#include <lua.h>
9#include <lauxlib.h>
10
11#include "luasocket.h"
12
13#include "aux.h"
14#include "inet.h"
15#include "tcp.h"
16
17/*=========================================================================*\
18* Internal function prototypes
19\*=========================================================================*/
20static int tcp_global_create(lua_State *L);
21static int tcp_meth_connect(lua_State *L);
22static int tcp_meth_bind(lua_State *L);
23static int tcp_meth_send(lua_State *L);
24static int tcp_meth_getsockname(lua_State *L);
25static int tcp_meth_getpeername(lua_State *L);
26static int tcp_meth_receive(lua_State *L);
27static int tcp_meth_accept(lua_State *L);
28static int tcp_meth_close(lua_State *L);
29static int tcp_meth_timeout(lua_State *L);
30
31/* tcp object methods */
32static luaL_reg tcp[] = {
33 {"connect", tcp_meth_connect},
34 {"send", tcp_meth_send},
35 {"receive", tcp_meth_receive},
36 {"bind", tcp_meth_bind},
37 {"accept", tcp_meth_accept},
38 {"setpeername", tcp_meth_connect},
39 {"setsockname", tcp_meth_bind},
40 {"getpeername", tcp_meth_getpeername},
41 {"getsockname", tcp_meth_getsockname},
42 {"timeout", tcp_meth_timeout},
43 {"close", tcp_meth_close},
44 {NULL, NULL}
45};
46
47/* functions in library namespace */
48static luaL_reg func[] = {
49 {"tcp", tcp_global_create},
50 {NULL, NULL}
51};
52
53/*-------------------------------------------------------------------------*\
54* Initializes module
55\*-------------------------------------------------------------------------*/
56void tcp_open(lua_State *L)
57{
58 /* create classes */
59 aux_newclass(L, "tcp{master}", tcp);
60 aux_newclass(L, "tcp{client}", tcp);
61 aux_newclass(L, "tcp{server}", tcp);
62 /* create class groups */
63 aux_add2group(L, "tcp{client}", "tcp{client, server}");
64 aux_add2group(L, "tcp{server}", "tcp{client, server}");
65 aux_add2group(L, "tcp{master}", "tcp{any}");
66 aux_add2group(L, "tcp{client}", "tcp{any}");
67 aux_add2group(L, "tcp{server}", "tcp{any}");
68 /* define library functions */
69 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
70 lua_pop(L, 1);
71}
72
73/*=========================================================================*\
74* Lua methods
75\*=========================================================================*/
76/*-------------------------------------------------------------------------*\
77* Just call buffered IO methods
78\*-------------------------------------------------------------------------*/
79static int tcp_meth_send(lua_State *L)
80{
81 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
82 return buf_meth_send(L, &tcp->buf);
83}
84
85static int tcp_meth_receive(lua_State *L)
86{
87 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
88 return buf_meth_receive(L, &tcp->buf);
89}
90
91/*-------------------------------------------------------------------------*\
92* Just call inet methods
93\*-------------------------------------------------------------------------*/
94static int tcp_meth_getpeername(lua_State *L)
95{
96 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
97 return inet_meth_getpeername(L, &tcp->sock);
98}
99
100static int tcp_meth_getsockname(lua_State *L)
101{
102 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
103 return inet_meth_getsockname(L, &tcp->sock);
104}
105
106/*-------------------------------------------------------------------------*\
107* Just call tm methods
108\*-------------------------------------------------------------------------*/
109static int tcp_meth_timeout(lua_State *L)
110{
111 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
112 return tm_meth_timeout(L, &tcp->tm);
113}
114
115/*-------------------------------------------------------------------------*\
116* Closes socket used by object
117\*-------------------------------------------------------------------------*/
118static int tcp_meth_close(lua_State *L)
119{
120 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
121 sock_destroy(&tcp->sock);
122 return 0;
123}
124
125/*-------------------------------------------------------------------------*\
126* Turns a master tcp object into a client object.
127\*-------------------------------------------------------------------------*/
128static int tcp_meth_connect(lua_State *L)
129{
130 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
131 const char *address = luaL_checkstring(L, 2);
132 unsigned short port = (ushort) luaL_checknumber(L, 3);
133 const char *err = inet_tryconnect(&tcp->sock, address, port);
134 if (err) {
135 lua_pushnil(L);
136 lua_pushstring(L, err);
137 return 2;
138 }
139 /* turn master object into a client object */
140 aux_setclass(L, "tcp{client}", 1);
141 lua_pushnumber(L, 1);
142 return 1;
143}
144
145/*-------------------------------------------------------------------------*\
146* Turns a master object into a server object
147\*-------------------------------------------------------------------------*/
148static int tcp_meth_bind(lua_State *L)
149{
150 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
151 const char *address = luaL_checkstring(L, 2);
152 unsigned short port = (ushort) luaL_checknumber(L, 3);
153 int backlog = (int) luaL_optnumber(L, 4, 1);
154 const char *err = inet_trybind(&tcp->sock, address, port, backlog);
155 if (err) {
156 lua_pushnil(L);
157 lua_pushstring(L, err);
158 return 2;
159 }
160 /* turn master object into a server object */
161 aux_setclass(L, "tcp{server}", 1);
162 lua_pushnumber(L, 1);
163 return 1;
164}
165
166/*-------------------------------------------------------------------------*\
167* Waits for and returns a client object attempting connection to the
168* server object
169\*-------------------------------------------------------------------------*/
170static int tcp_meth_accept(lua_State *L)
171{
172 struct sockaddr_in addr;
173 size_t addr_len = sizeof(addr);
174 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
175 p_tm tm = &server->tm;
176 p_tcp client = lua_newuserdata(L, sizeof(t_tcp));
177 tm_markstart(tm);
178 aux_setclass(L, "tcp{client}", -1);
179 for ( ;; ) {
180 sock_accept(&server->sock, &client->sock,
181 (SA *) &addr, &addr_len, tm_get(tm));
182 if (client->sock == SOCK_INVALID) {
183 if (tm_get(tm) == 0) {
184 lua_pushnil(L);
185 error_push(L, IO_TIMEOUT);
186 return 2;
187 }
188 } else break;
189 }
190 /* initialize remaining structure fields */
191 io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock);
192 tm_init(&client->tm, -1, -1);
193 buf_init(&client->buf, &client->io, &client->tm);
194 return 1;
195}
196
197/*=========================================================================*\
198* Library functions
199\*=========================================================================*/
200/*-------------------------------------------------------------------------*\
201* Creates a master tcp object
202\*-------------------------------------------------------------------------*/
203int tcp_global_create(lua_State *L)
204{
205 /* allocate tcp object */
206 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
207 /* set its type as master object */
208 aux_setclass(L, "tcp{master}", -1);
209 /* try to allocate a system socket */
210 const char *err = inet_trycreate(&tcp->sock, SOCK_STREAM);
211 if (err) { /* get rid of object on stack and push error */
212 lua_pop(L, 1);
213 lua_pushnil(L);
214 lua_pushstring(L, err);
215 return 2;
216 }
217 /* initialize remaining structure fields */
218 io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv, &tcp->sock);
219 tm_init(&tcp->tm, -1, -1);
220 buf_init(&tcp->buf, &tcp->io, &tcp->tm);
221 return 1;
222}