1526 lines
		
	
	
	
		
			72 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			1526 lines
		
	
	
	
		
			72 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| ;********************************
 | |
| ;*
 | |
| ;* lweb.pbi
 | |
| ;*
 | |
| ;* LiHaSo Webserver Main module.
 | |
| ;*
 | |
| ;* It is usable as standalone Webserver, look at lwebd.pb
 | |
| ;*
 | |
| 
 | |
| 
 | |
| XIncludeFile "lhs_lib/NET/lhs_net_tls.pbi"
 | |
| XIncludeFile "lhs_lib/NET/lhs_net_socket.pbi"
 | |
| XIncludeFile "inc/lweb_http_post_decoder.pbi"
 | |
| 
 | |
| 
 | |
| 
 | |
| Module lhs_web
 | |
|   ;********************************
 | |
|   ;*
 | |
|   ;* WebServer Variabeln / Parameter
 | |
|   ;*
 | |
|   ;{
 | |
|   
 | |
|   ;*
 | |
|   ;* Configuration Structures
 | |
|   ;*
 | |
|   ;{
 | |
|   XIncludeFile "inc/lweb_header_privat.pbi"
 | |
|   ;}
 | |
|   ;*
 | |
|   
 | |
|   ;*
 | |
|   ;* Identifikation des Servers.
 | |
|   ;*
 | |
|   
 | |
|   Global configuration.server
 | |
|   configuration\version = "V0.9"
 | |
|   configuration\identifikation = "LiHaSo Webserver " + configuration\version
 | |
|   configuration\config_file("status_xml")\name = "cfg/default_http_status_codes.xml"
 | |
|   configuration\config_file("status_xml")\type = "file"
 | |
|   configuration\config_file("hosts_dir")\name = "cfg/server/"
 | |
|   configuration\config_file("hosts_dir")\type = "dir"
 | |
|   
 | |
|   ;*
 | |
|   ;* 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.
 | |
| 
 | |
|   configuration\type = 0
 | |
|   configuration\global_max_cli_memory = 0                    ; Unlimited
 | |
|   configuration\global_max_cli_threads = 0                   ; Unlimited
 | |
|   
 | |
|   
 | |
| 
 | |
|   
 | |
|   
 | |
|   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
 | |
|   EndEnumeration
 | |
|   
 | |
|   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.
 | |
|   EndEnumeration
 | |
|   
 | |
|   Enumeration e_type_client 1
 | |
|     #client_HTTP
 | |
|     #client_HTTPS
 | |
|   EndEnumeration
 | |
|   
 | |
|   #client_add = 1
 | |
|   #client_remove = -1
 | |
|   
 | |
|   #http_method_get  = "GET"
 | |
|   #http_method_post = "POST"
 | |
|   #http_method_put  = "PUT"
 | |
|   #http_method_connect = "CONNECT"
 | |
|   #http_method_delete = "DELETE"
 | |
|   #http_method_options = "OPTIONS"
 | |
|   #http_method_trace = "TRACE"
 | |
|   #http_method_patch = "PATCH"
 | |
|   
 | |
|   ;***********************
 | |
|   ;* 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
 | |
|     *Buffer
 | |
|     Initialized.b
 | |
|     Size.i
 | |
|   EndStructure
 | |
|   
 | |
|   Structure s_file_cache
 | |
|     *Buffer
 | |
|     Size.i
 | |
|     Timer.i
 | |
|     Is.i
 | |
|   EndStructure
 | |
|   
 | |
|   Structure PORT_used
 | |
|     UUID.s
 | |
|   EndStructure
 | |
|   
 | |
|   Structure IP_used
 | |
|     Map PortS.PORT_used()
 | |
|   EndStructure
 | |
|   
 | |
|   Structure s_clients
 | |
|     client_id.i
 | |
|     client_do_cli.i
 | |
|     client_do_srv.i
 | |
|     client_type.i                        ;What type of Client.
 | |
|     client_mutex.i
 | |
|     client_thread.i
 | |
|     List datenbuffer.s_client_memory()
 | |
|     client_test_cli.i
 | |
|     client_test_srv.i
 | |
|     client_cctx.i
 | |
|     server_uuid.s                        ;On which Server it is received.
 | |
|     host_id.s
 | |
|     client_timeout.i                     ;Individual timeout per Server to cleanup Client connections
 | |
|   EndStructure
 | |
|   
 | |
|   Structure s_request_handler
 | |
|     call.i
 | |
|     type.i
 | |
|     routetype.i
 | |
|     host.s
 | |
|     route.s
 | |
|     library.s
 | |
|     perm.i
 | |
|   EndStructure
 | |
|   
 | |
|   Structure s_server_runs
 | |
|     server_connection_id.i
 | |
|     UUID.s
 | |
|     configuration_map_id.s
 | |
|   EndStructure
 | |
|   
 | |
|   Structure s_header_functions
 | |
|     header_name.s
 | |
|     call.i
 | |
|     type.i
 | |
|     library.s
 | |
|     perm.i
 | |
|   EndStructure
 | |
| 
 | |
|   Enumeration cli_handler_infos 1
 | |
|     #get_handler_procedure      ;Funktion die Aufgerufen werden muss
 | |
|     #get_handler_prototype      ;Welcher Prototype
 | |
|     #get_handler_library        ;Library to open
 | |
|     #get_handler_library_perm   ;Library permanent in memory?
 | |
|   EndEnumeration
 | |
|   
 | |
|   Global.i count_HTTP_client
 | |
|   Global.i count_HTTPS_client
 | |
|   Global.i server_HTTP_id
 | |
|   Global.i server_HTTPS_id
 | |
|   Global.i server_mutex = CreateMutex() ;Dieser Mutex dient zu der Sicherheit der Element Liste.
 | |
|   Global.i server_start_semaphore = CreateSemaphore()
 | |
|   Global.i count_HTTP_mutex = CreateMutex()
 | |
|   Global.i count_HTTPS_mutex = CreateMutex()
 | |
|   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()
 | |
|   Global NewMap m_clients.s_clients()
 | |
|   Global NewMap m_request.s_request_handler()
 | |
|   Global NewMap server_used.IP_used()
 | |
|   Global NewMap m_server_running.s_server_runs()
 | |
|   
 | |
|   ;}
 | |
|   
 | |
|   ;********************************
 | |
|   ;*
 | |
|   ;* Handler Prototypen
 | |
|   ;*
 | |
|   
 | |
|   PrototypeC WebHandler_Get(handler_Map_JSON.s)
 | |
|   PrototypeC WebHandler_Post(handler_Map_JSON.s, ContentString.s)
 | |
|   PrototypeC WebHandler_Universal(handler_Map_JSON.s, ContentString.s)
 | |
|   PrototypeC.s WebHandler_i_Get(handler_Map_JSON.s)
 | |
|   PrototypeC.s WebHandler_i_Post(handler_Map_JSON.s, ContentString.s)
 | |
|   PrototypeC.s WebHandler_i_Universal(handler_Map_JSON.s, ContentString.s)
 | |
|   PrototypeC WebSocket_Handler_String(handler_Map_JSON.s, Back_Semaphore.i)
 | |
|   
 | |
|   ;********************************
 | |
|   ;*
 | |
|   ;* Used Librarys
 | |
|   ;*
 | |
|   
 | |
|   XIncludeFile "inc/lweb_http_header.pbi"
 | |
|   ;XIncludeFile "inc/lweb_file_cache_header.pbi"
 | |
|   XIncludeFile "inc/lweb_config_header.pbi"
 | |
|   
 | |
|   ;********************************
 | |
|   ;*
 | |
|   ;* Proceduren Deklarierung
 | |
|   ;*
 | |
|   
 | |
|   Declare server_HTTP(network_server_id.i)
 | |
|   Declare server_HTTPS(network_server_id.i)
 | |
|   Declare client(network_client_id.i)
 | |
|   Declare.s file_check(thread_requested.s, hostid.s)
 | |
|   Declare.s call_request_string(RequestString.s, Info.i=#get_handler_procedure)
 | |
|   Declare call_request(RequestString.s, Info.i=#get_handler_procedure)
 | |
|   Declare.s call_function(ToCallType.i, ToCall.i, Map Header.s(), PostMapString.s ="")
 | |
|   Declare advanced_register_handler(RequesterString.s, Permament.i = 0, Library.s = "", Host.s = "")
 | |
|   ;Declare.s Work_Post_ToJSON_multipart_form_data(ContentLength.i, MemorSize.i, Memory.i)
 | |
|   ;Declare.s Work_Post_ToJSON_x_www_form_urlencoded(ContentLength.i, MemorSize.i, Memory.i)
 | |
|   Declare count_client(Type.i, Countchange.i)
 | |
|   
 | |
|   XIncludeFile "inc/lweb_IP.pbi"
 | |
|   XIncludeFile "inc/lweb_http.pbi"
 | |
|   XIncludeFile "inc/lweb_helper.pbi"  
 | |
|   ;XIncludeFile "inc/lweb_file_cache.pbi"  Currently in dev.
 | |
|   XIncludeFile "inc/lweb_config.pbi"
 | |
|   IncludeFile "lhs_lib/SYS/lhs_uuid.pbi"    ;It is needed as local function.
 | |
|   
 | |
|   XIncludeFile "inc/lweb_server_cfg.pbi"
 | |
|   ;XIncludeFile "inc/lweb_dynamic.pbi"
 | |
|   
 | |
|   Procedure server_reload(UUID.s)
 | |
|     
 | |
|     ProcedureReturn #True
 | |
|   EndProcedure
 | |
| 
 | |
|   IncludeFile "inc/lweb_http_status.pbi"
 | |
|   
 | |
|   Procedure.s http_server_prepare(http_port.i = 8080, http_binding.s = "127.0.0.1", https_port.i=8443, https_binding.s="127.0.0.1", https_enabled.b = #False)
 | |
|     ;CreateUUID
 | |
|     Protected UUID.s
 | |
|     UUID = CreateUUID()
 | |
|     configuration\hosts(UUID)\defaultfile = "index.html"
 | |
|     configuration\hosts(UUID)\basedir = "/srv/lweb-srv/"
 | |
|     
 | |
|     configuration\hosts(UUID)\http\max_clients = 10        ; Max sametime HTTP connections. 
 | |
|     configuration\hosts(UUID)\http\port = 8080
 | |
|     configuration\hosts(UUID)\http\binding = "127.0.0.1"
 | |
|     
 | |
|     configuration\hosts(UUID)\https\max_clients = 100
 | |
|     configuration\hosts(UUID)\https\port = 8443
 | |
|     configuration\hosts(UUID)\https\binding = "127.0.0.1"
 | |
|     configuration\hosts(UUID)\https\enabled = 0
 | |
|     configuration\hosts(UUID)\https\CA = ""
 | |
|     configuration\hosts(UUID)\https\Certs = ""
 | |
|     configuration\hosts(UUID)\https\key = ""
 | |
|     configuration\hosts(UUID)\https\key_pass = ""
 | |
|     
 | |
|     configuration\hosts(UUID)\cache\enable = 0              ; Enable / Disable Cached Server
 | |
|     configuration\hosts(UUID)\cache\time = 120              ; TTL of cached files
 | |
|     configuration\hosts(UUID)\cache\maxsize = 1             ; Max Cache
 | |
|     configuration\hosts(UUID)\cache\current = 0             ;
 | |
|     
 | |
|     configuration\hosts(UUID)\mem\MaxFileSize = 524288      ; Default 512 KiB
 | |
|     configuration\hosts(UUID)\mem\DefaultBlockSize = 65536  ; Default Blocksize 64 KiB
 | |
|     ProcedureReturn UUID
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure main_server(id.i)
 | |
|     ldl::Logging("main Server Loading")
 | |
|     status_defaults()
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure server_start()
 | |
|     Protected server_id_HTTP
 | |
|     Protected server_id_HTTPS
 | |
|     Protected server_UUID_HTTP.s
 | |
|     Protected server_UUID_HTTPS.s
 | |
|     Protected counter.i, id.i
 | |
|     Global NewMap m_clients.s_clients(configuration\global_max_cli_threads) ;configuration\http\max_clients+configuration\https\max_clients
 | |
|     Protected tlsresponse.i
 | |
|     Protected current_lib.i
 | |
|     Protected current_lib_function.i, current_lib_perm.i
 | |
|     Protected current_lib_close.i
 | |
|     Protected current_register_type.i
 | |
|     Protected current_register_react.s
 | |
|     Protected current_register_proto.i
 | |
|     ;Initialize all Servers in configuration\hosts()
 | |
|     ResetMap(configuration\hosts())
 | |
|     While NextMapElement(configuration\hosts())
 | |
|       server_id_HTTP = lsocket::CreateSocket(configuration\hosts()\http\port, configuration\hosts()\http\max_clients, lsocket::#SOCK_STREAM, lsocket::#AF_INET, configuration\hosts()\http\binding)
 | |
|       If server_id_HTTP 
 | |
| 
 | |
|         ;Check for HTTPS
 | |
|         If configuration\hosts()\https\enabled = 1
 | |
|           server_id_HTTPS = lsocket::CreateSocket(configuration\hosts()\https\port, configuration\hosts()\https\max_clients, lsocket::#SOCK_STREAM, lsocket::#AF_INET, configuration\hosts()\https\binding)
 | |
|           If server_id_HTTPS
 | |
|             ;Now Create TLS Socket
 | |
|             tlsresponse = tls::InitSimpleTLS(configuration\hosts()\https\CA,configuration\hosts()\https\Certs, configuration\hosts()\https\key, configuration\hosts()\https\key_pass)
 | |
|             If tlsresponse > 0
 | |
|               m_server_running(Str(server_id_HTTPS))\configuration_map_id = MapKey(configuration\hosts())
 | |
|               configuration\hosts()\https\thread_id = CreateThread(@server_HTTPS(), server_id_HTTPS)
 | |
|               counter + 1
 | |
|             Else
 | |
|               ldl::Logging("HTTPS Socket configuration failed with error:"+Str(tlsresponse))
 | |
|               End
 | |
|             EndIf
 | |
|           Else
 | |
|             ldl::Logging("HTTPS Socket ["+configuration\hosts()\https\port+"] could Not opened.")
 | |
|             End
 | |
|           EndIf
 | |
|         EndIf
 | |
|         
 | |
|         ;HTTP server start
 | |
|         m_server_running(Str(server_id_HTTP))\configuration_map_id = MapKey(configuration\hosts())
 | |
|         configuration\hosts()\http\thread_id = CreateThread(@server_HTTP(), server_id_HTTP)
 | |
|         counter + 1
 | |
|         configuration\hosts()\log\AccesslogUUID   = lhs_log_ext::Create("Accesslog "+configuration\hosts()\description)
 | |
|         configuration\hosts()\log\ErrorlogUUID    = lhs_log_ext::Create("Errorlog "+configuration\hosts()\description)
 | |
|         lhs_log_ext::SetLogFile(configuration\hosts()\log\AccesslogUUID, configuration\hosts()\log\AccesslogFile)
 | |
|         lhs_log_ext::SetLogFile(configuration\hosts()\log\ErrorlogUUID, configuration\hosts()\log\ErrorlogFile)
 | |
|         lhs_log_ext::Init(configuration\hosts()\log\AccesslogUUID)
 | |
|         lhs_log_ext::Init(configuration\hosts()\log\ErrorlogUUID)
 | |
|         ldl::Register(lhs_log_ext::@Out(), configuration\hosts()\log\AccesslogUUID, 0,configuration\hosts()\log\AccesslogUUID ,ldl::#AdvancedLog)
 | |
|         ldl::Register(lhs_log_ext::@Out(), configuration\hosts()\log\ErrorlogUUID, 0,configuration\hosts()\log\ErrorlogUUID ,ldl::#AdvancedLog)
 | |
|         ldl::Logging("Accesslog UUID:"+configuration\hosts()\log\AccesslogUUID)
 | |
|         ldl::Logging("Errorlog UUID:"+configuration\hosts()\log\ErrorlogUUID)
 | |
|         
 | |
|         ;Register Handlers
 | |
|         ResetMap(configuration\hosts()\dynamichandler())
 | |
|         While NextMapElement(configuration\hosts()\dynamichandler())
 | |
|           ldl::Logging("Register Handler:"+MapKey(configuration\hosts()\dynamichandler()))
 | |
|           ldl::Logging("Parameters library:"+configuration\hosts()\dynamichandler()\file+" Type:"+configuration\hosts()\dynamichandler()\functiontype+" uri:"+configuration\hosts()\dynamichandler()\url+" extension:"+configuration\hosts()\dynamichandler()\extension)
 | |
|           
 | |
|           If FindMapElement(configuration\hosts()\usedlibs(), configuration\hosts()\dynamichandler()\file)
 | |
|             current_lib = configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\lib_id
 | |
|           Else
 | |
|             current_lib = OpenLibrary(#PB_Any, configuration\hosts()\dynamichandler()\file)
 | |
|           EndIf
 | |
|             
 | |
|           If current_lib
 | |
|             current_lib_function = GetFunction(current_lib, configuration\hosts()\dynamichandler()\proc)
 | |
|             If current_lib_function
 | |
|               ldl::Logging("Function "+configuration\hosts()\dynamichandler()\proc+" found")
 | |
|               If FindMapElement(configuration\hosts()\usedlibs(), configuration\hosts()\dynamichandler()\file)
 | |
|                 If configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\permlib = "false" And configuration\hosts()\dynamichandler()\permlib = "false"
 | |
|                   current_lib_close = 1
 | |
|                   current_lib_perm = 0
 | |
|                 ElseIf configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\permlib = "false" And configuration\hosts()\dynamichandler()\permlib = "true"
 | |
|                   configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\permlib = configuration\hosts()\dynamichandler()\permlib
 | |
|                   configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\lib_id = current_lib
 | |
|                   current_lib_close = 0
 | |
|                   current_lib_perm = 1
 | |
|                 EndIf
 | |
|               Else
 | |
|                 configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\permlib = configuration\hosts()\dynamichandler()\permlib
 | |
|                 If configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\permlib = "false" 
 | |
|                   current_lib_close = 1
 | |
|                   current_lib_perm = 0
 | |
|                 Else
 | |
|                   configuration\hosts()\usedlibs(configuration\hosts()\dynamichandler()\file)\lib_id = current_lib
 | |
|                   current_lib_close = 0
 | |
|                   current_lib_perm = 1
 | |
|                 EndIf
 | |
|               EndIf
 | |
|               
 | |
|               ;Now register the function
 | |
|               Select configuration\hosts()\dynamichandler()\routetype
 | |
|                 Case "handler_only"
 | |
|                   current_register_type = #handler_only
 | |
|                   current_register_react = configuration\hosts()\dynamichandler()\url
 | |
|                 Case "handler_sub"
 | |
|                   current_register_type = #handler_sub
 | |
|                   current_register_react = configuration\hosts()\dynamichandler()\url                  
 | |
|                 Case "handler_type"
 | |
|                   current_register_type = #handler_type
 | |
|                   current_register_react = configuration\hosts()\dynamichandler()\extension
 | |
|               EndSelect
 | |
|               
 | |
|               Select configuration\hosts()\dynamichandler()\functiontype
 | |
|                 Case "GET"
 | |
|                   current_register_proto = #handler_proto_get
 | |
|                 Case "POST"
 | |
|                   current_register_proto = #handler_proto_post
 | |
|                 Case "Universal"
 | |
|                   current_register_proto = #handler_proto_universal
 | |
|                 Case "GET_int"
 | |
|                   current_register_proto = #handler_proto_i_get
 | |
|                 Case "POST_int"
 | |
|                   current_register_proto = #handler_proto_i_post
 | |
|                 Case "Universal_int"
 | |
|                   current_register_proto = #handler_proto_i_universal
 | |
|               EndSelect
 | |
|               
 | |
|               ldl::Logging("react:"+current_register_react+" file:"+configuration\hosts()\dynamichandler()\file+" Host ID:"+MapKey(configuration\hosts()))
 | |
|               If FindString(configuration\hosts()\dynamichandler()\functiontype, "_int")
 | |
|                 register_client_handler(current_register_react, current_lib_function, current_register_proto, current_register_type, MapKey(configuration\hosts()))
 | |
|               Else
 | |
|                 register_client_handler(current_register_react, current_lib_function, current_register_proto, current_register_type, MapKey(configuration\hosts()))
 | |
|                 advanced_register_handler(current_register_react, current_lib_perm, configuration\hosts()\dynamichandler()\file, MapKey(configuration\hosts()))
 | |
|               EndIf
 | |
|               
 | |
|               If current_lib_close = 1
 | |
|                 CloseLibrary(current_lib)
 | |
|               EndIf
 | |
|               current_lib_close = 0
 | |
|             Else
 | |
|               ldl::Logging("Error: Function "+configuration\hosts()\dynamichandler()\proc+" not found")
 | |
|               If configuration\hosts()\dynamichandler()\permlib = "false"
 | |
|                 CloseLibrary(current_lib)
 | |
|               EndIf
 | |
|             EndIf
 | |
|           Else
 | |
|             ldl::Logging("Error: Library "+configuration\hosts()\dynamichandler()\file+" could not be opened")
 | |
|           EndIf
 | |
|         Wend
 | |
|         
 | |
|       Else
 | |
|         ldl::Logging("HTTP Socket ["+configuration\hosts()\http\port+"] could Not be opened.")
 | |
|         End
 | |
|       EndIf
 | |
|     Wend
 | |
|     ;Initalize Loggers:
 | |
| 
 | |
|     
 | |
| 
 | |
|     
 | |
|     
 | |
|     For id = 1 To counter
 | |
|       SignalSemaphore(server_start_semaphore)
 | |
|     Next
 | |
|     
 | |
|     ProcedureReturn #True
 | |
|   
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure server_stop(UUID.s = "all")
 | |
|     ;Current easy kill HTTP and HTTPS thread.
 | |
|     ;Must be changed if Caching is active !
 | |
| ;     If configuration\https\enabled = 1 And configuration\https\thread_id <> 0
 | |
| ;       KillThread(configuration\https\thread_id)
 | |
| ;     EndIf
 | |
| ;     If configuration\http\thread_id <> 0
 | |
| ;       KillThread(configuration\http\thread_id)
 | |
| ;     EndIf
 | |
|     
 | |
|   EndProcedure
 | |
|   
 | |
|   
 | |
|   Procedure server_HTTPS(network_server_id.i)
 | |
|     ;**************************
 | |
|     ;*
 | |
|     ;* Main thread for HTTPS networksocket management. Create the Client Threads.
 | |
|     ;* 
 | |
|     Protected.i client_id
 | |
|     Protected.i server_host.s = m_server_running(Str(network_server_id))\configuration_map_id
 | |
|     thread_alive = #True
 | |
|     WaitSemaphore(server_start_semaphore)
 | |
|     ldl::Logging("HTTPS Server Started.")
 | |
|     Repeat
 | |
|       client_id = tls::WaitTLSSocket(network_server_id)
 | |
|       ldl::Logging("New HTTPS Client:"+Str(client_id))
 | |
|       If client_id > 0
 | |
|         If m_clients(Str(client_id))\client_id = client_id
 | |
|           ldl::Logging("Client Thread for socket already exist :"+Str(client_id))
 | |
|         Else
 | |
|           If count_HTTPS_client < 128
 | |
|             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
 | |
|             m_clients(Str(client_id))\host_id = server_host
 | |
|             ;Thread erstellen
 | |
|             m_clients(Str(client_id))\client_thread = CreateThread(@client(), client_id)
 | |
|             count_client(#client_HTTPS, #client_add)
 | |
|           Else
 | |
|             ldl::Logging("Max HTTPS Clients reached...")
 | |
|             tls::CloseTLSSocket(client_id)
 | |
|           EndIf          
 | |
|         EndIf
 | |
|       Else
 | |
|         Break
 | |
|       EndIf
 | |
|     ForEver
 | |
|     tls::CloseTLS(network_server_id)
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure server_HTTP(network_server_id.i)
 | |
|     ;**************************
 | |
|     ;*
 | |
|     ;* Main thread for HTTP networksocket management. Create the Client Threads.
 | |
|     ;* 
 | |
|     Protected.i client_id
 | |
|     Protected.i server_host.s = m_server_running(Str(network_server_id))\configuration_map_id
 | |
| 
 | |
|     thread_alive = #True
 | |
|     WaitSemaphore(server_start_semaphore)
 | |
|     ldl::Logging("HTTP Server Started.")
 | |
|     Repeat
 | |
|       client_id = lsocket::WaitSocket(network_server_id)
 | |
|       ldl::Logging("New HTTP Client:"+Str(client_id))
 | |
|       If client_id > 0
 | |
|         If m_clients(Str(client_id))\client_id = client_id
 | |
|           ldl::Logging("Client Thread for socket already exist :"+Str(client_id))
 | |
|         Else
 | |
|           If count_HTTP_client < 128
 | |
|             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
 | |
|             m_clients(Str(client_id))\host_id = server_host
 | |
|             ;Thread erstellen
 | |
|             m_clients(Str(client_id))\client_thread = CreateThread(@client(), client_id)
 | |
|             count_client(#client_HTTP, #client_add)
 | |
|           Else
 | |
|             ldl::Logging("Max HTTP Clients reached...")
 | |
|             lsocket::CloseSocket(client_id)
 | |
|           EndIf          
 | |
|         EndIf
 | |
|       Else
 | |
|         Break
 | |
|       EndIf
 | |
|     ForEver
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure server_WebSocket(network_client_id)
 | |
|     Protected Quit = 1
 | |
|     Protected.i thread_cli_id = network_client_id
 | |
|     
 | |
|     Repeat
 | |
|       ; Check if we get data from client
 | |
|       If  m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
 | |
|         temp_receivelength = tls::ReadTLSSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)  
 | |
|       Else
 | |
|         temp_receivelength = lsocket::ReadSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
 | |
|         
 | |
|       EndIf      
 | |
|       ; Check if Library has data to send
 | |
|       
 | |
|     Until Quit = 1
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure client(network_client_id.i)
 | |
|     Protected thread_cli_id = network_client_id, sent
 | |
|     Protected MyThreadJSON, ToCall, ToCallType
 | |
|     Protected thread_temp_cache.s, thread_temp_cache_memory, temp_receivelength, thread_temp_decode_memory
 | |
|     Protected thread_reasign, thread_oversized_file.b, thread_data_to_read.i, thread_data_readed.i
 | |
|     Protected thread_data_size, thread_file_handle, Handle_Response_Address
 | |
|     Protected.s thread_requested, thread_type, thread_date, thread_header, thread_work, JSONStringToMap, Handler_Response, response_status, PostMapString
 | |
|     Protected thread_buffer, thread_buffer_offset, thread_buffer_length, buffer_sent
 | |
|     Protected sent_length, sent_buffer_address, sent_total
 | |
|     Protected.b thread_alive = #True, error_message = #False, thread_redirect = #False
 | |
|     
 | |
|     Protected.s default_file = configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\defaultfile
 | |
|     Protected.s home_dir = configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\basedir
 | |
|     Protected.s AccessLog = configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\log\AccesslogUUID
 | |
|     Protected.s ErrorLog = configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\log\ErrorlogUUID
 | |
|     Protected.s Host_ID = m_clients(Str(thread_cli_id))\host_id
 | |
|     Protected.s Host_call = "SpecServer:["+Host_ID+"]"
 | |
|     Protected.s Header_string = ""
 | |
|     Protected Library_ID, LibraryToCall.s
 | |
|     Define NewMap Header.s() 
 | |
|     Define NewMap Response.s()
 | |
|     Define NewMap Post.s()
 | |
| 
 | |
|     
 | |
|     ldl::Logging("Client Thread Started. ID:" + Str(network_client_id))
 | |
|     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
 | |
|             ldl::Logging("Buffer Initialisierung fehlgeschlagen.")
 | |
|             Break
 | |
|           EndIf
 | |
|           If  m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
 | |
|             temp_receivelength = tls::ReadTLSSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)  
 | |
|           Else
 | |
|             temp_receivelength = lsocket::ReadSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
 | |
|           EndIf
 | |
|           
 | |
|           If temp_receivelength = -1
 | |
|             ldl::Logging("Empfangsfehler.")
 | |
|             Break
 | |
|           ElseIf temp_receivelength = 65536
 | |
|             m_clients(Str(thread_cli_id))\datenbuffer()\Size = temp_receivelength
 | |
|             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
 | |
|                 ldl::Logging("Buffer Initialisierung fehlgeschlagen.")
 | |
|                 Break 2
 | |
|               EndIf
 | |
|               If  m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
 | |
|                 temp_receivelength = tls::ReadTLSSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
 | |
|               Else
 | |
|                 temp_receivelength = lsocket::ReadSocket(thread_cli_id, m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, 65536)
 | |
|               EndIf
 | |
|               
 | |
|               m_clients(Str(thread_cli_id))\datenbuffer()\Size = temp_receivelength
 | |
|               counter_mem_buffers + 1
 | |
|               If temp_receivelength = -1
 | |
|                 Break 2
 | |
|               EndIf
 | |
|             Until temp_receivelength < 65536
 | |
|           Else
 | |
|             m_clients(Str(thread_cli_id))\datenbuffer()\Size = temp_receivelength
 | |
|           EndIf
 | |
|           ;Alle Daten empfangen.
 | |
|           ldl::Logging("Anzahl Buffer:" + Str(ListSize(m_clients(Str(thread_cli_id))\datenbuffer())))
 | |
|           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
 | |
|           ldl::Logging("#SRV_DO_ClientDisconnect")
 | |
|           thread_alive = #False
 | |
|           ;* Alles IO
 | |
|         Default 
 | |
|           ;Ressourcen freigeben und Threadzeit reduzieren
 | |
|           Delay(1)
 | |
|           ldl::Logging("--------------------------------------------------------- FAILING ???")
 | |
|       EndSelect
 | |
|       ;}
 | |
|       
 | |
|       ;{ Client Side Triggered Things
 | |
|       If thread_alive = #True
 | |
|         Select m_clients(Str(thread_cli_id))\client_do_cli
 | |
|           Case #CLI_DO_DataWorking
 | |
|             ;Receive done.
 | |
|             ;Do Buffer work
 | |
|             ;Change Thread to Work mode.
 | |
|             
 | |
|             ;{
 | |
|             ldl::Logging("Data received, working...")
 | |
|             m_clients(Str(thread_cli_id))\client_do_cli = #CLI_DO_DataWorking
 | |
|             ;Work on Answer.
 | |
|             ResetList(m_clients(Str(thread_cli_id))\datenbuffer())
 | |
|             ;TODO: Only first Buffer have a Header.
 | |
| 
 | |
|             While NextElement(m_clients(Str(thread_cli_id))\datenbuffer())
 | |
|                             
 | |
|               thread_work = PeekS(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer, m_clients(Str(thread_cli_id))\datenbuffer()\Size, #PB_Ascii)
 | |
|               
 | |
|               ;Move Header to Map
 | |
|               ldl::Logging("Preheaderwork:"+ thread_work)
 | |
|  
 | |
|               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
 | |
|                   ;Should not be a case.
 | |
|                   Break 2 ; Kill Thread.
 | |
|                 EndIf
 | |
|               Else
 | |
|                 error_message = #True
 | |
|               EndIf
 | |
|               ;TODO: Url with GET Parameter (Also by POST/PUT & Co.)
 | |
|               ;? Wen da abschneiden
 | |
|               
 | |
|               
 | |
|               
 | |
|               ldl::Logging("JSONString:"+ JSONStringToMap)
 | |
|               thread_type = ""
 | |
|               If AccessLog <> ""
 | |
|                 If  m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
 | |
|                   ldl::Logging("Connect:"+lsocket::GetSocketIP(tls::GetSocket(thread_cli_id)) + " " + Header(#http_head_method) + " " + Header(#http_head_request), AccessLog)  
 | |
|                   ldl::Logging("Connect:"+lsocket::GetSocketIP(tls::GetSocket(thread_cli_id)) + " " + Header(#http_head_method) + " " + Header(#http_head_request))  
 | |
|                 Else
 | |
|                   ldl::Logging("Connect:"+lsocket::GetSocketIP(thread_cli_id) + " " + Header(#http_head_method) + " " + Header(#http_head_request), AccessLog)  
 | |
|                   ldl::Logging("Connect:"+lsocket::GetSocketIP(thread_cli_id) + " " + Header(#http_head_method) + " " + Header(#http_head_request))  
 | |
|                 EndIf
 | |
|               Else
 | |
|                 ldl::Logging("Empty accesslog:["+AccessLog+"]")
 | |
|               EndIf
 | |
|               
 | |
|               ;TODO: Header Handler
 | |
|               ; ex. Cookie: #http_head_cookie and #http_head_cookie_set
 | |
|               ;TODO: Optimizing and change Cookie Session Handling.
 | |
|               ldl::Logging("Check {"+#http_head_cookie+"}:["+Header(#http_head_cookie)+"]")
 | |
|               If Header(#http_head_cookie) <> ""
 | |
|                 ldl::Logging("Session:"+Header(#http_head_cookie))
 | |
|                 If configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie))\KillTime >= Second(Date())
 | |
|                   ;Session Lifetime over?
 | |
|                   ldl::Logging("Session TTL Over. Resetting.")
 | |
|                   DeleteMapElement(configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(), Header(#http_head_cookie))
 | |
|                   Header(#http_head_cookie_set) = CreateUUID()
 | |
|                   configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\Cookie = Header(#http_head_cookie_set)
 | |
|                   configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\TTL = 3600
 | |
|                   configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\KillTime = Second(Date()) + configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\TTL
 | |
|                 ElseIf configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie))\Cookie = Header(#http_head_cookie)
 | |
|                   configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie))\KillTime = Second(Date()) + configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie))\TTL
 | |
|                 Else
 | |
|                   ;Session unknown:
 | |
|                   ldl::Logging("Session unknown. Resetting.")
 | |
|                   Header(#http_head_cookie_set) = CreateUUID()
 | |
|                   configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\Cookie = Header(#http_head_cookie_set)
 | |
|                   configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\TTL = 3600
 | |
|                   configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\KillTime = Second(Date()) + configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\TTL
 | |
|                 EndIf
 | |
|                 
 | |
|               Else
 | |
|                 ldl::Logging("No Cookie set .... Set one:")
 | |
|                 Header(#http_head_cookie_set) = CreateUUID()
 | |
|                 ldl::Logging("Set {"+#http_head_cookie_set+"}:["+Header(#http_head_cookie_set)+"]")
 | |
|                 configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\Cookie = Header(#http_head_cookie_set)
 | |
|                 configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\TTL = 3600
 | |
|                 configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\KillTime = Second(Date()) + configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\sessions(Header(#http_head_cookie_set))\TTL
 | |
|                 
 | |
|               EndIf
 | |
|                               ldl::Logging("Header Map fields:")
 | |
|                 ForEach(Header())
 | |
|                   ldl::Logging("Field:["+MapKey(Header())+"] and content:["+Header()+"]")
 | |
|                 Next
 | |
|                 ldl::Logging("Header Map fields finished.")
 | |
|               Select Header(#http_head_method)
 | |
|                 Case #http_method_get
 | |
|                   ;********************************
 | |
|                   ;*
 | |
|                   ;* Default GET
 | |
|                   ;*
 | |
|                   ;{
 | |
|                   ldl::Logging(#http_method_get)
 | |
|                   
 | |
|                   ;*
 | |
|                   ;* Detect websocket upgrade request 
 | |
|                   ;*
 | |
|                   
 | |
|                   If LCase(Header(lhs_web_helper::#http_head_connection)) = lhs_web_helper::#http_connection_upgrade
 | |
|                     ;Whe have a Upgrade Request.
 | |
|                     ;Current Disconnect it with not supported
 | |
|                     response_status = lhs_web_helper::#http_state_501
 | |
|                     thread_type = lhs_web_helper::mimetype("html")
 | |
|                     thread_temp_cache_memory = AllocateMemory(StringByteLength("Unsuported"))
 | |
|                     PokeS(thread_temp_cache_memory, "Unsuported")
 | |
|                     thread_data_size = StringByteLength("Unsuported")
 | |
|                     If response_status = ""   ;Remove if finished...
 | |
|                       ;detect a route to there.
 | |
|                       If Left(Header(#http_head_request),2) = "ws"
 | |
|                         ;Whe have a websocket request.
 | |
|                         ;Detect if whe have a library who react to there:
 | |
|                         ToCallType = call_request(Host_call + thread_requested, #get_handler_prototype)
 | |
|                         If ToCallType = #handler_proto_i_get Or ToCallType = #handler_proto_get
 | |
|                           ;Call Websocket
 | |
|                           
 | |
|                         EndIf
 | |
|                       EndIf
 | |
|                     EndIf
 | |
|                     
 | |
|                   Else
 | |
|                   
 | |
|                     If Header(#http_head_request) = "/"
 | |
|                       thread_requested = default_file
 | |
|                     Else
 | |
|                       thread_requested = Header(#http_head_request)
 | |
|                     EndIf
 | |
|                     
 | |
|                     ldl::Logging("Requested:"+thread_requested)
 | |
|                     ToCallType = call_request(Host_call + thread_requested, #get_handler_prototype)
 | |
|                     If ToCallType = #handler_proto_universal Or ToCallType = #handler_proto_get Or ToCallType = #handler_proto_i_universal Or ToCallType = #handler_proto_i_get
 | |
|                       ToCall = call_request(Host_call + thread_requested)
 | |
|                       If call_request(Host_call + thread_requested, #get_handler_library_perm) = 0
 | |
|                         LibraryToCall = call_request_string(Host_call + thread_requested, #get_handler_library_perm)
 | |
|                         If Len(LibraryToCall) > 0
 | |
|                           Library_ID = OpenLibrary(#PB_Any, LibraryToCall)
 | |
|                           If Library_ID
 | |
|                             ldl::Logging("Library is opened:"+LibraryToCall)
 | |
|                           Else
 | |
|                             ldl::Logging("Library could not be opened")
 | |
|                           EndIf
 | |
|                         EndIf
 | |
|                       EndIf
 | |
|                     Else
 | |
|                       ToCall = 0
 | |
|                     EndIf
 | |
|                     If ToCall = 0
 | |
|                       If Right(thread_requested,1) = "/"
 | |
|                         thread_requested = default_file
 | |
|                       Else
 | |
|                         thread_requested = thread_requested
 | |
|                       EndIf
 | |
|                     EndIf
 | |
|                       
 | |
|                     If ToCall > 0 ;Dann ist eine Funktion hinterlegt und zulässig aufgerufen zu werden.
 | |
|                       ;{ Dynamischer WebHandler
 | |
|                       Handler_Response = call_function(ToCallType, ToCall, Header())
 | |
|   
 | |
|                       If call_request(Host_call + thread_requested, #get_handler_library_perm) = 0 And Library_ID <> 0
 | |
|                         CloseLibrary(Library_ID)
 | |
|                       EndIf
 | |
|                       
 | |
|                       ldl::Logging("Main Client Response :"+Handler_Response)
 | |
|                       MyThreadJSON = ParseJSON(#PB_Any, Handler_Response)
 | |
|                       If MyThreadJSON
 | |
|                         ClearMap(Response())
 | |
|                         ExtractJSONMap(JSONValue(MyThreadJSON), Response())
 | |
|                         FreeJSON(MyThreadJSON)
 | |
|                       Else
 | |
|                         ;WTF ???
 | |
|                         ldl::Logging("Fehler Absturz")
 | |
|                         Break 2 ; Thread abschiessen
 | |
|                       EndIf
 | |
|                       ldl::Logging("Response Content:"+Response(#cha_R_ResponseContentType))
 | |
|                       Select Response(#cha_R_ResponseContentType)
 | |
|                         Case #response_Memory
 | |
|                           ldl::Logging("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
 | |
|                           ldl::Logging("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
 | |
|                       ldl::Logging("Content Finished")
 | |
|                       ;}
 | |
|                       
 | |
|   ;                   ElseIf configuration\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
 | |
|   ;                       thread_file_handle = ReadFile(#PB_Any, configuration\basedir + thread_requested,#PB_File_SharedRead)
 | |
|   ;                     
 | |
|   ;                       If thread_file_handle
 | |
|   ;                         ;Alles Ok 
 | |
|   ;                       Else
 | |
|   ;                         thread_file_handle = ReadFile(#PB_Any, configuration\basedir + configuration\defaultfile,#PB_File_SharedRead)
 | |
|   ;                         ldl::Logging("FileDir:" + configuration\basedir + configuration\defaultfile)
 | |
|   ;                         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
 | |
|                       ;{ Uncached file sems to be stable tested up to 200 clients and 100 requests. 
 | |
|                       If file_check(thread_requested, m_clients(Str(thread_cli_id))\host_id) = thread_requested                    
 | |
|                         thread_file_handle = ReadFile(#PB_Any, home_dir + thread_requested,#PB_File_SharedRead)
 | |
|                         If Not thread_file_handle
 | |
|                             thread_file_handle = ReadFile(#PB_Any, home_dir + default_file ,#PB_File_SharedRead)
 | |
|                             ldl::Logging("FileDir:" + home_dir + default_file, ErrorLog)
 | |
|                             If Not thread_file_handle
 | |
|                               ldl::Logging("Error file set", ErrorLog)
 | |
|                               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\hosts(m_clients(Str(thread_cli_id))\host_id)\mem\MaxFileSize 
 | |
|                           ;Do Handle the File another way.
 | |
|                           thread_temp_cache_memory = AllocateMemory(configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\mem\MaxFileSize)
 | |
|                           thread_temp_file_readed = configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\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
 | |
|                       Else
 | |
|                         thread_redirect = #True  
 | |
|                       EndIf
 | |
|                       
 | |
|                       ;} 
 | |
|                       
 | |
|                     EndIf
 | |
|                 EndIf
 | |
|                 
 | |
|                   ;}
 | |
|                 Case #http_method_post
 | |
|                   
 | |
|                   ;********************************
 | |
|                   ;*
 | |
|                   ;* POST 
 | |
|                   ;*
 | |
|                   ;* Current Finaly Implementet is only application/x-www-form-urlencoded
 | |
|                   ;* Error Handling must be Optimized.
 | |
|                   ;*
 | |
|                   ldl::Logging(#http_method_post)
 | |
| 
 | |
|                   ;{ POST Content Type Decoder
 | |
|                   If LCase(Header(#http_head_content_type)) = #http_content_type_application_x_www_form_urlencoded
 | |
|                     PostMapString = lhs_web_post::mem_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
 | |
|                       ;Should not be possible.
 | |
|                       ldl::Logging("Error in thread, JSON Convert didn't Work")
 | |
|                       Break 2 ; Kill Thread
 | |
|                     EndIf
 | |
|                   ElseIf Left(LCase(Header(#http_head_content_type)), Len(#http_content_type_multipart_form_data)) = #http_content_type_multipart_form_data
 | |
|                     PostMapString = lhs_web_post::mem_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
 | |
|                       ;Someting wrong in the POST
 | |
|                       ldl::Logging("Error with Content. JSON Convert didn't Work")
 | |
|                       Break 2; Kill Thread
 | |
|                     EndIf
 | |
|                   EndIf
 | |
|                   ;}
 | |
|                   
 | |
|                   If Header(#http_head_request) = "/"
 | |
|                     thread_requested = default_file
 | |
|                   Else
 | |
|                     thread_requested = Header(#http_head_request)
 | |
|                   EndIf
 | |
|                   ldl::Logging("Requested:"+thread_requested)
 | |
|                   ToCallType = call_request(Host_call+thread_requested, #get_handler_prototype)
 | |
|                   If ToCallType = #handler_proto_universal Or ToCallType = #handler_proto_post Or ToCallType = #handler_proto_i_universal Or ToCallType = #handler_proto_i_post
 | |
|                     ToCall = call_request(Host_call + thread_requested)
 | |
|                     ldl::Logging("A To Call is found:"+Str(ToCall))
 | |
|                     If call_request(Host_call + thread_requested, #get_handler_library_perm) = 0
 | |
|                       LibraryToCall = call_request_string(Host_call + thread_requested, #get_handler_library)
 | |
|                       If Len(LibraryToCall) > 0
 | |
|                         Library_ID = OpenLibrary(#PB_Any, LibraryToCall)
 | |
|                         If Library_ID
 | |
|                           
 | |
|                         Else
 | |
|                           ldl::Logging("Library could not be opened")
 | |
|                         EndIf
 | |
|                       EndIf
 | |
|                     EndIf
 | |
|                   Else
 | |
|                     ToCall = 0
 | |
|                   EndIf
 | |
|                   
 | |
|                   If ToCall > 0 ;A dynamic webhandler is available, call.
 | |
|                     ;{ Dynamic webhandler.
 | |
|                     
 | |
|                     Handler_Response = call_function(ToCallType, ToCall, Header(), PostMapString)
 | |
|                     If call_request(Host_call + thread_requested, #get_handler_library_perm) = 0 And Library_ID <> 0
 | |
|                       CloseLibrary(Library_ID)
 | |
|                     EndIf                    
 | |
|                     ldl::Logging("Main Client Response :"+Handler_Response)
 | |
|                     MyThreadJSON = ParseJSON(#PB_Any, Handler_Response)
 | |
|                     If MyThreadJSON
 | |
|                       ClearMap(Response())
 | |
|                       ExtractJSONMap(JSONValue(MyThreadJSON), Response())
 | |
|                       FreeJSON(MyThreadJSON)
 | |
|                     Else
 | |
|                       ;WTF ???
 | |
|                       ldl::Logging("Fehler Absturz")
 | |
|                       Break 2 ; Thread abschiessen
 | |
|                     EndIf
 | |
|                     ldl::Logging("Response Content:"+Response(#cha_R_ResponseContentType))
 | |
|                     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
 | |
|                     ldl::Logging("Content Finished")
 | |
|                     ;}
 | |
|                     
 | |
|                   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
 | |
| ;                       thread_file_handle = ReadFile(#PB_Any, "srv/www" + thread_requested,#PB_File_SharedRead)
 | |
| ;                     
 | |
| ;                       If thread_file_handle
 | |
| ;                         ;Alles Ok 
 | |
| ;                       Else
 | |
| ;                         thread_file_handle = ReadFile(#PB_Any, "srv/www" + "index.html",#PB_File_SharedRead)
 | |
| ;                         ldl::Logging("FileDir:" + "srv/www" + "index.html")
 | |
| ;                         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
 | |
|                     ;{ Uncached file sems to be stable tested up to 200 clients and 100 requests.
 | |
|                     If file_check(thread_requested, m_clients(Str(thread_cli_id))\host_id) = thread_requested                    
 | |
|                       thread_file_handle = ReadFile(#PB_Any, home_dir+ thread_requested,#PB_File_SharedRead)
 | |
|                       If Not thread_file_handle
 | |
|                           thread_file_handle = ReadFile(#PB_Any, home_dir + default_file ,#PB_File_SharedRead)
 | |
|                           ldl::Logging("FileDir:" + home_dir + default_file)
 | |
|                           If Not thread_file_handle
 | |
|                             ldl::Logging("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\hosts(m_clients(Str(thread_cli_id))\host_id)\mem\MaxFileSize
 | |
|                         ;Do Handle the File another way.
 | |
|                         thread_temp_cache_memory = AllocateMemory(configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\mem\MaxFileSize)
 | |
|                         thread_temp_file_readed = configuration\hosts(m_clients(Str(thread_cli_id))\host_id)\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
 | |
|                     Else
 | |
|                       ;Send Redirect:
 | |
|                       thread_redirect = #True
 | |
|                     EndIf
 | |
|                     
 | |
|                     ;} 
 | |
|                     
 | |
|                   EndIf
 | |
| 
 | |
| 
 | |
|                   
 | |
|                 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
 | |
|               If thread_data_size Or thread_redirect = #True
 | |
|                 If thread_type = "" 
 | |
|                   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) = status_get_header("200")
 | |
|                 EndIf
 | |
|                 
 | |
|                 If Response(#http_head_cookie) <> ""
 | |
|                   Header(#http_head_cookie) = Response(#http_head_cookie)
 | |
|                 EndIf
 | |
|                 
 | |
|                 If thread_redirect = #True
 | |
|                   Header(#http_head_redirect) = file_check(thread_requested, m_clients(Str(thread_cli_id))\host_id)
 | |
|                   ;TODO: Verify it's a file or a configuration ...
 | |
|                   If Header(#http_head_redirect) = "configuration\errorfile404"
 | |
|                     ldl::Logging("Error 404 : ["+configuration\status("404")\content+"]")
 | |
|                     Header(#http_head_redirect) = ""
 | |
|                   EndIf
 | |
|                   
 | |
|                   Header(#http_head_status) = status_get_header("303")
 | |
|                 Else
 | |
|                   Header(#http_head_content_length) = Str(thread_data_size)
 | |
|                   Header(#http_head_content_type) = thread_type
 | |
|                 EndIf
 | |
|                 
 | |
|                 Header(#http_head_connection) = "Keep-Alive"
 | |
|                 Header(#http_head_keep_alive) = "timeout=15, max=1000"
 | |
|                 
 | |
|                 thread_header = http_header_generate(Header())
 | |
|                 ldl::Logging("Header:")
 | |
|                 ldl::Logging(thread_header)
 | |
|                 ;large File Handling
 | |
|                 If thread_redirect = #True
 | |
|                   thread_buffer = AllocateMemory(StringByteLength(thread_header)+12)
 | |
|                 ElseIf thread_oversized_file = #False 
 | |
|                   thread_buffer = AllocateMemory(thread_data_size+StringByteLength(thread_header)+12)
 | |
|                 Else
 | |
|                   thread_buffer = AllocateMemory(thread_temp_file_readed+StringByteLength(thread_header)+12)
 | |
|                 EndIf
 | |
|                 
 | |
|                 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
 | |
|                 ldl::Logging("Header Finished")
 | |
|                 ldl::Logging("Header Map fields:")
 | |
|                 ForEach(Header())
 | |
|                   ldl::Logging("Field:["+MapKey(Header())+"] and content:["+Header()+"]")
 | |
|                 Next
 | |
|                 ldl::Logging("Header Map fields finished.")
 | |
|               EndIf
 | |
|               ;Copy temporary File Buffer to normal Buffer.
 | |
|               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
 | |
|                 CopyMemory(thread_temp_cache_memory, thread_buffer_offset, thread_data_size)
 | |
|                 ldl::Logging("Cache Address Memory:"+Str(thread_temp_cache_memory))
 | |
|                 FreeMemory(thread_temp_cache_memory)
 | |
|                 thread_temp_cache_memory = 0
 | |
|               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
 | |
|                 CopyMemory(thread_temp_cache_memory, thread_buffer_offset, thread_temp_file_readed)
 | |
|                 ldl::Logging("Oversized Cache Address Memory:"+Str(thread_temp_cache_memory))
 | |
|                 FreeMemory(thread_temp_cache_memory)
 | |
|                 thread_temp_cache_memory = 0
 | |
|               ElseIf thread_redirect = #True
 | |
|                 thread_redirect = #False
 | |
|               Else             
 | |
|                 ldl::Logging("File Buffer Troubles.")
 | |
|                 If thread_temp_cache_memory = 0 : ldl::Logging("thread_temp_cache_memory = 0") : EndIf
 | |
|                 If thread_buffer_offset = 0 : ldl::Logging("thread_buffer_offset = 0") : EndIf
 | |
|                 If thread_data_size = 0 : ldl::Logging("thread_data_size = 0") : EndIf
 | |
|                 thread_alive = #False
 | |
|                 Break 2
 | |
|               EndIf
 | |
|               
 | |
|               ;   EndIf
 | |
|                 
 | |
|               ldl::Logging("HTTP File Buffer Cleaned.")
 | |
|               ;Löschen des eingang Speichers.
 | |
|               If m_clients(Str(thread_cli_id))\datenbuffer()\Buffer > 0
 | |
|                 FreeMemory(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)
 | |
|               EndIf
 | |
|               DeleteElement(m_clients(Str(thread_cli_id))\datenbuffer())
 | |
| 
 | |
|               ;Send the data in memory to client.
 | |
|               If thread_redirect = #True
 | |
|                 sent_total = thread_buffer_offset - thread_buffer
 | |
|               ElseIf thread_oversized_file = #False
 | |
|                 sent_total = thread_data_size+(thread_buffer_offset-thread_buffer)
 | |
|               Else
 | |
|                 sent_total = thread_temp_file_readed+(thread_buffer_offset-thread_buffer)
 | |
|               EndIf
 | |
|               ldl::Logging("Memory send_total:"+Str(sent_total))
 | |
|               ;Erledigt: Stoped download kill server...
 | |
|               If  m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
 | |
|                 sent_length = sent_total 
 | |
|                 sent_buffer_address = thread_buffer                
 | |
|                 sent_total = 0
 | |
|                 Repeat 
 | |
|                   sent = tls::WriteTLSSocket(thread_cli_id, sent_buffer_address , sent_length)
 | |
|                   If sent <> -1
 | |
|                     ldl::Logging("ClientID:" + Str(thread_cli_id) + " HTTPS Sent:"+Str(sent)+" bytes")
 | |
|                     sent_length - sent
 | |
|                     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)
 | |
|                         ldl::Logging("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
 | |
|                         ldl::Logging("ClientID:" + Str(thread_cli_id) + " HTTPS Large File -> to Send:"+Str(sent_length)+" bytes")
 | |
|                         sent_buffer_address + sent
 | |
|                       EndIf                      
 | |
|                     EndIf
 | |
|                     
 | |
|                     sent_total + sent
 | |
|                   Else
 | |
|                     If IsFile(thread_file_handle)
 | |
|                       CloseFile(thread_file_handle)
 | |
|                     EndIf
 | |
|                     
 | |
|                     ldl::Logging("HTTPS Sent error:"+tls::ErrorTLSCli(thread_cli_id))
 | |
|                     thread_alive = #False
 | |
|                     Break 2
 | |
|                   EndIf
 | |
|                   
 | |
|                 Until sent_length <= 0 
 | |
|                 sent = sent_total
 | |
| 
 | |
|               Else
 | |
|                 sent_length = sent_total 
 | |
|                 sent_buffer_address = thread_buffer
 | |
|                 sent_total = 0
 | |
|                 Repeat 
 | |
|                   If lsocket::IsClientSocket(thread_cli_id)
 | |
|                     sent = lsocket::WriteSocket(thread_cli_id, thread_buffer , sent_length) 
 | |
|                   Else
 | |
|                     thread_alive=#False
 | |
|                     Break 2
 | |
|                   EndIf
 | |
|                   
 | |
|                   If sent <> -1
 | |
|                     ldl::Logging("HTTP Sent:"+Str(sent)+" bytes")
 | |
|                     sent_length - sent
 | |
|                     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
 | |
|                     
 | |
|                     sent_total + sent
 | |
|                   Else
 | |
|                     If IsFile(thread_file_handle)
 | |
|                       CloseFile(thread_file_handle)
 | |
|                     EndIf
 | |
|                     
 | |
|                     ldl::Logging("HTTP Sent error:"+Str(sent))
 | |
|                     thread_alive = #False
 | |
|                     Break 2
 | |
|                   EndIf
 | |
|                   
 | |
|                 Until sent_length <= 0 
 | |
|                 sent = sent_total                
 | |
|               EndIf
 | |
|               
 | |
|               If sent = thread_data_size+(thread_buffer_offset-thread_buffer)
 | |
|                 ;Ok
 | |
|                 ;ldl::Logging("Gesendet:" + PeekS(thread_buffer,thread_buffer_length, #PB_Ascii))
 | |
|                 If thread_buffer > 0
 | |
|                   FreeMemory(thread_buffer)
 | |
|                 EndIf
 | |
|                 
 | |
|                 m_clients(Str(thread_cli_id))\client_do_cli = #CLI_DO_WaitDataReceive
 | |
|                 m_clients(Str(thread_cli_id))\client_do_srv = #SRV_DO_DataReceive             
 | |
|               Else
 | |
|                 ;Fehler beim Senden ... Thread beenden.
 | |
|                 ldl::Logging("Fehler:" + Str(Sent))
 | |
|                 thread_alive = #False
 | |
|             
 | |
|               EndIf
 | |
|               ;
 | |
|             Wend  
 | |
|             ;}
 | |
|             
 | |
|             
 | |
|             m_clients(Str(thread_cli_id))\client_do_cli = #CLI_DO_WaitDataReceive
 | |
|             
 | |
|         EndSelect
 | |
|       EndIf
 | |
|       ;}
 | |
|       
 | |
|     Until thread_alive = #False
 | |
|     ldl::Logging("Thread should now die...")
 | |
|     ResetList(m_clients(Str(thread_cli_id))\datenbuffer())
 | |
|     ldl::Logging("Thread kill all Initialized Memory buffers:")
 | |
|     While NextElement(m_clients(Str(thread_cli_id))\datenbuffer())
 | |
|       If m_clients(Str(thread_cli_id))\datenbuffer()\Initialized
 | |
|         ldl::Logging("Kill:"+Str(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)+ " ...")
 | |
|         FreeMemory(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer)
 | |
|         DeleteElement(m_clients(Str(thread_cli_id))\datenbuffer())
 | |
|         ldl::Logging("Freed and removed")
 | |
|       Else
 | |
|         ldl::Logging("Remove element from List with uninitialized Memory ID: "+Str(m_clients(Str(thread_cli_id))\datenbuffer()\Buffer))
 | |
|         DeleteElement(m_clients(Str(thread_cli_id))\datenbuffer())
 | |
|         ldl::Logging("Removed")
 | |
|       EndIf
 | |
|     Wend
 | |
|     If m_clients(Str(thread_cli_id))\client_type = #client_HTTPS
 | |
|       ldl::Logging("Kill HTTPS Socket:" + Str(thread_cli_id))
 | |
|       ;tls::CloseTLSSocket(thread_cli_id)
 | |
|       count_client(#client_HTTPS, #client_remove)
 | |
|       ldl::Logging("Killed.")
 | |
|     Else
 | |
|       ldl::Logging("Kill HTTP Socket:" + Str(thread_cli_id))
 | |
|       lsocket::CloseSocket(thread_cli_id)
 | |
|       count_client(#client_HTTP, #client_remove)
 | |
|       ldl::Logging("Killed.")
 | |
|     EndIf
 | |
|     ldl::Logging("Remove Client from map...")
 | |
|     DeleteMapElement(m_clients(), Str(thread_cli_id))
 | |
|     ldl::Logging("Removed and thread now died.")
 | |
|     
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure.s call_request_string(RequestString.s, Info.i = #get_handler_procedure)
 | |
|     Protected CurrPos, Count, Counter, PartString.s
 | |
|     ;"SpecServer:["+Host_ID+"]"
 | |
|     Protected.s Host_ID = ""
 | |
|     Protected HF_Count, HF_Pos
 | |
|     If Left(RequestString,12) = "SpecServer:["
 | |
|       ;Whe have host specific
 | |
|       HF_Pos = FindString(RequestString, "]",12)
 | |
|       Host_ID = Left(RequestString, HF_Pos)
 | |
|     EndIf
 | |
|     ldl::Logging("call_request: "+RequestString)
 | |
|     If m_request(GetExtensionPart(RequestString))\routetype = #handler_type
 | |
|       Select Info
 | |
|         Case #get_handler_procedure
 | |
|           ProcedureReturn Str(m_request(Host_ID+GetExtensionPart(RequestString))\call)
 | |
|         Case #get_handler_prototype
 | |
|           ProcedureReturn Str(m_request(Host_ID+GetExtensionPart(RequestString))\type)
 | |
|         Case #get_handler_library
 | |
|           ProcedureReturn m_request(Host_ID+GetExtensionPart(RequestString))\library
 | |
|         Case #get_handler_library_perm
 | |
|           ProcedureReturn Str(m_request(Host_ID+GetExtensionPart(RequestString))\perm)
 | |
|         Default
 | |
|           ProcedureReturn "0"
 | |
|       EndSelect
 | |
|     EndIf
 | |
|     
 | |
|     ldl::Logging("call_request: "+RequestString + " Routetype :["+Str(m_request(RequestString)\routetype)+"]")
 | |
|     If m_request(RequestString)\routetype = #handler_only Or m_request(RequestString)\routetype = #handler_sub
 | |
|       Select Info
 | |
|         Case #get_handler_procedure
 | |
|           ProcedureReturn Str(m_request(RequestString)\call)
 | |
|         Case #get_handler_prototype
 | |
|           ProcedureReturn Str(m_request(RequestString)\type)
 | |
|         Case #get_handler_library
 | |
|           ProcedureReturn m_request(RequestString)\library
 | |
|         Case #get_handler_library_perm
 | |
|           ProcedureReturn Str(m_request(RequestString)\perm)          
 | |
|         Default
 | |
|           ProcedureReturn "0"
 | |
|       EndSelect
 | |
|     ElseIf m_request(GetExtensionPart(RequestString))\routetype = #handler_sub
 | |
|       Select Info
 | |
|         Case #get_handler_procedure
 | |
|           ProcedureReturn Str(m_request(Host_ID+GetExtensionPart(RequestString))\call)
 | |
|         Case #get_handler_prototype
 | |
|           ProcedureReturn Str(m_request(Host_ID+GetExtensionPart(RequestString))\type)
 | |
|         Case #get_handler_library
 | |
|           ProcedureReturn m_request(Host_ID+GetExtensionPart(RequestString))\library
 | |
|         Case #get_handler_library_perm
 | |
|           ProcedureReturn Str(m_request(Host_ID+GetExtensionPart(RequestString))\perm)             
 | |
|         Default
 | |
|           ProcedureReturn "0"
 | |
|       EndSelect
 | |
|     EndIf
 | |
|     ldl::Logging("call_request now on sub check: "+RequestString + " Routetype :["+Str(m_request(RequestString)\routetype)+"]")
 | |
|    
 | |
|     ;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 Str(m_request(PartString)\call)
 | |
|           Case #get_handler_prototype
 | |
|             ProcedureReturn Str(m_request(PartString)\type)
 | |
|           Case #get_handler_library
 | |
|             ProcedureReturn m_request(PartString)\library
 | |
|           Case #get_handler_library_perm
 | |
|             ProcedureReturn Str(m_request(PartString)\type)
 | |
|           Default
 | |
|             ProcedureReturn "0"
 | |
|         EndSelect
 | |
|       EndIf
 | |
|       Count + 1
 | |
|     Wend
 | |
|     ldl::Logging("call_request Not found !!!!!!!!! : "+RequestString + "Routetype :["+Str(m_request(RequestString)\routetype)+"]")
 | |
|    
 | |
|     ProcedureReturn "0"
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure call_request(RequestString.s, Info.i = #get_handler_procedure)
 | |
|     ProcedureReturn Val(call_request_string(RequestString.s, Info.i))
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure.s register_client_handler(Route.s, Callback.i, AppPrototype.i = #handler_proto_get, RouteType.i = #handler_sub, Host.s = "")
 | |
|     If Len(Host) > 0
 | |
|       Host = "SpecServer:["+Host+"]"
 | |
|     EndIf
 | |
|     
 | |
|     m_request(Host+Route)\type = AppPrototype
 | |
|     m_request(Host+Route)\call = Callback
 | |
|     m_request(Host+Route)\routetype = RouteType
 | |
|     m_request(Host+Route)\route = Route
 | |
|     m_request(Host+Route)\host = Host
 | |
|     ldl::Logging("Handler Registriert:"+Route+ " at Host:["+Host+"]")
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure advanced_register_handler(Route.s, Permament.i = 0, Library.s = "", Host.s="")
 | |
|     If Len(Host) > 0
 | |
|       Host = "SpecServer:["+Host+"]"
 | |
|     EndIf
 | |
|     m_request(Host+Route)\perm = Permament
 | |
|     m_request(Host+Route)\library = Library
 | |
|   EndProcedure
 | |
|   
 | |
|   Procedure.s call_function(ToCallType.i, ToCall.i, Map Header.s(), PostMapString.s ="")
 | |
|     Define.i Handler_Response_Adress
 | |
|     Define.s Handler_Response, Header_string
 | |
|     Header_string = MapToJSONString(Header())
 | |
|     Select ToCallType
 | |
|       Case #handler_proto_universal
 | |
|         Define.WebHandler_Universal ToCallProcedure_Universal = ToCall
 | |
|         Handler_Response_Adress = ToCallProcedure_Universal(Header_string, PostMapString )
 | |
|         ldl::Logging("Response Address:"+Str(Handler_Response_Adress))
 | |
|         Handler_Response = PeekS(Handler_Response_Adress)
 | |
|       Case #handler_proto_get
 | |
|         Define.WebHandler_Get ToCallProcedureGet = ToCall
 | |
|         Handler_Response_Adress = ToCallProcedureGet(Header_string)
 | |
|         Handler_Response = PeekS(Handler_Response_Adress)
 | |
|       Case #handler_proto_post
 | |
|         Define.WebHandler_Post ToCallProcedure_Post = ToCall
 | |
|         Handler_Response_Adress = ToCallProcedure_Post(Header_string, PostMapString)
 | |
|         Handler_Response = PeekS(Handler_Response_Adress)
 | |
|       Case #handler_proto_i_universal
 | |
|         Define.WebHandler_i_Universal ToCallProcedure_i_Universal = ToCall
 | |
|         Handler_Response = ToCallProcedure_i_Universal(Header_string, PostMapString )
 | |
|       Case #handler_proto_i_get
 | |
|         Define.WebHandler_i_get ToCallProcedure_i_get = ToCall
 | |
|         Handler_Response = ToCallProcedure_i_get(Header_string)
 | |
|       Case #handler_proto_i_post
 | |
|         Define.WebHandler_i_Universal ToCallProcedure_i_post = ToCall
 | |
|         Handler_Response = ToCallProcedure_i_post(Header_string, PostMapString )
 | |
|     EndSelect
 | |
|     ProcedureReturn Handler_Response
 | |
|   EndProcedure
 | |
|   
 | |
|   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
 | |
|   
 | |
|   Procedure.s file_check(thread_requested.s, hostid.s)
 | |
|     Protected file_type.i
 | |
|     Debug thread_requested
 | |
|     file_type = FileSize(configuration\hosts(hostid)\basedir + thread_requested)
 | |
|     If file_type  = -1
 | |
|       thread_requested = "configuration\errorfile404"       ;TODO: Change wrong File
 | |
|       
 | |
|     ElseIf file_type = -2
 | |
|       ;Is a Directory
 | |
|       If Right(thread_requested,1) = "/" 
 | |
|         thread_requested = thread_requested + "index.html"
 | |
|       Else
 | |
|         thread_requested = thread_requested + "/" + "index.html"
 | |
|       EndIf
 | |
|     EndIf
 | |
|     Debug "Final:"+thread_requested
 | |
|     ProcedureReturn thread_requested.s
 | |
|   EndProcedure
 | |
|   
 | |
|   
 | |
| EndModule
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |