Freeciv-3.3: /fast/freeciv/nightly/main/server/scripting/script_fcdb.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
script_fcdb.c
Go to the documentation of this file.
1/*****************************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12*****************************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19#include <stdlib.h>
20#include <time.h>
21
22/* dependencies/lua */
23#include "lua.h"
24#include "lualib.h"
25
26/* dependencies/tolua */
27#include "tolua.h"
28
29/* dependencies/luasql */
30#ifdef HAVE_FCDB_MYSQL
31#include "ls_mysql.h"
32#endif
33#ifdef HAVE_FCDB_ODBC
34#include "ls_odbc.h"
35#endif
36#ifdef HAVE_FCDB_POSTGRES
37#include "ls_postgres.h"
38#endif
39#ifdef HAVE_FCDB_SQLITE3
40#include "ls_sqlite3.h"
41#endif
42
43/* utility */
44#include "capability.h"
45#include "log.h"
46#include "md5.h"
47#include "registry.h"
48#include "string_vector.h"
49
50/* common/scriptcore */
51#include "luascript.h"
52#include "luascript_types.h"
53#include "tolua_common_a_gen.h"
54#include "tolua_common_z_gen.h"
55#include "tolua_game_gen.h"
56
57/* server */
58#include "console.h"
59#include "srv_main.h"
60#include "stdinhand.h"
61
62/* server/scripting */
63#include "api_fcdb_specenum.h"
64
65#ifdef HAVE_FCDB
66#include <tolua_fcdb_gen.h> /* <> so looked from the build directory first. */
67#endif /* HAVE_FCDB */
68
69#include "script_fcdb.h"
70
71#ifdef HAVE_FCDB
72
73#define SCRIPT_FCDB_LUA_FILE "database.lua"
74
75#define FCDB_CAPS "+fcdb"
76
77static void script_fcdb_functions_define(void);
78static bool script_fcdb_functions_check(const char *fcdb_luafile);
79
80static void script_fcdb_cmd_reply(struct fc_lua *lfcl, enum log_level level,
81 const char *format, ...)
82 fc__attribute((__format__ (__printf__, 3, 4)));
83
84/**********************************************************************/
87 static struct fc_lua *fcl = NULL;
88
89/**********************************************************************/
122 static void script_fcdb_functions_define(void)
123{
124 luascript_func_add(fcl, "database_init", TRUE, 0, 0);
125 luascript_func_add(fcl, "database_capstr", TRUE, 0, 1, API_TYPE_STRING);
126 luascript_func_add(fcl, "database_free", TRUE, 0, 0);
127
128 luascript_func_add(fcl, "user_exists", TRUE, 1, 1, API_TYPE_CONNECTION,
129 API_TYPE_BOOL);
130 luascript_func_add(fcl, "user_verify", TRUE, 2, 1, API_TYPE_CONNECTION,
131 API_TYPE_STRING, API_TYPE_BOOL);
132 luascript_func_add(fcl, "user_save", FALSE, 2, 0, API_TYPE_CONNECTION,
133 API_TYPE_STRING);
134 luascript_func_add(fcl, "user_log", TRUE, 2, 0, API_TYPE_CONNECTION,
135 API_TYPE_BOOL);
136 luascript_func_add(fcl, "user_delegate_to", FALSE, 3, 1,
137 API_TYPE_CONNECTION, API_TYPE_PLAYER, API_TYPE_STRING,
138 API_TYPE_BOOL);
139 luascript_func_add(fcl, "user_take", FALSE, 4, 1, API_TYPE_CONNECTION,
140 API_TYPE_CONNECTION, API_TYPE_PLAYER, API_TYPE_BOOL,
141 API_TYPE_BOOL);
142 luascript_func_add(fcl, "conn_established", FALSE, 1, 0, API_TYPE_CONNECTION);
143 luascript_func_add(fcl, "game_start", FALSE, 1, 1,
144 API_TYPE_INT, API_TYPE_INT);
145}
146
147/**********************************************************************/
150static bool script_fcdb_functions_check(const char *fcdb_luafile)
151{
152 bool ret = TRUE;
153 struct strvec *missing_func_required = strvec_new();
154 struct strvec *missing_func_optional = strvec_new();
155
156 if (!luascript_func_check(fcl, missing_func_required,
157 missing_func_optional)) {
158 strvec_iterate(missing_func_required, func_name) {
159 log_error("Database script '%s' does not define the required function "
160 "'%s'.", fcdb_luafile, func_name);
161 ret = FALSE;
162 } strvec_iterate_end;
163 strvec_iterate(missing_func_optional, func_name) {
164 log_verbose("Database script '%s' does not define the optional "
165 "function '%s'.", fcdb_luafile, func_name);
166 } strvec_iterate_end;
167 }
168
169 strvec_destroy(missing_func_required);
170 strvec_destroy(missing_func_optional);
171
172 return ret;
173}
174
175/**********************************************************************/
178static void script_fcdb_cmd_reply(struct fc_lua *lfcl, enum log_level level,
179 const char *format, ...)
180{
181 va_list args;
182 enum rfc_status rfc_status = C_OK;
183 char buf[1024];
184
185 va_start(args, format);
186 fc_vsnprintf(buf, sizeof(buf), format, args);
187 va_end(args);
188
189 switch (level) {
190 case LOG_FATAL:
191 /* Special case - will quit the server. */
192 log_fatal("%s", buf);
193 break;
194 case LOG_ERROR:
195 case LOG_WARN:
196 rfc_status = C_WARNING;
197 break;
198 case LOG_NORMAL:
199 rfc_status = C_COMMENT;
200 break;
201 case LOG_VERBOSE:
202 rfc_status = C_LOG_BASE;
203 break;
204 case LOG_DEBUG:
205 rfc_status = C_DEBUG;
206 break;
207 }
208
209 cmd_reply(CMD_FCDB, lfcl->caller, rfc_status, "%s", buf);
210}
211
212/**********************************************************************/
215static int md5sum(lua_State *L)
216{
217 int n = lua_gettop(L);
218 char sum[MD5_HEX_BYTES + 1];
219 const char *plaintext;
220 size_t len;
221
222 if (n != 1 || lua_type(L, -1) != LUA_TSTRING) {
223 lua_pushliteral(L, "invalid argument");
224 lua_error(L);
225 }
226
227 plaintext = lua_tolstring(L, -1, &len);
228 create_md5sum((unsigned char*)plaintext, len, sum);
229
230 lua_pushstring(L, sum);
231 return 1;
232}
233#endif /* HAVE_FCDB */
234
235/**********************************************************************/
239 bool script_fcdb_init(const char *fcdb_luafile)
240{
241#ifdef HAVE_FCDB
242 if (fcl != NULL) {
243 fc_assert_ret_val(fcl->state != NULL, FALSE);
244
245 return TRUE;
246 }
247
248 if (!fcdb_luafile) {
249 /* Use default freeciv database lua file. */
250 fcdb_luafile = FC_CONF_PATH "/" SCRIPT_FCDB_LUA_FILE;
251 }
252
253 fcl = luascript_new(NULL, FALSE);
254 if (fcl == NULL) {
255 log_error("Error loading the Freeciv database lua definition.");
256 return FALSE;
257 }
258
259 tolua_common_a_open(fcl->state);
260 api_fcdb_specenum_open(fcl->state);
261 tolua_game_open(fcl->state);
262
263#ifdef MESON_BUILD
264 /* Tolua adds 'tolua_' prefix to _open() function names,
265 * and we can't pass it a basename where the original
266 * 'tolua_' has been stripped when generating from meson. */
267 tolua_tolua_fcdb_open(fcl->state);
268#else /* MESON_BUILD */
269 tolua_fcdb_open(fcl->state);
270#endif /* MESON_BUILD */
271 lua_register(fcl->state, "md5sum", md5sum);
272#ifdef HAVE_FCDB_MYSQL
273 luaL_requiref(fcl->state, "ls_mysql", luaopen_luasql_mysql, 1);
274 lua_pop(fcl->state, 1);
275#endif
276#ifdef HAVE_FCDB_ODBC
277 luaL_requiref(fcl->state, "ls_odbc", luaopen_luasql_odbc, 1);
278 lua_pop(fcl->state, 1);
279#endif
280#ifdef HAVE_FCDB_POSTGRES
281 luaL_requiref(fcl->state, "ls_postgres", luaopen_luasql_postgres, 1);
282 lua_pop(fcl->state, 1);
283#endif
284#ifdef HAVE_FCDB_SQLITE3
285 luaL_requiref(fcl->state, "ls_sqlite3", luaopen_luasql_sqlite3, 1);
286 lua_pop(fcl->state, 1);
287#endif
288 tolua_common_z_open(fcl->state);
289
290 luascript_func_init(fcl);
291
292 /* Define the prototypes for the needed lua functions. */
293 script_fcdb_functions_define();
294
295 if (luascript_do_file(fcl, fcdb_luafile)
296 || !script_fcdb_functions_check(fcdb_luafile)) {
297 log_error("Error loading the Freeciv database lua script '%s'.",
298 fcdb_luafile);
299 script_fcdb_free();
300 return FALSE;
301 }
302
303 if (srvarg.fcdb_enabled) {
304 if (!script_fcdb_call("database_init")) {
305 log_error("Error connecting to the database");
306 script_fcdb_free();
307 return FALSE;
308 }
309
310 if (!script_fcdb_capstr()) {
311 log_error(_("Database capabilities not compatible with server"));
312 return FALSE;
313 }
314 }
315
316#endif /* HAVE_FCDB */
317
318 return TRUE;
319}
320
321/**********************************************************************/
324 bool script_fcdb_capstr(void)
325{
326#ifdef HAVE_FCDB
327 static int checked = 0;
328 const char *fcdb_caps;
329
330 if (checked) {
331 return checked > 0;
332 }
333
334 script_fcdb_call("database_capstr", &fcdb_caps);
335
336 log_verbose("Server caps: %s", FCDB_CAPS);
337 log_verbose("DB caps: %s", fcdb_caps);
338
339 if (!has_capabilities(FCDB_CAPS, fcdb_caps)
340 || !has_capabilities(fcdb_caps, FCDB_CAPS)) {
341 log_error(_("Database not compatible. Freeciv caps: %s, DB caps: %s"),
342 FCDB_CAPS, fcdb_caps);
343 checked = -1; /* Negative */
344 return FALSE;
345 }
346
347 checked = 1; /* Positive */
348#endif /* HAVE_FCDB */
349
350 return TRUE;
351}
352
353/**********************************************************************/
359 bool script_fcdb_call(const char *func_name, ...)
360{
361 bool success = TRUE;
362#ifdef HAVE_FCDB
363
364 va_list args;
365 va_start(args, func_name);
366
367 success = luascript_func_call_valist(fcl, func_name, args);
368 va_end(args);
369#endif /* HAVE_FCDB */
370
371 return success;
372}
373
374/**********************************************************************/
377 void script_fcdb_free(void)
378{
379#ifdef HAVE_FCDB
380 if (!script_fcdb_call("database_free", 0)) {
381 log_error("Error closing the database connection. Continuing anyway...");
382 }
383
384 if (fcl) {
385 /* luascript_func_free() is called by luascript_destroy(). */
386 luascript_destroy(fcl);
387 fcl = NULL;
388 }
389#endif /* HAVE_FCDB */
390}
391
392/**********************************************************************/
396 bool script_fcdb_do_string(struct connection *caller, const char *str)
397{
398#ifdef HAVE_FCDB
399 int status;
400 struct connection *save_caller;
401 luascript_log_func_t save_output_fct;
402
403 /* Set a log callback function which allows to send the results of the
404 * command to the clients. */
405 save_caller = fcl->caller;
406 save_output_fct = fcl->output_fct;
407 fcl->output_fct = script_fcdb_cmd_reply;
408 fcl->caller = caller;
409
410 status = luascript_do_string(fcl, str, "cmd");
411
412 /* Reset the changes. */
413 fcl->caller = save_caller;
414 fcl->output_fct = save_output_fct;
415
416 return (status == 0);
417#else
418 return TRUE;
419#endif /* HAVE_FCDB */
420}
api_fcdb_specenum_open
int api_fcdb_specenum_open(lua_State *L)
Definition api_fcdb_specenum.c:46
api_fcdb_specenum.h
str
#define str
Definition astring.c:76
n
#define n
Definition astring.c:77
has_capabilities
bool has_capabilities(const char *us, const char *them)
Definition capability.c:86
capability.h
CMD_FCDB
@ CMD_FCDB
Definition commands.h:98
incite_cost
char * incite_cost
Definition comments.c:74
console.h
rfc_status
rfc_status
Definition console.h:35
C_DEBUG
@ C_DEBUG
Definition console.h:39
C_OK
@ C_OK
Definition console.h:41
C_LOG_BASE
@ C_LOG_BASE
Definition console.h:40
C_COMMENT
@ C_COMMENT
Definition console.h:37
C_WARNING
@ C_WARNING
Definition console.h:50
_
#define _(String)
Definition fcintl.h:67
log.h
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_fatal
#define log_fatal(message,...)
Definition log.h:100
log_level
log_level
Definition log.h:28
LOG_ERROR
@ LOG_ERROR
Definition log.h:30
LOG_DEBUG
@ LOG_DEBUG
Definition log.h:34
LOG_NORMAL
@ LOG_NORMAL
Definition log.h:32
LOG_FATAL
@ LOG_FATAL
Definition log.h:29
LOG_VERBOSE
@ LOG_VERBOSE
Definition log.h:33
LOG_WARN
@ LOG_WARN
Definition log.h:31
log_error
#define log_error(message,...)
Definition log.h:103
luascript_do_string
int luascript_do_string(struct fc_lua *fcl, const char *str, const char *name)
Definition luascript.c:618
luascript_do_file
int luascript_do_file(struct fc_lua *fcl, const char *filename)
Definition luascript.c:638
luascript_new
struct fc_lua * luascript_new(luascript_log_func_t output_fct, bool secured_environment)
Definition luascript.c:333
luascript_destroy
void luascript_destroy(struct fc_lua *fcl)
Definition luascript.c:387
luascript.h
luascript_log_func_t
void(* luascript_log_func_t)(struct fc_lua *fcl, enum log_level level, const char *format,...) fc__attribute((__format__(__printf__
Definition luascript.h:39
luascript_func_call_valist
bool luascript_func_call_valist(struct fc_lua *fcl, const char *func_name, va_list args)
Definition luascript_func.c:220
luascript_func_check
bool luascript_func_check(struct fc_lua *fcl, struct strvec *missing_func_required, struct strvec *missing_func_optional)
Definition luascript_func.c:94
luascript_func_init
void luascript_func_init(struct fc_lua *fcl)
Definition luascript_func.c:203
luascript_func_add
void luascript_func_add(struct fc_lua *fcl, const char *func_name, bool required, int nargs, int nreturns,...)
Definition luascript_func.c:178
luascript_types.h
create_md5sum
void create_md5sum(const unsigned char *input, int len, char output[MD5_HEX_BYTES+1])
Definition md5.c:335
md5.h
MD5_HEX_BYTES
#define MD5_HEX_BYTES
Definition md5.h:21
len
int len
Definition packhand.c:127
registry.h
script_fcdb_free
void script_fcdb_free(void)
Definition script_fcdb.c:377
script_fcdb_do_string
bool script_fcdb_do_string(struct connection *caller, const char *str)
Definition script_fcdb.c:396
script_fcdb_call
bool script_fcdb_call(const char *func_name,...)
Definition script_fcdb.c:359
script_fcdb_init
bool script_fcdb_init(const char *fcdb_luafile)
Definition script_fcdb.c:239
script_fcdb_capstr
bool script_fcdb_capstr(void)
Definition script_fcdb.c:324
script_fcdb.h
level
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
srvarg
struct server_arguments srvarg
Definition srv_main.c:180
srv_main.h
cmd_reply
void cmd_reply(enum command_id cmd, struct connection *caller, enum rfc_status rfc_status, const char *format,...)
Definition stdinhand.c:419
stdinhand.h
strvec_destroy
void strvec_destroy(struct strvec *psv)
Definition string_vector.c:72
strvec_new
struct strvec * strvec_new(void)
Definition string_vector.c:59
string_vector.h
strvec_iterate
#define strvec_iterate(psv, str)
Definition string_vector.h:61
strvec_iterate_end
#define strvec_iterate_end
Definition string_vector.h:68
connection
Definition connection.h:136
connection::status
enum auth_status status
Definition connection.h:217
fc_lua
Definition luascript.h:44
server_arguments::fcdb_enabled
bool fcdb_enabled
Definition srv_main.h:55
strvec
Definition string_vector.c:29
fc_vsnprintf
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
fc__attribute
#define fc__attribute(x)
Definition support.h:99
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
tolua_common_a_open
TOLUA_API int tolua_common_a_open(lua_State *tolua_S)
Definition tolua_common_a_gen.c:829
tolua_common_a_gen.h
tolua_common_z_open
TOLUA_API int tolua_common_z_open(lua_State *tolua_S)
Definition tolua_common_z_gen.c:144
tolua_common_z_gen.h
tolua_fcdb_open
TOLUA_API int tolua_fcdb_open(lua_State *tolua_S)
Definition tolua_fcdb_gen.c:225
tolua_fcdb_gen.h
tolua_game_open
TOLUA_API int tolua_game_open(lua_State *tolua_S)
Definition tolua_game_gen.c:5817
tolua_game_gen.h