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
17 * Szabo, Janos Zoltan – initial implementation
19 * Zalanyi, Balazs Andor
21 ******************************************************************************/
22 #include "Communication.hh"
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/utsname.h>
35 #include <netinet/in.h>
36 #include <netinet/tcp.h>
37 #include <arpa/inet.h>
40 #include "../common/dbgnew.hh"
42 #include "Message_types.hh"
43 #include "Module_list.hh"
44 #include "Verdicttype.hh"
45 #include "Fd_And_Timeout_User.hh"
49 #include "Component.hh"
51 #include "TitanLoggerApiSimple.hh"
52 #include "../common/version.h"
54 #include "Event_Handler.hh"
55 #include "Debugger.hh"
56 #include "DebugCommands.hh"
58 class MC_Connection
: public Fd_And_Timeout_Event_Handler
{
59 virtual void Handle_Fd_Event(int fd
,
60 boolean is_readable
, boolean is_writable
, boolean is_error
);
61 virtual void Handle_Timeout(double time_since_last_call
);
63 MC_Connection(const int * fd
, Text_Buf
* buf
) :
64 Fd_And_Timeout_Event_Handler(), mc_fd(fd
), incoming_buf(buf
) {}
65 virtual void log() const;
68 Text_Buf
* incoming_buf
;
71 int TTCN_Communication::mc_fd
= -1;
72 HCNetworkHandler
TTCN_Communication::hcnh
;
73 boolean
TTCN_Communication::local_addr_set
= FALSE
,
74 TTCN_Communication::mc_addr_set
= FALSE
,
75 TTCN_Communication::is_connected
= FALSE
;
76 Text_Buf
TTCN_Communication::incoming_buf
;
77 MC_Connection
TTCN_Communication::mc_connection(
78 &TTCN_Communication::mc_fd
, &TTCN_Communication::incoming_buf
);
79 double TTCN_Communication::call_interval
= 0.0;
81 void TTCN_Communication::set_local_address(const char *host_name
)
84 TTCN_warning("The local address has already been set.");
86 TTCN_error("Trying to change the local address, but there is an existing "
87 "control connection to MC.");
88 if (host_name
== NULL
){
89 fprintf(stderr
,"TTCN_Communication::set_local_address: internal error: " // There is no connection to the MC
90 "invalid host name.\r\n"); // We should log to the console also
91 TTCN_error("TTCN_Communication::set_local_address: internal error: "
92 "invalid host name.");
94 if (!hcnh
.set_local_addr(host_name
, 0)){
95 fprintf(stderr
,"Could not get the IP address for the local address " // There is no connection to the MC
96 "(%s): Host name lookup failure.\r\n", host_name
); // We should log to the console also
97 TTCN_error("Could not get the IP address for the local address "
98 "(%s): Host name lookup failure.", host_name
);
100 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::local__address__was__set
,
101 hcnh
.get_local_host_str(), hcnh
.get_local_addr_str(), 0);
102 local_addr_set
= TRUE
;
105 const IPAddress
*TTCN_Communication::get_local_address()
108 TTCN_error("TTCN_Communication::get_local_address: internal error: the "
109 "local address has not been set.");
110 return hcnh
.get_local_addr();
113 void TTCN_Communication::set_mc_address(const char *host_name
,
114 unsigned short tcp_port
)
117 TTCN_warning("The address of MC has already been set.");
119 TTCN_error("Trying to change the address of MC, but there is an existing connection.");
120 if (host_name
== NULL
){
121 fprintf(stderr
,"TTCN_Communication::set_mc_address: internal error: invalid host name.\r\n");
122 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid host name.");
125 fprintf(stderr
,"TTCN_Communication::set_mc_address: internal error: invalid TCP port. %hu\r\n",tcp_port
);
126 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid TCP port.");
128 hcnh
.set_family(host_name
);
129 if (!hcnh
.set_mc_addr(host_name
, tcp_port
)){
130 fprintf(stderr
,"Could not get the IP address of MC (%s): Host name lookup "
131 "failure.\r\n", host_name
);
132 TTCN_error("Could not get the IP address of MC (%s): Host name lookup "
133 "failure.", host_name
);
135 if ((hcnh
.get_mc_addr())->is_local()){
136 fprintf(stderr
,"The address of MC was set to a local IP address. This may "
137 "cause incorrect behavior if a HC from a remote host also "
138 "connects to MC.\r\n");
139 TTCN_warning("The address of MC was set to a local IP address. This may "
140 "cause incorrect behavior if a HC from a remote host also "
143 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__mc__was__set
,
144 hcnh
.get_mc_host_str(), hcnh
.get_mc_addr_str(), 0);
148 const IPAddress
*TTCN_Communication::get_mc_address()
151 TTCN_error("TTCN_Communication::get_mc_address: internal error: the "
152 "address of MC has not been set.");
153 return hcnh
.get_mc_addr();
156 bool TTCN_Communication::is_mc_connected()
161 void TTCN_Communication::connect_mc()
163 if (is_connected
) TTCN_error("Trying to re-connect to MC, but there is an "
164 "existing connection.");
165 if (!mc_addr_set
) TTCN_error("Trying to connect to MC, but the address of "
166 "MC has not yet been set.");
168 // Trying to connect to local mc through unix domain socket
169 // TODO: Disable if config file parameter is set
170 if ((hcnh
.get_mc_addr())->is_local()
171 || (local_addr_set
&& *(hcnh
.get_mc_addr()) == *(hcnh
.get_local_addr()))) {
172 sockaddr_un localaddr_unix
;
173 memset(&localaddr_unix
, 0, sizeof(localaddr_unix
));
174 localaddr_unix
.sun_family
= AF_UNIX
;
175 snprintf(localaddr_unix
.sun_path
, sizeof(localaddr_unix
.sun_path
),
176 "/tmp/ttcn3-mctr-%u", hcnh
.get_mc_port());
177 mc_fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
178 if (mc_fd
>= (int)FD_SETSIZE
) {
180 } else if (mc_fd
>= 0) {
181 if (connect(mc_fd
, (struct sockaddr
*)&localaddr_unix
,
182 sizeof(localaddr_unix
)) == 0) {
183 goto unix_end
; // connected successfully
193 mc_fd
= hcnh
.socket();
195 fprintf(stderr
,"Socket creation failed when connecting to MC.");
196 TTCN_error("Socket creation failed when connecting to MC.");
198 else if (mc_fd
>= (int)FD_SETSIZE
) {
200 fprintf(stderr
,"When connecting to MC: "
201 "The file descriptor returned by the operating system (%d) is "
202 "too large for use with the select() system call.\r\n", mc_fd
);
203 TTCN_error("When connecting to MC: "
204 "The file descriptor returned by the operating system (%d) is "
205 "too large for use with the select() system call.", mc_fd
);
208 if (local_addr_set
) {
209 if (hcnh
.bind_local_addr(mc_fd
)) {
210 fprintf(stderr
,"Binding IP address %s to the local endpoint of the "
211 "control connection failed when connecting to MC.\r\n", hcnh
.get_local_addr_str());
212 TTCN_error("Binding IP address %s to the local endpoint of the "
213 "control connection failed when connecting to MC.",
214 hcnh
.get_local_addr_str());
219 if (hcnh
.connect_to_mc(mc_fd
)) {
221 if (errno
== EADDRINUSE
) {
224 TTCN_warning("connect() returned error code EADDRINUSE. "
225 "Perhaps this is a Cygwin bug. Trying to connect again.");
229 fprintf(stderr
,"Connecting to MC failed. MC address: %s:%hu %s\r\n",hcnh
.get_mc_addr_str(),hcnh
.get_mc_port(),strerror(errno
));
230 TTCN_error("Connecting to MC failed.");
234 if (!local_addr_set
) {
235 if (hcnh
.getsockname_local_addr(mc_fd
)) {
237 TTCN_error("getsockname() system call failed on the socket of the "
238 "control connection to MC.");
240 TTCN_Logger::log_executor_misc(
241 TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__control__connection
,
242 NULL
, hcnh
.get_local_addr_str(), 0);
243 local_addr_set
= TRUE
;
246 if (!set_tcp_nodelay(mc_fd
)) {
248 TTCN_error("Setting the TCP_NODELAY flag failed on the socket of "
249 "the control connection to MC.");
254 if (!set_close_on_exec(mc_fd
)) {
256 TTCN_error("Setting the close-on-exec flag failed on the socket of "
257 "the control connection to MC.");
260 Fd_And_Timeout_User::add_fd(mc_fd
, &mc_connection
, FD_EVENT_RD
);
262 TTCN_Logger::log_executor_runtime(
263 TitanLoggerApiSimple::ExecutorRuntime_reason::connected__to__mc
);
268 void TTCN_Communication::disconnect_mc()
275 recv_len
= recv(mc_fd
, buf
, sizeof(buf
), 0);
276 } while (recv_len
> 0);
278 close_mc_connection();
279 TTCN_Logger::log_executor_runtime(
280 TitanLoggerApiSimple::ExecutorRuntime_reason::disconnected__from__mc
);
284 void TTCN_Communication::close_mc_connection()
287 int tmp_mc_fd
= mc_fd
;
291 is_connected
= FALSE
;
292 incoming_buf
.reset();
293 // Removing the fd has to be done after closing the mc connection
294 // to prevent segmentation fault or broken pipe error
295 // in case remove_fd would try to print an error log.
296 Fd_And_Timeout_User::remove_fd(tmp_mc_fd
, &mc_connection
, FD_EVENT_RD
);
297 Fd_And_Timeout_User::set_timer(&mc_connection
, 0.0);
301 boolean
TTCN_Communication::transport_unix_stream_supported()
303 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
306 TTCN_Logger::log_executor_misc(
307 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets
,
311 TTCN_Logger::log_executor_misc(
312 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets
,
318 boolean
TTCN_Communication::set_close_on_exec(int fd
)
320 int flags
= fcntl(fd
, F_GETFD
);
322 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
323 TTCN_Logger::log_event("System call fcntl(F_GETFD) failed on file "
324 "descriptor %d.", fd
);
325 TTCN_Logger::OS_error();
326 TTCN_Logger::end_event();
332 if (fcntl(fd
, F_SETFD
, flags
) == -1) {
333 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
334 TTCN_Logger::log_event("System call fcntl(F_SETFD) failed on file "
335 "descriptor %d.", fd
);
336 TTCN_Logger::OS_error();
337 TTCN_Logger::end_event();
343 boolean
TTCN_Communication::set_non_blocking_mode(int fd
,
344 boolean enable_nonblock
)
346 int flags
= fcntl(fd
, F_GETFL
);
348 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
349 TTCN_Logger::log_event("System call fcntl(F_GETFL) failed on file "
350 "descriptor %d.", fd
);
351 TTCN_Logger::OS_error();
352 TTCN_Logger::end_event();
356 if (enable_nonblock
) flags
|= O_NONBLOCK
;
357 else flags
&= ~O_NONBLOCK
;
359 if (fcntl(fd
, F_SETFL
, flags
) == -1) {
360 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
361 TTCN_Logger::log_event("System call fcntl(F_SETFL) failed on file "
362 "descriptor %d.", fd
);
363 TTCN_Logger::OS_error();
364 TTCN_Logger::end_event();
370 boolean
TTCN_Communication::set_tcp_nodelay(int fd
)
373 if (setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (const char*)&on
,
375 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
376 TTCN_Logger::log_event("System call setsockopt(TCP_NODELAY) failed on "
377 "file descriptor %d.", fd
);
378 TTCN_Logger::OS_error();
379 TTCN_Logger::end_event();
385 boolean
TTCN_Communication::increase_send_buffer(int fd
,
386 int &old_size
, int& new_size
)
389 socklen_type optlen
= sizeof(old_size
);
390 // obtaining the current buffer size first
391 if (getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&old_size
, &optlen
))
392 goto getsockopt_failure
;
394 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
395 "System call getsockopt(SO_SNDBUF) returned invalid buffer size (%d) "
396 "on file descriptor %d.", old_size
, fd
);
399 // trying to double the buffer size
400 set_size
= 2 * old_size
;
401 if (set_size
> old_size
) {
402 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (const char*)&set_size
,
404 // the operation failed
411 // other error codes indicate a fatal error
412 goto setsockopt_failure
;
415 // the operation was successful
419 // trying to perform a binary search to determine the maximum buffer size
421 for (int size_step
= old_size
/ 2; size_step
> 0; size_step
/= 2) {
422 int tried_size
= set_size
+ size_step
;
423 if (tried_size
> set_size
) {
424 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (const char*)&tried_size
,
425 sizeof(tried_size
))) {
426 // the operation failed
433 // other error codes indicate a fatal error
434 goto setsockopt_failure
;
437 // the operation was successful
438 set_size
= tried_size
;
442 if (set_size
<= old_size
) return FALSE
;
444 // querying the new effective buffer size (it might be smaller
445 // than set_size but should not be smaller than old_size)
446 optlen
= sizeof(new_size
);
447 if (getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&new_size
,
448 &optlen
)) goto getsockopt_failure
;
449 if (new_size
> old_size
) return TRUE
;
451 if (new_size
< old_size
) TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
452 "System call getsockopt(SO_SNDBUF) returned unexpected buffer size "
453 "(%d, after increasing it from %d to %d) on file descriptor %d.",
454 new_size
, old_size
, set_size
, fd
);
458 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
459 TTCN_Logger::log_event("System call getsockopt(SO_SNDBUF) failed on file "
460 "descriptor %d.", fd
);
461 TTCN_Logger::OS_error();
462 TTCN_Logger::end_event();
465 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
466 TTCN_Logger::log_event("System call setsockopt(SO_SNDBUF) failed on file "
467 "descriptor %d.", fd
);
468 TTCN_Logger::OS_error();
469 TTCN_Logger::end_event();
473 #define INITIAL_CALL_INTERVAL 1.0
474 #define CALL_INTERVAL_INCREMENT 2.0
476 void TTCN_Communication::enable_periodic_call()
478 call_interval
= INITIAL_CALL_INTERVAL
;
479 Fd_And_Timeout_User::set_timer(&mc_connection
, call_interval
, TRUE
,
480 FALSE
/*call_anyway*/);
483 void TTCN_Communication::increase_call_interval()
485 if (call_interval
<= 0.0) TTCN_error("Internal error: "
486 "TTCN_Communication::increase_call_interval() was called when call "
487 "interval is not set.");
488 call_interval
*= CALL_INTERVAL_INCREMENT
;
489 Fd_And_Timeout_User::set_timer(&mc_connection
, call_interval
, TRUE
,
490 FALSE
/*call_anyway*/);
493 void TTCN_Communication::disable_periodic_call()
495 Fd_And_Timeout_User::set_timer(&mc_connection
, 0.0);
499 void MC_Connection::Handle_Fd_Event(int fd
, boolean is_readable
, boolean
,
503 TTCN_error("MC_Connection::Fd_And_Timeout_Event_Handler: unexpected "
504 "file descriptor"); // not necessary - debugging
506 TTCN_warning("Error occurred on the control connection to MC");
510 incoming_buf
->get_end(buf_ptr
, buf_len
);
512 int recv_len
= recv(*mc_fd
, buf_ptr
, buf_len
, 0);
515 // reason: data has arrived
516 incoming_buf
->increase_length(recv_len
);
517 // If the component is idle the processing is done in the outer
518 // stack frame (i.e. in TTCN_Runtime::xxx_main()).
519 if (!TTCN_Runtime::is_idle())
520 TTCN_Communication::process_all_messages_tc();
522 // First closing the TCP connection to avoid EPIPE ("Broken pipe")
523 // errors and/or SIGPIPE signals when trying to send anything
524 // (e.g. log events or error messages) towards MC.
525 TTCN_Communication::close_mc_connection();
527 // reason: TCP connection was closed by peer
528 TTCN_error("Control connection was closed unexpectedly by MC.");
530 // reason: error occurred
531 TTCN_error("Receiving data on the control connection from MC "
538 void MC_Connection::Handle_Timeout(double /*time_since_last_call*/)
540 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_OVERLOADED
) {
541 // indicate the timeout to be handled in process_all_messages_hc()
542 TTCN_Runtime::set_state(TTCN_Runtime::HC_OVERLOADED_TIMEOUT
);
544 TTCN_warning("Unexpected timeout occurred on the control "
545 "connection to MC.");
546 TTCN_Communication::disable_periodic_call();
550 void MC_Connection::log() const
552 TTCN_Logger::log_event("mc connection");
555 void TTCN_Communication::process_all_messages_hc()
557 if (!TTCN_Runtime::is_hc()) TTCN_error("Internal error: "
558 "TTCN_Communication::process_all_messages_hc() was called in invalid "
560 TTCN_Runtime::wait_terminated_processes();
561 boolean wait_flag
= FALSE
;
562 boolean check_overload
= TTCN_Runtime::is_overloaded();
563 while (incoming_buf
.is_message()) {
565 int msg_len
= incoming_buf
.pull_int().get_val();
566 int msg_end
= incoming_buf
.get_pos() + msg_len
;
567 int msg_type
= incoming_buf
.pull_int().get_val();
568 // messages: MC -> HC
574 process_configure(msg_end
);
577 process_create_mtc();
578 TTCN_Runtime::wait_terminated_processes();
580 check_overload
= FALSE
;
583 process_create_ptc();
584 TTCN_Runtime::wait_terminated_processes();
586 check_overload
= FALSE
;
588 case MSG_KILL_PROCESS
:
589 process_kill_process();
590 TTCN_Runtime::wait_terminated_processes();
596 case MSG_DEBUG_COMMAND
:
597 process_debug_command();
600 process_unsupported_message(msg_type
, msg_end
);
603 if (wait_flag
) TTCN_Runtime::wait_terminated_processes();
604 if (check_overload
&& TTCN_Runtime::is_overloaded())
605 TTCN_Runtime::check_overload();
608 void TTCN_Communication::process_all_messages_tc()
610 if (!TTCN_Runtime::is_tc()) TTCN_error("Internal error: "
611 "TTCN_Communication::process_all_messages_tc() was called in invalid "
613 while (incoming_buf
.is_message()) {
614 int msg_len
= incoming_buf
.pull_int().get_val();
615 int msg_end
= incoming_buf
.get_pos() + msg_len
;
616 int msg_type
= incoming_buf
.pull_int().get_val();
617 // messages: MC -> TC
623 process_create_ack();
644 process_done_ack(msg_end
);
647 process_killed_ack();
649 case MSG_CANCEL_DONE
:
650 if (TTCN_Runtime::is_mtc()) process_cancel_done_mtc();
651 else process_cancel_done_ptc();
653 case MSG_COMPONENT_STATUS
:
654 if (TTCN_Runtime::is_mtc()) process_component_status_mtc(msg_end
);
655 else process_component_status_ptc(msg_end
);
657 case MSG_CONNECT_LISTEN
:
658 process_connect_listen();
663 case MSG_CONNECT_ACK
:
664 process_connect_ack();
667 process_disconnect();
669 case MSG_DISCONNECT_ACK
:
670 process_disconnect_ack();
684 case MSG_DEBUG_COMMAND
:
685 process_debug_command();
688 if (TTCN_Runtime::is_mtc()) {
689 // messages: MC -> MTC
691 case MSG_EXECUTE_CONTROL
:
692 process_execute_control();
694 case MSG_EXECUTE_TESTCASE
:
695 process_execute_testcase();
697 case MSG_PTC_VERDICT
:
698 process_ptc_verdict();
707 process_unsupported_message(msg_type
, msg_end
);
710 // messages: MC -> PTC
719 process_unsupported_message(msg_type
, msg_end
);
726 void TTCN_Communication::process_debug_messages()
728 // receives and processes messages from the MC, while test execution is halted
732 Text_Buf storage_buf
;
733 while (ttcn3_debugger
.is_halted()) {
734 incoming_buf
.get_end(buf_ptr
, buf_len
);
736 int recv_len
= recv(mc_fd
, buf_ptr
, buf_len
, 0);
739 incoming_buf
.increase_length(recv_len
);
741 while (incoming_buf
.is_message() && ttcn3_debugger
.is_halted()) {
742 int msg_len
= incoming_buf
.pull_int().get_val();
743 int msg_end
= incoming_buf
.get_pos() + msg_len
;
744 int msg_type
= incoming_buf
.pull_int().get_val();
745 // process only debug commands and 'stop' messages, store the rest
747 case MSG_DEBUG_COMMAND
:
748 process_debug_command();
754 // store all other messages in a different buffer
755 int data_len
= msg_end
- incoming_buf
.get_pos();
756 char* msg_data
= new char[data_len
];
757 incoming_buf
.pull_raw(data_len
, msg_data
);
758 incoming_buf
.cut_message();
759 storage_buf
.push_int(msg_type
);
760 storage_buf
.push_raw(data_len
, msg_data
);
762 storage_buf
.calculate_length();
768 // append the stored messages to the beginning of the main buffer and
770 if (storage_buf
.is_message()) {
771 incoming_buf
.push_raw_front(storage_buf
.get_len(), storage_buf
.get_data());
772 process_all_messages_tc();
776 void TTCN_Communication::send_version()
779 text_buf
.push_int(MSG_VERSION
);
780 text_buf
.push_int(TTCN3_MAJOR
);
781 text_buf
.push_int(TTCN3_MINOR
);
782 text_buf
.push_int(TTCN3_PATCHLEVEL
);
783 #ifdef TTCN3_BUILDNUMBER
784 text_buf
.push_int(TTCN3_BUILDNUMBER
);
786 text_buf
.push_int((RInt
)0);
788 Module_List::push_version(text_buf
);
790 if (uname(&uts
) < 0) TTCN_error("System call uname() failed.");
791 text_buf
.push_string(uts
.nodename
);
792 text_buf
.push_string(uts
.machine
);
793 text_buf
.push_string(uts
.sysname
);
794 text_buf
.push_string(uts
.release
);
795 text_buf
.push_string(uts
.version
);
796 boolean unix_stream_supported
= transport_unix_stream_supported();
798 // LOCAL (software loop) and INET_STREAM (TCP) transports are always
800 int n_supported_transports
= 2;
802 if (unix_stream_supported
) n_supported_transports
++;
803 text_buf
.push_int(n_supported_transports
);
804 text_buf
.push_int(TRANSPORT_LOCAL
);
805 text_buf
.push_int(TRANSPORT_INET_STREAM
);
806 if (unix_stream_supported
)
807 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
808 send_message(text_buf
);
811 void TTCN_Communication::send_configure_ack()
814 text_buf
.push_int(MSG_CONFIGURE_ACK
);
815 send_message(text_buf
);
818 void TTCN_Communication::send_configure_nak()
821 text_buf
.push_int(MSG_CONFIGURE_NAK
);
822 send_message(text_buf
);
825 void TTCN_Communication::send_create_nak(component component_reference
,
826 const char *fmt_str
, ...)
829 va_start(ap
, fmt_str
);
830 char *error_str
= mprintf_va_list(fmt_str
, ap
);
833 text_buf
.push_int(MSG_CREATE_NAK
);
834 text_buf
.push_int(component_reference
);
835 text_buf
.push_string(error_str
);
837 send_message(text_buf
);
840 void TTCN_Communication::send_hc_ready()
843 text_buf
.push_int(MSG_HC_READY
);
844 send_message(text_buf
);
847 void TTCN_Communication::send_create_req(const char *component_type_module
,
848 const char *component_type_name
, const char *component_name
,
849 const char *component_location
, boolean is_alive
)
852 text_buf
.push_int(MSG_CREATE_REQ
);
853 text_buf
.push_string(component_type_module
);
854 text_buf
.push_string(component_type_name
);
855 text_buf
.push_string(component_name
);
856 text_buf
.push_string(component_location
);
857 text_buf
.push_int(is_alive
? 1 : 0);
858 send_message(text_buf
);
861 void TTCN_Communication::prepare_start_req(Text_Buf
& text_buf
,
862 component component_reference
, const char *module_name
,
863 const char *function_name
)
865 text_buf
.push_int(MSG_START_REQ
);
866 text_buf
.push_int(component_reference
);
867 text_buf
.push_string(module_name
);
868 text_buf
.push_string(function_name
);
871 void TTCN_Communication::send_stop_req(component component_reference
)
874 text_buf
.push_int(MSG_STOP_REQ
);
875 text_buf
.push_int(component_reference
);
876 send_message(text_buf
);
879 void TTCN_Communication::send_kill_req(component component_reference
)
882 text_buf
.push_int(MSG_KILL_REQ
);
883 text_buf
.push_int(component_reference
);
884 send_message(text_buf
);
887 void TTCN_Communication::send_is_running(component component_reference
)
890 text_buf
.push_int(MSG_IS_RUNNING
);
891 text_buf
.push_int(component_reference
);
892 send_message(text_buf
);
895 void TTCN_Communication::send_is_alive(component component_reference
)
898 text_buf
.push_int(MSG_IS_ALIVE
);
899 text_buf
.push_int(component_reference
);
900 send_message(text_buf
);
903 void TTCN_Communication::send_done_req(component component_reference
)
906 text_buf
.push_int(MSG_DONE_REQ
);
907 text_buf
.push_int(component_reference
);
908 send_message(text_buf
);
911 void TTCN_Communication::send_killed_req(component component_reference
)
914 text_buf
.push_int(MSG_KILLED_REQ
);
915 text_buf
.push_int(component_reference
);
916 send_message(text_buf
);
919 void TTCN_Communication::send_cancel_done_ack(component component_reference
)
922 text_buf
.push_int(MSG_CANCEL_DONE_ACK
);
923 text_buf
.push_int(component_reference
);
924 send_message(text_buf
);
927 void TTCN_Communication::send_connect_req(component src_component
,
928 const char *src_port
, component dst_component
, const char *dst_port
)
931 text_buf
.push_int(MSG_CONNECT_REQ
);
932 text_buf
.push_int(src_component
);
933 text_buf
.push_string(src_port
);
934 text_buf
.push_int(dst_component
);
935 text_buf
.push_string(dst_port
);
936 send_message(text_buf
);
939 void TTCN_Communication::send_connect_listen_ack_inet_stream(
940 const char *local_port
, component remote_component
,
941 const char *remote_port
, const IPAddress
*local_address
)
944 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
945 text_buf
.push_string(local_port
);
946 text_buf
.push_int(remote_component
);
947 text_buf
.push_string(remote_port
);
948 text_buf
.push_int(TRANSPORT_INET_STREAM
);
949 local_address
->push_raw(text_buf
);
950 send_message(text_buf
);
953 void TTCN_Communication::send_connect_listen_ack_unix_stream(
954 const char *local_port
, component remote_component
,
955 const char *remote_port
, const struct sockaddr_un
*local_address
)
958 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
959 text_buf
.push_string(local_port
);
960 text_buf
.push_int(remote_component
);
961 text_buf
.push_string(remote_port
);
962 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
963 text_buf
.push_string(local_address
->sun_path
);
964 send_message(text_buf
);
967 void TTCN_Communication::send_connected(const char *local_port
,
968 component remote_component
, const char *remote_port
)
971 text_buf
.push_int(MSG_CONNECTED
);
972 text_buf
.push_string(local_port
);
973 text_buf
.push_int(remote_component
);
974 text_buf
.push_string(remote_port
);
975 send_message(text_buf
);
978 void TTCN_Communication::send_connect_error(const char *local_port
,
979 component remote_component
, const char *remote_port
,
980 const char *fmt_str
, ...)
983 va_start(ap
, fmt_str
);
984 char *error_str
= mprintf_va_list(fmt_str
, ap
);
987 text_buf
.push_int(MSG_CONNECT_ERROR
);
988 text_buf
.push_string(local_port
);
989 text_buf
.push_int(remote_component
);
990 text_buf
.push_string(remote_port
);
991 text_buf
.push_string(error_str
);
993 send_message(text_buf
);
996 void TTCN_Communication::send_disconnect_req(component src_component
,
997 const char *src_port
, component dst_component
, const char *dst_port
)
1000 text_buf
.push_int(MSG_DISCONNECT_REQ
);
1001 text_buf
.push_int(src_component
);
1002 text_buf
.push_string(src_port
);
1003 text_buf
.push_int(dst_component
);
1004 text_buf
.push_string(dst_port
);
1005 send_message(text_buf
);
1008 void TTCN_Communication::send_disconnected(const char *local_port
,
1009 component remote_component
, const char *remote_port
)
1012 text_buf
.push_int(MSG_DISCONNECTED
);
1013 text_buf
.push_string(local_port
);
1014 text_buf
.push_int(remote_component
);
1015 text_buf
.push_string(remote_port
);
1016 send_message(text_buf
);
1019 void TTCN_Communication::send_map_req(component src_component
,
1020 const char *src_port
, const char *system_port
)
1023 text_buf
.push_int(MSG_MAP_REQ
);
1024 text_buf
.push_int(src_component
);
1025 text_buf
.push_string(src_port
);
1026 text_buf
.push_string(system_port
);
1027 send_message(text_buf
);
1030 void TTCN_Communication::send_mapped(const char *local_port
,
1031 const char *system_port
)
1034 text_buf
.push_int(MSG_MAPPED
);
1035 text_buf
.push_string(local_port
);
1036 text_buf
.push_string(system_port
);
1037 send_message(text_buf
);
1040 void TTCN_Communication::send_unmap_req(component src_component
,
1041 const char *src_port
, const char *system_port
)
1044 text_buf
.push_int(MSG_UNMAP_REQ
);
1045 text_buf
.push_int(src_component
);
1046 text_buf
.push_string(src_port
);
1047 text_buf
.push_string(system_port
);
1048 send_message(text_buf
);
1051 void TTCN_Communication::send_unmapped(const char *local_port
,
1052 const char *system_port
)
1055 text_buf
.push_int(MSG_UNMAPPED
);
1056 text_buf
.push_string(local_port
);
1057 text_buf
.push_string(system_port
);
1058 send_message(text_buf
);
1061 void TTCN_Communication::send_mtc_created()
1064 text_buf
.push_int(MSG_MTC_CREATED
);
1065 send_message(text_buf
);
1068 void TTCN_Communication::send_testcase_started(const char *testcase_module
,
1069 const char *testcase_name
, const char *mtc_comptype_module
,
1070 const char *mtc_comptype_name
, const char *system_comptype_module
,
1071 const char *system_comptype_name
)
1074 text_buf
.push_int(MSG_TESTCASE_STARTED
);
1075 text_buf
.push_string(testcase_module
);
1076 text_buf
.push_string(testcase_name
);
1077 text_buf
.push_string(mtc_comptype_module
);
1078 text_buf
.push_string(mtc_comptype_name
);
1079 text_buf
.push_string(system_comptype_module
);
1080 text_buf
.push_string(system_comptype_name
);
1081 send_message(text_buf
);
1084 void TTCN_Communication::send_testcase_finished(verdicttype final_verdict
,
1088 text_buf
.push_int(MSG_TESTCASE_FINISHED
);
1089 text_buf
.push_int(final_verdict
);
1090 text_buf
.push_string(reason
);
1091 send_message(text_buf
);
1094 void TTCN_Communication::send_mtc_ready()
1097 text_buf
.push_int(MSG_MTC_READY
);
1098 send_message(text_buf
);
1101 void TTCN_Communication::send_ptc_created(component component_reference
)
1104 text_buf
.push_int(MSG_PTC_CREATED
);
1105 text_buf
.push_int(component_reference
);
1106 send_message(text_buf
);
1109 void TTCN_Communication::prepare_stopped(Text_Buf
& text_buf
,
1110 const char *return_type
)
1112 text_buf
.push_int(MSG_STOPPED
);
1113 text_buf
.push_string(return_type
);
1116 void TTCN_Communication::send_stopped()
1119 text_buf
.push_int(MSG_STOPPED
);
1120 // add an empty return type
1121 text_buf
.push_string(NULL
);
1122 send_message(text_buf
);
1125 void TTCN_Communication::prepare_stopped_killed(Text_Buf
& text_buf
,
1126 verdicttype final_verdict
, const char *return_type
, const char* reason
)
1128 text_buf
.push_int(MSG_STOPPED_KILLED
);
1129 text_buf
.push_int(final_verdict
);
1130 text_buf
.push_string(reason
);
1131 text_buf
.push_string(return_type
);
1134 void TTCN_Communication::send_stopped_killed(verdicttype final_verdict
,
1138 text_buf
.push_int(MSG_STOPPED_KILLED
);
1139 text_buf
.push_int(final_verdict
);
1140 text_buf
.push_string(reason
);
1141 // add an empty return type
1142 text_buf
.push_string(NULL
);
1143 send_message(text_buf
);
1146 void TTCN_Communication::send_killed(verdicttype final_verdict
,
1150 text_buf
.push_int(MSG_KILLED
);
1151 text_buf
.push_int(final_verdict
);
1152 text_buf
.push_string(reason
);
1153 send_message(text_buf
);
1156 void TTCN_Communication::send_debug_return_value(int return_type
, const char* message
)
1159 text_buf
.push_int(MSG_DEBUG_RETURN_VALUE
);
1160 text_buf
.push_int(return_type
);
1162 gettimeofday(&tv
, NULL
);
1163 text_buf
.push_int(tv
.tv_sec
);
1164 text_buf
.push_int(tv
.tv_usec
);
1165 text_buf
.push_string(message
);
1166 send_message(text_buf
);
1169 void TTCN_Communication::send_debug_halt_req()
1172 text_buf
.push_int(MSG_DEBUG_HALT_REQ
);
1173 send_message(text_buf
);
1176 boolean
TTCN_Communication::send_log(time_t timestamp_sec
, long timestamp_usec
,
1177 unsigned int event_severity
, size_t message_text_len
,
1178 const char *message_text
)
1182 text_buf
.push_int(MSG_LOG
);
1183 text_buf
.push_int(timestamp_sec
);
1184 text_buf
.push_int(timestamp_usec
);
1185 text_buf
.push_int(event_severity
);
1186 text_buf
.push_int(message_text_len
);
1187 text_buf
.push_raw(message_text_len
, message_text
);
1188 send_message(text_buf
);
1189 /* If an ERROR message (indicating a version mismatch) arrives from MC
1190 in state HC_IDLE (i.e. before CONFIGURE) it shall be
1191 printed to the console as well. */
1192 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_IDLE
) return FALSE
;
1195 switch (TTCN_Runtime::get_state()) {
1196 case TTCN_Runtime::HC_EXIT
:
1197 case TTCN_Runtime::MTC_INITIAL
:
1198 case TTCN_Runtime::MTC_EXIT
:
1199 case TTCN_Runtime::PTC_INITIAL
:
1200 case TTCN_Runtime::PTC_EXIT
:
1201 /* Do not print the first/last few lines of logs to the console
1202 even if ConsoleMask is set to LOG_ALL */
1210 void TTCN_Communication::send_error(const char *fmt_str
, ...)
1213 va_start(ap
, fmt_str
);
1214 char *error_str
= mprintf_va_list(fmt_str
, ap
);
1217 text_buf
.push_int((RInt
)MSG_ERROR
);
1218 text_buf
.push_string(error_str
);
1220 send_message(text_buf
);
1223 void TTCN_Communication::send_message(Text_Buf
& text_buf
)
1225 if (!is_connected
) TTCN_error("Trying to send a message to MC, but the "
1226 "control connection is down.");
1227 text_buf
.calculate_length();
1228 const char *msg_ptr
= text_buf
.get_data();
1229 size_t msg_len
= text_buf
.get_len(), sent_len
= 0;
1230 while (sent_len
< msg_len
) {
1231 int ret_val
= send(mc_fd
, msg_ptr
+ sent_len
, msg_len
- sent_len
, 0);
1232 if (ret_val
> 0) sent_len
+= ret_val
;
1236 // a signal occurred: do nothing, just try again
1240 close_mc_connection();
1241 TTCN_error("Sending data on the control connection to MC "
1248 void TTCN_Communication::process_configure(int msg_end
)
1250 switch (TTCN_Runtime::get_state()) {
1251 case TTCN_Runtime::HC_IDLE
:
1252 case TTCN_Runtime::HC_ACTIVE
:
1253 case TTCN_Runtime::HC_OVERLOADED
:
1256 incoming_buf
.cut_message();
1257 send_error("Message CONFIGURE arrived in invalid state.");
1261 TTCN_Runtime::set_state(TTCN_Runtime::HC_CONFIGURING
);
1262 TTCN_Logger::log_configdata(TitanLoggerApiSimple::ExecutorConfigdata_reason::received__from__mc
);
1264 // take the config string directly from the buffer for efficiency reasons
1265 int config_str_len
= incoming_buf
.pull_int().get_val();
1266 int config_str_begin
= incoming_buf
.get_pos();
1267 if (config_str_begin
+ config_str_len
!= msg_end
) {
1268 incoming_buf
.cut_message();
1269 send_error("Malformed message CONFIGURE was received.");
1272 const char *config_str
= incoming_buf
.get_data() + config_str_begin
;
1273 boolean success
= process_config_string(config_str
, config_str_len
);
1275 // Only non component specific settings will be applied. The plug-ins need
1276 // to be loaded due to resetting.
1277 TTCN_Logger::load_plugins(NULL_COMPREF
, "");
1278 TTCN_Logger::set_plugin_parameters(NULL_COMPREF
, "");
1279 TTCN_Logger::open_file();
1282 Module_List::log_param();
1283 Module_List::post_init_modules();
1284 } catch (const TC_Error
& TC_error
) {
1285 TTCN_Logger::log_executor_runtime(
1286 TitanLoggerApiSimple::ExecutorRuntime_reason::initialization__of__modules__failed
);
1290 TTCN_Logger::log_configdata(
1291 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__failed
, NULL
);
1295 send_configure_ack();
1296 TTCN_Runtime::set_state(TTCN_Runtime::HC_ACTIVE
);
1297 TTCN_Logger::log_configdata(
1298 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__succeeded
);
1300 send_configure_nak();
1301 TTCN_Runtime::set_state(TTCN_Runtime::HC_IDLE
);
1304 incoming_buf
.cut_message();
1307 void TTCN_Communication::process_create_mtc()
1309 incoming_buf
.cut_message();
1310 TTCN_Runtime::process_create_mtc();
1313 void TTCN_Communication::process_create_ptc()
1315 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1316 if (component_reference
< FIRST_PTC_COMPREF
) {
1317 incoming_buf
.cut_message();
1318 send_error("Message CREATE_PTC refers to invalid "
1319 "component reference %d.", component_reference
);
1322 qualified_name component_type
;
1323 incoming_buf
.pull_qualified_name(component_type
);
1324 if (component_type
.module_name
== NULL
||
1325 component_type
.definition_name
== NULL
) {
1326 incoming_buf
.cut_message();
1327 delete [] component_type
.module_name
;
1328 delete [] component_type
.definition_name
;
1329 send_error("Message CREATE_PTC with component reference %d contains "
1330 "an invalid component type.", component_reference
);
1333 char *component_name
= incoming_buf
.pull_string();
1334 boolean is_alive
= incoming_buf
.pull_int().get_val();
1335 qualified_name current_testcase
;
1336 incoming_buf
.pull_qualified_name(current_testcase
);
1337 incoming_buf
.cut_message();
1340 TTCN_Runtime::process_create_ptc(component_reference
,
1341 component_type
.module_name
, component_type
.definition_name
,
1342 component_name
, is_alive
, current_testcase
.module_name
,
1343 current_testcase
.definition_name
);
1345 // to prevent from memory leaks
1346 delete [] component_type
.module_name
;
1347 delete [] component_type
.definition_name
;
1348 delete [] component_name
;
1349 delete [] current_testcase
.module_name
;
1350 delete [] current_testcase
.definition_name
;
1354 delete [] component_type
.module_name
;
1355 delete [] component_type
.definition_name
;
1356 delete [] component_name
;
1357 delete [] current_testcase
.module_name
;
1358 delete [] current_testcase
.definition_name
;
1361 void TTCN_Communication::process_kill_process()
1363 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1364 incoming_buf
.cut_message();
1365 TTCN_Runtime::process_kill_process(component_reference
);
1368 void TTCN_Communication::process_exit_hc()
1370 incoming_buf
.cut_message();
1371 TTCN_Logger::log_executor_runtime(
1372 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__hc
);
1373 TTCN_Runtime::set_state(TTCN_Runtime::HC_EXIT
);
1376 void TTCN_Communication::process_create_ack()
1378 component component_reference
= incoming_buf
.pull_int().get_val();
1379 incoming_buf
.cut_message();
1380 TTCN_Runtime::process_create_ack(component_reference
);
1383 void TTCN_Communication::process_start_ack()
1385 incoming_buf
.cut_message();
1387 switch (TTCN_Runtime::get_state()) {
1388 case TTCN_Runtime::MTC_START
:
1389 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1390 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1392 case TTCN_Runtime::PTC_START
:
1393 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1396 TTCN_error("Internal error: Message START_ACK arrived in invalid "
1401 void TTCN_Communication::process_stop()
1403 incoming_buf
.cut_message();
1404 switch (TTCN_Runtime::get_state()) {
1405 case TTCN_Runtime::MTC_IDLE
:
1406 TTCN_Logger::log_executor_runtime(
1407 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__mtc
);
1409 case TTCN_Runtime::MTC_PAUSED
:
1410 TTCN_Logger::log_executor_runtime(
1411 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1412 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TERMINATING_EXECUTION
);
1414 case TTCN_Runtime::PTC_IDLE
:
1415 case TTCN_Runtime::PTC_STOPPED
:
1416 TTCN_Logger::log_executor_runtime(
1417 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__ptc
);
1419 case TTCN_Runtime::PTC_EXIT
:
1423 TTCN_Logger::log_executor_runtime(
1424 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1425 TTCN_Runtime::stop_execution();
1430 void TTCN_Communication::process_stop_ack()
1432 incoming_buf
.cut_message();
1433 switch (TTCN_Runtime::get_state()) {
1434 case TTCN_Runtime::MTC_STOP
:
1435 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1436 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1438 case TTCN_Runtime::PTC_STOP
:
1439 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1442 TTCN_error("Internal error: Message STOP_ACK arrived in invalid "
1447 void TTCN_Communication::process_kill_ack()
1449 incoming_buf
.cut_message();
1450 switch (TTCN_Runtime::get_state()) {
1451 case TTCN_Runtime::MTC_KILL
:
1452 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1453 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1455 case TTCN_Runtime::PTC_KILL
:
1456 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1459 TTCN_error("Internal error: Message KILL_ACK arrived in invalid "
1464 void TTCN_Communication::process_running()
1466 boolean answer
= incoming_buf
.pull_int().get_val();
1467 incoming_buf
.cut_message();
1468 TTCN_Runtime::process_running(answer
);
1471 void TTCN_Communication::process_alive()
1473 boolean answer
= incoming_buf
.pull_int().get_val();
1474 incoming_buf
.cut_message();
1475 TTCN_Runtime::process_alive(answer
);
1478 void TTCN_Communication::process_done_ack(int msg_end
)
1480 // decoding the mandatory attributes
1481 boolean answer
= incoming_buf
.pull_int().get_val();
1482 char *return_type
= incoming_buf
.pull_string();
1483 // the return value starts here
1484 int return_value_begin
= incoming_buf
.get_pos();
1487 TTCN_Runtime::process_done_ack(answer
, return_type
,
1488 msg_end
- return_value_begin
,
1489 incoming_buf
.get_data() + return_value_begin
);
1491 // avoid memory leaks in case of error
1492 incoming_buf
.cut_message();
1493 delete [] return_type
;
1497 incoming_buf
.cut_message();
1498 delete [] return_type
;
1501 void TTCN_Communication::process_killed_ack()
1503 boolean answer
= incoming_buf
.pull_int().get_val();
1504 incoming_buf
.cut_message();
1505 TTCN_Runtime::process_killed_ack(answer
);
1508 void TTCN_Communication::process_cancel_done_mtc()
1510 component component_reference
= incoming_buf
.pull_int().get_val();
1511 boolean cancel_any
= incoming_buf
.pull_int().get_val();
1512 incoming_buf
.cut_message();
1513 TTCN_Runtime::cancel_component_done(component_reference
);
1514 if (cancel_any
) TTCN_Runtime::cancel_component_done(ANY_COMPREF
);
1515 send_cancel_done_ack(component_reference
);
1518 void TTCN_Communication::process_cancel_done_ptc()
1520 component component_reference
= incoming_buf
.pull_int().get_val();
1521 incoming_buf
.cut_message();
1522 TTCN_Runtime::cancel_component_done(component_reference
);
1523 send_cancel_done_ack(component_reference
);
1526 void TTCN_Communication::process_component_status_mtc(int msg_end
)
1528 // decoding the mandatory attributes
1529 component component_reference
= incoming_buf
.pull_int().get_val();
1530 boolean is_done
= incoming_buf
.pull_int().get_val();
1531 boolean is_killed
= incoming_buf
.pull_int().get_val();
1532 boolean is_any_done
= incoming_buf
.pull_int().get_val();
1533 boolean is_all_done
= incoming_buf
.pull_int().get_val();
1534 boolean is_any_killed
= incoming_buf
.pull_int().get_val();
1535 boolean is_all_killed
= incoming_buf
.pull_int().get_val();
1537 // the return type and value is valid
1538 char *return_type
= incoming_buf
.pull_string();
1539 int return_value_begin
= incoming_buf
.get_pos();
1541 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1542 msg_end
- return_value_begin
,
1543 incoming_buf
.get_data() + return_value_begin
);
1545 // avoid memory leaks
1546 incoming_buf
.cut_message();
1547 delete [] return_type
;
1550 delete [] return_type
;
1552 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1554 TTCN_Runtime::set_component_done(ANY_COMPREF
, NULL
, 0, NULL
);
1556 TTCN_Runtime::set_component_done(ALL_COMPREF
, NULL
, 0, NULL
);
1557 if (is_any_killed
) TTCN_Runtime::set_component_killed(ANY_COMPREF
);
1558 if (is_all_killed
) TTCN_Runtime::set_component_killed(ALL_COMPREF
);
1559 incoming_buf
.cut_message();
1560 if (!is_done
&& !is_killed
&& (component_reference
!= NULL_COMPREF
||
1561 (!is_any_done
&& !is_all_done
&& !is_any_killed
&& !is_all_killed
)))
1562 TTCN_error("Internal error: Malformed COMPONENT_STATUS message was "
1566 void TTCN_Communication::process_component_status_ptc(int msg_end
)
1568 // decoding the mandatory attributes
1569 component component_reference
= incoming_buf
.pull_int().get_val();
1570 boolean is_done
= incoming_buf
.pull_int().get_val();
1571 boolean is_killed
= incoming_buf
.pull_int().get_val();
1573 // the return type and value is valid
1574 char *return_type
= incoming_buf
.pull_string();
1575 int return_value_begin
= incoming_buf
.get_pos();
1577 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1578 msg_end
- return_value_begin
,
1579 incoming_buf
.get_data() + return_value_begin
);
1581 // avoid memory leaks
1582 incoming_buf
.cut_message();
1583 delete [] return_type
;
1586 delete [] return_type
;
1588 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1589 incoming_buf
.cut_message();
1590 if (!is_done
&& !is_killed
) TTCN_error("Internal error: Malformed "
1591 "COMPONENT_STATUS message was received.");
1594 void TTCN_Communication::process_connect_listen()
1596 char *local_port
= incoming_buf
.pull_string();
1597 component remote_component
= incoming_buf
.pull_int().get_val();
1598 char *remote_component_name
= incoming_buf
.pull_string();
1599 char *remote_port
= incoming_buf
.pull_string();
1600 transport_type_enum transport_type
=
1601 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1602 incoming_buf
.cut_message();
1605 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1606 COMPONENT::register_component_name(remote_component
,
1607 remote_component_name
);
1608 PORT::process_connect_listen(local_port
, remote_component
, remote_port
,
1611 delete [] local_port
;
1612 delete [] remote_component_name
;
1613 delete [] remote_port
;
1617 delete [] local_port
;
1618 delete [] remote_component_name
;
1619 delete [] remote_port
;
1622 void TTCN_Communication::process_connect()
1624 char *local_port
= incoming_buf
.pull_string();
1625 component remote_component
= incoming_buf
.pull_int().get_val();
1626 char *remote_component_name
= incoming_buf
.pull_string();
1627 char *remote_port
= incoming_buf
.pull_string();
1628 transport_type_enum transport_type
=
1629 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1632 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1633 COMPONENT::register_component_name(remote_component
,
1634 remote_component_name
);
1635 PORT::process_connect(local_port
, remote_component
, remote_port
,
1636 transport_type
, incoming_buf
);
1638 incoming_buf
.cut_message();
1639 delete [] local_port
;
1640 delete [] remote_component_name
;
1641 delete [] remote_port
;
1645 incoming_buf
.cut_message();
1646 delete [] local_port
;
1647 delete [] remote_component_name
;
1648 delete [] remote_port
;
1651 void TTCN_Communication::process_connect_ack()
1653 incoming_buf
.cut_message();
1655 switch (TTCN_Runtime::get_state()) {
1656 case TTCN_Runtime::MTC_CONNECT
:
1657 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1658 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1660 case TTCN_Runtime::PTC_CONNECT
:
1661 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1664 TTCN_error("Internal error: Message CONNECT_ACK arrived in invalid "
1669 void TTCN_Communication::process_disconnect()
1671 char *local_port
= incoming_buf
.pull_string();
1672 component remote_component
= incoming_buf
.pull_int().get_val();
1673 char *remote_port
= incoming_buf
.pull_string();
1674 incoming_buf
.cut_message();
1677 PORT::process_disconnect(local_port
, remote_component
, remote_port
);
1679 delete [] local_port
;
1680 delete [] remote_port
;
1684 delete [] local_port
;
1685 delete [] remote_port
;
1688 void TTCN_Communication::process_disconnect_ack()
1690 incoming_buf
.cut_message();
1692 switch (TTCN_Runtime::get_state()) {
1693 case TTCN_Runtime::MTC_DISCONNECT
:
1694 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1695 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1697 case TTCN_Runtime::PTC_DISCONNECT
:
1698 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1701 TTCN_error("Internal error: Message DISCONNECT_ACK arrived in invalid "
1706 void TTCN_Communication::process_map()
1708 char *local_port
= incoming_buf
.pull_string();
1709 char *system_port
= incoming_buf
.pull_string();
1710 incoming_buf
.cut_message();
1713 PORT::map_port(local_port
, system_port
);
1715 delete [] local_port
;
1716 delete [] system_port
;
1720 delete [] local_port
;
1721 delete [] system_port
;
1724 void TTCN_Communication::process_map_ack()
1726 incoming_buf
.cut_message();
1728 switch (TTCN_Runtime::get_state()) {
1729 case TTCN_Runtime::MTC_MAP
:
1730 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1731 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1733 case TTCN_Runtime::PTC_MAP
:
1734 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1737 TTCN_error("Internal error: Message MAP_ACK arrived in invalid state.");
1741 void TTCN_Communication::process_unmap()
1743 char *local_port
= incoming_buf
.pull_string();
1744 char *system_port
= incoming_buf
.pull_string();
1745 incoming_buf
.cut_message();
1748 PORT::unmap_port(local_port
, system_port
);
1750 delete [] local_port
;
1751 delete [] system_port
;
1755 delete [] local_port
;
1756 delete [] system_port
;
1759 void TTCN_Communication::process_unmap_ack()
1761 incoming_buf
.cut_message();
1763 switch(TTCN_Runtime::get_state()){
1764 case TTCN_Runtime::MTC_UNMAP
:
1765 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1766 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1768 case TTCN_Runtime::PTC_UNMAP
:
1769 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1772 TTCN_error("Internal error: Message UNMAP_ACK arrived in invalid "
1777 void TTCN_Communication::process_execute_control()
1779 char *module_name
= incoming_buf
.pull_string();
1780 incoming_buf
.cut_message();
1782 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1783 delete [] module_name
;
1784 TTCN_error("Internal error: Message EXECUTE_CONTROL arrived in "
1788 TTCN_Logger::log(TTCN_Logger::PARALLEL_UNQUALIFIED
,
1789 "Executing control part of module %s.", module_name
);
1791 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1794 Module_List::execute_control(module_name
);
1795 } catch (const TC_End
& TC_end
) {
1796 } catch (const TC_Error
& TC_error
) {
1799 delete [] module_name
;
1803 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1804 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1807 void TTCN_Communication::process_execute_testcase()
1809 char *module_name
= incoming_buf
.pull_string();
1810 char *testcase_name
= incoming_buf
.pull_string();
1811 incoming_buf
.cut_message();
1813 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1814 delete [] module_name
;
1815 delete [] testcase_name
;
1816 TTCN_error("Internal error: Message EXECUTE_TESTCASE arrived in "
1820 TTCN_Logger::log_testcase_exec(testcase_name
, module_name
);
1822 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1825 if (testcase_name
!= NULL
&& testcase_name
[0] != '\0')
1826 Module_List::execute_testcase(module_name
, testcase_name
);
1827 else Module_List::execute_all_testcases(module_name
);
1828 } catch (const TC_End
& TC_end
) {
1829 } catch (const TC_Error
& TC_error
) {
1834 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1835 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1837 delete [] module_name
;
1838 delete [] testcase_name
;
1841 void TTCN_Communication::process_ptc_verdict()
1843 TTCN_Runtime::process_ptc_verdict(incoming_buf
);
1844 incoming_buf
.cut_message();
1847 void TTCN_Communication::process_continue()
1849 incoming_buf
.cut_message();
1851 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_PAUSED
)
1852 TTCN_error("Internal error: Message CONTINUE arrived in invalid "
1855 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1858 void TTCN_Communication::process_exit_mtc()
1860 incoming_buf
.cut_message();
1861 TTCN_Runtime::log_verdict_statistics();
1862 TTCN_Logger::log_executor_runtime(
1863 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__mtc
);
1864 TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1867 void TTCN_Communication::process_start()
1869 qualified_name function_name
;
1870 incoming_buf
.pull_qualified_name(function_name
);
1871 if (function_name
.module_name
== NULL
||
1872 function_name
.definition_name
== NULL
) {
1873 incoming_buf
.cut_message();
1874 delete [] function_name
.module_name
;
1875 delete [] function_name
.definition_name
;
1876 TTCN_error("Internal error: Message START contains an invalid "
1881 TTCN_Runtime::start_function(function_name
.module_name
,
1882 function_name
.definition_name
, incoming_buf
);
1884 // avoid memory leaks
1885 delete [] function_name
.module_name
;
1886 delete [] function_name
.definition_name
;
1890 delete [] function_name
.module_name
;
1891 delete [] function_name
.definition_name
;
1894 void TTCN_Communication::process_kill()
1896 incoming_buf
.cut_message();
1897 TTCN_Runtime::process_kill();
1900 void TTCN_Communication::process_error()
1902 char *error_string
= incoming_buf
.pull_string();
1903 incoming_buf
.cut_message();
1906 TTCN_error("Error message was received from MC: %s", error_string
);
1908 delete [] error_string
;
1913 void TTCN_Communication::process_unsupported_message(int msg_type
, int msg_end
)
1915 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED
);
1916 TTCN_Logger::log_event("Unsupported message was received from MC: "
1917 "type (decimal): %d, data (hexadecimal): ", msg_type
);
1918 const unsigned char *msg_ptr
=
1919 (const unsigned char*)incoming_buf
.get_data();
1920 for (int i
= incoming_buf
.get_pos(); i
< msg_end
; i
++)
1921 TTCN_Logger::log_octet(msg_ptr
[i
]);
1922 TTCN_Logger::end_event();
1923 incoming_buf
.cut_message();
1926 void TTCN_Communication::process_debug_command()
1928 int command
= incoming_buf
.pull_int().get_val();
1929 int argument_count
= incoming_buf
.pull_int().get_val();
1930 char** arguments
= NULL
;
1931 if (argument_count
> 0) {
1932 arguments
= new char*[argument_count
];
1933 for (int i
= 0; i
< argument_count
; ++i
) {
1934 arguments
[i
] = incoming_buf
.pull_string();
1937 incoming_buf
.cut_message();
1938 ttcn3_debugger
.execute_command(command
, argument_count
, arguments
);
1939 if (argument_count
> 0) {
1940 for (int i
= 0; i
< argument_count
; ++i
) {
1941 delete [] arguments
[i
];
1943 delete [] arguments
;
1947 /* * * * Temporary squatting place because it includes version.h * * * */
1949 const struct runtime_version current_runtime_version
= {
1950 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
, TITAN_RUNTIME_NR
1953 static const char *runtime_name
[] = { 0, "load", "function " };
1955 RuntimeVersionChecker::RuntimeVersionChecker(
1956 int ver_major
, int ver_minor
, int patch_level
, int rt
)
1958 if ( TTCN3_MAJOR
!= ver_major
1959 || TTCN3_MINOR
!= ver_minor
1960 || TTCN3_PATCHLEVEL
!= patch_level
)
1963 "Version mismatch detected: generated code %d.%d.pl%d, "
1964 "runtime is %d.%d.pl%d",
1965 ver_major
, ver_minor
, patch_level
,
1966 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
);
1969 if (TITAN_RUNTIME_NR
!= rt
) {
1970 TTCN_error("Runtime mismatch detected: files compiled for the %stest"
1971 " runtime cannot be linked to %stest library",
1972 runtime_name
[TITAN_RUNTIME_NR
], runtime_name
[rt
]);
1976 reffer::reffer(const char*) {}