1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 #include "Communication.hh"
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/utsname.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <arpa/inet.h>
26 #include "../common/dbgnew.hh"
28 #include "Message_types.hh"
29 #include "Module_list.hh"
30 #include "Verdicttype.hh"
31 #include "Fd_And_Timeout_User.hh"
35 #include "Component.hh"
37 #include "TitanLoggerApiSimple.hh"
38 #include "../common/version.h"
40 #include "Event_Handler.hh"
42 class MC_Connection
: public Fd_And_Timeout_Event_Handler
{
43 virtual void Handle_Fd_Event(int fd
,
44 boolean is_readable
, boolean is_writable
, boolean is_error
);
45 virtual void Handle_Timeout(double time_since_last_call
);
47 MC_Connection(const int * fd
, Text_Buf
* buf
) :
48 Fd_And_Timeout_Event_Handler(), mc_fd(fd
), incoming_buf(buf
) {}
49 virtual void log() const;
52 Text_Buf
* incoming_buf
;
55 int TTCN_Communication::mc_fd
= -1;
56 HCNetworkHandler
TTCN_Communication::hcnh
;
57 boolean
TTCN_Communication::local_addr_set
= FALSE
,
58 TTCN_Communication::mc_addr_set
= FALSE
,
59 TTCN_Communication::is_connected
= FALSE
;
60 Text_Buf
TTCN_Communication::incoming_buf
;
61 MC_Connection
TTCN_Communication::mc_connection(
62 &TTCN_Communication::mc_fd
, &TTCN_Communication::incoming_buf
);
63 double TTCN_Communication::call_interval
= 0.0;
65 void TTCN_Communication::set_local_address(const char *host_name
)
68 TTCN_warning("The local address has already been set.");
70 TTCN_error("Trying to change the local address, but there is an existing "
71 "control connection to MC.");
72 if (host_name
== NULL
){
73 fprintf(stderr
,"TTCN_Communication::set_local_address: internal error: " // There is no connection to the MC
74 "invalid host name.\r\n"); // We should log to the console also
75 TTCN_error("TTCN_Communication::set_local_address: internal error: "
76 "invalid host name.");
78 if (!hcnh
.set_local_addr(host_name
, 0)){
79 fprintf(stderr
,"Could not get the IP address for the local address " // There is no connection to the MC
80 "(%s): Host name lookup failure.\r\n", host_name
); // We should log to the console also
81 TTCN_error("Could not get the IP address for the local address "
82 "(%s): Host name lookup failure.", host_name
);
84 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::local__address__was__set
,
85 hcnh
.get_local_host_str(), hcnh
.get_local_addr_str(), 0);
86 local_addr_set
= TRUE
;
89 const IPAddress
*TTCN_Communication::get_local_address()
92 TTCN_error("TTCN_Communication::get_local_address: internal error: the "
93 "local address has not been set.");
94 return hcnh
.get_local_addr();
97 void TTCN_Communication::set_mc_address(const char *host_name
,
98 unsigned short tcp_port
)
101 TTCN_warning("The address of MC has already been set.");
103 TTCN_error("Trying to change the address of MC, but there is an existing connection.");
104 if (host_name
== NULL
){
105 fprintf(stderr
,"TTCN_Communication::set_mc_address: internal error: invalid host name.\r\n");
106 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid host name.");
109 fprintf(stderr
,"TTCN_Communication::set_mc_address: internal error: invalid TCP port. %hu\r\n",tcp_port
);
110 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid TCP port.");
112 hcnh
.set_family(host_name
);
113 if (!hcnh
.set_mc_addr(host_name
, tcp_port
)){
114 fprintf(stderr
,"Could not get the IP address of MC (%s): Host name lookup "
115 "failure.\r\n", host_name
);
116 TTCN_error("Could not get the IP address of MC (%s): Host name lookup "
117 "failure.", host_name
);
119 if ((hcnh
.get_mc_addr())->is_local()){
120 fprintf(stderr
,"The address of MC was set to a local IP address. This may "
121 "cause incorrect behavior if a HC from a remote host also "
122 "connects to MC.\r\n");
123 TTCN_warning("The address of MC was set to a local IP address. This may "
124 "cause incorrect behavior if a HC from a remote host also "
127 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__mc__was__set
,
128 hcnh
.get_mc_host_str(), hcnh
.get_mc_addr_str(), 0);
132 const IPAddress
*TTCN_Communication::get_mc_address()
135 TTCN_error("TTCN_Communication::get_mc_address: internal error: the "
136 "address of MC has not been set.");
137 return hcnh
.get_mc_addr();
140 bool TTCN_Communication::is_mc_connected()
145 void TTCN_Communication::connect_mc()
147 if (is_connected
) TTCN_error("Trying to re-connect to MC, but there is an "
148 "existing connection.");
149 if (!mc_addr_set
) TTCN_error("Trying to connect to MC, but the address of "
150 "MC has not yet been set.");
152 // Trying to connect to local mc through unix domain socket
153 // TODO: Disable if config file parameter is set
154 if ((hcnh
.get_mc_addr())->is_local()
155 || (local_addr_set
&& *(hcnh
.get_mc_addr()) == *(hcnh
.get_local_addr()))) {
156 sockaddr_un localaddr_unix
;
157 memset(&localaddr_unix
, 0, sizeof(localaddr_unix
));
158 localaddr_unix
.sun_family
= AF_UNIX
;
159 snprintf(localaddr_unix
.sun_path
, sizeof(localaddr_unix
.sun_path
),
160 "/tmp/ttcn3-mctr-%u", hcnh
.get_mc_port());
161 mc_fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
162 if (mc_fd
>= (int)FD_SETSIZE
) {
164 } else if (mc_fd
>= 0) {
165 if (connect(mc_fd
, (struct sockaddr
*)&localaddr_unix
,
166 sizeof(localaddr_unix
)) == 0) {
167 goto unix_end
; // connected successfully
177 mc_fd
= hcnh
.socket();
179 fprintf(stderr
,"Socket creation failed when connecting to MC.");
180 TTCN_error("Socket creation failed when connecting to MC.");
182 else if (mc_fd
>= (int)FD_SETSIZE
) {
184 fprintf(stderr
,"When connecting to MC: "
185 "The file descriptor returned by the operating system (%d) is "
186 "too large for use with the select() system call.\r\n", mc_fd
);
187 TTCN_error("When connecting to MC: "
188 "The file descriptor returned by the operating system (%d) is "
189 "too large for use with the select() system call.", mc_fd
);
192 if (local_addr_set
) {
193 if (hcnh
.bind_local_addr(mc_fd
)) {
194 fprintf(stderr
,"Binding IP address %s to the local endpoint of the "
195 "control connection failed when connecting to MC.\r\n", hcnh
.get_local_addr_str());
196 TTCN_error("Binding IP address %s to the local endpoint of the "
197 "control connection failed when connecting to MC.",
198 hcnh
.get_local_addr_str());
203 if (hcnh
.connect_to_mc(mc_fd
)) {
205 if (errno
== EADDRINUSE
) {
208 TTCN_warning("connect() returned error code EADDRINUSE. "
209 "Perhaps this is a Cygwin bug. Trying to connect again.");
213 fprintf(stderr
,"Connecting to MC failed. MC address: %s:%hu %s\r\n",hcnh
.get_mc_addr_str(),hcnh
.get_mc_port(),strerror(errno
));
214 TTCN_error("Connecting to MC failed.");
218 if (!local_addr_set
) {
219 if (hcnh
.getsockname_local_addr(mc_fd
)) {
221 TTCN_error("getsockname() system call failed on the socket of the "
222 "control connection to MC.");
224 TTCN_Logger::log_executor_misc(
225 TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__control__connection
,
226 NULL
, hcnh
.get_local_addr_str(), 0);
227 local_addr_set
= TRUE
;
230 if (!set_tcp_nodelay(mc_fd
)) {
232 TTCN_error("Setting the TCP_NODELAY flag failed on the socket of "
233 "the control connection to MC.");
238 if (!set_close_on_exec(mc_fd
)) {
240 TTCN_error("Setting the close-on-exec flag failed on the socket of "
241 "the control connection to MC.");
244 Fd_And_Timeout_User::add_fd(mc_fd
, &mc_connection
, FD_EVENT_RD
);
246 TTCN_Logger::log_executor_runtime(
247 TitanLoggerApiSimple::ExecutorRuntime_reason::connected__to__mc
);
252 void TTCN_Communication::disconnect_mc()
259 recv_len
= recv(mc_fd
, buf
, sizeof(buf
), 0);
260 } while (recv_len
> 0);
262 close_mc_connection();
263 TTCN_Logger::log_executor_runtime(
264 TitanLoggerApiSimple::ExecutorRuntime_reason::disconnected__from__mc
);
268 void TTCN_Communication::close_mc_connection()
271 int tmp_mc_fd
= mc_fd
;
275 is_connected
= FALSE
;
276 incoming_buf
.reset();
277 // Removing the fd has to be done after closing the mc connection
278 // to prevent segmentation fault or broken pipe error
279 // in case remove_fd would try to print an error log.
280 Fd_And_Timeout_User::remove_fd(tmp_mc_fd
, &mc_connection
, FD_EVENT_RD
);
281 Fd_And_Timeout_User::set_timer(&mc_connection
, 0.0);
285 boolean
TTCN_Communication::transport_unix_stream_supported()
287 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
290 TTCN_Logger::log_executor_misc(
291 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets
,
295 TTCN_Logger::log_executor_misc(
296 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets
,
302 boolean
TTCN_Communication::set_close_on_exec(int fd
)
304 int flags
= fcntl(fd
, F_GETFD
);
306 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
307 TTCN_Logger::log_event("System call fcntl(F_GETFD) failed on file "
308 "descriptor %d.", fd
);
309 TTCN_Logger::OS_error();
310 TTCN_Logger::end_event();
316 if (fcntl(fd
, F_SETFD
, flags
) == -1) {
317 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
318 TTCN_Logger::log_event("System call fcntl(F_SETFD) failed on file "
319 "descriptor %d.", fd
);
320 TTCN_Logger::OS_error();
321 TTCN_Logger::end_event();
327 boolean
TTCN_Communication::set_non_blocking_mode(int fd
,
328 boolean enable_nonblock
)
330 int flags
= fcntl(fd
, F_GETFL
);
332 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
333 TTCN_Logger::log_event("System call fcntl(F_GETFL) failed on file "
334 "descriptor %d.", fd
);
335 TTCN_Logger::OS_error();
336 TTCN_Logger::end_event();
340 if (enable_nonblock
) flags
|= O_NONBLOCK
;
341 else flags
&= ~O_NONBLOCK
;
343 if (fcntl(fd
, F_SETFL
, flags
) == -1) {
344 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
345 TTCN_Logger::log_event("System call fcntl(F_SETFL) failed on file "
346 "descriptor %d.", fd
);
347 TTCN_Logger::OS_error();
348 TTCN_Logger::end_event();
354 boolean
TTCN_Communication::set_tcp_nodelay(int fd
)
357 if (setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (const char*)&on
,
359 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
360 TTCN_Logger::log_event("System call setsockopt(TCP_NODELAY) failed on "
361 "file descriptor %d.", fd
);
362 TTCN_Logger::OS_error();
363 TTCN_Logger::end_event();
369 boolean
TTCN_Communication::increase_send_buffer(int fd
,
370 int &old_size
, int& new_size
)
373 socklen_type optlen
= sizeof(old_size
);
374 // obtaining the current buffer size first
375 if (getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&old_size
, &optlen
))
376 goto getsockopt_failure
;
378 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
379 "System call getsockopt(SO_SNDBUF) returned invalid buffer size (%d) "
380 "on file descriptor %d.", old_size
, fd
);
383 // trying to double the buffer size
384 set_size
= 2 * old_size
;
385 if (set_size
> old_size
) {
386 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (const char*)&set_size
,
388 // the operation failed
395 // other error codes indicate a fatal error
396 goto setsockopt_failure
;
399 // the operation was successful
403 // trying to perform a binary search to determine the maximum buffer size
405 for (int size_step
= old_size
/ 2; size_step
> 0; size_step
/= 2) {
406 int tried_size
= set_size
+ size_step
;
407 if (tried_size
> set_size
) {
408 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (const char*)&tried_size
,
409 sizeof(tried_size
))) {
410 // the operation failed
417 // other error codes indicate a fatal error
418 goto setsockopt_failure
;
421 // the operation was successful
422 set_size
= tried_size
;
426 if (set_size
<= old_size
) return FALSE
;
428 // querying the new effective buffer size (it might be smaller
429 // than set_size but should not be smaller than old_size)
430 optlen
= sizeof(new_size
);
431 if (getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&new_size
,
432 &optlen
)) goto getsockopt_failure
;
433 if (new_size
> old_size
) return TRUE
;
435 if (new_size
< old_size
) TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
436 "System call getsockopt(SO_SNDBUF) returned unexpected buffer size "
437 "(%d, after increasing it from %d to %d) on file descriptor %d.",
438 new_size
, old_size
, set_size
, fd
);
442 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
443 TTCN_Logger::log_event("System call getsockopt(SO_SNDBUF) failed on file "
444 "descriptor %d.", fd
);
445 TTCN_Logger::OS_error();
446 TTCN_Logger::end_event();
449 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
450 TTCN_Logger::log_event("System call setsockopt(SO_SNDBUF) failed on file "
451 "descriptor %d.", fd
);
452 TTCN_Logger::OS_error();
453 TTCN_Logger::end_event();
457 #define INITIAL_CALL_INTERVAL 1.0
458 #define CALL_INTERVAL_INCREMENT 2.0
460 void TTCN_Communication::enable_periodic_call()
462 call_interval
= INITIAL_CALL_INTERVAL
;
463 Fd_And_Timeout_User::set_timer(&mc_connection
, call_interval
, TRUE
,
464 FALSE
/*call_anyway*/);
467 void TTCN_Communication::increase_call_interval()
469 if (call_interval
<= 0.0) TTCN_error("Internal error: "
470 "TTCN_Communication::increase_call_interval() was called when call "
471 "interval is not set.");
472 call_interval
*= CALL_INTERVAL_INCREMENT
;
473 Fd_And_Timeout_User::set_timer(&mc_connection
, call_interval
, TRUE
,
474 FALSE
/*call_anyway*/);
477 void TTCN_Communication::disable_periodic_call()
479 Fd_And_Timeout_User::set_timer(&mc_connection
, 0.0);
483 void MC_Connection::Handle_Fd_Event(int fd
, boolean is_readable
, boolean
,
487 TTCN_error("MC_Connection::Fd_And_Timeout_Event_Handler: unexpected "
488 "file descriptor"); // not necessary - debugging
490 TTCN_warning("Error occurred on the control connection to MC");
494 incoming_buf
->get_end(buf_ptr
, buf_len
);
496 int recv_len
= recv(*mc_fd
, buf_ptr
, buf_len
, 0);
499 // reason: data has arrived
500 incoming_buf
->increase_length(recv_len
);
501 // If the component is idle the processing is done in the outer
502 // stack frame (i.e. in TTCN_Runtime::xxx_main()).
503 if (!TTCN_Runtime::is_idle())
504 TTCN_Communication::process_all_messages_tc();
506 // First closing the TCP connection to avoid EPIPE ("Broken pipe")
507 // errors and/or SIGPIPE signals when trying to send anything
508 // (e.g. log events or error messages) towards MC.
509 TTCN_Communication::close_mc_connection();
511 // reason: TCP connection was closed by peer
512 TTCN_error("Control connection was closed unexpectedly by MC.");
514 // reason: error occurred
515 TTCN_error("Receiving data on the control connection from MC "
522 void MC_Connection::Handle_Timeout(double /*time_since_last_call*/)
524 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_OVERLOADED
) {
525 // indicate the timeout to be handled in process_all_messages_hc()
526 TTCN_Runtime::set_state(TTCN_Runtime::HC_OVERLOADED_TIMEOUT
);
528 TTCN_warning("Unexpected timeout occurred on the control "
529 "connection to MC.");
530 TTCN_Communication::disable_periodic_call();
534 void MC_Connection::log() const
536 TTCN_Logger::log_event("mc connection");
539 void TTCN_Communication::process_all_messages_hc()
541 if (!TTCN_Runtime::is_hc()) TTCN_error("Internal error: "
542 "TTCN_Communication::process_all_messages_hc() was called in invalid "
544 TTCN_Runtime::wait_terminated_processes();
545 boolean wait_flag
= FALSE
;
546 boolean check_overload
= TTCN_Runtime::is_overloaded();
547 while (incoming_buf
.is_message()) {
549 int msg_len
= incoming_buf
.pull_int().get_val();
550 int msg_end
= incoming_buf
.get_pos() + msg_len
;
551 int msg_type
= incoming_buf
.pull_int().get_val();
552 // messages: MC -> HC
558 process_configure(msg_end
);
561 process_create_mtc();
562 TTCN_Runtime::wait_terminated_processes();
564 check_overload
= FALSE
;
567 process_create_ptc();
568 TTCN_Runtime::wait_terminated_processes();
570 check_overload
= FALSE
;
572 case MSG_KILL_PROCESS
:
573 process_kill_process();
574 TTCN_Runtime::wait_terminated_processes();
581 process_unsupported_message(msg_type
, msg_end
);
584 if (wait_flag
) TTCN_Runtime::wait_terminated_processes();
585 if (check_overload
&& TTCN_Runtime::is_overloaded())
586 TTCN_Runtime::check_overload();
589 void TTCN_Communication::process_all_messages_tc()
591 if (!TTCN_Runtime::is_tc()) TTCN_error("Internal error: "
592 "TTCN_Communication::process_all_messages_tc() was called in invalid "
594 while (incoming_buf
.is_message()) {
595 int msg_len
= incoming_buf
.pull_int().get_val();
596 int msg_end
= incoming_buf
.get_pos() + msg_len
;
597 int msg_type
= incoming_buf
.pull_int().get_val();
598 // messages: MC -> TC
604 process_create_ack();
625 process_done_ack(msg_end
);
628 process_killed_ack();
630 case MSG_CANCEL_DONE
:
631 if (TTCN_Runtime::is_mtc()) process_cancel_done_mtc();
632 else process_cancel_done_ptc();
634 case MSG_COMPONENT_STATUS
:
635 if (TTCN_Runtime::is_mtc()) process_component_status_mtc(msg_end
);
636 else process_component_status_ptc(msg_end
);
638 case MSG_CONNECT_LISTEN
:
639 process_connect_listen();
644 case MSG_CONNECT_ACK
:
645 process_connect_ack();
648 process_disconnect();
650 case MSG_DISCONNECT_ACK
:
651 process_disconnect_ack();
666 if (TTCN_Runtime::is_mtc()) {
667 // messages: MC -> MTC
669 case MSG_EXECUTE_CONTROL
:
670 process_execute_control();
672 case MSG_EXECUTE_TESTCASE
:
673 process_execute_testcase();
675 case MSG_PTC_VERDICT
:
676 process_ptc_verdict();
685 process_unsupported_message(msg_type
, msg_end
);
688 // messages: MC -> PTC
697 process_unsupported_message(msg_type
, msg_end
);
704 void TTCN_Communication::send_version()
707 text_buf
.push_int(MSG_VERSION
);
708 text_buf
.push_int(TTCN3_MAJOR
);
709 text_buf
.push_int(TTCN3_MINOR
);
710 text_buf
.push_int(TTCN3_PATCHLEVEL
);
711 #ifdef TTCN3_BUILDNUMBER
712 text_buf
.push_int(TTCN3_BUILDNUMBER
);
714 text_buf
.push_int((RInt
)0);
716 Module_List::push_version(text_buf
);
718 if (uname(&uts
) < 0) TTCN_error("System call uname() failed.");
719 text_buf
.push_string(uts
.nodename
);
720 text_buf
.push_string(uts
.machine
);
721 text_buf
.push_string(uts
.sysname
);
722 text_buf
.push_string(uts
.release
);
723 text_buf
.push_string(uts
.version
);
724 boolean unix_stream_supported
= transport_unix_stream_supported();
726 // LOCAL (software loop) and INET_STREAM (TCP) transports are always
728 int n_supported_transports
= 2;
730 if (unix_stream_supported
) n_supported_transports
++;
731 text_buf
.push_int(n_supported_transports
);
732 text_buf
.push_int(TRANSPORT_LOCAL
);
733 text_buf
.push_int(TRANSPORT_INET_STREAM
);
734 if (unix_stream_supported
)
735 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
736 send_message(text_buf
);
739 void TTCN_Communication::send_configure_ack()
742 text_buf
.push_int(MSG_CONFIGURE_ACK
);
743 send_message(text_buf
);
746 void TTCN_Communication::send_configure_nak()
749 text_buf
.push_int(MSG_CONFIGURE_NAK
);
750 send_message(text_buf
);
753 void TTCN_Communication::send_create_nak(component component_reference
,
754 const char *fmt_str
, ...)
757 va_start(ap
, fmt_str
);
758 char *error_str
= mprintf_va_list(fmt_str
, ap
);
761 text_buf
.push_int(MSG_CREATE_NAK
);
762 text_buf
.push_int(component_reference
);
763 text_buf
.push_string(error_str
);
765 send_message(text_buf
);
768 void TTCN_Communication::send_hc_ready()
771 text_buf
.push_int(MSG_HC_READY
);
772 send_message(text_buf
);
775 void TTCN_Communication::send_create_req(const char *component_type_module
,
776 const char *component_type_name
, const char *component_name
,
777 const char *component_location
, boolean is_alive
)
780 text_buf
.push_int(MSG_CREATE_REQ
);
781 text_buf
.push_string(component_type_module
);
782 text_buf
.push_string(component_type_name
);
783 text_buf
.push_string(component_name
);
784 text_buf
.push_string(component_location
);
785 text_buf
.push_int(is_alive
? 1 : 0);
786 send_message(text_buf
);
789 void TTCN_Communication::prepare_start_req(Text_Buf
& text_buf
,
790 component component_reference
, const char *module_name
,
791 const char *function_name
)
793 text_buf
.push_int(MSG_START_REQ
);
794 text_buf
.push_int(component_reference
);
795 text_buf
.push_string(module_name
);
796 text_buf
.push_string(function_name
);
799 void TTCN_Communication::send_stop_req(component component_reference
)
802 text_buf
.push_int(MSG_STOP_REQ
);
803 text_buf
.push_int(component_reference
);
804 send_message(text_buf
);
807 void TTCN_Communication::send_kill_req(component component_reference
)
810 text_buf
.push_int(MSG_KILL_REQ
);
811 text_buf
.push_int(component_reference
);
812 send_message(text_buf
);
815 void TTCN_Communication::send_is_running(component component_reference
)
818 text_buf
.push_int(MSG_IS_RUNNING
);
819 text_buf
.push_int(component_reference
);
820 send_message(text_buf
);
823 void TTCN_Communication::send_is_alive(component component_reference
)
826 text_buf
.push_int(MSG_IS_ALIVE
);
827 text_buf
.push_int(component_reference
);
828 send_message(text_buf
);
831 void TTCN_Communication::send_done_req(component component_reference
)
834 text_buf
.push_int(MSG_DONE_REQ
);
835 text_buf
.push_int(component_reference
);
836 send_message(text_buf
);
839 void TTCN_Communication::send_killed_req(component component_reference
)
842 text_buf
.push_int(MSG_KILLED_REQ
);
843 text_buf
.push_int(component_reference
);
844 send_message(text_buf
);
847 void TTCN_Communication::send_cancel_done_ack(component component_reference
)
850 text_buf
.push_int(MSG_CANCEL_DONE_ACK
);
851 text_buf
.push_int(component_reference
);
852 send_message(text_buf
);
855 void TTCN_Communication::send_connect_req(component src_component
,
856 const char *src_port
, component dst_component
, const char *dst_port
)
859 text_buf
.push_int(MSG_CONNECT_REQ
);
860 text_buf
.push_int(src_component
);
861 text_buf
.push_string(src_port
);
862 text_buf
.push_int(dst_component
);
863 text_buf
.push_string(dst_port
);
864 send_message(text_buf
);
867 void TTCN_Communication::send_connect_listen_ack_inet_stream(
868 const char *local_port
, component remote_component
,
869 const char *remote_port
, const IPAddress
*local_address
)
872 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
873 text_buf
.push_string(local_port
);
874 text_buf
.push_int(remote_component
);
875 text_buf
.push_string(remote_port
);
876 text_buf
.push_int(TRANSPORT_INET_STREAM
);
877 local_address
->push_raw(text_buf
);
878 send_message(text_buf
);
881 void TTCN_Communication::send_connect_listen_ack_unix_stream(
882 const char *local_port
, component remote_component
,
883 const char *remote_port
, const struct sockaddr_un
*local_address
)
886 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
887 text_buf
.push_string(local_port
);
888 text_buf
.push_int(remote_component
);
889 text_buf
.push_string(remote_port
);
890 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
891 text_buf
.push_string(local_address
->sun_path
);
892 send_message(text_buf
);
895 void TTCN_Communication::send_connected(const char *local_port
,
896 component remote_component
, const char *remote_port
)
899 text_buf
.push_int(MSG_CONNECTED
);
900 text_buf
.push_string(local_port
);
901 text_buf
.push_int(remote_component
);
902 text_buf
.push_string(remote_port
);
903 send_message(text_buf
);
906 void TTCN_Communication::send_connect_error(const char *local_port
,
907 component remote_component
, const char *remote_port
,
908 const char *fmt_str
, ...)
911 va_start(ap
, fmt_str
);
912 char *error_str
= mprintf_va_list(fmt_str
, ap
);
915 text_buf
.push_int(MSG_CONNECT_ERROR
);
916 text_buf
.push_string(local_port
);
917 text_buf
.push_int(remote_component
);
918 text_buf
.push_string(remote_port
);
919 text_buf
.push_string(error_str
);
921 send_message(text_buf
);
924 void TTCN_Communication::send_disconnect_req(component src_component
,
925 const char *src_port
, component dst_component
, const char *dst_port
)
928 text_buf
.push_int(MSG_DISCONNECT_REQ
);
929 text_buf
.push_int(src_component
);
930 text_buf
.push_string(src_port
);
931 text_buf
.push_int(dst_component
);
932 text_buf
.push_string(dst_port
);
933 send_message(text_buf
);
936 void TTCN_Communication::send_disconnected(const char *local_port
,
937 component remote_component
, const char *remote_port
)
940 text_buf
.push_int(MSG_DISCONNECTED
);
941 text_buf
.push_string(local_port
);
942 text_buf
.push_int(remote_component
);
943 text_buf
.push_string(remote_port
);
944 send_message(text_buf
);
947 void TTCN_Communication::send_map_req(component src_component
,
948 const char *src_port
, const char *system_port
)
951 text_buf
.push_int(MSG_MAP_REQ
);
952 text_buf
.push_int(src_component
);
953 text_buf
.push_string(src_port
);
954 text_buf
.push_string(system_port
);
955 send_message(text_buf
);
958 void TTCN_Communication::send_mapped(const char *local_port
,
959 const char *system_port
)
962 text_buf
.push_int(MSG_MAPPED
);
963 text_buf
.push_string(local_port
);
964 text_buf
.push_string(system_port
);
965 send_message(text_buf
);
968 void TTCN_Communication::send_unmap_req(component src_component
,
969 const char *src_port
, const char *system_port
)
972 text_buf
.push_int(MSG_UNMAP_REQ
);
973 text_buf
.push_int(src_component
);
974 text_buf
.push_string(src_port
);
975 text_buf
.push_string(system_port
);
976 send_message(text_buf
);
979 void TTCN_Communication::send_unmapped(const char *local_port
,
980 const char *system_port
)
983 text_buf
.push_int(MSG_UNMAPPED
);
984 text_buf
.push_string(local_port
);
985 text_buf
.push_string(system_port
);
986 send_message(text_buf
);
989 void TTCN_Communication::send_mtc_created()
992 text_buf
.push_int(MSG_MTC_CREATED
);
993 send_message(text_buf
);
996 void TTCN_Communication::send_testcase_started(const char *testcase_module
,
997 const char *testcase_name
, const char *mtc_comptype_module
,
998 const char *mtc_comptype_name
, const char *system_comptype_module
,
999 const char *system_comptype_name
)
1002 text_buf
.push_int(MSG_TESTCASE_STARTED
);
1003 text_buf
.push_string(testcase_module
);
1004 text_buf
.push_string(testcase_name
);
1005 text_buf
.push_string(mtc_comptype_module
);
1006 text_buf
.push_string(mtc_comptype_name
);
1007 text_buf
.push_string(system_comptype_module
);
1008 text_buf
.push_string(system_comptype_name
);
1009 send_message(text_buf
);
1012 void TTCN_Communication::send_testcase_finished(verdicttype final_verdict
,
1016 text_buf
.push_int(MSG_TESTCASE_FINISHED
);
1017 text_buf
.push_int(final_verdict
);
1018 text_buf
.push_string(reason
);
1019 send_message(text_buf
);
1022 void TTCN_Communication::send_mtc_ready()
1025 text_buf
.push_int(MSG_MTC_READY
);
1026 send_message(text_buf
);
1029 void TTCN_Communication::send_ptc_created(component component_reference
)
1032 text_buf
.push_int(MSG_PTC_CREATED
);
1033 text_buf
.push_int(component_reference
);
1034 send_message(text_buf
);
1037 void TTCN_Communication::prepare_stopped(Text_Buf
& text_buf
,
1038 const char *return_type
)
1040 text_buf
.push_int(MSG_STOPPED
);
1041 text_buf
.push_string(return_type
);
1044 void TTCN_Communication::send_stopped()
1047 text_buf
.push_int(MSG_STOPPED
);
1048 // add an empty return type
1049 text_buf
.push_string(NULL
);
1050 send_message(text_buf
);
1053 void TTCN_Communication::prepare_stopped_killed(Text_Buf
& text_buf
,
1054 verdicttype final_verdict
, const char *return_type
, const char* reason
)
1056 text_buf
.push_int(MSG_STOPPED_KILLED
);
1057 text_buf
.push_int(final_verdict
);
1058 text_buf
.push_string(reason
);
1059 text_buf
.push_string(return_type
);
1062 void TTCN_Communication::send_stopped_killed(verdicttype final_verdict
,
1066 text_buf
.push_int(MSG_STOPPED_KILLED
);
1067 text_buf
.push_int(final_verdict
);
1068 text_buf
.push_string(reason
);
1069 // add an empty return type
1070 text_buf
.push_string(NULL
);
1071 send_message(text_buf
);
1074 void TTCN_Communication::send_killed(verdicttype final_verdict
,
1078 text_buf
.push_int(MSG_KILLED
);
1079 text_buf
.push_int(final_verdict
);
1080 text_buf
.push_string(reason
);
1081 send_message(text_buf
);
1084 boolean
TTCN_Communication::send_log(time_t timestamp_sec
, long timestamp_usec
,
1085 unsigned int event_severity
, size_t message_text_len
,
1086 const char *message_text
)
1090 text_buf
.push_int(MSG_LOG
);
1091 text_buf
.push_int(timestamp_sec
);
1092 text_buf
.push_int(timestamp_usec
);
1093 text_buf
.push_int(event_severity
);
1094 text_buf
.push_int(message_text_len
);
1095 text_buf
.push_raw(message_text_len
, message_text
);
1096 send_message(text_buf
);
1097 /* If an ERROR message (indicating a version mismatch) arrives from MC
1098 in state HC_IDLE (i.e. before CONFIGURE) it shall be
1099 printed to the console as well. */
1100 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_IDLE
) return FALSE
;
1103 switch (TTCN_Runtime::get_state()) {
1104 case TTCN_Runtime::HC_EXIT
:
1105 case TTCN_Runtime::MTC_INITIAL
:
1106 case TTCN_Runtime::MTC_EXIT
:
1107 case TTCN_Runtime::PTC_INITIAL
:
1108 case TTCN_Runtime::PTC_EXIT
:
1109 /* Do not print the first/last few lines of logs to the console
1110 even if ConsoleMask is set to LOG_ALL */
1118 void TTCN_Communication::send_error(const char *fmt_str
, ...)
1121 va_start(ap
, fmt_str
);
1122 char *error_str
= mprintf_va_list(fmt_str
, ap
);
1125 text_buf
.push_int((RInt
)MSG_ERROR
);
1126 text_buf
.push_string(error_str
);
1128 send_message(text_buf
);
1131 void TTCN_Communication::send_message(Text_Buf
& text_buf
)
1133 if (!is_connected
) TTCN_error("Trying to send a message to MC, but the "
1134 "control connection is down.");
1135 text_buf
.calculate_length();
1136 const char *msg_ptr
= text_buf
.get_data();
1137 size_t msg_len
= text_buf
.get_len(), sent_len
= 0;
1138 while (sent_len
< msg_len
) {
1139 int ret_val
= send(mc_fd
, msg_ptr
+ sent_len
, msg_len
- sent_len
, 0);
1140 if (ret_val
> 0) sent_len
+= ret_val
;
1144 // a signal occurred: do nothing, just try again
1148 close_mc_connection();
1149 TTCN_error("Sending data on the control connection to MC "
1156 void TTCN_Communication::process_configure(int msg_end
)
1158 switch (TTCN_Runtime::get_state()) {
1159 case TTCN_Runtime::HC_IDLE
:
1160 case TTCN_Runtime::HC_ACTIVE
:
1161 case TTCN_Runtime::HC_OVERLOADED
:
1164 incoming_buf
.cut_message();
1165 send_error("Message CONFIGURE arrived in invalid state.");
1169 TTCN_Runtime::set_state(TTCN_Runtime::HC_CONFIGURING
);
1170 TTCN_Logger::log_configdata(TitanLoggerApiSimple::ExecutorConfigdata_reason::received__from__mc
);
1172 // take the config string directly from the buffer for efficiency reasons
1173 int config_str_len
= incoming_buf
.pull_int().get_val();
1174 int config_str_begin
= incoming_buf
.get_pos();
1175 if (config_str_begin
+ config_str_len
!= msg_end
) {
1176 incoming_buf
.cut_message();
1177 send_error("Malformed message CONFIGURE was received.");
1180 const char *config_str
= incoming_buf
.get_data() + config_str_begin
;
1181 boolean success
= process_config_string(config_str
, config_str_len
);
1183 // Only non component specific settings will be applied. The plug-ins need
1184 // to be loaded due to resetting.
1185 TTCN_Logger::load_plugins(NULL_COMPREF
, "");
1186 TTCN_Logger::set_plugin_parameters(NULL_COMPREF
, "");
1187 TTCN_Logger::open_file();
1190 Module_List::log_param();
1191 Module_List::post_init_modules();
1192 } catch (const TC_Error
& TC_error
) {
1193 TTCN_Logger::log_executor_runtime(
1194 TitanLoggerApiSimple::ExecutorRuntime_reason::initialization__of__modules__failed
);
1198 TTCN_Logger::log_configdata(
1199 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__failed
, NULL
);
1203 send_configure_ack();
1204 TTCN_Runtime::set_state(TTCN_Runtime::HC_ACTIVE
);
1205 TTCN_Logger::log_configdata(
1206 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__succeeded
);
1208 send_configure_nak();
1209 TTCN_Runtime::set_state(TTCN_Runtime::HC_IDLE
);
1212 incoming_buf
.cut_message();
1215 void TTCN_Communication::process_create_mtc()
1217 incoming_buf
.cut_message();
1218 TTCN_Runtime::process_create_mtc();
1221 void TTCN_Communication::process_create_ptc()
1223 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1224 if (component_reference
< FIRST_PTC_COMPREF
) {
1225 incoming_buf
.cut_message();
1226 send_error("Message CREATE_PTC refers to invalid "
1227 "component reference %d.", component_reference
);
1230 qualified_name component_type
;
1231 incoming_buf
.pull_qualified_name(component_type
);
1232 if (component_type
.module_name
== NULL
||
1233 component_type
.definition_name
== NULL
) {
1234 incoming_buf
.cut_message();
1235 delete [] component_type
.module_name
;
1236 delete [] component_type
.definition_name
;
1237 send_error("Message CREATE_PTC with component reference %d contains "
1238 "an invalid component type.", component_reference
);
1241 char *component_name
= incoming_buf
.pull_string();
1242 boolean is_alive
= incoming_buf
.pull_int().get_val();
1243 qualified_name current_testcase
;
1244 incoming_buf
.pull_qualified_name(current_testcase
);
1245 incoming_buf
.cut_message();
1248 TTCN_Runtime::process_create_ptc(component_reference
,
1249 component_type
.module_name
, component_type
.definition_name
,
1250 component_name
, is_alive
, current_testcase
.module_name
,
1251 current_testcase
.definition_name
);
1253 // to prevent from memory leaks
1254 delete [] component_type
.module_name
;
1255 delete [] component_type
.definition_name
;
1256 delete [] component_name
;
1257 delete [] current_testcase
.module_name
;
1258 delete [] current_testcase
.definition_name
;
1262 delete [] component_type
.module_name
;
1263 delete [] component_type
.definition_name
;
1264 delete [] component_name
;
1265 delete [] current_testcase
.module_name
;
1266 delete [] current_testcase
.definition_name
;
1269 void TTCN_Communication::process_kill_process()
1271 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1272 incoming_buf
.cut_message();
1273 TTCN_Runtime::process_kill_process(component_reference
);
1276 void TTCN_Communication::process_exit_hc()
1278 incoming_buf
.cut_message();
1279 TTCN_Logger::log_executor_runtime(
1280 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__hc
);
1281 TTCN_Runtime::set_state(TTCN_Runtime::HC_EXIT
);
1284 void TTCN_Communication::process_create_ack()
1286 component component_reference
= incoming_buf
.pull_int().get_val();
1287 incoming_buf
.cut_message();
1288 TTCN_Runtime::process_create_ack(component_reference
);
1291 void TTCN_Communication::process_start_ack()
1293 incoming_buf
.cut_message();
1295 switch (TTCN_Runtime::get_state()) {
1296 case TTCN_Runtime::MTC_START
:
1297 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1298 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1300 case TTCN_Runtime::PTC_START
:
1301 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1304 TTCN_error("Internal error: Message START_ACK arrived in invalid "
1309 void TTCN_Communication::process_stop()
1311 incoming_buf
.cut_message();
1312 switch (TTCN_Runtime::get_state()) {
1313 case TTCN_Runtime::MTC_IDLE
:
1314 TTCN_Logger::log_executor_runtime(
1315 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__mtc
);
1317 case TTCN_Runtime::MTC_PAUSED
:
1318 TTCN_Logger::log_executor_runtime(
1319 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1320 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TERMINATING_EXECUTION
);
1322 case TTCN_Runtime::PTC_IDLE
:
1323 case TTCN_Runtime::PTC_STOPPED
:
1324 TTCN_Logger::log_executor_runtime(
1325 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__ptc
);
1327 case TTCN_Runtime::PTC_EXIT
:
1331 TTCN_Logger::log_executor_runtime(
1332 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1333 TTCN_Runtime::stop_execution();
1338 void TTCN_Communication::process_stop_ack()
1340 incoming_buf
.cut_message();
1341 switch (TTCN_Runtime::get_state()) {
1342 case TTCN_Runtime::MTC_STOP
:
1343 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1344 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1346 case TTCN_Runtime::PTC_STOP
:
1347 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1350 TTCN_error("Internal error: Message STOP_ACK arrived in invalid "
1355 void TTCN_Communication::process_kill_ack()
1357 incoming_buf
.cut_message();
1358 switch (TTCN_Runtime::get_state()) {
1359 case TTCN_Runtime::MTC_KILL
:
1360 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1361 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1363 case TTCN_Runtime::PTC_KILL
:
1364 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1367 TTCN_error("Internal error: Message KILL_ACK arrived in invalid "
1372 void TTCN_Communication::process_running()
1374 boolean answer
= incoming_buf
.pull_int().get_val();
1375 incoming_buf
.cut_message();
1376 TTCN_Runtime::process_running(answer
);
1379 void TTCN_Communication::process_alive()
1381 boolean answer
= incoming_buf
.pull_int().get_val();
1382 incoming_buf
.cut_message();
1383 TTCN_Runtime::process_alive(answer
);
1386 void TTCN_Communication::process_done_ack(int msg_end
)
1388 // decoding the mandatory attributes
1389 boolean answer
= incoming_buf
.pull_int().get_val();
1390 char *return_type
= incoming_buf
.pull_string();
1391 // the return value starts here
1392 int return_value_begin
= incoming_buf
.get_pos();
1395 TTCN_Runtime::process_done_ack(answer
, return_type
,
1396 msg_end
- return_value_begin
,
1397 incoming_buf
.get_data() + return_value_begin
);
1399 // avoid memory leaks in case of error
1400 incoming_buf
.cut_message();
1401 delete [] return_type
;
1405 incoming_buf
.cut_message();
1406 delete [] return_type
;
1409 void TTCN_Communication::process_killed_ack()
1411 boolean answer
= incoming_buf
.pull_int().get_val();
1412 incoming_buf
.cut_message();
1413 TTCN_Runtime::process_killed_ack(answer
);
1416 void TTCN_Communication::process_cancel_done_mtc()
1418 component component_reference
= incoming_buf
.pull_int().get_val();
1419 boolean cancel_any
= incoming_buf
.pull_int().get_val();
1420 incoming_buf
.cut_message();
1421 TTCN_Runtime::cancel_component_done(component_reference
);
1422 if (cancel_any
) TTCN_Runtime::cancel_component_done(ANY_COMPREF
);
1423 send_cancel_done_ack(component_reference
);
1426 void TTCN_Communication::process_cancel_done_ptc()
1428 component component_reference
= incoming_buf
.pull_int().get_val();
1429 incoming_buf
.cut_message();
1430 TTCN_Runtime::cancel_component_done(component_reference
);
1431 send_cancel_done_ack(component_reference
);
1434 void TTCN_Communication::process_component_status_mtc(int msg_end
)
1436 // decoding the mandatory attributes
1437 component component_reference
= incoming_buf
.pull_int().get_val();
1438 boolean is_done
= incoming_buf
.pull_int().get_val();
1439 boolean is_killed
= incoming_buf
.pull_int().get_val();
1440 boolean is_any_done
= incoming_buf
.pull_int().get_val();
1441 boolean is_all_done
= incoming_buf
.pull_int().get_val();
1442 boolean is_any_killed
= incoming_buf
.pull_int().get_val();
1443 boolean is_all_killed
= incoming_buf
.pull_int().get_val();
1445 // the return type and value is valid
1446 char *return_type
= incoming_buf
.pull_string();
1447 int return_value_begin
= incoming_buf
.get_pos();
1449 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1450 msg_end
- return_value_begin
,
1451 incoming_buf
.get_data() + return_value_begin
);
1453 // avoid memory leaks
1454 incoming_buf
.cut_message();
1455 delete [] return_type
;
1458 delete [] return_type
;
1460 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1462 TTCN_Runtime::set_component_done(ANY_COMPREF
, NULL
, 0, NULL
);
1464 TTCN_Runtime::set_component_done(ALL_COMPREF
, NULL
, 0, NULL
);
1465 if (is_any_killed
) TTCN_Runtime::set_component_killed(ANY_COMPREF
);
1466 if (is_all_killed
) TTCN_Runtime::set_component_killed(ALL_COMPREF
);
1467 incoming_buf
.cut_message();
1468 if (!is_done
&& !is_killed
&& (component_reference
!= NULL_COMPREF
||
1469 (!is_any_done
&& !is_all_done
&& !is_any_killed
&& !is_all_killed
)))
1470 TTCN_error("Internal error: Malformed COMPONENT_STATUS message was "
1474 void TTCN_Communication::process_component_status_ptc(int msg_end
)
1476 // decoding the mandatory attributes
1477 component component_reference
= incoming_buf
.pull_int().get_val();
1478 boolean is_done
= incoming_buf
.pull_int().get_val();
1479 boolean is_killed
= incoming_buf
.pull_int().get_val();
1481 // the return type and value is valid
1482 char *return_type
= incoming_buf
.pull_string();
1483 int return_value_begin
= incoming_buf
.get_pos();
1485 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1486 msg_end
- return_value_begin
,
1487 incoming_buf
.get_data() + return_value_begin
);
1489 // avoid memory leaks
1490 incoming_buf
.cut_message();
1491 delete [] return_type
;
1494 delete [] return_type
;
1496 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1497 incoming_buf
.cut_message();
1498 if (!is_done
&& !is_killed
) TTCN_error("Internal error: Malformed "
1499 "COMPONENT_STATUS message was received.");
1502 void TTCN_Communication::process_connect_listen()
1504 char *local_port
= incoming_buf
.pull_string();
1505 component remote_component
= incoming_buf
.pull_int().get_val();
1506 char *remote_component_name
= incoming_buf
.pull_string();
1507 char *remote_port
= incoming_buf
.pull_string();
1508 transport_type_enum transport_type
=
1509 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1510 incoming_buf
.cut_message();
1513 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1514 COMPONENT::register_component_name(remote_component
,
1515 remote_component_name
);
1516 PORT::process_connect_listen(local_port
, remote_component
, remote_port
,
1519 delete [] local_port
;
1520 delete [] remote_component_name
;
1521 delete [] remote_port
;
1525 delete [] local_port
;
1526 delete [] remote_component_name
;
1527 delete [] remote_port
;
1530 void TTCN_Communication::process_connect()
1532 char *local_port
= incoming_buf
.pull_string();
1533 component remote_component
= incoming_buf
.pull_int().get_val();
1534 char *remote_component_name
= incoming_buf
.pull_string();
1535 char *remote_port
= incoming_buf
.pull_string();
1536 transport_type_enum transport_type
=
1537 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1540 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1541 COMPONENT::register_component_name(remote_component
,
1542 remote_component_name
);
1543 PORT::process_connect(local_port
, remote_component
, remote_port
,
1544 transport_type
, incoming_buf
);
1546 incoming_buf
.cut_message();
1547 delete [] local_port
;
1548 delete [] remote_component_name
;
1549 delete [] remote_port
;
1553 incoming_buf
.cut_message();
1554 delete [] local_port
;
1555 delete [] remote_component_name
;
1556 delete [] remote_port
;
1559 void TTCN_Communication::process_connect_ack()
1561 incoming_buf
.cut_message();
1563 switch (TTCN_Runtime::get_state()) {
1564 case TTCN_Runtime::MTC_CONNECT
:
1565 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1566 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1568 case TTCN_Runtime::PTC_CONNECT
:
1569 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1572 TTCN_error("Internal error: Message CONNECT_ACK arrived in invalid "
1577 void TTCN_Communication::process_disconnect()
1579 char *local_port
= incoming_buf
.pull_string();
1580 component remote_component
= incoming_buf
.pull_int().get_val();
1581 char *remote_port
= incoming_buf
.pull_string();
1582 incoming_buf
.cut_message();
1585 PORT::process_disconnect(local_port
, remote_component
, remote_port
);
1587 delete [] local_port
;
1588 delete [] remote_port
;
1592 delete [] local_port
;
1593 delete [] remote_port
;
1596 void TTCN_Communication::process_disconnect_ack()
1598 incoming_buf
.cut_message();
1600 switch (TTCN_Runtime::get_state()) {
1601 case TTCN_Runtime::MTC_DISCONNECT
:
1602 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1603 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1605 case TTCN_Runtime::PTC_DISCONNECT
:
1606 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1609 TTCN_error("Internal error: Message DISCONNECT_ACK arrived in invalid "
1614 void TTCN_Communication::process_map()
1616 char *local_port
= incoming_buf
.pull_string();
1617 char *system_port
= incoming_buf
.pull_string();
1618 incoming_buf
.cut_message();
1621 PORT::map_port(local_port
, system_port
);
1623 delete [] local_port
;
1624 delete [] system_port
;
1628 delete [] local_port
;
1629 delete [] system_port
;
1632 void TTCN_Communication::process_map_ack()
1634 incoming_buf
.cut_message();
1636 switch (TTCN_Runtime::get_state()) {
1637 case TTCN_Runtime::MTC_MAP
:
1638 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1639 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1641 case TTCN_Runtime::PTC_MAP
:
1642 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1645 TTCN_error("Internal error: Message MAP_ACK arrived in invalid state.");
1649 void TTCN_Communication::process_unmap()
1651 char *local_port
= incoming_buf
.pull_string();
1652 char *system_port
= incoming_buf
.pull_string();
1653 incoming_buf
.cut_message();
1656 PORT::unmap_port(local_port
, system_port
);
1658 delete [] local_port
;
1659 delete [] system_port
;
1663 delete [] local_port
;
1664 delete [] system_port
;
1667 void TTCN_Communication::process_unmap_ack()
1669 incoming_buf
.cut_message();
1671 switch(TTCN_Runtime::get_state()){
1672 case TTCN_Runtime::MTC_UNMAP
:
1673 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1674 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1676 case TTCN_Runtime::PTC_UNMAP
:
1677 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1680 TTCN_error("Internal error: Message UNMAP_ACK arrived in invalid "
1685 void TTCN_Communication::process_execute_control()
1687 char *module_name
= incoming_buf
.pull_string();
1688 incoming_buf
.cut_message();
1690 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1691 delete [] module_name
;
1692 TTCN_error("Internal error: Message EXECUTE_CONTROL arrived in "
1696 TTCN_Logger::log(TTCN_Logger::PARALLEL_UNQUALIFIED
,
1697 "Executing control part of module %s.", module_name
);
1699 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1702 Module_List::execute_control(module_name
);
1703 } catch (const TC_End
& TC_end
) {
1704 } catch (const TC_Error
& TC_error
) {
1707 delete [] module_name
;
1711 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1712 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1715 void TTCN_Communication::process_execute_testcase()
1717 char *module_name
= incoming_buf
.pull_string();
1718 char *testcase_name
= incoming_buf
.pull_string();
1719 incoming_buf
.cut_message();
1721 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1722 delete [] module_name
;
1723 delete [] testcase_name
;
1724 TTCN_error("Internal error: Message EXECUTE_TESTCASE arrived in "
1728 TTCN_Logger::log_testcase_exec(testcase_name
, module_name
);
1730 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1733 if (testcase_name
!= NULL
&& testcase_name
[0] != '\0')
1734 Module_List::execute_testcase(module_name
, testcase_name
);
1735 else Module_List::execute_all_testcases(module_name
);
1736 } catch (const TC_End
& TC_end
) {
1737 } catch (const TC_Error
& TC_error
) {
1742 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1743 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1745 delete [] module_name
;
1746 delete [] testcase_name
;
1749 void TTCN_Communication::process_ptc_verdict()
1751 TTCN_Runtime::process_ptc_verdict(incoming_buf
);
1752 incoming_buf
.cut_message();
1755 void TTCN_Communication::process_continue()
1757 incoming_buf
.cut_message();
1759 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_PAUSED
)
1760 TTCN_error("Internal error: Message CONTINUE arrived in invalid "
1763 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1766 void TTCN_Communication::process_exit_mtc()
1768 incoming_buf
.cut_message();
1769 TTCN_Runtime::log_verdict_statistics();
1770 TTCN_Logger::log_executor_runtime(
1771 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__mtc
);
1772 TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1775 void TTCN_Communication::process_start()
1777 qualified_name function_name
;
1778 incoming_buf
.pull_qualified_name(function_name
);
1779 if (function_name
.module_name
== NULL
||
1780 function_name
.definition_name
== NULL
) {
1781 incoming_buf
.cut_message();
1782 delete [] function_name
.module_name
;
1783 delete [] function_name
.definition_name
;
1784 TTCN_error("Internal error: Message START contains an invalid "
1789 TTCN_Runtime::start_function(function_name
.module_name
,
1790 function_name
.definition_name
, incoming_buf
);
1792 // avoid memory leaks
1793 delete [] function_name
.module_name
;
1794 delete [] function_name
.definition_name
;
1798 delete [] function_name
.module_name
;
1799 delete [] function_name
.definition_name
;
1802 void TTCN_Communication::process_kill()
1804 incoming_buf
.cut_message();
1805 TTCN_Runtime::process_kill();
1808 void TTCN_Communication::process_error()
1810 char *error_string
= incoming_buf
.pull_string();
1811 incoming_buf
.cut_message();
1814 TTCN_error("Error message was received from MC: %s", error_string
);
1816 delete [] error_string
;
1821 void TTCN_Communication::process_unsupported_message(int msg_type
, int msg_end
)
1823 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED
);
1824 TTCN_Logger::log_event("Unsupported message was received from MC: "
1825 "type (decimal): %d, data (hexadecimal): ", msg_type
);
1826 const unsigned char *msg_ptr
=
1827 (const unsigned char*)incoming_buf
.get_data();
1828 for (int i
= incoming_buf
.get_pos(); i
< msg_end
; i
++)
1829 TTCN_Logger::log_octet(msg_ptr
[i
]);
1830 TTCN_Logger::end_event();
1831 incoming_buf
.cut_message();
1834 /* * * * Temporary squatting place because it includes version.h * * * */
1836 const struct runtime_version current_runtime_version
= {
1837 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
, TITAN_RUNTIME_NR
1840 static const char *runtime_name
[] = { 0, "load", "function " };
1842 RuntimeVersionChecker::RuntimeVersionChecker(
1843 int ver_major
, int ver_minor
, int patch_level
, int rt
)
1845 if ( TTCN3_MAJOR
!= ver_major
1846 || TTCN3_MINOR
!= ver_minor
1847 || TTCN3_PATCHLEVEL
!= patch_level
)
1850 "Version mismatch detected: generated code %d.%d.pl%d, "
1851 "runtime is %d.%d.pl%d",
1852 ver_major
, ver_minor
, patch_level
,
1853 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
);
1856 if (TITAN_RUNTIME_NR
!= rt
) {
1857 TTCN_error("Runtime mismatch detected: files compiled for the %stest"
1858 " runtime cannot be linked to %stest library",
1859 runtime_name
[TITAN_RUNTIME_NR
], runtime_name
[rt
]);
1863 reffer::reffer(const char*) {}