Merge "implemented decmatch (artf724241)"
[deliverable/titan.core.git] / core / Communication.cc
CommitLineData
d44e3c4f 1/******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
f08ff9ca 11 * Baranyi, Botond
d44e3c4f 12 * Beres, Szabolcs
13 * Delic, Adam
14 * Feher, Csaba
15 * Forstner, Matyas
16 * Kovacs, Ferenc
17 * Raduly, Csaba
18 * Szabo, Janos Zoltan – initial implementation
19 * Szalai, Gabor
20 * Zalanyi, Balazs Andor
21 *
22 ******************************************************************************/
970ed795
EL
23#include "Communication.hh"
24
25#include <stdlib.h>
26#include <string.h>
27#include <stdarg.h>
28#include <unistd.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <netdb.h>
32
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <sys/utsname.h>
36#include <netinet/in.h>
37#include <netinet/tcp.h>
38#include <arpa/inet.h>
39#include <sys/un.h>
40
41#include "../common/dbgnew.hh"
42#include "Types.h"
43#include "Message_types.hh"
44#include "Module_list.hh"
45#include "Verdicttype.hh"
46#include "Fd_And_Timeout_User.hh"
47#include "Runtime.hh"
48#include "Logger.hh"
49#include "Port.hh"
50#include "Component.hh"
51
52#include "TitanLoggerApiSimple.hh"
53#include "../common/version.h"
54
55#include "Event_Handler.hh"
016a1a93
BB
56#include "Debugger.hh"
57#include "DebugCommands.hh"
970ed795
EL
58
59class MC_Connection : public Fd_And_Timeout_Event_Handler {
60 virtual void Handle_Fd_Event(int fd,
61 boolean is_readable, boolean is_writable, boolean is_error);
62 virtual void Handle_Timeout(double time_since_last_call);
63public:
64 MC_Connection(const int * fd, Text_Buf * buf) :
65 Fd_And_Timeout_Event_Handler(), mc_fd(fd), incoming_buf(buf) {}
66 virtual void log() const;
67private:
68 const int * mc_fd;
69 Text_Buf * incoming_buf;
70};
71
72int TTCN_Communication::mc_fd = -1;
73HCNetworkHandler TTCN_Communication::hcnh;
74boolean TTCN_Communication::local_addr_set = FALSE,
75 TTCN_Communication::mc_addr_set = FALSE,
76 TTCN_Communication::is_connected = FALSE;
77Text_Buf TTCN_Communication::incoming_buf;
78MC_Connection TTCN_Communication::mc_connection(
79 &TTCN_Communication::mc_fd, &TTCN_Communication::incoming_buf);
80double TTCN_Communication::call_interval = 0.0;
81
82void TTCN_Communication::set_local_address(const char *host_name)
83{
84 if (local_addr_set)
85 TTCN_warning("The local address has already been set.");
86 if (is_connected)
87 TTCN_error("Trying to change the local address, but there is an existing "
88 "control connection to MC.");
89 if (host_name == NULL){
90 fprintf(stderr,"TTCN_Communication::set_local_address: internal error: " // There is no connection to the MC
91 "invalid host name.\r\n"); // We should log to the console also
92 TTCN_error("TTCN_Communication::set_local_address: internal error: "
93 "invalid host name.");
94 }
95 if (!hcnh.set_local_addr(host_name, 0)){
96 fprintf(stderr,"Could not get the IP address for the local address " // There is no connection to the MC
97 "(%s): Host name lookup failure.\r\n", host_name); // We should log to the console also
98 TTCN_error("Could not get the IP address for the local address "
99 "(%s): Host name lookup failure.", host_name);
100 }
101 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::local__address__was__set,
102 hcnh.get_local_host_str(), hcnh.get_local_addr_str(), 0);
103 local_addr_set = TRUE;
104}
105
106const IPAddress *TTCN_Communication::get_local_address()
107{
108 if (!local_addr_set)
109 TTCN_error("TTCN_Communication::get_local_address: internal error: the "
110 "local address has not been set.");
111 return hcnh.get_local_addr();
112}
113
114void TTCN_Communication::set_mc_address(const char *host_name,
115 unsigned short tcp_port)
116{
117 if (mc_addr_set)
118 TTCN_warning("The address of MC has already been set.");
119 if (is_connected)
120 TTCN_error("Trying to change the address of MC, but there is an existing connection.");
121 if (host_name == NULL){
122 fprintf(stderr,"TTCN_Communication::set_mc_address: internal error: invalid host name.\r\n");
123 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid host name.");
124 }
125 if (tcp_port <= 0){
126 fprintf(stderr,"TTCN_Communication::set_mc_address: internal error: invalid TCP port. %hu\r\n",tcp_port);
127 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid TCP port.");
128 }
129 hcnh.set_family(host_name);
130 if (!hcnh.set_mc_addr(host_name, tcp_port)){
131 fprintf(stderr,"Could not get the IP address of MC (%s): Host name lookup "
132 "failure.\r\n", host_name);
133 TTCN_error("Could not get the IP address of MC (%s): Host name lookup "
134 "failure.", host_name);
135 }
136 if ((hcnh.get_mc_addr())->is_local()){
137 fprintf(stderr,"The address of MC was set to a local IP address. This may "
138 "cause incorrect behavior if a HC from a remote host also "
139 "connects to MC.\r\n");
140 TTCN_warning("The address of MC was set to a local IP address. This may "
141 "cause incorrect behavior if a HC from a remote host also "
142 "connects to MC.");
143 }
144 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__mc__was__set,
145 hcnh.get_mc_host_str(), hcnh.get_mc_addr_str(), 0);
146 mc_addr_set = TRUE;
147}
148
149const IPAddress *TTCN_Communication::get_mc_address()
150{
151 if (!mc_addr_set)
152 TTCN_error("TTCN_Communication::get_mc_address: internal error: the "
153 "address of MC has not been set.");
154 return hcnh.get_mc_addr();
155}
156
157bool TTCN_Communication::is_mc_connected()
158{
159 return is_connected;
160}
161
162void TTCN_Communication::connect_mc()
163{
164 if (is_connected) TTCN_error("Trying to re-connect to MC, but there is an "
165 "existing connection.");
166 if (!mc_addr_set) TTCN_error("Trying to connect to MC, but the address of "
167 "MC has not yet been set.");
168
169 // Trying to connect to local mc through unix domain socket
170 // TODO: Disable if config file parameter is set
171 if ((hcnh.get_mc_addr())->is_local()
172 || (local_addr_set && *(hcnh.get_mc_addr()) == *(hcnh.get_local_addr()))) {
173 sockaddr_un localaddr_unix;
174 memset(&localaddr_unix, 0, sizeof(localaddr_unix));
175 localaddr_unix.sun_family = AF_UNIX;
176 snprintf(localaddr_unix.sun_path, sizeof(localaddr_unix.sun_path),
177 "/tmp/ttcn3-mctr-%u", hcnh.get_mc_port());
178 mc_fd = socket(PF_UNIX, SOCK_STREAM, 0);
179 if (mc_fd >= (int)FD_SETSIZE) {
180 close(mc_fd);
181 } else if (mc_fd >= 0) {
182 if (connect(mc_fd, (struct sockaddr*)&localaddr_unix,
183 sizeof(localaddr_unix)) == 0) {
184 goto unix_end; // connected successfully
185 } else {
186 close(mc_fd);
187 }
188 }
189 }
190
191#ifdef WIN32
192again:
193#endif
194 mc_fd = hcnh.socket();
195 if (mc_fd < 0) {
196 fprintf(stderr,"Socket creation failed when connecting to MC.");
197 TTCN_error("Socket creation failed when connecting to MC.");
198 }
199 else if (mc_fd >= (int)FD_SETSIZE) {
200 close(mc_fd);
201 fprintf(stderr,"When connecting to MC: "
202 "The file descriptor returned by the operating system (%d) is "
203 "too large for use with the select() system call.\r\n", mc_fd);
204 TTCN_error("When connecting to MC: "
205 "The file descriptor returned by the operating system (%d) is "
206 "too large for use with the select() system call.", mc_fd);
207 }
208
209 if (local_addr_set) {
210 if (hcnh.bind_local_addr(mc_fd)) {
211 fprintf(stderr,"Binding IP address %s to the local endpoint of the "
212 "control connection failed when connecting to MC.\r\n", hcnh.get_local_addr_str());
213 TTCN_error("Binding IP address %s to the local endpoint of the "
214 "control connection failed when connecting to MC.",
215 hcnh.get_local_addr_str());
216 close(mc_fd);
217 }
218 }
219
220 if (hcnh.connect_to_mc(mc_fd)) {
221#ifdef WIN32
222 if (errno == EADDRINUSE) {
223 close(mc_fd);
224 errno = 0;
225 TTCN_warning("connect() returned error code EADDRINUSE. "
226 "Perhaps this is a Cygwin bug. Trying to connect again.");
227 goto again;
228 }
229#endif
230 fprintf(stderr,"Connecting to MC failed. MC address: %s:%hu %s\r\n",hcnh.get_mc_addr_str(),hcnh.get_mc_port(),strerror(errno));
231 TTCN_error("Connecting to MC failed.");
232 close(mc_fd);
233 }
234
235 if (!local_addr_set) {
236 if (hcnh.getsockname_local_addr(mc_fd)) {
237 close(mc_fd);
238 TTCN_error("getsockname() system call failed on the socket of the "
239 "control connection to MC.");
240 }
241 TTCN_Logger::log_executor_misc(
242 TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__control__connection,
243 NULL, hcnh.get_local_addr_str(), 0);
244 local_addr_set = TRUE;
245 }
246
247 if (!set_tcp_nodelay(mc_fd)) {
248 close(mc_fd);
249 TTCN_error("Setting the TCP_NODELAY flag failed on the socket of "
250 "the control connection to MC.");
251 }
252
253unix_end:
254
255 if (!set_close_on_exec(mc_fd)) {
256 close(mc_fd);
257 TTCN_error("Setting the close-on-exec flag failed on the socket of "
258 "the control connection to MC.");
259 }
260
261 Fd_And_Timeout_User::add_fd(mc_fd, &mc_connection, FD_EVENT_RD);
262
263 TTCN_Logger::log_executor_runtime(
264 TitanLoggerApiSimple::ExecutorRuntime_reason::connected__to__mc);
265
266 is_connected = TRUE;
267}
268
269void TTCN_Communication::disconnect_mc()
270{
271 if (is_connected) {
272 shutdown(mc_fd, 1);
273 int recv_len;
274 do {
275 char buf[1024];
276 recv_len = recv(mc_fd, buf, sizeof(buf), 0);
277 } while (recv_len > 0);
278 errno = 0;
279 close_mc_connection();
280 TTCN_Logger::log_executor_runtime(
281 TitanLoggerApiSimple::ExecutorRuntime_reason::disconnected__from__mc);
282 }
283}
284
285void TTCN_Communication::close_mc_connection()
286{
287 if (is_connected) {
288 int tmp_mc_fd = mc_fd;
289 call_interval = 0.0;
290 close(mc_fd);
291 mc_fd = -1;
292 is_connected = FALSE;
293 incoming_buf.reset();
294 // Removing the fd has to be done after closing the mc connection
295 // to prevent segmentation fault or broken pipe error
296 // in case remove_fd would try to print an error log.
297 Fd_And_Timeout_User::remove_fd(tmp_mc_fd, &mc_connection, FD_EVENT_RD);
298 Fd_And_Timeout_User::set_timer(&mc_connection, 0.0);
299 }
300}
301
302boolean TTCN_Communication::transport_unix_stream_supported()
303{
304 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
305 if (fd >= 0) {
306 close(fd);
307 TTCN_Logger::log_executor_misc(
308 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets,
309 NULL, NULL, 0);
310 return TRUE;
311 } else {
312 TTCN_Logger::log_executor_misc(
313 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets,
314 NULL, NULL, errno);
315 return FALSE;
316 }
317}
318
319boolean TTCN_Communication::set_close_on_exec(int fd)
320{
321 int flags = fcntl(fd, F_GETFD);
322 if (flags < 0) {
323 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
324 TTCN_Logger::log_event("System call fcntl(F_GETFD) failed on file "
325 "descriptor %d.", fd);
326 TTCN_Logger::OS_error();
327 TTCN_Logger::end_event();
328 return FALSE;
329 }
330
331 flags |= FD_CLOEXEC;
332
333 if (fcntl(fd, F_SETFD, flags) == -1) {
334 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
335 TTCN_Logger::log_event("System call fcntl(F_SETFD) failed on file "
336 "descriptor %d.", fd);
337 TTCN_Logger::OS_error();
338 TTCN_Logger::end_event();
339 return FALSE;
340 }
341 return TRUE;
342}
343
344boolean TTCN_Communication::set_non_blocking_mode(int fd,
345 boolean enable_nonblock)
346{
347 int flags = fcntl(fd, F_GETFL);
348 if (flags < 0) {
349 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
350 TTCN_Logger::log_event("System call fcntl(F_GETFL) failed on file "
351 "descriptor %d.", fd);
352 TTCN_Logger::OS_error();
353 TTCN_Logger::end_event();
354 return FALSE;
355 }
356
357 if (enable_nonblock) flags |= O_NONBLOCK;
358 else flags &= ~O_NONBLOCK;
359
360 if (fcntl(fd, F_SETFL, flags) == -1) {
361 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
362 TTCN_Logger::log_event("System call fcntl(F_SETFL) failed on file "
363 "descriptor %d.", fd);
364 TTCN_Logger::OS_error();
365 TTCN_Logger::end_event();
366 return FALSE;
367 }
368 return TRUE;
369}
370
371boolean TTCN_Communication::set_tcp_nodelay(int fd)
372{
373 const int on = 1;
374 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on,
375 sizeof(on))) {
376 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
377 TTCN_Logger::log_event("System call setsockopt(TCP_NODELAY) failed on "
378 "file descriptor %d.", fd);
379 TTCN_Logger::OS_error();
380 TTCN_Logger::end_event();
381 return FALSE;
382 }
383 return TRUE;
384}
385
386boolean TTCN_Communication::increase_send_buffer(int fd,
387 int &old_size, int& new_size)
388{
389 int set_size;
390 socklen_type optlen = sizeof(old_size);
391 // obtaining the current buffer size first
392 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&old_size, &optlen))
393 goto getsockopt_failure;
394 if (old_size <= 0) {
395 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED,
396 "System call getsockopt(SO_SNDBUF) returned invalid buffer size (%d) "
397 "on file descriptor %d.", old_size, fd);
398 return FALSE;
399 }
400 // trying to double the buffer size
401 set_size = 2 * old_size;
402 if (set_size > old_size) {
403 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char*)&set_size,
404 sizeof(set_size))) {
405 // the operation failed
406 switch (errno) {
407 case ENOMEM:
408 case ENOBUFS:
409 errno = 0;
410 break;
411 default:
412 // other error codes indicate a fatal error
413 goto setsockopt_failure;
414 }
415 } else {
416 // the operation was successful
417 goto success;
418 }
419 }
420 // trying to perform a binary search to determine the maximum buffer size
421 set_size = old_size;
422 for (int size_step = old_size / 2; size_step > 0; size_step /= 2) {
423 int tried_size = set_size + size_step;
424 if (tried_size > set_size) {
425 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char*)&tried_size,
426 sizeof(tried_size))) {
427 // the operation failed
428 switch (errno) {
429 case ENOMEM:
430 case ENOBUFS:
431 errno = 0;
432 break;
433 default:
434 // other error codes indicate a fatal error
435 goto setsockopt_failure;
436 }
437 } else {
438 // the operation was successful
439 set_size = tried_size;
440 }
441 }
442 }
443 if (set_size <= old_size) return FALSE;
444 success:
445 // querying the new effective buffer size (it might be smaller
446 // than set_size but should not be smaller than old_size)
447 optlen = sizeof(new_size);
448 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&new_size,
449 &optlen)) goto getsockopt_failure;
450 if (new_size > old_size) return TRUE;
451 else {
452 if (new_size < old_size) TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED,
453 "System call getsockopt(SO_SNDBUF) returned unexpected buffer size "
454 "(%d, after increasing it from %d to %d) on file descriptor %d.",
455 new_size, old_size, set_size, fd);
456 return FALSE;
457 }
458 getsockopt_failure:
459 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
460 TTCN_Logger::log_event("System call getsockopt(SO_SNDBUF) failed on file "
461 "descriptor %d.", fd);
462 TTCN_Logger::OS_error();
463 TTCN_Logger::end_event();
464 return FALSE;
465 setsockopt_failure:
466 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
467 TTCN_Logger::log_event("System call setsockopt(SO_SNDBUF) failed on file "
468 "descriptor %d.", fd);
469 TTCN_Logger::OS_error();
470 TTCN_Logger::end_event();
471 return FALSE;
472}
473
474#define INITIAL_CALL_INTERVAL 1.0
475#define CALL_INTERVAL_INCREMENT 2.0
476
477void TTCN_Communication::enable_periodic_call()
478{
479 call_interval = INITIAL_CALL_INTERVAL;
480 Fd_And_Timeout_User::set_timer(&mc_connection, call_interval, TRUE,
481 FALSE /*call_anyway*/);
482}
483
484void TTCN_Communication::increase_call_interval()
485{
486 if (call_interval <= 0.0) TTCN_error("Internal error: "
487 "TTCN_Communication::increase_call_interval() was called when call "
488 "interval is not set.");
489 call_interval *= CALL_INTERVAL_INCREMENT;
490 Fd_And_Timeout_User::set_timer(&mc_connection, call_interval, TRUE,
491 FALSE /*call_anyway*/);
492}
493
494void TTCN_Communication::disable_periodic_call()
495{
496 Fd_And_Timeout_User::set_timer(&mc_connection, 0.0);
497 call_interval = 0.0;
498}
499
500void MC_Connection::Handle_Fd_Event(int fd, boolean is_readable, boolean,
501 boolean is_error)
502{
503 if (fd != *mc_fd)
504 TTCN_error("MC_Connection::Fd_And_Timeout_Event_Handler: unexpected "
505 "file descriptor"); // not necessary - debugging
506 if (is_error)
507 TTCN_warning("Error occurred on the control connection to MC");
508 if (is_readable) {
509 char *buf_ptr;
510 int buf_len;
511 incoming_buf->get_end(buf_ptr, buf_len);
512
513 int recv_len = recv(*mc_fd, buf_ptr, buf_len, 0);
514
515 if (recv_len > 0) {
516 // reason: data has arrived
517 incoming_buf->increase_length(recv_len);
518 // If the component is idle the processing is done in the outer
519 // stack frame (i.e. in TTCN_Runtime::xxx_main()).
520 if (!TTCN_Runtime::is_idle())
521 TTCN_Communication::process_all_messages_tc();
522 } else {
523 // First closing the TCP connection to avoid EPIPE ("Broken pipe")
524 // errors and/or SIGPIPE signals when trying to send anything
525 // (e.g. log events or error messages) towards MC.
526 TTCN_Communication::close_mc_connection();
527 if (recv_len == 0) {
528 // reason: TCP connection was closed by peer
529 TTCN_error("Control connection was closed unexpectedly by MC.");
530 } else {
531 // reason: error occurred
532 TTCN_error("Receiving data on the control connection from MC "
533 "failed.");
534 }
535 }
536 }
537}
538
539void MC_Connection::Handle_Timeout(double /*time_since_last_call*/)
540{
541 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_OVERLOADED) {
542 // indicate the timeout to be handled in process_all_messages_hc()
543 TTCN_Runtime::set_state(TTCN_Runtime::HC_OVERLOADED_TIMEOUT);
544 } else {
545 TTCN_warning("Unexpected timeout occurred on the control "
546 "connection to MC.");
547 TTCN_Communication::disable_periodic_call();
548 }
549}
550
551void MC_Connection::log() const
552{
553 TTCN_Logger::log_event("mc connection");
554}
555
556void TTCN_Communication::process_all_messages_hc()
557{
558 if (!TTCN_Runtime::is_hc()) TTCN_error("Internal error: "
559 "TTCN_Communication::process_all_messages_hc() was called in invalid "
560 "state.");
561 TTCN_Runtime::wait_terminated_processes();
562 boolean wait_flag = FALSE;
563 boolean check_overload = TTCN_Runtime::is_overloaded();
564 while (incoming_buf.is_message()) {
565 wait_flag = TRUE;
566 int msg_len = incoming_buf.pull_int().get_val();
567 int msg_end = incoming_buf.get_pos() + msg_len;
568 int msg_type = incoming_buf.pull_int().get_val();
569 // messages: MC -> HC
570 switch (msg_type) {
571 case MSG_ERROR:
572 process_error();
573 break;
574 case MSG_CONFIGURE:
b0caada2 575 process_configure(msg_end, false);
970ed795
EL
576 break;
577 case MSG_CREATE_MTC:
578 process_create_mtc();
579 TTCN_Runtime::wait_terminated_processes();
580 wait_flag = FALSE;
581 check_overload = FALSE;
582 break;
583 case MSG_CREATE_PTC:
584 process_create_ptc();
585 TTCN_Runtime::wait_terminated_processes();
586 wait_flag = FALSE;
587 check_overload = FALSE;
588 break;
589 case MSG_KILL_PROCESS:
590 process_kill_process();
591 TTCN_Runtime::wait_terminated_processes();
592 wait_flag = FALSE;
593 break;
594 case MSG_EXIT_HC:
595 process_exit_hc();
596 break;
016a1a93
BB
597 case MSG_DEBUG_COMMAND:
598 process_debug_command();
599 break;
970ed795
EL
600 default:
601 process_unsupported_message(msg_type, msg_end);
602 }
603 }
604 if (wait_flag) TTCN_Runtime::wait_terminated_processes();
605 if (check_overload && TTCN_Runtime::is_overloaded())
606 TTCN_Runtime::check_overload();
607}
608
609void TTCN_Communication::process_all_messages_tc()
610{
611 if (!TTCN_Runtime::is_tc()) TTCN_error("Internal error: "
612 "TTCN_Communication::process_all_messages_tc() was called in invalid "
613 "state.");
614 while (incoming_buf.is_message()) {
615 int msg_len = incoming_buf.pull_int().get_val();
616 int msg_end = incoming_buf.get_pos() + msg_len;
617 int msg_type = incoming_buf.pull_int().get_val();
618 // messages: MC -> TC
619 switch (msg_type) {
620 case MSG_ERROR:
621 process_error();
622 break;
623 case MSG_CREATE_ACK:
624 process_create_ack();
625 break;
626 case MSG_START_ACK:
627 process_start_ack();
628 break;
629 case MSG_STOP:
630 process_stop();
631 break;
632 case MSG_STOP_ACK:
633 process_stop_ack();
634 break;
635 case MSG_KILL_ACK:
636 process_kill_ack();
637 break;
638 case MSG_RUNNING:
639 process_running();
640 break;
641 case MSG_ALIVE:
642 process_alive();
643 break;
644 case MSG_DONE_ACK:
645 process_done_ack(msg_end);
646 break;
647 case MSG_KILLED_ACK:
648 process_killed_ack();
649 break;
650 case MSG_CANCEL_DONE:
651 if (TTCN_Runtime::is_mtc()) process_cancel_done_mtc();
652 else process_cancel_done_ptc();
653 break;
654 case MSG_COMPONENT_STATUS:
655 if (TTCN_Runtime::is_mtc()) process_component_status_mtc(msg_end);
656 else process_component_status_ptc(msg_end);
657 break;
658 case MSG_CONNECT_LISTEN:
659 process_connect_listen();
660 break;
661 case MSG_CONNECT:
662 process_connect();
663 break;
664 case MSG_CONNECT_ACK:
665 process_connect_ack();
666 break;
667 case MSG_DISCONNECT:
668 process_disconnect();
669 break;
670 case MSG_DISCONNECT_ACK:
671 process_disconnect_ack();
672 break;
673 case MSG_MAP:
674 process_map();
675 break;
676 case MSG_MAP_ACK:
677 process_map_ack();
678 break;
679 case MSG_UNMAP:
680 process_unmap();
681 break;
682 case MSG_UNMAP_ACK:
683 process_unmap_ack();
684 break;
016a1a93
BB
685 case MSG_DEBUG_COMMAND:
686 process_debug_command();
687 break;
970ed795
EL
688 default:
689 if (TTCN_Runtime::is_mtc()) {
690 // messages: MC -> MTC
691 switch (msg_type) {
692 case MSG_EXECUTE_CONTROL:
693 process_execute_control();
694 break;
695 case MSG_EXECUTE_TESTCASE:
696 process_execute_testcase();
697 break;
698 case MSG_PTC_VERDICT:
699 process_ptc_verdict();
700 break;
701 case MSG_CONTINUE:
702 process_continue();
703 break;
704 case MSG_EXIT_MTC:
705 process_exit_mtc();
706 break;
b0caada2
BB
707 case MSG_CONFIGURE:
708 process_configure(msg_end, true);
709 break;
970ed795
EL
710 default:
711 process_unsupported_message(msg_type, msg_end);
712 }
713 } else {
714 // messages: MC -> PTC
715 switch (msg_type) {
716 case MSG_START:
717 process_start();
718 break;
719 case MSG_KILL:
720 process_kill();
721 break;
722 default:
723 process_unsupported_message(msg_type, msg_end);
724 }
725 }
726 }
727 }
728}
729
016a1a93
BB
730void TTCN_Communication::process_debug_messages()
731{
732 // receives and processes messages from the MC, while test execution is halted
733 // by the debugger
734 char *buf_ptr;
735 int buf_len;
736 Text_Buf storage_buf;
737 while (ttcn3_debugger.is_halted()) {
738 incoming_buf.get_end(buf_ptr, buf_len);
739
740 int recv_len = recv(mc_fd, buf_ptr, buf_len, 0);
741
742 if (recv_len > 0) {
743 incoming_buf.increase_length(recv_len);
744
745 while (incoming_buf.is_message() && ttcn3_debugger.is_halted()) {
746 int msg_len = incoming_buf.pull_int().get_val();
747 int msg_end = incoming_buf.get_pos() + msg_len;
748 int msg_type = incoming_buf.pull_int().get_val();
749 // process only debug commands and 'stop' messages, store the rest
750 switch (msg_type) {
751 case MSG_DEBUG_COMMAND:
752 process_debug_command();
753 break;
754 case MSG_STOP:
755 process_stop();
756 break;
757 default: {
758 // store all other messages in a different buffer
759 int data_len = msg_end - incoming_buf.get_pos();
760 char* msg_data = new char[data_len];
761 incoming_buf.pull_raw(data_len, msg_data);
762 incoming_buf.cut_message();
763 storage_buf.push_int(msg_type);
764 storage_buf.push_raw(data_len, msg_data);
765 delete [] msg_data;
766 storage_buf.calculate_length();
767 break; }
768 }
769 }
770 }
771 }
772 // append the stored messages to the beginning of the main buffer and
773 // process them
774 if (storage_buf.is_message()) {
775 incoming_buf.push_raw_front(storage_buf.get_len(), storage_buf.get_data());
776 process_all_messages_tc();
777 }
778}
779
970ed795
EL
780void TTCN_Communication::send_version()
781{
782 Text_Buf text_buf;
783 text_buf.push_int(MSG_VERSION);
784 text_buf.push_int(TTCN3_MAJOR);
785 text_buf.push_int(TTCN3_MINOR);
786 text_buf.push_int(TTCN3_PATCHLEVEL);
787#ifdef TTCN3_BUILDNUMBER
788 text_buf.push_int(TTCN3_BUILDNUMBER);
789#else
790 text_buf.push_int((RInt)0);
791#endif
792 Module_List::push_version(text_buf);
793 struct utsname uts;
794 if (uname(&uts) < 0) TTCN_error("System call uname() failed.");
795 text_buf.push_string(uts.nodename);
796 text_buf.push_string(uts.machine);
797 text_buf.push_string(uts.sysname);
798 text_buf.push_string(uts.release);
799 text_buf.push_string(uts.version);
800 boolean unix_stream_supported = transport_unix_stream_supported();
801
802 // LOCAL (software loop) and INET_STREAM (TCP) transports are always
803 // supported
804 int n_supported_transports = 2;
805
806 if (unix_stream_supported) n_supported_transports++;
807 text_buf.push_int(n_supported_transports);
808 text_buf.push_int(TRANSPORT_LOCAL);
809 text_buf.push_int(TRANSPORT_INET_STREAM);
810 if (unix_stream_supported)
811 text_buf.push_int(TRANSPORT_UNIX_STREAM);
812 send_message(text_buf);
813}
814
815void TTCN_Communication::send_configure_ack()
816{
817 Text_Buf text_buf;
818 text_buf.push_int(MSG_CONFIGURE_ACK);
819 send_message(text_buf);
820}
821
822void TTCN_Communication::send_configure_nak()
823{
824 Text_Buf text_buf;
825 text_buf.push_int(MSG_CONFIGURE_NAK);
826 send_message(text_buf);
827}
828
829void TTCN_Communication::send_create_nak(component component_reference,
830 const char *fmt_str, ...)
831{
832 va_list ap;
833 va_start(ap, fmt_str);
834 char *error_str = mprintf_va_list(fmt_str, ap);
835 va_end(ap);
836 Text_Buf text_buf;
837 text_buf.push_int(MSG_CREATE_NAK);
838 text_buf.push_int(component_reference);
839 text_buf.push_string(error_str);
840 Free(error_str);
841 send_message(text_buf);
842}
843
844void TTCN_Communication::send_hc_ready()
845{
846 Text_Buf text_buf;
847 text_buf.push_int(MSG_HC_READY);
848 send_message(text_buf);
849}
850
851void TTCN_Communication::send_create_req(const char *component_type_module,
852 const char *component_type_name, const char *component_name,
853 const char *component_location, boolean is_alive)
854{
855 Text_Buf text_buf;
856 text_buf.push_int(MSG_CREATE_REQ);
857 text_buf.push_string(component_type_module);
858 text_buf.push_string(component_type_name);
859 text_buf.push_string(component_name);
860 text_buf.push_string(component_location);
861 text_buf.push_int(is_alive ? 1 : 0);
862 send_message(text_buf);
863}
864
865void TTCN_Communication::prepare_start_req(Text_Buf& text_buf,
866 component component_reference, const char *module_name,
867 const char *function_name)
868{
869 text_buf.push_int(MSG_START_REQ);
870 text_buf.push_int(component_reference);
871 text_buf.push_string(module_name);
872 text_buf.push_string(function_name);
873}
874
875void TTCN_Communication::send_stop_req(component component_reference)
876{
877 Text_Buf text_buf;
878 text_buf.push_int(MSG_STOP_REQ);
879 text_buf.push_int(component_reference);
880 send_message(text_buf);
881}
882
883void TTCN_Communication::send_kill_req(component component_reference)
884{
885 Text_Buf text_buf;
886 text_buf.push_int(MSG_KILL_REQ);
887 text_buf.push_int(component_reference);
888 send_message(text_buf);
889}
890
891void TTCN_Communication::send_is_running(component component_reference)
892{
893 Text_Buf text_buf;
894 text_buf.push_int(MSG_IS_RUNNING);
895 text_buf.push_int(component_reference);
896 send_message(text_buf);
897}
898
899void TTCN_Communication::send_is_alive(component component_reference)
900{
901 Text_Buf text_buf;
902 text_buf.push_int(MSG_IS_ALIVE);
903 text_buf.push_int(component_reference);
904 send_message(text_buf);
905}
906
907void TTCN_Communication::send_done_req(component component_reference)
908{
909 Text_Buf text_buf;
910 text_buf.push_int(MSG_DONE_REQ);
911 text_buf.push_int(component_reference);
912 send_message(text_buf);
913}
914
915void TTCN_Communication::send_killed_req(component component_reference)
916{
917 Text_Buf text_buf;
918 text_buf.push_int(MSG_KILLED_REQ);
919 text_buf.push_int(component_reference);
920 send_message(text_buf);
921}
922
923void TTCN_Communication::send_cancel_done_ack(component component_reference)
924{
925 Text_Buf text_buf;
926 text_buf.push_int(MSG_CANCEL_DONE_ACK);
927 text_buf.push_int(component_reference);
928 send_message(text_buf);
929}
930
931void TTCN_Communication::send_connect_req(component src_component,
932 const char *src_port, component dst_component, const char *dst_port)
933{
934 Text_Buf text_buf;
935 text_buf.push_int(MSG_CONNECT_REQ);
936 text_buf.push_int(src_component);
937 text_buf.push_string(src_port);
938 text_buf.push_int(dst_component);
939 text_buf.push_string(dst_port);
940 send_message(text_buf);
941}
942
943void TTCN_Communication::send_connect_listen_ack_inet_stream(
944 const char *local_port, component remote_component,
945 const char *remote_port, const IPAddress *local_address)
946{
947 Text_Buf text_buf;
948 text_buf.push_int(MSG_CONNECT_LISTEN_ACK);
949 text_buf.push_string(local_port);
950 text_buf.push_int(remote_component);
951 text_buf.push_string(remote_port);
952 text_buf.push_int(TRANSPORT_INET_STREAM);
953 local_address->push_raw(text_buf);
954 send_message(text_buf);
955}
956
957void TTCN_Communication::send_connect_listen_ack_unix_stream(
958 const char *local_port, component remote_component,
959 const char *remote_port, const struct sockaddr_un *local_address)
960{
961 Text_Buf text_buf;
962 text_buf.push_int(MSG_CONNECT_LISTEN_ACK);
963 text_buf.push_string(local_port);
964 text_buf.push_int(remote_component);
965 text_buf.push_string(remote_port);
966 text_buf.push_int(TRANSPORT_UNIX_STREAM);
967 text_buf.push_string(local_address->sun_path);
968 send_message(text_buf);
969}
970
971void TTCN_Communication::send_connected(const char *local_port,
972 component remote_component, const char *remote_port)
973{
974 Text_Buf text_buf;
975 text_buf.push_int(MSG_CONNECTED);
976 text_buf.push_string(local_port);
977 text_buf.push_int(remote_component);
978 text_buf.push_string(remote_port);
979 send_message(text_buf);
980}
981
982void TTCN_Communication::send_connect_error(const char *local_port,
983 component remote_component, const char *remote_port,
984 const char *fmt_str, ...)
985{
986 va_list ap;
987 va_start(ap, fmt_str);
988 char *error_str = mprintf_va_list(fmt_str, ap);
989 va_end(ap);
990 Text_Buf text_buf;
991 text_buf.push_int(MSG_CONNECT_ERROR);
992 text_buf.push_string(local_port);
993 text_buf.push_int(remote_component);
994 text_buf.push_string(remote_port);
995 text_buf.push_string(error_str);
996 Free(error_str);
997 send_message(text_buf);
998}
999
1000void TTCN_Communication::send_disconnect_req(component src_component,
1001 const char *src_port, component dst_component, const char *dst_port)
1002{
1003 Text_Buf text_buf;
1004 text_buf.push_int(MSG_DISCONNECT_REQ);
1005 text_buf.push_int(src_component);
1006 text_buf.push_string(src_port);
1007 text_buf.push_int(dst_component);
1008 text_buf.push_string(dst_port);
1009 send_message(text_buf);
1010}
1011
1012void TTCN_Communication::send_disconnected(const char *local_port,
1013 component remote_component, const char *remote_port)
1014{
1015 Text_Buf text_buf;
1016 text_buf.push_int(MSG_DISCONNECTED);
1017 text_buf.push_string(local_port);
1018 text_buf.push_int(remote_component);
1019 text_buf.push_string(remote_port);
1020 send_message(text_buf);
1021}
1022
1023void TTCN_Communication::send_map_req(component src_component,
1024 const char *src_port, const char *system_port)
1025{
1026 Text_Buf text_buf;
1027 text_buf.push_int(MSG_MAP_REQ);
1028 text_buf.push_int(src_component);
1029 text_buf.push_string(src_port);
1030 text_buf.push_string(system_port);
1031 send_message(text_buf);
1032}
1033
1034void TTCN_Communication::send_mapped(const char *local_port,
1035 const char *system_port)
1036{
1037 Text_Buf text_buf;
1038 text_buf.push_int(MSG_MAPPED);
1039 text_buf.push_string(local_port);
1040 text_buf.push_string(system_port);
1041 send_message(text_buf);
1042}
1043
1044void TTCN_Communication::send_unmap_req(component src_component,
1045 const char *src_port, const char *system_port)
1046{
1047 Text_Buf text_buf;
1048 text_buf.push_int(MSG_UNMAP_REQ);
1049 text_buf.push_int(src_component);
1050 text_buf.push_string(src_port);
1051 text_buf.push_string(system_port);
1052 send_message(text_buf);
1053}
1054
1055void TTCN_Communication::send_unmapped(const char *local_port,
1056 const char *system_port)
1057{
1058 Text_Buf text_buf;
1059 text_buf.push_int(MSG_UNMAPPED);
1060 text_buf.push_string(local_port);
1061 text_buf.push_string(system_port);
1062 send_message(text_buf);
1063}
1064
1065void TTCN_Communication::send_mtc_created()
1066{
1067 Text_Buf text_buf;
1068 text_buf.push_int(MSG_MTC_CREATED);
1069 send_message(text_buf);
1070}
1071
1072void TTCN_Communication::send_testcase_started(const char *testcase_module,
1073 const char *testcase_name, const char *mtc_comptype_module,
1074 const char *mtc_comptype_name, const char *system_comptype_module,
1075 const char *system_comptype_name)
1076{
1077 Text_Buf text_buf;
1078 text_buf.push_int(MSG_TESTCASE_STARTED);
1079 text_buf.push_string(testcase_module);
1080 text_buf.push_string(testcase_name);
1081 text_buf.push_string(mtc_comptype_module);
1082 text_buf.push_string(mtc_comptype_name);
1083 text_buf.push_string(system_comptype_module);
1084 text_buf.push_string(system_comptype_name);
1085 send_message(text_buf);
1086}
1087
1088void TTCN_Communication::send_testcase_finished(verdicttype final_verdict,
1089 const char* reason)
1090{
1091 Text_Buf text_buf;
1092 text_buf.push_int(MSG_TESTCASE_FINISHED);
1093 text_buf.push_int(final_verdict);
1094 text_buf.push_string(reason);
1095 send_message(text_buf);
1096}
1097
1098void TTCN_Communication::send_mtc_ready()
1099{
1100 Text_Buf text_buf;
1101 text_buf.push_int(MSG_MTC_READY);
1102 send_message(text_buf);
1103}
1104
1105void TTCN_Communication::send_ptc_created(component component_reference)
1106{
1107 Text_Buf text_buf;
1108 text_buf.push_int(MSG_PTC_CREATED);
1109 text_buf.push_int(component_reference);
1110 send_message(text_buf);
1111}
1112
1113void TTCN_Communication::prepare_stopped(Text_Buf& text_buf,
1114 const char *return_type)
1115{
1116 text_buf.push_int(MSG_STOPPED);
1117 text_buf.push_string(return_type);
1118}
1119
1120void TTCN_Communication::send_stopped()
1121{
1122 Text_Buf text_buf;
1123 text_buf.push_int(MSG_STOPPED);
1124 // add an empty return type
1125 text_buf.push_string(NULL);
1126 send_message(text_buf);
1127}
1128
1129void TTCN_Communication::prepare_stopped_killed(Text_Buf& text_buf,
1130 verdicttype final_verdict, const char *return_type, const char* reason)
1131{
1132 text_buf.push_int(MSG_STOPPED_KILLED);
1133 text_buf.push_int(final_verdict);
1134 text_buf.push_string(reason);
1135 text_buf.push_string(return_type);
1136}
1137
1138void TTCN_Communication::send_stopped_killed(verdicttype final_verdict,
1139 const char* reason)
1140{
1141 Text_Buf text_buf;
1142 text_buf.push_int(MSG_STOPPED_KILLED);
1143 text_buf.push_int(final_verdict);
1144 text_buf.push_string(reason);
1145 // add an empty return type
1146 text_buf.push_string(NULL);
1147 send_message(text_buf);
1148}
1149
1150void TTCN_Communication::send_killed(verdicttype final_verdict,
1151 const char* reason)
1152{
1153 Text_Buf text_buf;
1154 text_buf.push_int(MSG_KILLED);
1155 text_buf.push_int(final_verdict);
1156 text_buf.push_string(reason);
1157 send_message(text_buf);
1158}
1159
016a1a93
BB
1160void TTCN_Communication::send_debug_return_value(int return_type, const char* message)
1161{
1162 Text_Buf text_buf;
1163 text_buf.push_int(MSG_DEBUG_RETURN_VALUE);
1164 text_buf.push_int(return_type);
f08ff9ca
BB
1165 if (message != NULL) {
1166 timeval tv;
1167 gettimeofday(&tv, NULL);
1168 text_buf.push_int(tv.tv_sec);
1169 text_buf.push_int(tv.tv_usec);
1170 text_buf.push_string(message);
1171 }
016a1a93
BB
1172 send_message(text_buf);
1173}
1174
1175void TTCN_Communication::send_debug_halt_req()
1176{
1177 Text_Buf text_buf;
1178 text_buf.push_int(MSG_DEBUG_HALT_REQ);
1179 send_message(text_buf);
1180}
1181
f08ff9ca
BB
1182void TTCN_Communication::send_debug_continue_req()
1183{
1184 Text_Buf text_buf;
1185 text_buf.push_int(MSG_DEBUG_CONTINUE_REQ);
1186 send_message(text_buf);
1187}
1188
1189void TTCN_Communication::send_debug_batch(const char* batch_file)
1190{
1191 Text_Buf text_buf;
1192 text_buf.push_int(MSG_DEBUG_BATCH);
1193 text_buf.push_string(batch_file);
1194 send_message(text_buf);
1195}
1196
970ed795
EL
1197boolean TTCN_Communication::send_log(time_t timestamp_sec, long timestamp_usec,
1198 unsigned int event_severity, size_t message_text_len,
1199 const char *message_text)
1200{
1201 if (is_connected) {
1202 Text_Buf text_buf;
1203 text_buf.push_int(MSG_LOG);
1204 text_buf.push_int(timestamp_sec);
1205 text_buf.push_int(timestamp_usec);
1206 text_buf.push_int(event_severity);
1207 text_buf.push_int(message_text_len);
1208 text_buf.push_raw(message_text_len, message_text);
1209 send_message(text_buf);
1210 /* If an ERROR message (indicating a version mismatch) arrives from MC
1211 in state HC_IDLE (i.e. before CONFIGURE) it shall be
1212 printed to the console as well. */
1213 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_IDLE) return FALSE;
1214 else return TRUE;
1215 } else {
1216 switch (TTCN_Runtime::get_state()) {
1217 case TTCN_Runtime::HC_EXIT:
1218 case TTCN_Runtime::MTC_INITIAL:
1219 case TTCN_Runtime::MTC_EXIT:
1220 case TTCN_Runtime::PTC_INITIAL:
1221 case TTCN_Runtime::PTC_EXIT:
1222 /* Do not print the first/last few lines of logs to the console
1223 even if ConsoleMask is set to LOG_ALL */
1224 return TRUE;
1225 default:
1226 return FALSE;
1227 }
1228 }
1229}
1230
1231void TTCN_Communication::send_error(const char *fmt_str, ...)
1232{
1233 va_list ap;
1234 va_start(ap, fmt_str);
1235 char *error_str = mprintf_va_list(fmt_str, ap);
1236 va_end(ap);
1237 Text_Buf text_buf;
1238 text_buf.push_int((RInt)MSG_ERROR);
1239 text_buf.push_string(error_str);
1240 Free(error_str);
1241 send_message(text_buf);
1242}
1243
1244void TTCN_Communication::send_message(Text_Buf& text_buf)
1245{
1246 if (!is_connected) TTCN_error("Trying to send a message to MC, but the "
1247 "control connection is down.");
1248 text_buf.calculate_length();
1249 const char *msg_ptr = text_buf.get_data();
1250 size_t msg_len = text_buf.get_len(), sent_len = 0;
1251 while (sent_len < msg_len) {
1252 int ret_val = send(mc_fd, msg_ptr + sent_len, msg_len - sent_len, 0);
1253 if (ret_val > 0) sent_len += ret_val;
1254 else {
1255 switch (errno) {
1256 case EINTR:
1257 // a signal occurred: do nothing, just try again
1258 errno = 0;
1259 break;
1260 default:
1261 close_mc_connection();
1262 TTCN_error("Sending data on the control connection to MC "
1263 "failed.");
1264 }
1265 }
1266 }
1267}
1268
b0caada2 1269void TTCN_Communication::process_configure(int msg_end, bool to_mtc)
970ed795
EL
1270{
1271 switch (TTCN_Runtime::get_state()) {
1272 case TTCN_Runtime::HC_IDLE:
1273 case TTCN_Runtime::HC_ACTIVE:
1274 case TTCN_Runtime::HC_OVERLOADED:
b0caada2
BB
1275 if (!to_mtc) {
1276 break;
1277 }
1278 // no break
1279 case TTCN_Runtime::MTC_IDLE:
1280 if (to_mtc) {
1281 break;
1282 }
1283 // no break
970ed795
EL
1284 default:
1285 incoming_buf.cut_message();
1286 send_error("Message CONFIGURE arrived in invalid state.");
1287 return;
1288 }
1289
b0caada2 1290 TTCN_Runtime::set_state(to_mtc ? TTCN_Runtime::MTC_CONFIGURING : TTCN_Runtime::HC_CONFIGURING);
970ed795
EL
1291 TTCN_Logger::log_configdata(TitanLoggerApiSimple::ExecutorConfigdata_reason::received__from__mc);
1292
1293 // take the config string directly from the buffer for efficiency reasons
1294 int config_str_len = incoming_buf.pull_int().get_val();
1295 int config_str_begin = incoming_buf.get_pos();
1296 if (config_str_begin + config_str_len != msg_end) {
1297 incoming_buf.cut_message();
1298 send_error("Malformed message CONFIGURE was received.");
1299 return;
1300 }
1301 const char *config_str = incoming_buf.get_data() + config_str_begin;
1302 boolean success = process_config_string(config_str, config_str_len);
1303
1304 // Only non component specific settings will be applied. The plug-ins need
1305 // to be loaded due to resetting.
1306 TTCN_Logger::load_plugins(NULL_COMPREF, "");
1307 TTCN_Logger::set_plugin_parameters(NULL_COMPREF, "");
1308 TTCN_Logger::open_file();
1309 if (success) {
1310 try {
1311 Module_List::log_param();
1312 Module_List::post_init_modules();
1313 } catch (const TC_Error& TC_error) {
1314 TTCN_Logger::log_executor_runtime(
1315 TitanLoggerApiSimple::ExecutorRuntime_reason::initialization__of__modules__failed);
1316 success = FALSE;
1317 }
1318 } else {
1319 TTCN_Logger::log_configdata(
1320 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__failed, NULL);
1321 }
1322
1323 if (success) {
1324 send_configure_ack();
b0caada2 1325 TTCN_Runtime::set_state(to_mtc ? TTCN_Runtime::MTC_IDLE : TTCN_Runtime::HC_ACTIVE);
970ed795
EL
1326 TTCN_Logger::log_configdata(
1327 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__succeeded);
1328 } else {
1329 send_configure_nak();
b0caada2 1330 TTCN_Runtime::set_state(to_mtc ? TTCN_Runtime::MTC_IDLE : TTCN_Runtime::HC_IDLE);
970ed795
EL
1331 }
1332
1333 incoming_buf.cut_message();
1334}
1335
1336void TTCN_Communication::process_create_mtc()
1337{
1338 incoming_buf.cut_message();
1339 TTCN_Runtime::process_create_mtc();
1340}
1341
1342void TTCN_Communication::process_create_ptc()
1343{
1344 component component_reference = (component)incoming_buf.pull_int().get_val();
1345 if (component_reference < FIRST_PTC_COMPREF) {
1346 incoming_buf.cut_message();
1347 send_error("Message CREATE_PTC refers to invalid "
1348 "component reference %d.", component_reference);
1349 return;
1350 }
1351 qualified_name component_type;
1352 incoming_buf.pull_qualified_name(component_type);
1353 if (component_type.module_name == NULL ||
1354 component_type.definition_name == NULL) {
1355 incoming_buf.cut_message();
1356 delete [] component_type.module_name;
1357 delete [] component_type.definition_name;
1358 send_error("Message CREATE_PTC with component reference %d contains "
1359 "an invalid component type.", component_reference);
1360 return;
1361 }
1362 char *component_name = incoming_buf.pull_string();
1363 boolean is_alive = incoming_buf.pull_int().get_val();
1364 qualified_name current_testcase;
1365 incoming_buf.pull_qualified_name(current_testcase);
1366 incoming_buf.cut_message();
1367
1368 try {
1369 TTCN_Runtime::process_create_ptc(component_reference,
1370 component_type.module_name, component_type.definition_name,
1371 component_name, is_alive, current_testcase.module_name,
1372 current_testcase.definition_name);
1373 } catch (...) {
1374 // to prevent from memory leaks
1375 delete [] component_type.module_name;
1376 delete [] component_type.definition_name;
1377 delete [] component_name;
1378 delete [] current_testcase.module_name;
1379 delete [] current_testcase.definition_name;
1380 throw;
1381 }
1382
1383 delete [] component_type.module_name;
1384 delete [] component_type.definition_name;
1385 delete [] component_name;
1386 delete [] current_testcase.module_name;
1387 delete [] current_testcase.definition_name;
1388}
1389
1390void TTCN_Communication::process_kill_process()
1391{
1392 component component_reference = (component)incoming_buf.pull_int().get_val();
1393 incoming_buf.cut_message();
1394 TTCN_Runtime::process_kill_process(component_reference);
1395}
1396
1397void TTCN_Communication::process_exit_hc()
1398{
1399 incoming_buf.cut_message();
1400 TTCN_Logger::log_executor_runtime(
1401 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__hc);
1402 TTCN_Runtime::set_state(TTCN_Runtime::HC_EXIT);
1403}
1404
1405void TTCN_Communication::process_create_ack()
1406{
1407 component component_reference = incoming_buf.pull_int().get_val();
1408 incoming_buf.cut_message();
1409 TTCN_Runtime::process_create_ack(component_reference);
1410}
1411
1412void TTCN_Communication::process_start_ack()
1413{
1414 incoming_buf.cut_message();
1415
1416 switch (TTCN_Runtime::get_state()) {
1417 case TTCN_Runtime::MTC_START:
1418 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1419 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1420 break;
1421 case TTCN_Runtime::PTC_START:
1422 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1423 break;
1424 default:
1425 TTCN_error("Internal error: Message START_ACK arrived in invalid "
1426 "state.");
1427 }
1428}
1429
1430void TTCN_Communication::process_stop()
1431{
1432 incoming_buf.cut_message();
1433 switch (TTCN_Runtime::get_state()) {
1434 case TTCN_Runtime::MTC_IDLE:
1435 TTCN_Logger::log_executor_runtime(
1436 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__mtc);
1437 break;
1438 case TTCN_Runtime::MTC_PAUSED:
1439 TTCN_Logger::log_executor_runtime(
1440 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc);
1441 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TERMINATING_EXECUTION);
1442 break;
1443 case TTCN_Runtime::PTC_IDLE:
1444 case TTCN_Runtime::PTC_STOPPED:
1445 TTCN_Logger::log_executor_runtime(
1446 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__ptc);
1447 break;
1448 case TTCN_Runtime::PTC_EXIT:
1449 // silently ignore
1450 break;
1451 default:
1452 TTCN_Logger::log_executor_runtime(
1453 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc);
1454 TTCN_Runtime::stop_execution();
1455 break;
1456 }
1457}
1458
1459void TTCN_Communication::process_stop_ack()
1460{
1461 incoming_buf.cut_message();
1462 switch (TTCN_Runtime::get_state()) {
1463 case TTCN_Runtime::MTC_STOP:
1464 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1465 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1466 break;
1467 case TTCN_Runtime::PTC_STOP:
1468 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1469 break;
1470 default:
1471 TTCN_error("Internal error: Message STOP_ACK arrived in invalid "
1472 "state.");
1473 }
1474}
1475
1476void TTCN_Communication::process_kill_ack()
1477{
1478 incoming_buf.cut_message();
1479 switch (TTCN_Runtime::get_state()) {
1480 case TTCN_Runtime::MTC_KILL:
1481 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1482 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1483 break;
1484 case TTCN_Runtime::PTC_KILL:
1485 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1486 break;
1487 default:
1488 TTCN_error("Internal error: Message KILL_ACK arrived in invalid "
1489 "state.");
1490 }
1491}
1492
1493void TTCN_Communication::process_running()
1494{
1495 boolean answer = incoming_buf.pull_int().get_val();
1496 incoming_buf.cut_message();
1497 TTCN_Runtime::process_running(answer);
1498}
1499
1500void TTCN_Communication::process_alive()
1501{
1502 boolean answer = incoming_buf.pull_int().get_val();
1503 incoming_buf.cut_message();
1504 TTCN_Runtime::process_alive(answer);
1505}
1506
1507void TTCN_Communication::process_done_ack(int msg_end)
1508{
1509 // decoding the mandatory attributes
1510 boolean answer = incoming_buf.pull_int().get_val();
1511 char *return_type = incoming_buf.pull_string();
1512 // the return value starts here
1513 int return_value_begin = incoming_buf.get_pos();
1514
1515 try {
1516 TTCN_Runtime::process_done_ack(answer, return_type,
1517 msg_end - return_value_begin,
1518 incoming_buf.get_data() + return_value_begin);
1519 } catch (...) {
1520 // avoid memory leaks in case of error
1521 incoming_buf.cut_message();
1522 delete [] return_type;
1523 throw;
1524 }
1525
1526 incoming_buf.cut_message();
1527 delete [] return_type;
1528}
1529
1530void TTCN_Communication::process_killed_ack()
1531{
1532 boolean answer = incoming_buf.pull_int().get_val();
1533 incoming_buf.cut_message();
1534 TTCN_Runtime::process_killed_ack(answer);
1535}
1536
1537void TTCN_Communication::process_cancel_done_mtc()
1538{
1539 component component_reference = incoming_buf.pull_int().get_val();
1540 boolean cancel_any = incoming_buf.pull_int().get_val();
1541 incoming_buf.cut_message();
1542 TTCN_Runtime::cancel_component_done(component_reference);
1543 if (cancel_any) TTCN_Runtime::cancel_component_done(ANY_COMPREF);
1544 send_cancel_done_ack(component_reference);
1545}
1546
1547void TTCN_Communication::process_cancel_done_ptc()
1548{
1549 component component_reference = incoming_buf.pull_int().get_val();
1550 incoming_buf.cut_message();
1551 TTCN_Runtime::cancel_component_done(component_reference);
1552 send_cancel_done_ack(component_reference);
1553}
1554
1555void TTCN_Communication::process_component_status_mtc(int msg_end)
1556{
1557 // decoding the mandatory attributes
1558 component component_reference = incoming_buf.pull_int().get_val();
1559 boolean is_done = incoming_buf.pull_int().get_val();
1560 boolean is_killed = incoming_buf.pull_int().get_val();
1561 boolean is_any_done = incoming_buf.pull_int().get_val();
1562 boolean is_all_done = incoming_buf.pull_int().get_val();
1563 boolean is_any_killed = incoming_buf.pull_int().get_val();
1564 boolean is_all_killed = incoming_buf.pull_int().get_val();
1565 if (is_done) {
1566 // the return type and value is valid
1567 char *return_type = incoming_buf.pull_string();
1568 int return_value_begin = incoming_buf.get_pos();
1569 try {
1570 TTCN_Runtime::set_component_done(component_reference, return_type,
1571 msg_end - return_value_begin,
1572 incoming_buf.get_data() + return_value_begin);
1573 } catch (...) {
1574 // avoid memory leaks
1575 incoming_buf.cut_message();
1576 delete [] return_type;
1577 throw;
1578 }
1579 delete [] return_type;
1580 }
1581 if (is_killed) TTCN_Runtime::set_component_killed(component_reference);
1582 if (is_any_done)
1583 TTCN_Runtime::set_component_done(ANY_COMPREF, NULL, 0, NULL);
1584 if (is_all_done)
1585 TTCN_Runtime::set_component_done(ALL_COMPREF, NULL, 0, NULL);
1586 if (is_any_killed) TTCN_Runtime::set_component_killed(ANY_COMPREF);
1587 if (is_all_killed) TTCN_Runtime::set_component_killed(ALL_COMPREF);
1588 incoming_buf.cut_message();
1589 if (!is_done && !is_killed && (component_reference != NULL_COMPREF ||
1590 (!is_any_done && !is_all_done && !is_any_killed && !is_all_killed)))
1591 TTCN_error("Internal error: Malformed COMPONENT_STATUS message was "
1592 "received.");
1593}
1594
1595void TTCN_Communication::process_component_status_ptc(int msg_end)
1596{
1597 // decoding the mandatory attributes
1598 component component_reference = incoming_buf.pull_int().get_val();
1599 boolean is_done = incoming_buf.pull_int().get_val();
1600 boolean is_killed = incoming_buf.pull_int().get_val();
1601 if (is_done) {
1602 // the return type and value is valid
1603 char *return_type = incoming_buf.pull_string();
1604 int return_value_begin = incoming_buf.get_pos();
1605 try {
1606 TTCN_Runtime::set_component_done(component_reference, return_type,
1607 msg_end - return_value_begin,
1608 incoming_buf.get_data() + return_value_begin);
1609 } catch (...) {
1610 // avoid memory leaks
1611 incoming_buf.cut_message();
1612 delete [] return_type;
1613 throw;
1614 }
1615 delete [] return_type;
1616 }
1617 if (is_killed) TTCN_Runtime::set_component_killed(component_reference);
1618 incoming_buf.cut_message();
1619 if (!is_done && !is_killed) TTCN_error("Internal error: Malformed "
1620 "COMPONENT_STATUS message was received.");
1621}
1622
1623void TTCN_Communication::process_connect_listen()
1624{
1625 char *local_port = incoming_buf.pull_string();
1626 component remote_component = incoming_buf.pull_int().get_val();
1627 char *remote_component_name = incoming_buf.pull_string();
1628 char *remote_port = incoming_buf.pull_string();
1629 transport_type_enum transport_type =
1630 (transport_type_enum)incoming_buf.pull_int().get_val();
1631 incoming_buf.cut_message();
1632
1633 try {
1634 if (remote_component != MTC_COMPREF && self != remote_component)
1635 COMPONENT::register_component_name(remote_component,
1636 remote_component_name);
1637 PORT::process_connect_listen(local_port, remote_component, remote_port,
1638 transport_type);
1639 } catch (...) {
1640 delete [] local_port;
1641 delete [] remote_component_name;
1642 delete [] remote_port;
1643 throw;
1644 }
1645
1646 delete [] local_port;
1647 delete [] remote_component_name;
1648 delete [] remote_port;
1649}
1650
1651void TTCN_Communication::process_connect()
1652{
1653 char *local_port = incoming_buf.pull_string();
1654 component remote_component = incoming_buf.pull_int().get_val();
1655 char *remote_component_name = incoming_buf.pull_string();
1656 char *remote_port = incoming_buf.pull_string();
1657 transport_type_enum transport_type =
1658 (transport_type_enum)incoming_buf.pull_int().get_val();
1659
1660 try {
1661 if (remote_component != MTC_COMPREF && self != remote_component)
1662 COMPONENT::register_component_name(remote_component,
1663 remote_component_name);
1664 PORT::process_connect(local_port, remote_component, remote_port,
1665 transport_type, incoming_buf);
1666 } catch (...) {
1667 incoming_buf.cut_message();
1668 delete [] local_port;
1669 delete [] remote_component_name;
1670 delete [] remote_port;
1671 throw;
1672 }
1673
1674 incoming_buf.cut_message();
1675 delete [] local_port;
1676 delete [] remote_component_name;
1677 delete [] remote_port;
1678}
1679
1680void TTCN_Communication::process_connect_ack()
1681{
1682 incoming_buf.cut_message();
1683
1684 switch (TTCN_Runtime::get_state()) {
1685 case TTCN_Runtime::MTC_CONNECT:
1686 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1687 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1688 break;
1689 case TTCN_Runtime::PTC_CONNECT:
1690 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1691 break;
1692 default:
1693 TTCN_error("Internal error: Message CONNECT_ACK arrived in invalid "
1694 "state.");
1695 }
1696}
1697
1698void TTCN_Communication::process_disconnect()
1699{
1700 char *local_port = incoming_buf.pull_string();
1701 component remote_component = incoming_buf.pull_int().get_val();
1702 char *remote_port = incoming_buf.pull_string();
1703 incoming_buf.cut_message();
1704
1705 try {
1706 PORT::process_disconnect(local_port, remote_component, remote_port);
1707 } catch (...) {
1708 delete [] local_port;
1709 delete [] remote_port;
1710 throw;
1711 }
1712
1713 delete [] local_port;
1714 delete [] remote_port;
1715}
1716
1717void TTCN_Communication::process_disconnect_ack()
1718{
1719 incoming_buf.cut_message();
1720
1721 switch (TTCN_Runtime::get_state()) {
1722 case TTCN_Runtime::MTC_DISCONNECT:
1723 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1724 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1725 break;
1726 case TTCN_Runtime::PTC_DISCONNECT:
1727 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1728 break;
1729 default:
1730 TTCN_error("Internal error: Message DISCONNECT_ACK arrived in invalid "
1731 "state.");
1732 }
1733}
1734
1735void TTCN_Communication::process_map()
1736{
1737 char *local_port = incoming_buf.pull_string();
1738 char *system_port = incoming_buf.pull_string();
1739 incoming_buf.cut_message();
1740
1741 try {
1742 PORT::map_port(local_port, system_port);
1743 } catch (...) {
1744 delete [] local_port;
1745 delete [] system_port;
1746 throw;
1747 }
1748
1749 delete [] local_port;
1750 delete [] system_port;
1751}
1752
1753void TTCN_Communication::process_map_ack()
1754{
1755 incoming_buf.cut_message();
1756
1757 switch (TTCN_Runtime::get_state()) {
1758 case TTCN_Runtime::MTC_MAP:
1759 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1760 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1761 break;
1762 case TTCN_Runtime::PTC_MAP:
1763 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1764 break;
1765 default:
1766 TTCN_error("Internal error: Message MAP_ACK arrived in invalid state.");
1767 }
1768}
1769
1770void TTCN_Communication::process_unmap()
1771{
1772 char *local_port = incoming_buf.pull_string();
1773 char *system_port = incoming_buf.pull_string();
1774 incoming_buf.cut_message();
1775
1776 try {
1777 PORT::unmap_port(local_port, system_port);
1778 } catch (...) {
1779 delete [] local_port;
1780 delete [] system_port;
1781 throw;
1782 }
1783
1784 delete [] local_port;
1785 delete [] system_port;
1786}
1787
1788void TTCN_Communication::process_unmap_ack()
1789{
1790 incoming_buf.cut_message();
1791
1792 switch(TTCN_Runtime::get_state()){
1793 case TTCN_Runtime::MTC_UNMAP:
1794 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1795 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1796 break;
1797 case TTCN_Runtime::PTC_UNMAP:
1798 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1799 break;
1800 default:
1801 TTCN_error("Internal error: Message UNMAP_ACK arrived in invalid "
1802 "state.");
1803 }
1804}
1805
1806void TTCN_Communication::process_execute_control()
1807{
1808 char *module_name = incoming_buf.pull_string();
1809 incoming_buf.cut_message();
1810
1811 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE) {
1812 delete [] module_name;
1813 TTCN_error("Internal error: Message EXECUTE_CONTROL arrived in "
1814 "invalid state.");
1815 }
1816
1817 TTCN_Logger::log(TTCN_Logger::PARALLEL_UNQUALIFIED,
1818 "Executing control part of module %s.", module_name);
1819
1820 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART);
1821
1822 try {
1823 Module_List::execute_control(module_name);
1824 } catch (const TC_End& TC_end) {
1825 } catch (const TC_Error& TC_error) {
1826 }
1827
1828 delete [] module_name;
1829
1830 if (is_connected) {
1831 send_mtc_ready();
1832 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE);
1833 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT);
1834}
1835
1836void TTCN_Communication::process_execute_testcase()
1837{
1838 char *module_name = incoming_buf.pull_string();
1839 char *testcase_name = incoming_buf.pull_string();
1840 incoming_buf.cut_message();
1841
1842 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE) {
1843 delete [] module_name;
1844 delete [] testcase_name;
1845 TTCN_error("Internal error: Message EXECUTE_TESTCASE arrived in "
1846 "invalid state.");
1847 }
1848
1849 TTCN_Logger::log_testcase_exec(testcase_name, module_name);
1850
1851 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART);
1852
1853 try {
1854 if (testcase_name != NULL && testcase_name[0] != '\0')
1855 Module_List::execute_testcase(module_name, testcase_name);
1856 else Module_List::execute_all_testcases(module_name);
1857 } catch (const TC_End& TC_end) {
1858 } catch (const TC_Error& TC_error) {
1859 }
1860
1861 if (is_connected) {
1862 send_mtc_ready();
1863 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE);
1864 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT);
1865
1866 delete [] module_name;
1867 delete [] testcase_name;
1868}
1869
1870void TTCN_Communication::process_ptc_verdict()
1871{
1872 TTCN_Runtime::process_ptc_verdict(incoming_buf);
1873 incoming_buf.cut_message();
1874}
1875
1876void TTCN_Communication::process_continue()
1877{
1878 incoming_buf.cut_message();
1879
1880 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_PAUSED)
1881 TTCN_error("Internal error: Message CONTINUE arrived in invalid "
1882 "state.");
1883
1884 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART);
1885}
1886
1887void TTCN_Communication::process_exit_mtc()
1888{
1889 incoming_buf.cut_message();
1890 TTCN_Runtime::log_verdict_statistics();
1891 TTCN_Logger::log_executor_runtime(
1892 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__mtc);
1893 TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT);
1894}
1895
1896void TTCN_Communication::process_start()
1897{
1898 qualified_name function_name;
1899 incoming_buf.pull_qualified_name(function_name);
1900 if (function_name.module_name == NULL ||
1901 function_name.definition_name == NULL) {
1902 incoming_buf.cut_message();
1903 delete [] function_name.module_name;
1904 delete [] function_name.definition_name;
1905 TTCN_error("Internal error: Message START contains an invalid "
1906 "function name.");
1907 }
1908
1909 try {
1910 TTCN_Runtime::start_function(function_name.module_name,
1911 function_name.definition_name, incoming_buf);
1912 } catch (...) {
1913 // avoid memory leaks
1914 delete [] function_name.module_name;
1915 delete [] function_name.definition_name;
1916 throw;
1917 }
1918
1919 delete [] function_name.module_name;
1920 delete [] function_name.definition_name;
1921}
1922
1923void TTCN_Communication::process_kill()
1924{
1925 incoming_buf.cut_message();
1926 TTCN_Runtime::process_kill();
1927}
1928
1929void TTCN_Communication::process_error()
1930{
1931 char *error_string = incoming_buf.pull_string();
1932 incoming_buf.cut_message();
1933
1934 try {
1935 TTCN_error("Error message was received from MC: %s", error_string);
1936 } catch (...) {
1937 delete [] error_string;
1938 throw;
1939 }
1940}
1941
1942void TTCN_Communication::process_unsupported_message(int msg_type, int msg_end)
1943{
1944 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED);
1945 TTCN_Logger::log_event("Unsupported message was received from MC: "
1946 "type (decimal): %d, data (hexadecimal): ", msg_type);
1947 const unsigned char *msg_ptr =
1948 (const unsigned char*)incoming_buf.get_data();
1949 for (int i = incoming_buf.get_pos(); i < msg_end; i++)
1950 TTCN_Logger::log_octet(msg_ptr[i]);
1951 TTCN_Logger::end_event();
1952 incoming_buf.cut_message();
1953}
1954
016a1a93
BB
1955void TTCN_Communication::process_debug_command()
1956{
1957 int command = incoming_buf.pull_int().get_val();
1958 int argument_count = incoming_buf.pull_int().get_val();
1959 char** arguments = NULL;
1960 if (argument_count > 0) {
1961 arguments = new char*[argument_count];
1962 for (int i = 0; i < argument_count; ++i) {
1963 arguments[i] = incoming_buf.pull_string();
1964 }
1965 }
1966 incoming_buf.cut_message();
1967 ttcn3_debugger.execute_command(command, argument_count, arguments);
1968 if (argument_count > 0) {
1969 for (int i = 0; i < argument_count; ++i) {
1970 delete [] arguments[i];
1971 }
1972 delete [] arguments;
1973 }
1974}
1975
970ed795
EL
1976/* * * * Temporary squatting place because it includes version.h * * * */
1977
1978const struct runtime_version current_runtime_version = {
1979 TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL, TITAN_RUNTIME_NR
1980};
1981
1982static const char *runtime_name[] = { 0, "load", "function " };
1983
1984RuntimeVersionChecker::RuntimeVersionChecker(
1985 int ver_major, int ver_minor, int patch_level, int rt)
1986{
1987 if ( TTCN3_MAJOR != ver_major
1988 || TTCN3_MINOR != ver_minor
1989 || TTCN3_PATCHLEVEL != patch_level)
1990 {
1991 TTCN_error(
1992 "Version mismatch detected: generated code %d.%d.pl%d, "
1993 "runtime is %d.%d.pl%d",
1994 ver_major, ver_minor, patch_level,
1995 TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL);
1996 }
1997
1998 if (TITAN_RUNTIME_NR != rt) {
1999 TTCN_error("Runtime mismatch detected: files compiled for the %stest"
2000 " runtime cannot be linked to %stest library",
2001 runtime_name[TITAN_RUNTIME_NR], runtime_name[rt]);
2002 }
2003}
2004
2005reffer::reffer(const char*) {}
2006
This page took 0.109245 seconds and 5 git commands to generate.