Philipp Maier | 964533e | 2024-03-04 10:53:23 +0100 | [diff] [blame] | 1 | /* HTTP Emulation in TTCN-3 |
| 2 | * |
| 3 | * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH |
| 4 | * |
| 5 | * Released under the terms of GNU General Public License, Version 2 or |
| 6 | * (at your option) any later version. |
| 7 | * |
| 8 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 9 | * |
| 10 | * This module implements a HTTP/HTTPs server based on TestPorts/HTTPmsg, |
| 11 | * (see also deps/titan.TestPorts.HTTPmsg) |
| 12 | */ |
| 13 | |
| 14 | module HTTP_Server_Emulation { |
| 15 | |
| 16 | import from General_Types all; |
| 17 | import from Osmocom_Types all; |
| 18 | import from HTTPmsg_Types all; |
| 19 | import from HTTPmsg_PortType all; |
| 20 | |
| 21 | /*********************************************************************** |
| 22 | * Main Emulation Component |
| 23 | ***********************************************************************/ |
| 24 | |
| 25 | type record HttpServerEmulationCfg { |
| 26 | charstring http_bind_ip, |
| 27 | integer http_bind_port, |
| 28 | boolean use_ssl |
| 29 | }; |
| 30 | |
| 31 | type component HTTP_Server_Emulation_CT { |
| 32 | /* Communication with underlying HTTP CodecPort */ |
| 33 | port HTTPmsg_PT HTTP_server_port; |
| 34 | |
| 35 | /* Communication with Clients */ |
| 36 | port HTTP_SRV_PT CLIENT; |
| 37 | port HTTP_SRV_PROC_PT CLIENT_PROC; |
| 38 | port HTTP_SRV_PT CLIENT_DEFAULT; |
| 39 | |
| 40 | /* Configuration by the user */ |
| 41 | var HttpServerEmulationCfg g_http_cfg; |
| 42 | |
| 43 | /* State */ |
| 44 | var HTTP_ConnHdlr vc_conn_table[16]; |
| 45 | }; |
| 46 | |
| 47 | private function f_init(HttpServerEmulationCfg cfg) runs on HTTP_Server_Emulation_CT { |
| 48 | |
| 49 | g_http_cfg := cfg; |
| 50 | |
| 51 | map(self:HTTP_server_port, system:HTTP_server_port); |
| 52 | var Listen listen := { local_hostname := g_http_cfg.http_bind_ip, |
| 53 | portnumber := g_http_cfg.http_bind_port, |
| 54 | use_ssl := g_http_cfg.use_ssl }; |
| 55 | |
| 56 | /* Start HTTP server */ |
| 57 | HTTP_server_port.send(listen); |
| 58 | } |
| 59 | |
| 60 | private function f_vc_conn_table_add(HTTP_ConnHdlr vc_conn) runs on HTTP_Server_Emulation_CT { |
| 61 | var integer i; |
| 62 | for (i := 0; i < sizeof(vc_conn_table); i := i + 1) { |
| 63 | if (not isbound(vc_conn_table[i])) { |
| 64 | vc_conn_table[i] := vc_conn; |
| 65 | return; |
| 66 | } |
| 67 | } |
| 68 | testcase.stop("No Space in vc_conn_table[i] for ", vc_conn); |
| 69 | } |
| 70 | |
| 71 | /* Forward request to all registered clients */ |
| 72 | private function forward_req(HTTPMessage recv_req_value) runs on HTTP_Server_Emulation_CT { |
| 73 | |
| 74 | var integer i; |
| 75 | for (i := 0; i < sizeof(vc_conn_table); i := i + 1) { |
| 76 | if (isbound(vc_conn_table[i])) { |
| 77 | CLIENT.send(recv_req_value) to vc_conn_table[i]; |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | function main(HttpServerEmulationCfg cfg) runs on HTTP_Server_Emulation_CT { |
| 83 | |
| 84 | var HTTP_ConnHdlr vc_conn; |
| 85 | var template (value) Close close := { client_id := omit }; |
| 86 | var template (present) Half_close half_close := { client_id := ? }; |
| 87 | var template (present) HTTPMessage recv_req := { request := ? }; |
| 88 | var template (present) HTTPMessage recv_req_bin := { request_binary := ? }; |
| 89 | var HTTPMessage recv_req_value; |
| 90 | var HTTPMessage send_resp_value; |
| 91 | |
| 92 | f_init(cfg); |
| 93 | |
| 94 | while(true) { |
| 95 | alt { |
| 96 | [] HTTP_server_port.receive(recv_req) -> value recv_req_value { |
| 97 | forward_req(recv_req_value); |
| 98 | } |
| 99 | [] HTTP_server_port.receive(recv_req_bin) -> value recv_req_value { |
| 100 | forward_req(recv_req_value); |
| 101 | } |
| 102 | [] CLIENT.receive(HTTPMessage:?) -> value send_resp_value sender vc_conn { |
| 103 | HTTP_server_port.send(send_resp_value); |
| 104 | } |
| 105 | [] HTTP_server_port.receive(half_close) { |
| 106 | HTTP_server_port.send(close); |
| 107 | } |
| 108 | [] CLIENT_PROC.getcall(HTTPEM_register:{}) -> sender vc_conn { |
| 109 | f_vc_conn_table_add(vc_conn); |
| 110 | CLIENT_PROC.reply(HTTPEM_register:{}) to vc_conn; |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | } |
| 116 | |
| 117 | |
| 118 | /*********************************************************************** |
| 119 | * Interaction between Main and Client Components |
| 120 | ***********************************************************************/ |
| 121 | type port HTTP_SRV_PT message { |
| 122 | inout HTTPMessage; |
| 123 | } with { extension "internal" }; |
| 124 | |
| 125 | signature HTTPEM_register(); |
| 126 | |
| 127 | type port HTTP_SRV_PROC_PT procedure { |
| 128 | inout HTTPEM_register; |
| 129 | } with { extension "internal" }; |
| 130 | |
| 131 | |
| 132 | /*********************************************************************** |
| 133 | * Client Component |
| 134 | ***********************************************************************/ |
| 135 | |
| 136 | type component HTTP_ConnHdlr { |
| 137 | port HTTP_SRV_PT HTTP_SRV; |
| 138 | port HTTP_SRV_PROC_PT HTTP_SRV_PROC; |
| 139 | }; |
| 140 | |
| 141 | function f_http_register() runs on HTTP_ConnHdlr { |
| 142 | HTTP_SRV_PROC.call(HTTPEM_register:{}) { |
| 143 | [] HTTP_SRV_PROC.getreply(HTTPEM_register:{}); |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | } |