aboutsummaryrefslogtreecommitdiffstats
path: root/library/HTTP_Server_Emulation.ttcn
blob: 16d142d2716425bedc2b9684d7d05dbea1476a40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* HTTP Emulation in TTCN-3
 *
 * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * This module implements a HTTP/HTTPs server based on TestPorts/HTTPmsg,
 * (see also deps/titan.TestPorts.HTTPmsg)
 */

module HTTP_Server_Emulation {

import from General_Types all;
import from Osmocom_Types all;
import from HTTPmsg_Types all;
import from HTTPmsg_PortType all;

/***********************************************************************
 * Main Emulation Component
 ***********************************************************************/

type record HttpServerEmulationCfg {
	charstring http_bind_ip,
	integer http_bind_port,
	boolean use_ssl
};

type component HTTP_Server_Emulation_CT {
	/* Communication with underlying HTTP CodecPort */
	port HTTPmsg_PT HTTP_server_port;

	/* Communication with Clients */
	port HTTP_SRV_PT CLIENT;
	port HTTP_SRV_PROC_PT CLIENT_PROC;
	port HTTP_SRV_PT CLIENT_DEFAULT;

	/* Configuration by the user */
	var HttpServerEmulationCfg g_http_cfg;

	/* State */
	var HTTP_ConnHdlr vc_conn_table[16];
};

private function f_init(HttpServerEmulationCfg cfg) runs on HTTP_Server_Emulation_CT {

	g_http_cfg := cfg;

	map(self:HTTP_server_port, system:HTTP_server_port);
	var Listen listen := { local_hostname := g_http_cfg.http_bind_ip,
			       portnumber := g_http_cfg.http_bind_port,
			       use_ssl := g_http_cfg.use_ssl };

	/* Start HTTP server */
	HTTP_server_port.send(listen);
}

private function f_vc_conn_table_add(HTTP_ConnHdlr vc_conn) runs on HTTP_Server_Emulation_CT {
	var integer i;
	for (i := 0; i < sizeof(vc_conn_table); i := i + 1) {
		if (not isbound(vc_conn_table[i])) {
			vc_conn_table[i] := vc_conn;
			return;
		}
	}
	testcase.stop("No Space in vc_conn_table[i] for ", vc_conn);
}

/* Forward request to all registered clients */
private function forward_req(HTTPMessage recv_req_value) runs on HTTP_Server_Emulation_CT {

	var integer i;
	for (i := 0; i < sizeof(vc_conn_table); i := i + 1) {
		if (isbound(vc_conn_table[i])) {
			CLIENT.send(recv_req_value) to vc_conn_table[i];
		}
	}
}

function main(HttpServerEmulationCfg cfg) runs on HTTP_Server_Emulation_CT {

	var HTTP_ConnHdlr vc_conn;
	var template (value) Close close := { client_id := omit };
	var template (present) Half_close half_close := { client_id := ? };
	var template (present) HTTPMessage recv_req := { request := ? };
	var template (present) HTTPMessage recv_req_bin := { request_binary := ? };
	var HTTPMessage recv_req_value;
	var HTTPMessage send_resp_value;

	f_init(cfg);

	while(true) {
	alt {
	[] HTTP_server_port.receive(recv_req) -> value recv_req_value {
		forward_req(recv_req_value);
        	}
	[] HTTP_server_port.receive(recv_req_bin) -> value recv_req_value {
		forward_req(recv_req_value);
        	}
	[] CLIENT.receive(HTTPMessage:?) -> value send_resp_value sender vc_conn {
		HTTP_server_port.send(send_resp_value);
		}
	[] HTTP_server_port.receive(half_close) {
		HTTP_server_port.send(close);
		}
	[] CLIENT_PROC.getcall(HTTPEM_register:{}) -> sender vc_conn {
		f_vc_conn_table_add(vc_conn);
		CLIENT_PROC.reply(HTTPEM_register:{}) to vc_conn;
		}
	}
	}

}


/***********************************************************************
 * Interaction between Main and Client Components
 ***********************************************************************/
type port HTTP_SRV_PT message {
	inout HTTPMessage;
} with { extension "internal" };

signature HTTPEM_register();

type port HTTP_SRV_PROC_PT procedure {
	inout HTTPEM_register;
} with { extension "internal" };


/***********************************************************************
 * Client Component
 ***********************************************************************/

type component HTTP_ConnHdlr {
	port HTTP_SRV_PT HTTP_SRV;
	port HTTP_SRV_PROC_PT HTTP_SRV_PROC;
};

function f_http_register() runs on HTTP_ConnHdlr {
	HTTP_SRV_PROC.call(HTTPEM_register:{}) {
		[] HTTP_SRV_PROC.getreply(HTTPEM_register:{});
	}
}

}