1 /*****************************************************************************
2 * net.c: Network related functions
3 *****************************************************************************
4 * Copyright (C) 2007-2008 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_network.h>
40 #include <lua.h> /* Low level lua C API */
41 #include <lauxlib.h> /* Higher level C API */
44 #include <poll.h> /* poll structures and defines */
51 /*****************************************************************************
53 *****************************************************************************/
54 static int vlclua_url_parse( lua_State
*L
)
56 const char *psz_url
= luaL_checkstring( L
, 1 );
57 const char *psz_option
= luaL_optstring( L
, 2, NULL
);
60 vlc_UrlParse( &url
, psz_url
, psz_option
?*psz_option
:0 );
63 lua_pushstring( L
, url
.psz_protocol
);
64 lua_setfield( L
, -2, "protocol" );
65 lua_pushstring( L
, url
.psz_username
);
66 lua_setfield( L
, -2, "username" );
67 lua_pushstring( L
, url
.psz_password
);
68 lua_setfield( L
, -2, "password" );
69 lua_pushstring( L
, url
.psz_host
);
70 lua_setfield( L
, -2, "host" );
71 lua_pushinteger( L
, url
.i_port
);
72 lua_setfield( L
, -2, "port" );
73 lua_pushstring( L
, url
.psz_path
);
74 lua_setfield( L
, -2, "path" );
75 lua_pushstring( L
, url
.psz_option
);
76 lua_setfield( L
, -2, "option" );
83 /*****************************************************************************
85 *****************************************************************************/
86 static int vlclua_net_listen_close( lua_State
* );
87 static int vlclua_net_accept( lua_State
* );
88 static int vlclua_net_fds( lua_State
* );
90 static const luaL_Reg vlclua_net_listen_reg
[] = {
91 { "accept", vlclua_net_accept
},
92 { "fds", vlclua_net_fds
},
96 static int vlclua_net_listen_tcp( lua_State
*L
)
98 vlc_object_t
*p_this
= vlclua_get_this( L
);
99 const char *psz_host
= luaL_checkstring( L
, 1 );
100 int i_port
= luaL_checkint( L
, 2 );
101 int *pi_fd
= net_ListenTCP( p_this
, psz_host
, i_port
);
103 return luaL_error( L
, "Cannot listen on %s:%d", psz_host
, i_port
);
105 int **ppi_fd
= lua_newuserdata( L
, sizeof( int * ) );
108 if( luaL_newmetatable( L
, "net_listen" ) )
111 luaL_register( L
, NULL
, vlclua_net_listen_reg
);
112 lua_setfield( L
, -2, "__index" );
113 lua_pushcfunction( L
, vlclua_net_listen_close
);
114 lua_setfield( L
, -2, "__gc" );
117 lua_setmetatable( L
, -2 );
121 static int vlclua_net_listen_close( lua_State
*L
)
123 int **ppi_fd
= (int**)luaL_checkudata( L
, 1, "net_listen" );
124 net_ListenClose( *ppi_fd
);
128 static int vlclua_net_fds( lua_State
*L
)
130 int **ppi_fd
= (int**)luaL_checkudata( L
, 1, "net_listen" );
131 int *pi_fd
= *ppi_fd
;
134 while( pi_fd
[i_count
] != -1 )
135 lua_pushinteger( L
, pi_fd
[i_count
++] );
140 static int vlclua_net_accept( lua_State
*L
)
142 vlc_object_t
*p_this
= vlclua_get_this( L
);
143 int **ppi_fd
= (int**)luaL_checkudata( L
, 1, "net_listen" );
144 int i_fd
= net_Accept( p_this
, *ppi_fd
);
146 lua_pushinteger( L
, i_fd
);
150 /*****************************************************************************
152 *****************************************************************************/
153 static int vlclua_net_close( lua_State
*L
)
155 int i_fd
= luaL_checkint( L
, 1 );
160 static int vlclua_net_send( lua_State
*L
)
162 int i_fd
= luaL_checkint( L
, 1 );
164 const char *psz_buffer
= luaL_checklstring( L
, 2, &i_len
);
165 i_len
= luaL_optint( L
, 3, i_len
);
166 i_len
= send( i_fd
, psz_buffer
, i_len
, 0 );
167 lua_pushinteger( L
, i_len
);
171 static int vlclua_net_recv( lua_State
*L
)
173 int i_fd
= luaL_checkint( L
, 1 );
174 size_t i_len
= luaL_optint( L
, 2, 1 );
175 char psz_buffer
[i_len
];
176 i_len
= recv( i_fd
, psz_buffer
, i_len
, 0 );
177 lua_pushlstring( L
, psz_buffer
, i_len
);
181 /*****************************************************************************
183 *****************************************************************************/
184 /* Takes a { fd : events } table as first arg and modifies it to { fd : revents } */
185 static int vlclua_net_poll( lua_State
*L
)
187 luaL_checktype( L
, 1, LUA_TTABLE
);
188 double f_timeout
= luaL_optnumber( L
, 2, -1. );
192 while( lua_next( L
, 1 ) )
197 struct pollfd
*p_fds
= malloc( i_fds
* sizeof( struct pollfd
) );
198 vlc_cleanup_push( free
, p_fds
);
201 while( lua_next( L
, 1 ) )
203 p_fds
[i
].fd
= luaL_checkinteger( L
, -2 );
204 p_fds
[i
].events
= luaL_checkinteger( L
, -1 );
205 p_fds
[i
].revents
= 0;
210 int i_ret
= poll( p_fds
, i_fds
, f_timeout
< 0. ? -1 : (int)(f_timeout
*1000) );
211 for( i
= 0; i
< i_fds
; i
++ )
213 lua_pushinteger( L
, p_fds
[i
].fd
);
214 lua_pushinteger( L
, p_fds
[i
].revents
);
215 lua_settable( L
, 1 );
217 lua_pushinteger( L
, i_ret
);
222 /*****************************************************************************
224 *****************************************************************************/
226 static int vlclua_fd_open( lua_State *L )
231 static int vlclua_fd_write( lua_State
*L
)
233 int i_fd
= luaL_checkint( L
, 1 );
236 const char *psz_buffer
= luaL_checklstring( L
, 2, &i_len
);
237 i_len
= luaL_optint( L
, 3, i_len
);
238 i_ret
= write( i_fd
, psz_buffer
, i_len
);
239 lua_pushinteger( L
, i_ret
);
243 static int vlclua_fd_read( lua_State
*L
)
245 int i_fd
= luaL_checkint( L
, 1 );
246 size_t i_len
= luaL_optint( L
, 2, 1 );
247 char psz_buffer
[i_len
];
248 i_len
= read( i_fd
, psz_buffer
, i_len
);
249 lua_pushlstring( L
, psz_buffer
, i_len
);
253 /*****************************************************************************
255 *****************************************************************************/
256 static int vlclua_stat( lua_State
*L
)
258 #ifdef HAVE_SYS_STAT_H
259 const char *psz_path
= luaL_checkstring( L
, 1 );
261 if( vlc_stat( psz_path
, &s
) )
263 //return luaL_error( L, "Couldn't stat %s.", psz_path );
265 if( S_ISREG( s
.st_mode
) )
266 lua_pushstring( L
, "file" );
267 else if( S_ISDIR( s
.st_mode
) )
268 lua_pushstring( L
, "dir" );
270 else if( S_ISCHR( s
.st_mode
) )
271 lua_pushstring( L
, "character device" );
274 else if( S_ISBLK( s
.st_mode
) )
275 lua_pushstring( L
, "block device" );
278 else if( S_ISFIFO( s
.st_mode
) )
279 lua_pushstring( L
, "fifo" );
282 else if( S_ISLNK( s
.st_mode
) )
283 lua_pushstring( L
, "symbolic link" );
286 else if( S_ISSOCK( s
.st_mode
) )
287 lua_pushstring( L
, "socket" );
290 lua_pushstring( L
, "unknown" );
291 lua_setfield( L
, -2, "type" );
292 lua_pushinteger( L
, s
.st_mode
);
293 lua_setfield( L
, -2, "mode" );
294 lua_pushinteger( L
, s
.st_uid
);
295 lua_setfield( L
, -2, "uid" );
296 lua_pushinteger( L
, s
.st_gid
);
297 lua_setfield( L
, -2, "gid" );
298 lua_pushinteger( L
, s
.st_size
);
299 lua_setfield( L
, -2, "size" );
300 lua_pushinteger( L
, s
.st_atime
);
301 lua_setfield( L
, -2, "access_time" );
302 lua_pushinteger( L
, s
.st_mtime
);
303 lua_setfield( L
, -2, "modification_time" );
304 lua_pushinteger( L
, s
.st_ctime
);
305 lua_setfield( L
, -2, "creation_time" );
308 # warning "Woops, looks like we don't have stat on your platform"
309 return luaL_error( L
, "System is missing <sys/stat.h>" );
313 static int vlclua_opendir( lua_State
*L
)
315 const char *psz_dir
= luaL_checkstring( L
, 1 );
319 if( ( p_dir
= vlc_opendir( psz_dir
) ) == NULL
)
320 return luaL_error( L
, "cannot open directory `%s'.", psz_dir
);
325 char *psz_filename
= vlc_readdir( p_dir
);
326 if( !psz_filename
) break;
328 lua_pushstring( L
, psz_filename
);
329 lua_rawseti( L
, -2, i
);
330 free( psz_filename
);
336 /*****************************************************************************
338 *****************************************************************************/
339 static const luaL_Reg vlclua_net_reg
[] = {
340 { "url_parse", vlclua_url_parse
},
341 { "listen_tcp", vlclua_net_listen_tcp
},
342 { "close", vlclua_net_close
},
343 { "send", vlclua_net_send
},
344 { "recv", vlclua_net_recv
},
345 { "poll", vlclua_net_poll
},
346 { "read", vlclua_fd_read
},
347 { "write", vlclua_fd_write
},
348 { "stat", vlclua_stat
}, /* Not really "net" */
349 { "opendir", vlclua_opendir
}, /* Not really "net" */
353 void luaopen_net( lua_State
*L
)
356 luaL_register( L
, NULL
, vlclua_net_reg
);
357 #define ADD_CONSTANT( name, value ) \
358 lua_pushinteger( L, value ); \
359 lua_setfield( L, -2, name );
360 ADD_CONSTANT( "POLLIN", POLLIN
)
361 ADD_CONSTANT( "POLLPRI", POLLPRI
)
362 ADD_CONSTANT( "POLLOUT", POLLOUT
)
363 ADD_CONSTANT( "POLLERR", POLLERR
)
364 ADD_CONSTANT( "POLLHUP", POLLHUP
)
365 ADD_CONSTANT( "POLLNVAL", POLLNVAL
)
366 lua_setfield( L
, -2, "net" );