Line data Source code
1 : /*
2 : Minetest
3 : Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 :
5 : This program is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU Lesser General Public License as published by
7 : the Free Software Foundation; either version 2.1 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU Lesser General Public License for more details.
14 :
15 : You should have received a copy of the GNU Lesser General Public License along
16 : with this program; if not, write to the Free Software Foundation, Inc.,
17 : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "lua_api/l_server.h"
21 : #include "lua_api/l_internal.h"
22 : #include "common/c_converter.h"
23 : #include "common/c_content.h"
24 : #include "cpp_api/s_base.h"
25 : #include "server.h"
26 : #include "environment.h"
27 : #include "player.h"
28 : #include "log.h"
29 :
30 : // request_shutdown()
31 0 : int ModApiServer::l_request_shutdown(lua_State *L)
32 : {
33 0 : getServer(L)->requestShutdown();
34 0 : return 0;
35 : }
36 :
37 : // get_server_status()
38 0 : int ModApiServer::l_get_server_status(lua_State *L)
39 : {
40 0 : NO_MAP_LOCK_REQUIRED;
41 0 : lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
42 0 : return 1;
43 : }
44 :
45 : // chat_send_all(text)
46 0 : int ModApiServer::l_chat_send_all(lua_State *L)
47 : {
48 0 : NO_MAP_LOCK_REQUIRED;
49 0 : const char *text = luaL_checkstring(L, 1);
50 : // Get server from registry
51 0 : Server *server = getServer(L);
52 : // Send
53 0 : server->notifyPlayers(narrow_to_wide(text));
54 0 : return 0;
55 : }
56 :
57 : // chat_send_player(name, text)
58 0 : int ModApiServer::l_chat_send_player(lua_State *L)
59 : {
60 0 : NO_MAP_LOCK_REQUIRED;
61 0 : const char *name = luaL_checkstring(L, 1);
62 0 : const char *text = luaL_checkstring(L, 2);
63 :
64 : // Get server from registry
65 0 : Server *server = getServer(L);
66 : // Send
67 0 : server->notifyPlayer(name, narrow_to_wide(text));
68 0 : return 0;
69 : }
70 :
71 : // get_player_privs(name, text)
72 0 : int ModApiServer::l_get_player_privs(lua_State *L)
73 : {
74 0 : NO_MAP_LOCK_REQUIRED;
75 0 : const char *name = luaL_checkstring(L, 1);
76 : // Get server from registry
77 0 : Server *server = getServer(L);
78 : // Do it
79 0 : lua_newtable(L);
80 0 : int table = lua_gettop(L);
81 0 : std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
82 0 : for(std::set<std::string>::const_iterator
83 0 : i = privs_s.begin(); i != privs_s.end(); i++){
84 0 : lua_pushboolean(L, true);
85 0 : lua_setfield(L, table, i->c_str());
86 : }
87 0 : lua_pushvalue(L, table);
88 0 : return 1;
89 : }
90 :
91 : // get_player_ip()
92 0 : int ModApiServer::l_get_player_ip(lua_State *L)
93 : {
94 0 : NO_MAP_LOCK_REQUIRED;
95 0 : const char * name = luaL_checkstring(L, 1);
96 0 : Player *player = getEnv(L)->getPlayer(name);
97 0 : if(player == NULL)
98 : {
99 0 : lua_pushnil(L); // no such player
100 0 : return 1;
101 : }
102 : try
103 : {
104 0 : Address addr = getServer(L)->getPeerAddress(player->peer_id);
105 0 : std::string ip_str = addr.serializeString();
106 0 : lua_pushstring(L, ip_str.c_str());
107 0 : return 1;
108 : }
109 0 : catch(con::PeerNotFoundException) // unlikely
110 : {
111 0 : dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
112 0 : lua_pushnil(L); // error
113 0 : return 1;
114 : }
115 : }
116 :
117 : // get_player_information()
118 0 : int ModApiServer::l_get_player_information(lua_State *L)
119 : {
120 :
121 0 : NO_MAP_LOCK_REQUIRED;
122 0 : const char * name = luaL_checkstring(L, 1);
123 0 : Player *player = getEnv(L)->getPlayer(name);
124 0 : if(player == NULL)
125 : {
126 0 : lua_pushnil(L); // no such player
127 0 : return 1;
128 : }
129 :
130 0 : Address addr;
131 : try
132 : {
133 0 : addr = getServer(L)->getPeerAddress(player->peer_id);
134 : }
135 0 : catch(con::PeerNotFoundException) // unlikely
136 : {
137 0 : dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
138 0 : lua_pushnil(L); // error
139 0 : return 1;
140 : }
141 :
142 : float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
143 : ClientState state;
144 : u32 uptime;
145 : u16 prot_vers;
146 : u8 ser_vers,major,minor,patch;
147 0 : std::string vers_string;
148 :
149 : #define ERET(code) \
150 : if (!(code)) { \
151 : dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; \
152 : lua_pushnil(L); /* error */ \
153 : return 1; \
154 : }
155 :
156 0 : ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_RTT,&min_rtt))
157 0 : ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_RTT,&max_rtt))
158 0 : ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_RTT,&avg_rtt))
159 0 : ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_JITTER,&min_jitter))
160 0 : ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_JITTER,&max_jitter))
161 0 : ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_JITTER,&avg_jitter))
162 :
163 0 : ERET(getServer(L)->getClientInfo(player->peer_id,
164 : &state, &uptime, &ser_vers, &prot_vers,
165 : &major, &minor, &patch, &vers_string))
166 :
167 0 : lua_newtable(L);
168 0 : int table = lua_gettop(L);
169 :
170 0 : lua_pushstring(L,"address");
171 0 : lua_pushstring(L, addr.serializeString().c_str());
172 0 : lua_settable(L, table);
173 :
174 0 : lua_pushstring(L,"ip_version");
175 0 : if (addr.getFamily() == AF_INET) {
176 0 : lua_pushnumber(L, 4);
177 0 : } else if (addr.getFamily() == AF_INET6) {
178 0 : lua_pushnumber(L, 6);
179 : } else {
180 0 : lua_pushnumber(L, 0);
181 : }
182 0 : lua_settable(L, table);
183 :
184 0 : lua_pushstring(L,"min_rtt");
185 0 : lua_pushnumber(L, min_rtt);
186 0 : lua_settable(L, table);
187 :
188 0 : lua_pushstring(L,"max_rtt");
189 0 : lua_pushnumber(L, max_rtt);
190 0 : lua_settable(L, table);
191 :
192 0 : lua_pushstring(L,"avg_rtt");
193 0 : lua_pushnumber(L, avg_rtt);
194 0 : lua_settable(L, table);
195 :
196 0 : lua_pushstring(L,"min_jitter");
197 0 : lua_pushnumber(L, min_jitter);
198 0 : lua_settable(L, table);
199 :
200 0 : lua_pushstring(L,"max_jitter");
201 0 : lua_pushnumber(L, max_jitter);
202 0 : lua_settable(L, table);
203 :
204 0 : lua_pushstring(L,"avg_jitter");
205 0 : lua_pushnumber(L, avg_jitter);
206 0 : lua_settable(L, table);
207 :
208 0 : lua_pushstring(L,"connection_uptime");
209 0 : lua_pushnumber(L, uptime);
210 0 : lua_settable(L, table);
211 :
212 : #ifndef NDEBUG
213 : lua_pushstring(L,"serialization_version");
214 : lua_pushnumber(L, ser_vers);
215 : lua_settable(L, table);
216 :
217 : lua_pushstring(L,"protocol_version");
218 : lua_pushnumber(L, prot_vers);
219 : lua_settable(L, table);
220 :
221 : lua_pushstring(L,"major");
222 : lua_pushnumber(L, major);
223 : lua_settable(L, table);
224 :
225 : lua_pushstring(L,"minor");
226 : lua_pushnumber(L, minor);
227 : lua_settable(L, table);
228 :
229 : lua_pushstring(L,"patch");
230 : lua_pushnumber(L, patch);
231 : lua_settable(L, table);
232 :
233 : lua_pushstring(L,"version_string");
234 : lua_pushstring(L, vers_string.c_str());
235 : lua_settable(L, table);
236 :
237 : lua_pushstring(L,"state");
238 : lua_pushstring(L,ClientInterface::state2Name(state).c_str());
239 : lua_settable(L, table);
240 : #endif
241 :
242 : #undef ERET
243 0 : return 1;
244 : }
245 :
246 : // get_ban_list()
247 0 : int ModApiServer::l_get_ban_list(lua_State *L)
248 : {
249 0 : NO_MAP_LOCK_REQUIRED;
250 0 : lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
251 0 : return 1;
252 : }
253 :
254 : // get_ban_description()
255 0 : int ModApiServer::l_get_ban_description(lua_State *L)
256 : {
257 0 : NO_MAP_LOCK_REQUIRED;
258 0 : const char * ip_or_name = luaL_checkstring(L, 1);
259 0 : lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
260 0 : return 1;
261 : }
262 :
263 : // ban_player()
264 0 : int ModApiServer::l_ban_player(lua_State *L)
265 : {
266 0 : NO_MAP_LOCK_REQUIRED;
267 0 : const char * name = luaL_checkstring(L, 1);
268 0 : Player *player = getEnv(L)->getPlayer(name);
269 0 : if(player == NULL)
270 : {
271 0 : lua_pushboolean(L, false); // no such player
272 0 : return 1;
273 : }
274 : try
275 : {
276 0 : Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
277 0 : std::string ip_str = addr.serializeString();
278 0 : getServer(L)->setIpBanned(ip_str, name);
279 : }
280 0 : catch(con::PeerNotFoundException) // unlikely
281 : {
282 0 : dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
283 0 : lua_pushboolean(L, false); // error
284 0 : return 1;
285 : }
286 0 : lua_pushboolean(L, true);
287 0 : return 1;
288 : }
289 :
290 : // kick_player(name, [reason]) -> success
291 0 : int ModApiServer::l_kick_player(lua_State *L)
292 : {
293 0 : NO_MAP_LOCK_REQUIRED;
294 0 : const char *name = luaL_checkstring(L, 1);
295 0 : std::string message;
296 0 : if (lua_isstring(L, 2))
297 : {
298 0 : message = std::string("Kicked: ") + lua_tostring(L, 2);
299 : }
300 : else
301 : {
302 0 : message = "Kicked.";
303 : }
304 0 : Player *player = getEnv(L)->getPlayer(name);
305 0 : if (player == NULL)
306 : {
307 0 : lua_pushboolean(L, false); // No such player
308 0 : return 1;
309 : }
310 0 : getServer(L)->DenyAccess_Legacy(player->peer_id, narrow_to_wide(message));
311 0 : lua_pushboolean(L, true);
312 0 : return 1;
313 : }
314 :
315 : // unban_player_or_ip()
316 0 : int ModApiServer::l_unban_player_or_ip(lua_State *L)
317 : {
318 0 : NO_MAP_LOCK_REQUIRED;
319 0 : const char * ip_or_name = luaL_checkstring(L, 1);
320 0 : getServer(L)->unsetIpBanned(ip_or_name);
321 0 : lua_pushboolean(L, true);
322 0 : return 1;
323 : }
324 :
325 : // show_formspec(playername,formname,formspec)
326 0 : int ModApiServer::l_show_formspec(lua_State *L)
327 : {
328 0 : NO_MAP_LOCK_REQUIRED;
329 0 : const char *playername = luaL_checkstring(L, 1);
330 0 : const char *formname = luaL_checkstring(L, 2);
331 0 : const char *formspec = luaL_checkstring(L, 3);
332 :
333 0 : if(getServer(L)->showFormspec(playername,formspec,formname))
334 : {
335 0 : lua_pushboolean(L, true);
336 : }else{
337 0 : lua_pushboolean(L, false);
338 : }
339 0 : return 1;
340 : }
341 :
342 : // get_current_modname()
343 0 : int ModApiServer::l_get_current_modname(lua_State *L)
344 : {
345 0 : NO_MAP_LOCK_REQUIRED;
346 0 : lua_getfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
347 0 : return 1;
348 : }
349 :
350 : // get_modpath(modname)
351 0 : int ModApiServer::l_get_modpath(lua_State *L)
352 : {
353 0 : NO_MAP_LOCK_REQUIRED;
354 0 : std::string modname = luaL_checkstring(L, 1);
355 0 : const ModSpec *mod = getServer(L)->getModSpec(modname);
356 0 : if (!mod) {
357 0 : lua_pushnil(L);
358 0 : return 1;
359 : }
360 0 : lua_pushstring(L, mod->path.c_str());
361 0 : return 1;
362 : }
363 :
364 : // get_modnames()
365 : // the returned list is sorted alphabetically for you
366 0 : int ModApiServer::l_get_modnames(lua_State *L)
367 : {
368 0 : NO_MAP_LOCK_REQUIRED;
369 :
370 : // Get a list of mods
371 0 : std::vector<std::string> modlist;
372 0 : getServer(L)->getModNames(modlist);
373 :
374 : // Take unsorted items from mods_unsorted and sort them into
375 : // mods_sorted; not great performance but the number of mods on a
376 : // server will likely be small.
377 0 : std::sort(modlist.begin(), modlist.end());
378 :
379 : // Package them up for Lua
380 0 : lua_createtable(L, modlist.size(), 0);
381 0 : std::vector<std::string>::iterator iter = modlist.begin();
382 0 : for (u16 i = 0; iter != modlist.end(); iter++) {
383 0 : lua_pushstring(L, iter->c_str());
384 0 : lua_rawseti(L, -2, ++i);
385 : }
386 0 : return 1;
387 : }
388 :
389 : // get_worldpath()
390 0 : int ModApiServer::l_get_worldpath(lua_State *L)
391 : {
392 0 : NO_MAP_LOCK_REQUIRED;
393 0 : std::string worldpath = getServer(L)->getWorldPath();
394 0 : lua_pushstring(L, worldpath.c_str());
395 0 : return 1;
396 : }
397 :
398 : // sound_play(spec, parameters)
399 0 : int ModApiServer::l_sound_play(lua_State *L)
400 : {
401 0 : NO_MAP_LOCK_REQUIRED;
402 0 : SimpleSoundSpec spec;
403 0 : read_soundspec(L, 1, spec);
404 0 : ServerSoundParams params;
405 0 : read_server_sound_params(L, 2, params);
406 0 : s32 handle = getServer(L)->playSound(spec, params);
407 0 : lua_pushinteger(L, handle);
408 0 : return 1;
409 : }
410 :
411 : // sound_stop(handle)
412 0 : int ModApiServer::l_sound_stop(lua_State *L)
413 : {
414 0 : NO_MAP_LOCK_REQUIRED;
415 0 : int handle = luaL_checkinteger(L, 1);
416 0 : getServer(L)->stopSound(handle);
417 0 : return 0;
418 : }
419 :
420 : // is_singleplayer()
421 0 : int ModApiServer::l_is_singleplayer(lua_State *L)
422 : {
423 0 : NO_MAP_LOCK_REQUIRED;
424 0 : lua_pushboolean(L, getServer(L)->isSingleplayer());
425 0 : return 1;
426 : }
427 :
428 : // notify_authentication_modified(name)
429 0 : int ModApiServer::l_notify_authentication_modified(lua_State *L)
430 : {
431 0 : NO_MAP_LOCK_REQUIRED;
432 0 : std::string name = "";
433 0 : if(lua_isstring(L, 1))
434 0 : name = lua_tostring(L, 1);
435 0 : getServer(L)->reportPrivsModified(name);
436 0 : return 0;
437 : }
438 :
439 : #ifndef NDEBUG
440 : // cause_error(type_of_error)
441 : int ModApiServer::l_cause_error(lua_State *L)
442 : {
443 : NO_MAP_LOCK_REQUIRED;
444 : std::string type_of_error = "none";
445 : if(lua_isstring(L, 1))
446 : type_of_error = lua_tostring(L, 1);
447 :
448 : errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
449 :
450 : if(type_of_error == "segv") {
451 : volatile int* some_pointer = 0;
452 : errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
453 :
454 : } else if (type_of_error == "zerodivision") {
455 :
456 : unsigned int some_number = porting::getTimeS();
457 : unsigned int zerovalue = 0;
458 : unsigned int result = some_number / zerovalue;
459 : errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
460 :
461 : } else if (type_of_error == "exception") {
462 : throw BaseException("Errorhandler test fct called");
463 : }
464 :
465 : return 0;
466 : }
467 : #endif
468 :
469 0 : void ModApiServer::Initialize(lua_State *L, int top)
470 : {
471 0 : API_FCT(request_shutdown);
472 0 : API_FCT(get_server_status);
473 0 : API_FCT(get_worldpath);
474 0 : API_FCT(is_singleplayer);
475 :
476 0 : API_FCT(get_current_modname);
477 0 : API_FCT(get_modpath);
478 0 : API_FCT(get_modnames);
479 :
480 0 : API_FCT(chat_send_all);
481 0 : API_FCT(chat_send_player);
482 0 : API_FCT(show_formspec);
483 0 : API_FCT(sound_play);
484 0 : API_FCT(sound_stop);
485 :
486 0 : API_FCT(get_player_information);
487 0 : API_FCT(get_player_privs);
488 0 : API_FCT(get_player_ip);
489 0 : API_FCT(get_ban_list);
490 0 : API_FCT(get_ban_description);
491 0 : API_FCT(ban_player);
492 0 : API_FCT(kick_player);
493 0 : API_FCT(unban_player_or_ip);
494 0 : API_FCT(notify_authentication_modified);
495 :
496 : #ifndef NDEBUG
497 : API_FCT(cause_error);
498 : #endif
499 3 : }
|