2020-11-03 19:09:17 +01:00
;********************************
;*
2020-12-01 15:17:48 +01:00
;* lweb.pbi
2020-11-03 19:09:17 +01:00
;*
2020-11-30 09:52:27 +01:00
;* LiHaSo Webserver Main module.
2020-11-03 19:09:17 +01:00
;*
2020-11-30 09:52:27 +01:00
;* It is usable as standalone Webserver, look at lwebd.pb
2020-11-03 19:09:17 +01:00
;*
2020-11-27 11:52:35 +01:00
XIncludeFile "ltls.pbi"
2020-12-01 15:17:48 +01:00
XIncludeFile "lsocket.pbi"
2020-11-27 11:52:35 +01:00
2020-11-03 19:09:17 +01:00
Module lhs_web
;********************************
;*
;* WebServer Variabeln / Parameter
;*
;{
2021-05-22 12:09:31 +02:00
;*
;* Configuration Structures
;*
;{
Structure server_http
enabled.i
port.i
binding.s
max_clients.i
EndStructure
Structure server_https
enabled.i
port.i
binding.s
max_clients.i
CA.s
Certs.s
key.s
key_pass.s
EndStructure
Structure server_cache
time.i
maxsize.i
current.i
enable.i
EndStructure
2022-02-17 13:23:42 +01:00
Structure memory
MaxFileSize.i
DefaultBlockSize.i
EndStructure
2021-05-25 10:05:41 +02:00
Structure log_config
2021-05-26 11:41:59 +02:00
Debuglog.s
Debugdisable.i
2021-05-25 10:05:41 +02:00
Accesslog.s
2021-05-26 11:41:59 +02:00
AccesslogUUID.s
2021-05-25 10:05:41 +02:00
Errorlog.s
2021-05-26 11:41:59 +02:00
ErrorlogUUID.s
2021-06-06 09:49:08 +02:00
Cachelog.s
CachelogUUID.s
2021-05-25 10:05:41 +02:00
EndStructure
2021-05-22 12:09:31 +02:00
Structure server
http.server_http
https.server_https
cache.server_cache
2021-05-25 10:05:41 +02:00
log.log_config
2022-02-17 13:23:42 +01:00
mem.memory
2021-05-22 12:09:31 +02:00
version.s
identifikation.s
defaultfile.s
basedir.s
error400.s
2022-02-18 16:05:48 +01:00
errorfile404.s
2021-05-22 12:09:31 +02:00
type.i
EndStructure
;}
;*
2020-11-03 19:09:17 +01:00
;*
;* Identifikation des Servers.
;*
2021-05-22 12:09:31 +02:00
Global configuration.server
configuration\version = "V0.9"
configuration\identifikation = "LiHaSo Webserver " + configuration\version
2020-11-03 19:09:17 +01:00
;*
;* Diese Parameter müssen entsprechend angepasst sein.
;* Später ausgelagert in ein nicht synchronisiertes lweb-cfg.pbi
;* Folgende Parameter müssen im Hauptprogramm definiert sein.
2021-05-22 12:09:31 +02:00
configuration\defaultfile = "index.html"
configuration\basedir = "/srv/lweb-srv/"
configuration\error400 = "integrated" ; Kann "integrated" sein wass die integrierte Standard Fehlermeldung hervorruft.
2022-02-18 16:05:48 +01:00
configuration\errorfile404 = "error.html"
2021-05-22 12:09:31 +02:00
configuration\type = 0
configuration\http\max_clients = 10 ; Max sametime HTTP connections.
configuration\http\port = 8080
configuration\http\binding = "127.0.0.1"
configuration\https\max_clients = 100
configuration\https\port = 8443
configuration\https\binding = "127.0.0.1"
configuration\https\enabled = 0
configuration\https\CA = ""
configuration\https\Certs = ""
configuration\https\key = ""
configuration\https\key_pass = ""
2022-02-17 13:23:42 +01:00
configuration\cache\enable = 0 ; Enable / Disable Cached Server
configuration\cache\time = 120 ; TTL of cached files
configuration\cache\maxsize = 1 ; Max Cache
configuration\cache\current = 0 ;
2022-02-17 14:20:25 +01:00
configuration\mem\MaxFileSize = 524288 ; Default 512 KiB
configuration\mem\DefaultBlockSize = 65536 ; Default Blocksize 64 KiB
2021-05-22 12:09:31 +02:00
2020-11-03 19:09:17 +01:00
2020-11-08 17:31:26 +01:00
Enumeration s_client_do ;client_do_cli
#CLI_DO_NOP ;Keine Arbeit
#CLI_DO_DataWorking ;Datenverarbeitung
#CLI_DO_DataToSend ;Daten zum Senden vorhanden
#CLI_DO_WaitDataReceive ;Wartet auf Datenempfang
#CLI_DO_WaitDataSend ;Wartet auf gesendete Daten
2020-11-03 19:09:17 +01:00
EndEnumeration
2020-11-08 17:31:26 +01:00
Enumeration s_server_do ;client_do_srv
#SRV_DO_NOP ;Keine Arbeit
#SRV_DO_NewDatainBuffer ;Neue Daten im incoming Buffer zur bearbeitung.
#SRV_DO_MoreDatainBuffer ;Weitere Daten im incoming Buffer
#SRV_DO_DataReceive ;Datem Empfangen Client Thread muss sich darum Kümmern
#SRV_DO_DataReceiveCompleted ;Empfang der Daten Abgeschlossen
#SRV_DO_DataReceiveFailes ;Beim Empfangen der Daten ist ein fehler passiert.
#SRV_DO_DataSendOK ;Daten erfolgreich gesendet, Thread kann weiterarbeiten.
#SRV_DO_DataSendNOK ;Daten nicht erfolgreich gesendet.
#SRV_DO_ClientDisconnect ;Beenden des Threads Client hat verbindung getrennt.
2020-11-03 19:09:17 +01:00
EndEnumeration
2020-12-01 08:53:53 +01:00
Enumeration e_type_client 1
#client_HTTP
#client_HTTPS
EndEnumeration
#client_add = 1
#client_remove = -1
2020-11-03 19:09:17 +01:00
#http_method_get = "GET"
#http_method_post = "POST"
2020-11-08 17:31:26 +01:00
#http_method_put = "PUT"
2020-11-03 19:09:17 +01:00
;***********************
;* s_lweb_client Struktur Jeder Clientthread muss in die Liste eingetragen werden.:
;*
;* client_id = Client ID von EventClient()
;* client_mutex = Client Thread Blockierer für den Hauptthread um gefahrenlos Daten in den Buffer Speichern zu können. (Vorsichtshalber drinn)
;* client_datenbuffer = 128KByte Speicherblock in diesen Speicher Schreibt nur der Hauptthread.
;* client_output_datenbuffer = 128KByte Speicherblock in diesen Speicher Schreibt nur der Clientthread.
;* client_datenbuffer = 128KByte Speicherblock für die Module achtung dieser Speicherblock wird unter umständen von den Modulen
;* vergrössert wird nach abgeschlossener Arbeit wieder auf Default gesetzt.
;*
Structure s_client_memory
2020-11-27 11:52:35 +01:00
*Buffer
2020-11-03 19:09:17 +01:00
Initialized.b
2020-11-08 01:31:57 +01:00
Size.i
2020-11-03 19:09:17 +01:00
EndStructure
Structure s_file_cache
2020-11-27 11:52:35 +01:00
*Buffer
2020-11-03 19:09:17 +01:00
Size.i
Timer.i
Is.i
EndStructure
Structure s_clients
client_id.i
client_do_cli.i
client_do_srv.i
2020-12-01 08:53:53 +01:00
client_type.i ;What type of Client.
2020-11-03 19:09:17 +01:00
client_mutex.i
client_thread.i
List datenbuffer.s_client_memory()
client_test_cli.i
client_test_srv.i
2020-11-27 11:52:35 +01:00
client_cctx.i
2020-11-03 19:09:17 +01:00
EndStructure
2020-11-08 01:31:57 +01:00
Structure s_request_handler
call.i
type.i
routetype.i
EndStructure
Enumeration cli_handler_infos 1
#get_handler_procedure ;Funktion die Aufgerufen werden muss
#get_handler_prototype ;Welcher Prototype
EndEnumeration
2020-11-28 16:49:22 +01:00
Global.i count_HTTP_client
Global.i count_HTTPS_client
Global.i server_HTTP_id
Global.i server_HTTPS_id
2020-11-03 19:09:17 +01:00
Global.i server_mutex = CreateMutex() ;Dieser Mutex dient zu der Sicherheit der Element Liste.
2020-12-01 08:53:53 +01:00
Global.i count_HTTP_mutex = CreateMutex()
Global.i count_HTTPS_mutex = CreateMutex()
2020-11-03 19:09:17 +01:00
Global.i file_cache_mutex = CreateMutex()
Global.i file_cache_semaphore = CreateSemaphore()
Global.i file_cache_semaphore_thread = CreateSemaphore()
Global NewMap m_file_cache_map.i()
Global NewMap m_file_cache.s_file_cache()
2021-05-22 12:09:31 +02:00
Global NewMap m_clients.s_clients(configuration\http\max_clients+configuration\https\max_clients)
2020-11-08 01:31:57 +01:00
Global NewMap m_request.s_request_handler()
2020-11-03 19:09:17 +01:00
;}
2020-11-08 01:31:57 +01:00
;********************************
;*
;* Handler Prototypen
;*
Prototype.s WebHandler_Get(Map handler_Map.s())
Prototype.s WebHandler_Post(Map handler_Map.s(), ContentString.s)
Prototype.s WebHandler_Universal(Map handler_Map.s(), ContentString.s)
2020-12-01 15:17:48 +01:00
;********************************
;*
;* Used Librarys
;*
XIncludeFile "inc/lweb_http_header.pbi"
XIncludeFile "inc/lweb_file_cache_header.pbi"
2020-11-03 19:09:17 +01:00
;********************************
;*
;* Proceduren Deklarierung
;*
2020-11-28 16:49:22 +01:00
Declare server_HTTP(network_server_id.i)
Declare server_HTTPS(network_server_id.i)
2020-11-03 19:09:17 +01:00
Declare client(network_client_id.i)
2022-02-18 16:05:48 +01:00
Declare.s file_check(thread_requested.s)
2020-11-08 01:31:57 +01:00
Declare call_request(RequestString.s, Info.i=#get_handler_procedure)
2020-12-01 15:17:48 +01:00
2021-05-21 07:45:23 +02:00
Declare.s Work_Post_ToJSON_multipart_form_data(ContentLength.i, MemorSize.i, Memory.i)
2020-11-08 01:31:57 +01:00
Declare.s Work_Post_ToJSON_x_www_form_urlencoded(ContentLength.i, MemorSize.i, Memory.i)
2020-12-01 08:53:53 +01:00
Declare count_client(Type.i, Countchange.i)
2020-11-03 19:09:17 +01:00
2020-12-01 15:17:48 +01:00
XIncludeFile "inc/lweb_IP.pbi"
XIncludeFile "inc/lweb_http.pbi"
XIncludeFile "inc/lweb_helper.pbi"
XIncludeFile "inc/lweb_file_cache.pbi"
2020-11-03 19:09:17 +01:00
Procedure set_config(parameter.i=#conf_defaultfile, setting.s="index.html")
Select parameter
2022-02-17 14:20:25 +01:00
Case #conf_File_BlockSize
configuration\mem\DefaultBlockSize = Val(setting)
Case #conf_File_max_in_Memory
configuration\mem\MaxFileSize = Val(setting)
2021-05-26 11:41:59 +02:00
Case #conf_Access_logfile
2021-05-25 10:05:41 +02:00
configuration\log\Accesslog = setting
2021-05-26 11:41:59 +02:00
Case #conf_Error_logfile
2021-05-25 10:05:41 +02:00
configuration\log\Errorlog = setting
2021-05-26 11:41:59 +02:00
Case #conf_Access_logUUID
configuration\log\AccesslogUUID = setting
Case #conf_Error_logUUID
configuration\log\ErrorlogUUID = setting
2021-06-06 09:49:08 +02:00
Case #conf_Cache_logUUID
configuration\log\CachelogUUID = setting
2021-05-26 11:41:59 +02:00
Case #conf_debug_logfile
configuration\log\Debuglog = setting
Case #conf_debug_disable
If setting = "true"
configuration\log\Debugdisable = #True
Else
configuration\log\Debugdisable = #False
EndIf
Case #conf_runfile
2020-11-30 10:04:29 +01:00
Case #conf_HTTP_port
2021-05-22 12:09:31 +02:00
configuration\http\port = Val(setting)
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_Port
2021-05-22 12:09:31 +02:00
configuration\https\port = Val(setting)
2020-11-30 10:04:29 +01:00
Case #conf_HTTP_binding
2020-11-03 19:09:17 +01:00
If IsIPStringValid(setting)
2021-05-22 12:09:31 +02:00
configuration\http\binding = setting
2020-11-03 19:09:17 +01:00
Else
2021-05-22 12:09:31 +02:00
configuration\http\binding = "127.0.0.1"
2020-11-03 19:09:17 +01:00
ProcedureReturn #False
EndIf
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_Binding
2020-11-27 11:52:35 +01:00
If IsIPStringValid(setting)
2021-05-22 12:09:31 +02:00
configuration\https\binding = setting
2020-11-27 11:52:35 +01:00
Else
2021-05-22 12:09:31 +02:00
configuration\https\binding = "127.0.0.1"
2020-11-27 11:52:35 +01:00
ProcedureReturn #False
EndIf
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_CA
2021-05-22 12:09:31 +02:00
configuration\https\CA = setting
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_Cert
2021-05-22 12:09:31 +02:00
configuration\https\Certs = setting
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_Key
2021-05-22 12:09:31 +02:00
configuration\https\Key = setting
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_Key_Pass
2021-05-22 12:09:31 +02:00
configuration\https\key_pass = setting
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_Enable
2021-05-22 12:09:31 +02:00
configuration\https\enabled = Val(setting)
2020-11-03 19:09:17 +01:00
Case #conf_defaultfile
2021-05-22 12:09:31 +02:00
configuration\defaultfile = setting
2020-11-03 19:09:17 +01:00
Case #conf_basedir
2021-05-22 12:09:31 +02:00
configuration\basedir = setting
2020-11-03 19:09:17 +01:00
Case #conf_error400
2021-05-22 12:09:31 +02:00
configuration\error400 = setting ; Kann "integrated" sein wass die integrierte Standard Fehlermeldung hervorruft.
2020-11-30 10:04:29 +01:00
Case #conf_max_HTTP_clients
2020-11-03 19:09:17 +01:00
If MemoryStatus(#PB_System_FreePhysical) > (Val(setting)*(1024*384))
2021-05-22 12:09:31 +02:00
configuration\http\max_clients = Val(setting)
2020-11-03 19:09:17 +01:00
Else
2021-05-22 12:09:31 +02:00
configuration\http\max_clients = 10
2020-11-03 19:09:17 +01:00
ProcedureReturn #False
EndIf
2020-11-30 10:04:29 +01:00
Case #conf_max_HTTPS_clients
If MemoryStatus(#PB_System_FreePhysical) > (Val(setting)*(1024*384))
2021-05-22 12:09:31 +02:00
configuration\https\max_clients = Val(setting)
2020-11-30 10:04:29 +01:00
Else
2021-05-22 12:09:31 +02:00
configuration\https\max_clients = 10
2020-11-30 10:04:29 +01:00
ProcedureReturn #False
EndIf
2020-11-03 19:09:17 +01:00
Case #conf_server_type
2021-05-22 12:09:31 +02:00
configuration\type = Val(setting)
2020-11-03 19:09:17 +01:00
Case #conf_cache_enable
2021-05-22 12:09:31 +02:00
configuration\cache\enable = Val(Setting)
2020-11-03 19:09:17 +01:00
Default
ProcedureReturn #False
EndSelect
ProcedureReturn #True
EndProcedure
Procedure.s get_config(parameter.i=#conf_defaultfile)
Select parameter
2022-02-17 14:20:25 +01:00
Case #conf_File_BlockSize
ProcedureReturn Str(configuration\mem\DefaultBlockSize)
Case #conf_File_max_in_Memory
ProcedureReturn Str(configuration\mem\MaxFileSize)
2021-05-26 11:41:59 +02:00
Case #conf_Access_logfile
ProcedureReturn configuration\log\Accesslog
Case #conf_Error_logfile
ProcedureReturn configuration\log\Errorlog
Case #conf_Access_logUUID
ProcedureReturn configuration\log\AccesslogUUID
Case #conf_Error_logUUID
ProcedureReturn configuration\log\ErrorlogUUID
Case #conf_debug_logfile
ProcedureReturn configuration\log\Debuglog
Case #conf_debug_disable
If configuration\log\Debugdisable = #True
ProcedureReturn "true"
Else
ProcedureReturn "false"
EndIf
2020-11-03 19:09:17 +01:00
Case #conf_defaultfile
2021-05-22 12:09:31 +02:00
ProcedureReturn configuration\defaultfile
2020-11-03 19:09:17 +01:00
Case #conf_basedir
2021-05-22 12:09:31 +02:00
ProcedureReturn configuration\basedir
2020-11-03 19:09:17 +01:00
Case #conf_error400
2021-05-22 12:09:31 +02:00
ProcedureReturn configuration\error400
2020-11-30 10:04:29 +01:00
Case #conf_max_HTTP_clients
2021-05-22 12:09:31 +02:00
ProcedureReturn Str(configuration\http\max_clients)
2020-11-03 19:09:17 +01:00
Case #conf_server_type
2021-05-22 12:09:31 +02:00
ProcedureReturn Str(configuration\type)
2020-11-30 10:04:29 +01:00
Case #conf_HTTP_port
2021-05-22 12:09:31 +02:00
ProcedureReturn Str(configuration\http\port)
2020-11-28 16:49:22 +01:00
Case #conf_HTTPS_Port
2021-05-22 12:09:31 +02:00
ProcedureReturn Str(configuration\https\port)
2020-11-03 19:09:17 +01:00
Default
ProcedureReturn ""
EndSelect
EndProcedure
Procedure start_server()
2021-05-22 12:09:31 +02:00
Global NewMap m_clients.s_clients(configuration\http\max_clients+configuration\https\max_clients)
2020-11-27 11:52:35 +01:00
Protected tlsresponse.i
2021-05-26 11:41:59 +02:00
If configuration\log\Debugdisable
lhs_log::Disable()
EndIf
2020-11-27 11:52:35 +01:00
2020-11-28 16:49:22 +01:00
;Init HTTP Socket
2021-05-22 12:09:31 +02:00
server_HTTP_id = lsocket::CreateSocket(configuration\http\port, configuration\http\max_clients, lsocket::#SOCK_STREAM, lsocket::#AF_INET, configuration\http\binding)
If configuration\https\enabled = 1
server_HTTPS_id = lsocket::CreateSocket(configuration\https\port, configuration\https\max_clients, lsocket::#SOCK_STREAM, lsocket::#AF_INET, configuration\https\binding)
2020-11-28 16:49:22 +01:00
If server_HTTPS_id
2021-05-22 12:09:31 +02:00
tlsresponse = ltls::InitSimpleTLS(configuration\https\CA, configuration\https\Certs, configuration\https\key, configuration\https\key_pass)
2020-11-27 11:52:35 +01:00
If tlsresponse > 0
2020-11-28 16:49:22 +01:00
CreateThread(@server_HTTPS(), server_HTTPS_id)
2020-11-27 11:52:35 +01:00
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("TLS Fehler:"+Str(tlsresponse))
2020-11-27 11:52:35 +01:00
ProcedureReturn #False
EndIf
Else
ProcedureReturn #False
EndIf
EndIf
2020-11-28 16:49:22 +01:00
If server_HTTP_id
CreateThread(@server_HTTP(), server_HTTP_id)
2020-11-03 19:09:17 +01:00
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
2020-11-28 16:49:22 +01:00
Procedure server_HTTPS(network_server_id.i)
2020-11-27 11:52:35 +01:00
;**************************
;*
2020-11-28 16:49:22 +01:00
;* Main thread for HTTPS networksocket management. Create the Client Threads.
2020-11-27 11:52:35 +01:00
;*
Protected.i client_id
thread_alive = #True
2021-05-21 07:45:23 +02:00
lhs_log::Out("HTTPS Server Started.")
2020-11-27 11:52:35 +01:00
Repeat
client_id = ltls::WaitTLSSocket(network_server_id)
2021-05-21 07:45:23 +02:00
lhs_log::Out("New HTTPS Client:"+Str(client_id))
2020-11-27 11:52:35 +01:00
If client_id > 0
2020-12-04 21:03:03 +01:00
If m_clients(Str(client_id))\client_id = client_id
2021-05-21 07:45:23 +02:00
lhs_log::Out("Client Thread for socket already exist :"+Str(client_id))
2020-11-27 11:52:35 +01:00
Else
2021-05-22 12:09:31 +02:00
If count_HTTPS_client < configuration\https\max_clients
2020-12-04 21:03:03 +01:00
m_clients(Str(client_id))\client_id = client_id
m_clients(Str(client_id))\client_do_cli = #CLI_DO_WaitDataReceive
m_clients(Str(client_id))\client_do_srv = #SRV_DO_DataReceive
m_clients(Str(client_id))\client_type = #client_HTTPS
;Thread erstellen
m_clients(Str(client_id))\client_thread = CreateThread(@client(), client_id)
count_client(#client_HTTPS, #client_add)
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("Max HTTPS Clients reached...")
2020-12-04 21:03:03 +01:00
ltls::CloseTLSSocket(client_id)
EndIf
EndIf
2020-11-27 11:52:35 +01:00
Else
Break
EndIf
ForEver
2020-11-28 10:42:10 +01:00
ltls::CloseTLS(network_server_id)
2020-11-27 11:52:35 +01:00
EndProcedure
2020-11-28 16:49:22 +01:00
Procedure server_HTTP(network_server_id.i)
2020-11-03 19:09:17 +01:00
;**************************
;*
2020-11-28 16:49:22 +01:00
;* Main thread for HTTP networksocket management. Create the Client Threads.
2020-11-03 19:09:17 +01:00
;*
2020-11-28 16:49:22 +01:00
Protected.i client_id
2020-11-03 19:09:17 +01:00
thread_alive = #True
2020-11-28 16:49:22 +01:00
2021-05-21 07:45:23 +02:00
lhs_log::Out("HTTP Server Started.")
2020-11-03 19:09:17 +01:00
Repeat
2020-11-28 16:49:22 +01:00
client_id = lsocket::WaitSocket(network_server_id)
2021-05-21 07:45:23 +02:00
lhs_log::Out("New HTTP Client:"+Str(client_id))
2020-11-28 16:49:22 +01:00
If client_id > 0
2020-12-04 21:03:03 +01:00
If m_clients(Str(client_id))\client_id = client_id
2021-05-21 07:45:23 +02:00
lhs_log::Out("Client Thread for socket already exist :"+Str(client_id))
2020-11-28 16:49:22 +01:00
Else
2021-05-22 12:09:31 +02:00
If count_HTTP_client < configuration\http\max_clients
2020-12-04 21:03:03 +01:00
m_clients(Str(client_id))\client_id = client_id
m_clients(Str(client_id))\client_do_cli = #CLI_DO_WaitDataReceive
m_clients(Str(client_id))\client_do_srv = #SRV_DO_DataReceive
m_clients(Str(client_id))\client_type = #client_HTTP
;Thread erstellen
m_clients(Str(client_id))\client_thread = CreateThread(@client(), client_id)
count_client(#client_HTTP, #client_add)
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("Max HTTP Clients reached...")
2020-12-04 21:03:03 +01:00
lsocket::CloseSocket(client_id)
EndIf
EndIf
2020-11-28 16:49:22 +01:00
Else
Break
EndIf
ForEver
2020-11-03 19:09:17 +01:00
EndProcedure
Procedure client(network_client_id.i)
2020-11-27 11:52:35 +01:00
Protected thread_cli_id = network_client_id, sent
2020-11-08 23:26:35 +01:00
Protected MyThreadJSON, ToCall, ToCallType
Protected thread_temp_cache.s, thread_temp_cache_memory, temp_receivelength, thread_temp_decode_memory
2022-02-17 13:23:42 +01:00
Protected thread_reasign, thread_oversized_file.b, thread_data_to_read.i, thread_data_readed.i
2020-11-08 01:31:57 +01:00
Protected thread_data_size, thread_file_handle
Protected.s thread_requested, thread_type, thread_date, thread_header, thread_work, JSONStringToMap, Handler_Response, response_status, PostMapString
2020-11-03 19:09:17 +01:00
Protected thread_buffer, thread_buffer_offset, thread_buffer_length, buffer_sent
2020-11-27 21:43:38 +01:00
Protected sent_length, sent_buffer_address, sent_total
2022-02-18 16:05:48 +01:00
Protected.b thread_alive = #True, error_message = #False, thread_redirect = #False
2020-11-03 19:09:17 +01:00
Define NewMap Header.s()
2020-11-08 01:31:57 +01:00
Define NewMap Response.s()
Define NewMap Post.s()
2020-12-01 08:53:53 +01:00
2021-05-21 07:45:23 +02:00
lhs_log::Out("Client Thread Started. ID:" + Str(network_client_id))
2020-11-03 19:09:17 +01:00
Repeat
;Prüfen ob der Thread was zu tun hat.
;{ Main Server Triggered Things
Select m_clients(Str(thread_cli_id))\client_do_srv
Case #SRV_DO_NOP
;Ressourcen freigeben und Threadzeit reduzieren
Delay(1)
Case #SRV_DO_DataReceive
LastElement(m_clients(Str(thread_cli_id))\datenbuffer())
AddElement(m_clients(Str(thread_cli_id))\datenbuffer())
m_clients(Str(thread_cli_id))\datenbuffer()\Buffer = AllocateMemory(131072)
If m_clients(Str(thread_cli_id))\datenbuffer()\Buffer
m_clients(Str(thread_cli_id))\datenbuffer()\Initialized = #True
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("Buffer Initialisierung fehlgeschlagen.")
2020-11-03 19:09:17 +01:00
Break
EndIf
2020-12-01 08:53:53 +01:00
If m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
2020-11-27 11:52:35 +01:00
temp_receivelength = ltls::ReadTLSSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
Else
2020-11-28 16:49:22 +01:00
temp_receivelength = lsocket::ReadSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
2020-11-27 11:52:35 +01:00
EndIf
2020-11-03 19:09:17 +01:00
If temp_receivelength = -1
2021-05-21 07:45:23 +02:00
lhs_log::Out("Empfangsfehler.")
2020-11-03 19:09:17 +01:00
Break
ElseIf temp_receivelength = 65536
2020-11-08 01:31:57 +01:00
m_clients(Str(thread_cli_id))\datenbuffer()\Size = temp_receivelength
2020-11-03 19:09:17 +01:00
counter_mem_buffers = 2
Repeat
AddElement(m_clients(Str(thread_cli_id))\datenbuffer())
m_clients(Str(thread_cli_id))\datenbuffer()\Buffer = AllocateMemory(131072)
If m_clients(Str(thread_cli_id))\datenbuffer()\Buffer
m_clients(Str(thread_cli_id))\datenbuffer()\Initialized = #True
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("Buffer Initialisierung fehlgeschlagen.")
2020-11-03 19:09:17 +01:00
Break 2
EndIf
2020-12-01 08:53:53 +01:00
If m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
2020-11-27 11:52:35 +01:00
temp_receivelength = ltls::ReadTLSSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
Else
2020-11-28 16:49:22 +01:00
temp_receivelength = lsocket::ReadSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
2020-11-27 11:52:35 +01:00
EndIf
2020-11-08 01:31:57 +01:00
m_clients(Str(thread_cli_id))\datenbuffer()\Size = temp_receivelength
2020-11-03 19:09:17 +01:00
counter_mem_buffers + 1
If temp_receivelength = -1
Break 2
EndIf
Until temp_receivelength < 65536
2020-11-08 01:31:57 +01:00
Else
m_clients(Str(thread_cli_id))\datenbuffer()\Size = temp_receivelength
2020-11-03 19:09:17 +01:00
EndIf
;Alle Daten empfangen.
2021-05-21 07:45:23 +02:00
lhs_log::Out("Anzahl Buffer:" + Str(ListSize(m_clients(Str(thread_cli_id))\datenbuffer())))
2020-11-03 19:09:17 +01:00
m_clients(Str(thread_cli_id))\client_do_srv = #SRV_DO_NOP
m_clients(Str(thread_cli_id))\client_do_cli = #CLI_DO_DataWorking
Case #SRV_DO_ClientDisconnect
;Thread beenden
2021-05-21 07:45:23 +02:00
lhs_log::Out("#SRV_DO_ClientDisconnect")
2020-11-03 19:09:17 +01:00
thread_alive = #False
;* Alles IO
Default
;Ressourcen freigeben und Threadzeit reduzieren
Delay(1)
2021-05-21 07:45:23 +02:00
lhs_log::Out("--------------------------------------------------------- FAILING ???")
2020-11-03 19:09:17 +01:00
EndSelect
;}
;{ Client Side Triggered Things
If thread_alive = #True
Select m_clients(Str(thread_cli_id))\client_do_cli
Case #CLI_DO_DataWorking
2021-04-29 09:41:41 +02:00
;Receive done.
;Do Buffer work
;Change Thread to Work mode.
2020-11-08 01:31:57 +01:00
2020-11-03 19:09:17 +01:00
;{
2021-05-22 12:09:31 +02:00
lhs_log::Out("Data received, working...")
2020-11-03 19:09:17 +01:00
m_clients(Str(thread_cli_id))\client_do_cli = #CLI_DO_DataWorking
2021-04-29 09:41:41 +02:00
;Work on Answer.
2020-11-03 19:09:17 +01:00
ResetList(m_clients(Str(thread_cli_id))\datenbuffer())
2021-04-29 09:41:41 +02:00
;TODO: Only first Buffer have a Header.
2020-11-03 19:09:17 +01:00
While NextElement(m_clients(Str(thread_cli_id))\datenbuffer())
2020-11-08 01:31:57 +01:00
thread_work = PeekS(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, m_clients(Str(thread_cli_id))\datenbuffer()\Size, #PB_Ascii)
2021-04-29 09:41:41 +02:00
;Move Header to Map
2020-11-03 19:09:17 +01:00
JSONStringToMap = Work_Header_to_JSONMap(thread_work)
If JSONStringToMap <> #error_string
MyThreadJSON = ParseJSON(#PB_Any, JSONStringToMap)
If MyThreadJSON
ClearMap(Header())
ExtractJSONMap(JSONValue(MyThreadJSON), Header())
FreeJSON(MyThreadJSON)
Else
2021-04-29 09:41:41 +02:00
;Should not be a case.
Break 2 ; Kill Thread.
2020-11-03 19:09:17 +01:00
EndIf
Else
error_message = #True
EndIf
2021-05-21 07:45:23 +02:00
;lhs_log::Out("JSONString:"+ JSONStringToMap)
2020-11-08 01:31:57 +01:00
thread_type = ""
2021-05-26 11:41:59 +02:00
If configuration\log\AccesslogUUID <> ""
2021-05-25 10:05:41 +02:00
If m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
2021-05-26 11:41:59 +02:00
lhs_log_ext::Out(configuration\log\AccesslogUUID, lsocket::GetSocketIP(ltls::GetSocket(thread_cli_id)) + " " + Header(#http_head_method) + " " + Header(#http_head_request))
2021-05-25 10:05:41 +02:00
Else
2021-05-26 11:41:59 +02:00
lhs_log_ext::Out(configuration\log\AccesslogUUID, lsocket::GetSocketIP(thread_cli_id) + " " + Header(#http_head_method) + " " + Header(#http_head_request))
2021-05-25 10:05:41 +02:00
EndIf
EndIf
2020-11-08 01:31:57 +01:00
Select Header(#http_head_method)
Case #http_method_get
;********************************
;*
;* Default GET
;*
;{
2021-05-21 07:45:23 +02:00
lhs_log::Out(#http_method_get)
2022-02-18 16:05:48 +01:00
2020-11-08 01:31:57 +01:00
If Header(#http_head_request) = "/"
2021-05-22 12:09:31 +02:00
thread_requested = configuration\defaultfile
2020-11-08 01:31:57 +01:00
Else
thread_requested = Header(#http_head_request)
EndIf
2022-02-18 16:05:48 +01:00
2021-05-21 07:45:23 +02:00
lhs_log::Out("Requested:"+thread_requested)
2020-11-08 01:31:57 +01:00
ToCallType = call_request(thread_requested, #get_handler_prototype)
If ToCallType = #handler_proto_universal Or ToCallType = #handler_proto_get
ToCall = call_request(thread_requested)
Else
ToCall = 0
EndIf
2022-02-18 16:05:48 +01:00
If ToCall = 0
If Right(thread_requested,1) = "/"
thread_requested = thread_requested+configuration\defaultfile
Else
thread_requested = thread_requested
EndIf
EndIf
2020-11-08 01:31:57 +01:00
If ToCall > 0 ;Dann ist eine Funktion hinterlegt und zulässig aufgerufen zu werden.
;{ Dynamischer WebHandler
Select ToCallType
Case #handler_proto_universal
Define.WebHandler_Universal ToCallProcedure = ToCall
Handler_Response = ToCallProcedure(Header(), "")
Case #handler_proto_get
2022-02-17 13:23:42 +01:00
Define.WebHandler_Get ToCallProcedureGet = ToCall
Handler_Response = ToCallProcedureGet(Header())
2020-11-08 01:31:57 +01:00
EndSelect
2021-05-21 07:45:23 +02:00
lhs_log::Out("Main Client Response :"+Handler_Response)
2020-11-08 01:31:57 +01:00
MyThreadJSON = ParseJSON(#PB_Any, Handler_Response)
If MyThreadJSON
ClearMap(Response())
ExtractJSONMap(JSONValue(MyThreadJSON), Response())
FreeJSON(MyThreadJSON)
2020-11-03 19:09:17 +01:00
Else
2020-11-08 01:31:57 +01:00
;WTF ???
2021-05-21 07:45:23 +02:00
lhs_log::Out("Fehler Absturz")
2020-11-08 01:31:57 +01:00
Break 2 ; Thread abschiessen
EndIf
2021-05-21 07:45:23 +02:00
lhs_log::Out("Response Content:"+Response(#cha_R_ResponseContentType))
2020-11-08 01:31:57 +01:00
Select Response(#cha_R_ResponseContentType)
Case #response_Memory
2021-05-21 07:45:23 +02:00
lhs_log::Out("Response Memory")
2020-11-08 01:31:57 +01:00
thread_data_size = Val(Response(#cha_R_MemorySize))
thread_temp_cache_memory = Val(Response(#cha_R_MemoryAdress))
thread_type = Response(#cha_R_ResponseType)
Case #response_string
2021-05-21 07:45:23 +02:00
lhs_log::Out("Response String")
2020-11-08 01:31:57 +01:00
thread_temp_decode_memory = AllocateMemory(StringByteLength(Response(#cha_R_StringBase64)))
thread_data_size = Base64Decoder(Response(#cha_R_StringBase64), thread_temp_decode_memory, StringByteLength(Response(#cha_R_StringBase64)))
thread_temp_cache_memory = AllocateMemory(thread_data_size)
CopyMemory(thread_temp_decode_memory, thread_temp_cache_memory, thread_data_size)
FreeMemory(thread_temp_decode_memory)
thread_type = Response(#cha_R_ResponseType)
Default
;Solte ja nicht passieren.
EndSelect
2021-05-21 07:45:23 +02:00
lhs_log::Out("Content Finished")
2020-11-08 01:31:57 +01:00
;}
2021-05-22 12:09:31 +02:00
ElseIf configuration\cache\enable = 1
2020-11-08 01:31:57 +01:00
;{ Cached File Handling BUGGY!!!!!!!
thread_temp_cache_memory = AllocateMemory(1024)
thread_temp_cache = GetFileFromCache(thread_requested, thread_temp_cache_memory)
If thread_temp_cache = #error_string
2021-05-22 12:09:31 +02:00
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + thread_requested,#PB_File_SharedRead)
2020-11-08 01:31:57 +01:00
If thread_file_handle
;Alles Ok
Else
2021-05-22 12:09:31 +02:00
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + configuration\defaultfile,#PB_File_SharedRead)
lhs_log::Out("FileDir:" + configuration\basedir + configuration\defaultfile)
2020-11-08 01:31:57 +01:00
If Not thread_file_handle
thread_file_handle = ReadFile(#PB_Any, "error.html")
EndIf
2020-11-03 19:09:17 +01:00
EndIf
2020-11-08 01:31:57 +01:00
thread_data_size = Lof(thread_file_handle)
thread_temp_cache_memory = ReAllocateMemory(thread_temp_cache_memory, thread_data_size)
ReadData(thread_file_handle, thread_temp_cache_memory, thread_data_size)
CloseFile(thread_file_handle)
AddFileToCache(thread_temp_cache_memory, thread_requested, thread_data_size)
2020-11-03 19:09:17 +01:00
2020-11-08 01:31:57 +01:00
Else
thread_data_size = Val(StringField(thread_temp_cache, 1, ":"))
thread_temp_cache_memory = Val(StringField(thread_temp_cache, 2, ":"))
2020-11-03 19:09:17 +01:00
EndIf
2020-11-08 01:31:57 +01:00
;}
2020-11-03 19:09:17 +01:00
Else
2020-11-30 09:52:27 +01:00
;{ Uncached file sems to be stable tested up to 200 clients and 100 requests.
2022-02-18 16:05:48 +01:00
If file_check(thread_requested) = thread_requested
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + thread_requested,#PB_File_SharedRead)
If Not thread_file_handle
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + configuration\defaultfile,#PB_File_SharedRead)
lhs_log::Out("FileDir:" + configuration\basedir + configuration\defaultfile)
If Not thread_file_handle
lhs_log::Out("Error file set")
thread_file_handle = ReadFile(#PB_Any, "error.html")
EndIf
EndIf
thread_data_size = Lof(thread_file_handle)
; Is File bigger than MaxFileSize in Memory allowed ?
If thread_data_size >= configuration\mem\MaxFileSize
;Do Handle the File another way.
thread_temp_cache_memory = AllocateMemory(configuration\mem\MaxFileSize)
thread_temp_file_readed = configuration\mem\DefaultBlockSize
thread_data_readed = ReadData(thread_file_handle, thread_temp_cache_memory, thread_temp_file_readed)
thread_data_to_read = thread_data_size - thread_data_readed
thread_oversized_file = #True
Else
thread_temp_cache_memory = AllocateMemory(thread_data_size)
ReadData(thread_file_handle, thread_temp_cache_memory, thread_data_size)
CloseFile(thread_file_handle)
thread_oversized_file = #False
EndIf
2022-02-17 13:23:42 +01:00
Else
2022-02-18 16:05:48 +01:00
thread_redirect = #True
2022-02-17 13:23:42 +01:00
EndIf
2020-11-08 01:31:57 +01:00
;}
2020-11-03 19:09:17 +01:00
EndIf
2020-11-08 01:31:57 +01:00
;}
Case #http_method_post
2020-11-03 19:09:17 +01:00
2020-11-08 01:31:57 +01:00
;********************************
;*
;* POST
;*
2021-05-21 07:45:23 +02:00
;* Current Finaly Implementet is only application/x-www-form-urlencoded
;* Error Handling must be Optimized.
;*
lhs_log::Out(#http_method_post)
;{ POST Content Type Decoder
2020-11-08 01:31:57 +01:00
If LCase(Header(#http_head_content_type)) = #http_content_type_application_x_www_form_urlencoded
PostMapString = Work_Post_ToJSON_x_www_form_urlencoded(Val(Header(#http_head_content_length)), m_clients(Str(thread_cli_id))\datenbuffer()\Size, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)
MyThreadJSON = ParseJSON(#PB_Any, PostMapString)
If MyThreadJSON
ClearMap(Post())
ExtractJSONMap(JSONValue(MyThreadJSON), Post())
FreeJSON(MyThreadJSON)
Else
2020-11-30 09:52:27 +01:00
;Should not be possible.
2021-05-21 07:45:23 +02:00
lhs_log::Out("Error in thread, JSON Convert didn't Work")
2020-11-30 09:52:27 +01:00
Break 2 ; Kill Thread
2020-11-08 01:31:57 +01:00
EndIf
2021-05-21 07:45:23 +02:00
ElseIf Left(LCase(Header(#http_head_content_type)), Len(#http_content_type_multipart_form_data)) = #http_content_type_multipart_form_data
PostMapString = Work_Post_ToJSON_multipart_form_data(Val(Header(#http_head_content_length)), m_clients(Str(thread_cli_id))\datenbuffer()\Size, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)
MyThreadJSON = ParseJSON(#PB_Any, PostMapString)
If MyThreadJSON
ClearMap(Post())
ExtractJSONMap(JSONValue(MyThreadJSON), Post())
FreeJSON(MyThreadJSON)
Else
;Someting wrong in the POST
lhs_log::Out("Error with Content. JSON Convert didn't Work")
Break 2; Kill Thread
EndIf
2020-11-03 19:09:17 +01:00
EndIf
2021-05-21 07:45:23 +02:00
;}
2020-11-03 19:09:17 +01:00
2020-11-08 01:31:57 +01:00
If Header(#http_head_request) = "/"
2021-05-22 12:09:31 +02:00
thread_requested = configuration\defaultfile
2020-11-08 01:31:57 +01:00
Else
thread_requested = Header(#http_head_request)
EndIf
2021-05-21 07:45:23 +02:00
lhs_log::Out("Requested:"+thread_requested)
2020-11-08 01:31:57 +01:00
ToCallType = call_request(thread_requested, #get_handler_prototype)
If ToCallType = #handler_proto_universal Or ToCallType = #handler_proto_post
ToCall = call_request(thread_requested)
Else
ToCall = 0
EndIf
2020-11-03 19:09:17 +01:00
2020-11-30 09:52:27 +01:00
If ToCall > 0 ;A dynamic webhandler is available, call.
;{ Dynamic webhandler.
2020-11-08 01:31:57 +01:00
Select ToCallType
Case #handler_proto_universal
Define.WebHandler_Universal ToCallProcedure = ToCall
Handler_Response = ToCallProcedure(Header(), PostMapString )
Case #handler_proto_post
Define.WebHandler_Post ToCallProcedure = ToCall
Handler_Response = ToCallProcedure(Header(), PostMapString)
EndSelect
2021-05-21 07:45:23 +02:00
lhs_log::Out("Main Client Response :"+Handler_Response)
2020-11-08 01:31:57 +01:00
MyThreadJSON = ParseJSON(#PB_Any, Handler_Response)
If MyThreadJSON
ClearMap(Response())
ExtractJSONMap(JSONValue(MyThreadJSON), Response())
FreeJSON(MyThreadJSON)
Else
;WTF ???
2021-05-21 07:45:23 +02:00
lhs_log::Out("Fehler Absturz")
2020-11-08 01:31:57 +01:00
Break 2 ; Thread abschiessen
EndIf
2021-05-21 07:45:23 +02:00
lhs_log::Out("Response Content:"+Response(#cha_R_ResponseContentType))
2020-11-08 01:31:57 +01:00
Select Response(#cha_R_ResponseContentType)
Case #response_Memory
thread_data_size = Val(Response(#cha_R_MemorySize))
thread_temp_cache_memory = Val(Response(#cha_R_MemoryAdress))
thread_type = Response(#cha_R_ResponseType)
Case #response_string
thread_temp_decode_memory = AllocateMemory(StringByteLength(Response(#cha_R_StringBase64)))
thread_data_size = Base64Decoder(Response(#cha_R_StringBase64), thread_temp_decode_memory, StringByteLength(Response(#cha_R_StringBase64)))
thread_temp_cache_memory = AllocateMemory(thread_data_size)
CopyMemory(thread_temp_decode_memory, thread_temp_cache_memory, thread_data_size)
FreeMemory(thread_temp_decode_memory)
thread_type = Response(#cha_R_ResponseType)
Default
;Solte ja nicht passieren.
EndSelect
2021-05-21 07:45:23 +02:00
lhs_log::Out("Content Finished")
2020-11-08 01:31:57 +01:00
;}
ElseIf conf_cache_enable = 1
;{ Cached File Handling BUGGY!!!!!!!
thread_temp_cache_memory = AllocateMemory(1024)
thread_temp_cache = GetFileFromCache(thread_requested, thread_temp_cache_memory)
If thread_temp_cache = #error_string
2021-05-22 12:09:31 +02:00
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + thread_requested,#PB_File_SharedRead)
2020-11-08 01:31:57 +01:00
If thread_file_handle
;Alles Ok
Else
2021-05-22 12:09:31 +02:00
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + configuration\defaultfile,#PB_File_SharedRead)
lhs_log::Out("FileDir:" + configuration\basedir + configuration\defaultfile)
2020-11-08 01:31:57 +01:00
If Not thread_file_handle
thread_file_handle = ReadFile(#PB_Any, "error.html")
EndIf
EndIf
thread_data_size = Lof(thread_file_handle)
thread_temp_cache_memory = ReAllocateMemory(thread_temp_cache_memory, thread_data_size)
ReadData(thread_file_handle, thread_temp_cache_memory, thread_data_size)
CloseFile(thread_file_handle)
AddFileToCache(thread_temp_cache_memory, thread_requested, thread_data_size)
Else
thread_data_size = Val(StringField(thread_temp_cache, 1, ":"))
thread_temp_cache_memory = Val(StringField(thread_temp_cache, 2, ":"))
EndIf
;}
Else
2020-11-30 09:52:27 +01:00
;{ Uncached file sems to be stable tested up to 200 clients and 100 requests.
2022-02-18 16:05:48 +01:00
If file_check(thread_requested) = thread_requested
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + thread_requested,#PB_File_SharedRead)
If Not thread_file_handle
thread_file_handle = ReadFile(#PB_Any, configuration\basedir + configuration\defaultfile,#PB_File_SharedRead)
lhs_log::Out("FileDir:" + configuration\basedir + configuration\defaultfile)
If Not thread_file_handle
lhs_log::Out("Error file set")
thread_file_handle = ReadFile(#PB_Any, "error.html")
EndIf
EndIf
2020-11-08 01:31:57 +01:00
2022-02-18 16:05:48 +01:00
thread_data_size = Lof(thread_file_handle)
; Is File bigger than MaxFileSize in Memory allowed ?
If thread_data_size >= configuration\mem\MaxFileSize
;Do Handle the File another way.
thread_temp_cache_memory = AllocateMemory(configuration\mem\MaxFileSize)
thread_temp_file_readed = configuration\mem\DefaultBlockSize
thread_data_readed = ReadData(thread_file_handle, thread_temp_cache_memory, thread_temp_file_readed)
thread_data_to_read = thread_data_size - thread_data_readed
thread_oversized_file = #True
Else
thread_temp_cache_memory = AllocateMemory(thread_data_size)
ReadData(thread_file_handle, thread_temp_cache_memory, thread_data_size)
CloseFile(thread_file_handle)
thread_oversized_file = 0
EndIf
2022-02-17 13:23:42 +01:00
Else
2022-02-18 16:05:48 +01:00
;Send Redirect:
thread_redirect = #True
2022-02-17 13:23:42 +01:00
EndIf
2020-11-08 01:31:57 +01:00
2022-02-18 16:05:48 +01:00
;}
2020-11-08 01:31:57 +01:00
EndIf
2020-11-08 17:31:26 +01:00
2022-02-18 16:05:48 +01:00
2020-11-08 01:31:57 +01:00
Default
;************************************
;*
;* Not a supported Command in HTTP Header Cleanup.
;*
;* Read Buffer to Memory and Clear Buffer to Zero until the complete Networkbuffer from this Client is Cleaned.
;*
EndSelect
2022-02-18 16:05:48 +01:00
If thread_data_size Or thread_redirect = #True
If thread_type = ""
2020-11-08 17:31:26 +01:00
thread_type = mimetype(GetExtensionPart(thread_requested))
EndIf
thread_date = http_day(DayOfWeek(Date())) +
Str(Day(Date())) +
http_month(Month(Date())) +
Str(Year(Date())) +
" " +
FormatDate("%hh:%ii:%ss GMT+1", Date())
ClearMap(Header())
If Response(#cha_R_http_head_status) <> ""
Header(#http_head_status) = Response(#cha_R_http_head_status)
ElseIf response_status <> ""
Header(#http_head_status) = response_status
Else
Header(#http_head_status) = "200 OK"
EndIf
2020-12-10 16:37:17 +01:00
If Response(#http_head_set_cookie) <> ""
Header(#http_head_set_cookie) = Response(#http_head_set_cookie)
EndIf
2022-02-18 16:05:48 +01:00
If thread_redirect = #True
Header(#http_head_redirect) = file_check(thread_requested)
Header(#http_head_status) = "303 See Other"
Else
Header(#http_head_content_length) = Str(thread_data_size)
Header(#http_head_content_type) = thread_type
EndIf
2020-11-08 17:31:26 +01:00
Header(#http_head_connection) = "Keep-Alive"
Header(#http_head_keep_alive) = "timeout=15, max=1000"
thread_header = http_header_generate(Header())
2022-02-17 13:23:42 +01:00
;large File Handling
2022-02-18 16:05:48 +01:00
If thread_redirect = #True
thread_buffer = AllocateMemory(StringByteLength(thread_header)+12)
ElseIf thread_oversized_file = #False
2022-02-17 13:23:42 +01:00
thread_buffer = AllocateMemory(thread_data_size+StringByteLength(thread_header)+12)
Else
thread_buffer = AllocateMemory(thread_temp_file_readed+StringByteLength(thread_header)+12)
EndIf
2020-11-08 17:31:26 +01:00
thread_buffer_offset = thread_buffer
thread_buffer_length = PokeS(thread_buffer_offset, thread_header,-1, #PB_UTF8|#PB_String_NoZero) : thread_buffer_offset + thread_buffer_length
2021-05-21 07:45:23 +02:00
lhs_log::Out("Header Finished")
2020-11-08 17:31:26 +01:00
EndIf
2022-02-17 13:23:42 +01:00
;Copy temporary File Buffer to normal Buffer.
2022-02-18 16:05:48 +01:00
If thread_temp_cache_memory <> 0 And thread_buffer_offset <> 0 And thread_data_size <> 0 And thread_oversized_file = #False And thread_redirect = #False
2020-11-27 21:43:38 +01:00
CopyMemory(thread_temp_cache_memory, thread_buffer_offset, thread_data_size)
2022-02-17 13:23:42 +01:00
lhs_log::Out("Cache Address Memory:"+Str(thread_temp_cache_memory))
2020-11-27 21:43:38 +01:00
FreeMemory(thread_temp_cache_memory)
2022-02-17 13:23:42 +01:00
thread_temp_cache_memory = 0
2022-02-18 16:05:48 +01:00
ElseIf thread_temp_cache_memory <> 0 And thread_buffer_offset <> 0 And thread_data_size <> 0 And thread_temp_file_readed <> 0 And thread_oversized_file = #True And thread_redirect = #False
2022-02-17 13:23:42 +01:00
CopyMemory(thread_temp_cache_memory, thread_buffer_offset, thread_temp_file_readed)
lhs_log::Out("Cache Address Memory:"+Str(thread_temp_cache_memory))
FreeMemory(thread_temp_cache_memory)
thread_temp_cache_memory = 0
2022-02-18 16:05:48 +01:00
ElseIf thread_redirect = #True
thread_redirect = #False
2022-02-17 13:23:42 +01:00
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("File Buffer Troubles.")
If thread_temp_cache_memory = 0 : lhs_log::Out("thread_temp_cache_memory = 0") : EndIf
If thread_buffer_offset = 0 : lhs_log::Out("thread_buffer_offset = 0") : EndIf
If thread_data_size = 0 : lhs_log::Out("thread_data_size = 0") : EndIf
2020-12-04 21:03:03 +01:00
thread_alive = #False
Break 2
2020-11-27 21:43:38 +01:00
EndIf
2020-11-03 19:09:17 +01:00
; EndIf
2021-05-21 07:45:23 +02:00
lhs_log::Out("HTTP File Buffer Cleaned.")
2020-11-03 19:09:17 +01:00
;Löschen des eingang Speichers.
2020-11-08 01:31:57 +01:00
If m_clients(Str(thread_cli_id))\datenbuffer()\Buffer > 0
FreeMemory(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)
EndIf
2020-11-03 19:09:17 +01:00
DeleteElement(m_clients(Str(thread_cli_id))\datenbuffer())
2020-11-30 09:52:27 +01:00
;Send the data in memory to client.
2022-02-18 16:05:48 +01:00
If thread_redirect = #True
sent_total = thread_buffer_offset - thread_buffer
ElseIf thread_oversized_file = #False
2022-02-17 13:23:42 +01:00
sent_total = thread_data_size+(thread_buffer_offset-thread_buffer)
Else
sent_total = thread_temp_file_readed+(thread_buffer_offset-thread_buffer)
EndIf
;TODO: Stoped download kill server...
2020-12-01 08:53:53 +01:00
If m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
2020-11-27 21:43:38 +01:00
sent_length = sent_total
2022-02-17 13:23:42 +01:00
sent_buffer_address = thread_buffer
2020-11-27 21:43:38 +01:00
sent_total = 0
Repeat
sent = ltls::WriteTLSSocket(thread_cli_id, sent_buffer_address , sent_length)
If sent <> -1
2022-02-17 13:23:42 +01:00
;lhs_log::Out("ClientID:" + Str(thread_cli_id) + " HTTPS Sent:"+Str(sent)+" bytes")
2020-11-27 21:43:38 +01:00
sent_length - sent
2022-02-17 13:23:42 +01:00
If thread_oversized_file = #False
sent_buffer_address + sent
Else
;Read next Block to Memory
If sent_length <= 0 And IsFile(thread_file_handle)
sent_readed = ReadData(thread_file_handle, thread_buffer, thread_temp_file_readed)
;lhs_log::Out("ClientID:" + Str(thread_cli_id) + " HTTPS Large File -> Read Next:"+Str(sent_readed)+" bytes")
If sent_readed < thread_temp_file_readed
CloseFile(thread_file_handle)
EndIf
sent_buffer_address = thread_buffer
sent_length = sent_readed
Else
;lhs_log::Out("ClientID:" + Str(thread_cli_id) + " HTTPS Large File -> to Send:"+Str(sent_length)+" bytes")
sent_buffer_address + sent
EndIf
EndIf
2020-11-27 21:43:38 +01:00
sent_total + sent
Else
2022-02-17 13:23:42 +01:00
If IsFile(thread_file_handle)
CloseFile(thread_file_handle)
EndIf
2021-05-21 07:45:23 +02:00
lhs_log::Out("HTTPS Sent error:"+ltls::ErrorTLSCli(thread_cli_id))
2020-12-04 21:03:03 +01:00
thread_alive = #False
Break 2
2020-11-27 21:43:38 +01:00
EndIf
Until sent_length <= 0
sent = sent_total
2020-11-27 11:52:35 +01:00
Else
2020-11-28 16:49:22 +01:00
sent_length = sent_total
sent_buffer_address = thread_buffer
sent_total = 0
Repeat
sent = lsocket::WriteSocket(thread_cli_id, thread_buffer , sent_length)
If sent <> -1
2021-05-21 07:45:23 +02:00
lhs_log::Out("HTTP Sent:"+Str(sent)+" bytes")
2020-11-28 16:49:22 +01:00
sent_length - sent
2022-02-17 13:23:42 +01:00
If thread_oversized_file = 0
sent_buffer_address + sent
Else
;Read next Block to Memory
If sent_length <= 0 And IsFile(thread_file_handle)
sent_readed = ReadData(thread_file_handle, thread_buffer, thread_temp_file_readed)
If sent_readed < thread_temp_file_readed
CloseFile(thread_file_handle)
EndIf
sent_buffer_address = thread_buffer
sent_length = sent_readed
Else
sent_buffer_address + sent
EndIf
EndIf
2020-11-28 16:49:22 +01:00
sent_total + sent
Else
2022-02-17 13:23:42 +01:00
If IsFile(thread_file_handle)
CloseFile(thread_file_handle)
EndIf
2021-05-21 07:45:23 +02:00
lhs_log::Out("HTTP Sent error:"+Str(sent))
2020-12-04 21:03:03 +01:00
thread_alive = #False
Break 2
2020-11-28 16:49:22 +01:00
EndIf
Until sent_length <= 0
2020-11-30 09:52:27 +01:00
sent = sent_total
2020-11-27 11:52:35 +01:00
EndIf
2020-11-03 19:09:17 +01:00
2020-11-27 11:52:35 +01:00
If sent = thread_data_size+(thread_buffer_offset-thread_buffer)
2020-11-03 19:09:17 +01:00
;Ok
2021-05-21 07:45:23 +02:00
;lhs_log::Out("Gesendet:" + PeekS(thread_buffer,thread_buffer_length, #PB_Ascii))
2020-11-30 09:52:27 +01:00
If thread_buffer > 0
FreeMemory(thread_buffer)
EndIf
2020-11-03 19:09:17 +01:00
m_clients(Str(thread_cli_id))\client_do_cli = #CLI_DO_WaitDataReceive
2020-11-30 08:15:50 +01:00
m_clients(Str(thread_cli_id))\client_do_srv = #SRV_DO_DataReceive
2020-11-03 19:09:17 +01:00
Else
;Fehler beim Senden ... Thread beenden.
2021-05-21 07:45:23 +02:00
lhs_log::Out("Fehler:" + Str(Sent))
2020-11-03 19:09:17 +01:00
thread_alive = #False
EndIf
;
Wend
;}
m_clients(Str(thread_cli_id))\client_do_cli = #CLI_DO_WaitDataReceive
EndSelect
EndIf
2020-11-08 01:31:57 +01:00
;}
2020-11-03 19:09:17 +01:00
Until thread_alive = #False
2021-05-21 07:45:23 +02:00
lhs_log::Out("Thread should now die...")
2020-11-03 19:09:17 +01:00
ResetList(m_clients(Str(thread_cli_id))\datenbuffer())
2021-05-21 07:45:23 +02:00
lhs_log::Out("Thread kill all Initialized Memory buffers:")
2020-11-03 19:09:17 +01:00
While NextElement(m_clients(Str(thread_cli_id))\datenbuffer())
If m_clients(Str(thread_cli_id))\datenbuffer()\Initialized
2021-05-21 07:45:23 +02:00
lhs_log::Out("Kill:"+Str(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)+ " ...")
2020-11-03 19:09:17 +01:00
FreeMemory(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)
DeleteElement(m_clients(Str(thread_cli_id))\datenbuffer())
2021-05-21 07:45:23 +02:00
lhs_log::Out("Freed and removed")
2020-11-03 19:09:17 +01:00
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("Remove element from List with uninitialized Memory ID: "+Str(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer))
2020-11-03 19:09:17 +01:00
DeleteElement(m_clients(Str(thread_cli_id))\datenbuffer())
2021-05-21 07:45:23 +02:00
lhs_log::Out("Removed")
2020-11-03 19:09:17 +01:00
EndIf
Wend
2020-12-01 08:53:53 +01:00
If m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
2021-05-21 07:45:23 +02:00
lhs_log::Out("Kill HTTPS Socket:" + Str(thread_cli_id))
2020-12-04 21:03:03 +01:00
;ltls::CloseTLSSocket(thread_cli_id)
2020-12-01 08:53:53 +01:00
count_client(#client_HTTPS, #client_remove)
2021-05-21 07:45:23 +02:00
lhs_log::Out("Killed.")
2020-11-28 16:49:22 +01:00
Else
2021-05-21 07:45:23 +02:00
lhs_log::Out("Kill HTTP Socket:" + Str(thread_cli_id))
2020-11-28 16:49:22 +01:00
lsocket::CloseSocket(thread_cli_id)
2020-12-01 08:53:53 +01:00
count_client(#client_HTTP, #client_remove)
2021-05-21 07:45:23 +02:00
lhs_log::Out("Killed.")
2020-11-27 21:43:38 +01:00
EndIf
2021-05-21 07:45:23 +02:00
lhs_log::Out("Remove Client from map...")
2020-11-03 19:09:17 +01:00
DeleteMapElement(m_clients(), Str(thread_cli_id))
2021-05-21 07:45:23 +02:00
lhs_log::Out("Removed and thread now died.")
2020-11-03 19:09:17 +01:00
EndProcedure
2020-11-08 01:31:57 +01:00
Procedure call_request(RequestString.s, Info.i = #get_handler_procedure)
Protected CurrPos, Count, Counter, PartString.s
If m_request(GetExtensionPart(RequestString))\routetype = #handler_type
Select Info
Case #get_handler_procedure
ProcedureReturn m_request(GetExtensionPart(RequestString))\call
Case #get_handler_prototype
ProcedureReturn m_request(GetExtensionPart(RequestString))\type
Default
ProcedureReturn 0
EndSelect
EndIf
If m_request(RequestString)\routetype = #handler_only Or m_request(RequestString)\routetype = #handler_sub
Select Info
Case #get_handler_procedure
ProcedureReturn m_request(RequestString)\call
Case #get_handler_prototype
ProcedureReturn m_request(RequestString)\type
Default
ProcedureReturn 0
EndSelect
ElseIf m_request(GetExtensionPart(RequestString))\routetype = #handler_sub
Select Info
Case #get_handler_procedure
ProcedureReturn m_request(GetExtensionPart(RequestString))\call
Case #get_handler_prototype
ProcedureReturn m_request(GetExtensionPart(RequestString))\type
Default
ProcedureReturn 0
EndSelect
EndIf
;Check auf Sub
Counter = CountString(RequestString, "/")
Count = 0
CurrPos = 0
While Count < Counter
CurrPos = FindString(RequestString, "/", 2 + CurrPos )
PartString = Mid(RequestString, 1, CurrPos)
If m_request(PartString)\routetype = #handler_sub
Select Info
Case #get_handler_procedure
ProcedureReturn m_request(PartString)\call
Case #get_handler_prototype
ProcedureReturn m_request(PartString)\type
Default
ProcedureReturn 0
EndSelect
EndIf
Count + 1
Wend
ProcedureReturn 0
EndProcedure
Procedure.s Work_Post_ToJSON_x_www_form_urlencoded(ContentLength.i, MemorSize.i, Memory.i)
Define.s JSONString, Working, ContentString
Define CountParams, Count, JSON
Protected NewMap Posts.s()
If ContentLength > 0
OffsetMemory = Memory + (MemorSize - ContentLength)
ContentString = PeekS(OffsetMemory, ContentLength, #PB_UTF8)
;Zerlegen &
;Mapname = Content
If Len(ContentString) > 0
CountParams = CountString(ContentString,"&")
If CountParams = 0
If CountString(ContentString, "=")
Posts(StringField(ContentString, 1, "=")) = StringField(ContentString,2, "=")
Else
ProcedureReturn ""
EndIf
ElseIf CountParams > 0
Count = 0
Repeat
Posts(StringField(StringField(ContentString, Count + 1, "&"),1,"=")) = StringField(StringField(ContentString, Count + 1, "&"),2,"=")
2021-05-21 07:45:23 +02:00
;lhs_log::Out("Worked Count:"+Str(Count)+" of: "+Str(CountParams)+":"+StringField(StringField(ContentString, Count + 1, "&"),1,"=")+" = "+StringField(StringField(ContentString, Count + 1, "&"),2,"=")
2020-11-08 01:31:57 +01:00
Count + 1
Until Count > CountParams
Else
ProcedureReturn ""
EndIf
JSON = CreateJSON(#PB_Any)
If JSON
InsertJSONMap(JSONValue(JSON), Posts())
JSONString = ComposeJSON(JSON)
FreeMap(Posts())
FreeJSON(JSON)
ProcedureReturn JSONString.s
Else
ProcedureReturn #error_string
EndIf
Else
ProcedureReturn ""
EndIf
Else
ProcedureReturn ""
EndIf
EndProcedure
2021-05-21 07:45:23 +02:00
Procedure.s Work_Post_ToJSON_multipart_form_data(ContentLength.i, MemorySize.i, Memory.i)
ProcedureReturn "NA"
EndProcedure
2020-11-08 01:31:57 +01:00
Procedure.s register_client_handler(Route.s, Callback.i, AppPrototype.i = #handler_proto_get, RouteType.i = #handler_sub)
m_request(Route)\type = AppPrototype
m_request(Route)\call = Callback
m_request(Route)\routetype = RouteType
2021-05-21 07:45:23 +02:00
lhs_log::Out("Handler Registriert:"+Route)
2020-11-08 01:31:57 +01:00
EndProcedure
2020-12-01 08:53:53 +01:00
Procedure count_client(Type.i, Countchange.i)
Select Type
Case #client_HTTP
LockMutex(count_HTTP_mutex)
count_HTTP_client + Countchange
UnlockMutex(count_HTTP_mutex)
Case #client_HTTPS
LockMutex(count_HTTPS_mutex)
count_HTTPS_client + Countchange
UnlockMutex(count_HTTPS_mutex)
EndSelect
EndProcedure
2022-02-18 16:05:48 +01:00
Procedure.s file_check(thread_requested.s)
Protected file_type.i
file_type = FileSize(configuration\basedir + thread_requested)
If file_type = -1
thread_requested = configuration\errorfile404
ElseIf file_type = -2
;Is a Directory
If Right(thread_requested,1) = "/"
thread_requested = thread_requested + configuration\defaultfile
Else
thread_requested = thread_requested + "/" + configuration\defaultfile
EndIf
EndIf
ProcedureReturn thread_requested.s
EndProcedure
2020-11-03 19:09:17 +01:00
EndModule