2023-12-18 00:25:33 +01:00
/*************************************************************************/
/* web_server.cpp */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://github.com/Relintai/pandemonium_engine */
/*************************************************************************/
/* Copyright (c) 2022-present Péter Magyar. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2022-06-25 01:55:54 +02:00
# include "web_server.h"
2022-08-17 13:45:14 +02:00
# include "core/object/class_db.h"
2022-06-26 21:34:29 +02:00
# include "web_node.h"
# include "web_server_request.h"
2022-06-27 14:16:23 +02:00
# include "http_session_manager.h"
2022-07-07 21:44:14 +02:00
bool WebServer : : get_is_running ( ) {
return _is_running ;
2022-06-26 21:34:29 +02:00
}
2022-06-25 01:55:54 +02:00
WebNode * WebServer : : get_web_root ( ) {
return _web_root ;
}
2022-06-27 14:16:23 +02:00
HTTPSessionManager * WebServer : : get_session_manager ( ) {
return _session_manager ;
}
2022-06-27 01:03:01 +02:00
void WebServer : : server_handle_request ( Ref < WebServerRequest > request ) {
2022-06-25 01:55:54 +02:00
ERR_FAIL_COND ( ! _web_root ) ;
2022-07-21 23:25:04 +02:00
request - > _set_server ( this ) ;
request - > _set_web_root ( _web_root ) ;
2022-06-27 01:03:01 +02:00
2022-06-25 01:55:54 +02:00
_rw_lock . read_lock ( ) ;
_web_root - > handle_request_main ( request ) ;
_rw_lock . read_unlock ( ) ;
}
2022-06-27 14:59:09 +02:00
void WebServer : : request_write_lock ( ) {
_write_lock_requested = true ;
}
2022-07-07 21:44:14 +02:00
void WebServer : : refresh_root ( ) {
_web_root = nullptr ;
_session_manager = nullptr ;
for ( int i = 0 ; i < get_child_count ( ) ; + + i ) {
if ( ! _web_root ) {
_web_root = Object : : cast_to < WebNode > ( get_child ( i ) ) ;
}
if ( ! _session_manager ) {
_session_manager = Object : : cast_to < HTTPSessionManager > ( get_child ( i ) ) ;
}
}
}
2022-06-27 14:16:23 +02:00
void WebServer : : start ( ) {
call ( " _start " ) ;
}
void WebServer : : stop ( ) {
call ( " _stop " ) ;
}
void WebServer : : _start ( ) {
2022-07-07 21:44:14 +02:00
if ( _is_running ) {
return ;
2022-06-27 15:42:40 +02:00
}
2022-07-07 21:44:14 +02:00
_is_running = true ;
refresh_root ( ) ;
2022-06-27 14:16:23 +02:00
}
void WebServer : : _stop ( ) {
2022-07-07 21:44:14 +02:00
if ( ! _is_running ) {
return ;
}
_is_running = false ;
}
2023-12-22 12:38:38 +01:00
Dictionary WebServer : : unregister_connection_for_request ( const Ref < WebServerRequest > & request ) {
return call ( " _unregister_connection_for_request " , request ) ;
}
Dictionary WebServer : : _unregister_connection_for_request ( const Ref < WebServerRequest > & request ) {
return Dictionary ( ) ;
}
2022-07-07 21:44:14 +02:00
String WebServer : : get_configuration_warning ( ) const {
int webnode_count = 0 ;
int session_manager_count = 0 ;
for ( int i = 0 ; i < get_child_count ( ) ; + + i ) {
2023-08-30 15:18:41 +02:00
WebNode * wn = Object : : cast_to < WebNode > ( get_child ( i ) ) ;
2022-07-07 21:44:14 +02:00
2023-08-30 15:18:41 +02:00
if ( wn ) {
+ + webnode_count ;
2022-07-07 21:44:14 +02:00
}
if ( ! _session_manager ) {
HTTPSessionManager * sm = Object : : cast_to < HTTPSessionManager > ( get_child ( i ) ) ;
if ( sm ) {
+ + session_manager_count ;
}
}
}
String err ;
if ( webnode_count = = 0 ) {
err + = " You need one (and only one) WebNode as the child for the webserver to work. (A WebRoot Node is recommended by default.) " ;
} else if ( webnode_count > 1 ) {
err + = " You have more than one root WebNode as the child of the server. Please move them under a new common WebNode, else the server will only use the first one! " ;
}
if ( session_manager_count > 1 ) {
if ( err ! = " " ) {
err + = " \n " ;
}
err + = " You have more than one HTTPSessionManager nodes as child, the server will only be able use the first one. Please remove the other. " ;
}
return err ;
2022-06-27 14:16:23 +02:00
}
2022-06-26 21:34:29 +02:00
WebServer : : WebServer ( ) {
2022-07-07 21:44:14 +02:00
_is_running = false ;
2022-06-25 01:55:54 +02:00
_web_root = nullptr ;
2022-07-07 21:44:14 +02:00
_session_manager = nullptr ;
2022-06-26 21:34:29 +02:00
_write_lock_requested = false ;
2022-07-07 21:44:14 +02:00
set_process_internal ( true ) ;
2022-06-25 01:55:54 +02:00
}
WebServer : : ~ WebServer ( ) {
}
2022-06-26 21:34:29 +02:00
2022-07-07 21:44:14 +02:00
void WebServer : : _notification ( int p_what ) {
if ( p_what = = NOTIFICATION_INTERNAL_PROCESS ) {
if ( _write_lock_requested ) {
_rw_lock . write_lock ( ) ;
notification ( NOTIFICATION_WEB_SERVER_WRITE_LOCK_ACQUIRED ) ;
//the root could have changed.
refresh_root ( ) ;
_rw_lock . write_unlock ( ) ;
2022-07-07 21:46:13 +02:00
_write_lock_requested = false ;
2022-07-07 21:44:14 +02:00
}
}
}
2022-06-26 21:34:29 +02:00
2022-07-07 21:44:14 +02:00
void WebServer : : _bind_methods ( ) {
2022-07-22 12:05:05 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_web_root " ) , & WebServer : : get_web_root ) ;
ClassDB : : bind_method ( D_METHOD ( " get_session_manager " ) , & WebServer : : get_session_manager ) ;
2022-06-26 21:34:29 +02:00
2022-06-27 01:03:01 +02:00
ClassDB : : bind_method ( D_METHOD ( " server_handle_request " , " request " ) , & WebServer : : server_handle_request ) ;
2022-06-26 21:34:29 +02:00
ClassDB : : bind_method ( D_METHOD ( " request_write_lock " ) , & WebServer : : request_write_lock ) ;
2022-06-27 14:16:23 +02:00
BIND_VMETHOD ( MethodInfo ( " _start " ) ) ;
BIND_VMETHOD ( MethodInfo ( " _stop " ) ) ;
ClassDB : : bind_method ( D_METHOD ( " start " ) , & WebServer : : start ) ;
ClassDB : : bind_method ( D_METHOD ( " stop " ) , & WebServer : : stop ) ;
ClassDB : : bind_method ( D_METHOD ( " _start " ) , & WebServer : : _start ) ;
ClassDB : : bind_method ( D_METHOD ( " _stop " ) , & WebServer : : _stop ) ;
2022-07-07 21:44:14 +02:00
2023-12-22 12:38:38 +01:00
BIND_VMETHOD ( MethodInfo ( Variant : : DICTIONARY , " _unregister_connection_for_request " ,
PropertyInfo ( Variant : : OBJECT , " request " , PROPERTY_HINT_RESOURCE_TYPE , " WebServerRequest " ) ) ) ;
ClassDB : : bind_method ( D_METHOD ( " unregister_connection_for_request " , " request " ) , & WebServer : : unregister_connection_for_request ) ;
ClassDB : : bind_method ( D_METHOD ( " _unregister_connection_for_request " , " request " ) , & WebServer : : _unregister_connection_for_request ) ;
2022-07-07 21:44:14 +02:00
BIND_CONSTANT ( NOTIFICATION_WEB_SERVER_STARTED ) ;
BIND_CONSTANT ( NOTIFICATION_WEB_SERVER_STOPPED ) ;
BIND_CONSTANT ( NOTIFICATION_WEB_SERVER_WRITE_LOCK_ACQUIRED ) ;
2022-06-26 21:34:29 +02:00
}