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
18 * Szabo, Janos Zoltan – initial implementation
20 * Zalanyi, Balazs Andor
22 ******************************************************************************/
23 #include "Communication.hh"
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/utsname.h>
36 #include <netinet/in.h>
37 #include <netinet/tcp.h>
38 #include <arpa/inet.h>
41 #include "../common/dbgnew.hh"
43 #include "Message_types.hh"
44 #include "Module_list.hh"
45 #include "Verdicttype.hh"
46 #include "Fd_And_Timeout_User.hh"
50 #include "Component.hh"
52 #include "TitanLoggerApiSimple.hh"
53 #include "../common/version.h"
55 #include "Event_Handler.hh"
56 #include "Debugger.hh"
57 #include "DebugCommands.hh"
59 class MC_Connection
: public Fd_And_Timeout_Event_Handler
{
60 virtual void Handle_Fd_Event(int fd
,
61 boolean is_readable
, boolean is_writable
, boolean is_error
);
62 virtual void Handle_Timeout(double time_since_last_call
);
64 MC_Connection(const int * fd
, Text_Buf
* buf
) :
65 Fd_And_Timeout_Event_Handler(), mc_fd(fd
), incoming_buf(buf
) {}
66 virtual void log() const;
69 Text_Buf
* incoming_buf
;
72 int TTCN_Communication::mc_fd
= -1;
73 HCNetworkHandler
TTCN_Communication::hcnh
;
74 boolean
TTCN_Communication::local_addr_set
= FALSE
,
75 TTCN_Communication::mc_addr_set
= FALSE
,
76 TTCN_Communication::is_connected
= FALSE
;
77 Text_Buf
TTCN_Communication::incoming_buf
;
78 MC_Connection
TTCN_Communication::mc_connection(
79 &TTCN_Communication::mc_fd
, &TTCN_Communication::incoming_buf
);
80 double TTCN_Communication::call_interval
= 0.0;
82 void TTCN_Communication::set_local_address(const char *host_name
)
85 TTCN_warning("The local address has already been set.");
87 TTCN_error("Trying to change the local address, but there is an existing "
88 "control connection to MC.");
89 if (host_name
== NULL
){
90 fprintf(stderr
,"TTCN_Communication::set_local_address: internal error: " // There is no connection to the MC
91 "invalid host name.\r\n"); // We should log to the console also
92 TTCN_error("TTCN_Communication::set_local_address: internal error: "
93 "invalid host name.");
95 if (!hcnh
.set_local_addr(host_name
, 0)){
96 fprintf(stderr
,"Could not get the IP address for the local address " // There is no connection to the MC
97 "(%s): Host name lookup failure.\r\n", host_name
); // We should log to the console also
98 TTCN_error("Could not get the IP address for the local address "
99 "(%s): Host name lookup failure.", host_name
);
101 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::local__address__was__set
,
102 hcnh
.get_local_host_str(), hcnh
.get_local_addr_str(), 0);
103 local_addr_set
= TRUE
;
106 const IPAddress
*TTCN_Communication::get_local_address()
109 TTCN_error("TTCN_Communication::get_local_address: internal error: the "
110 "local address has not been set.");
111 return hcnh
.get_local_addr();
114 void TTCN_Communication::set_mc_address(const char *host_name
,
115 unsigned short tcp_port
)
118 TTCN_warning("The address of MC has already been set.");
120 TTCN_error("Trying to change the address of MC, but there is an existing connection.");
121 if (host_name
== NULL
){
122 fprintf(stderr
,"TTCN_Communication::set_mc_address: internal error: invalid host name.\r\n");
123 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid host name.");
126 fprintf(stderr
,"TTCN_Communication::set_mc_address: internal error: invalid TCP port. %hu\r\n",tcp_port
);
127 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid TCP port.");
129 hcnh
.set_family(host_name
);
130 if (!hcnh
.set_mc_addr(host_name
, tcp_port
)){
131 fprintf(stderr
,"Could not get the IP address of MC (%s): Host name lookup "
132 "failure.\r\n", host_name
);
133 TTCN_error("Could not get the IP address of MC (%s): Host name lookup "
134 "failure.", host_name
);
136 if ((hcnh
.get_mc_addr())->is_local()){
137 fprintf(stderr
,"The address of MC was set to a local IP address. This may "
138 "cause incorrect behavior if a HC from a remote host also "
139 "connects to MC.\r\n");
140 TTCN_warning("The address of MC was set to a local IP address. This may "
141 "cause incorrect behavior if a HC from a remote host also "
144 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__mc__was__set
,
145 hcnh
.get_mc_host_str(), hcnh
.get_mc_addr_str(), 0);
149 const IPAddress
*TTCN_Communication::get_mc_address()
152 TTCN_error("TTCN_Communication::get_mc_address: internal error: the "
153 "address of MC has not been set.");
154 return hcnh
.get_mc_addr();
157 bool TTCN_Communication::is_mc_connected()
162 void TTCN_Communication::connect_mc()
164 if (is_connected
) TTCN_error("Trying to re-connect to MC, but there is an "
165 "existing connection.");
166 if (!mc_addr_set
) TTCN_error("Trying to connect to MC, but the address of "
167 "MC has not yet been set.");
169 // Trying to connect to local mc through unix domain socket
170 // TODO: Disable if config file parameter is set
171 if ((hcnh
.get_mc_addr())->is_local()
172 || (local_addr_set
&& *(hcnh
.get_mc_addr()) == *(hcnh
.get_local_addr()))) {
173 sockaddr_un localaddr_unix
;
174 memset(&localaddr_unix
, 0, sizeof(localaddr_unix
));
175 localaddr_unix
.sun_family
= AF_UNIX
;
176 snprintf(localaddr_unix
.sun_path
, sizeof(localaddr_unix
.sun_path
),
177 "/tmp/ttcn3-mctr-%u", hcnh
.get_mc_port());
178 mc_fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
179 if (mc_fd
>= (int)FD_SETSIZE
) {
181 } else if (mc_fd
>= 0) {
182 if (connect(mc_fd
, (struct sockaddr
*)&localaddr_unix
,
183 sizeof(localaddr_unix
)) == 0) {
184 goto unix_end
; // connected successfully
194 mc_fd
= hcnh
.socket();
196 fprintf(stderr
,"Socket creation failed when connecting to MC.");
197 TTCN_error("Socket creation failed when connecting to MC.");
199 else if (mc_fd
>= (int)FD_SETSIZE
) {
201 fprintf(stderr
,"When connecting to MC: "
202 "The file descriptor returned by the operating system (%d) is "
203 "too large for use with the select() system call.\r\n", mc_fd
);
204 TTCN_error("When connecting to MC: "
205 "The file descriptor returned by the operating system (%d) is "
206 "too large for use with the select() system call.", mc_fd
);
209 if (local_addr_set
) {
210 if (hcnh
.bind_local_addr(mc_fd
)) {
211 fprintf(stderr
,"Binding IP address %s to the local endpoint of the "
212 "control connection failed when connecting to MC.\r\n", hcnh
.get_local_addr_str());
213 TTCN_error("Binding IP address %s to the local endpoint of the "
214 "control connection failed when connecting to MC.",
215 hcnh
.get_local_addr_str());
220 if (hcnh
.connect_to_mc(mc_fd
)) {
222 if (errno
== EADDRINUSE
) {
225 TTCN_warning("connect() returned error code EADDRINUSE. "
226 "Perhaps this is a Cygwin bug. Trying to connect again.");
230 fprintf(stderr
,"Connecting to MC failed. MC address: %s:%hu %s\r\n",hcnh
.get_mc_addr_str(),hcnh
.get_mc_port(),strerror(errno
));
231 TTCN_error("Connecting to MC failed.");
235 if (!local_addr_set
) {
236 if (hcnh
.getsockname_local_addr(mc_fd
)) {
238 TTCN_error("getsockname() system call failed on the socket of the "
239 "control connection to MC.");
241 TTCN_Logger::log_executor_misc(
242 TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__control__connection
,
243 NULL
, hcnh
.get_local_addr_str(), 0);
244 local_addr_set
= TRUE
;
247 if (!set_tcp_nodelay(mc_fd
)) {
249 TTCN_error("Setting the TCP_NODELAY flag failed on the socket of "
250 "the control connection to MC.");
255 if (!set_close_on_exec(mc_fd
)) {
257 TTCN_error("Setting the close-on-exec flag failed on the socket of "
258 "the control connection to MC.");
261 Fd_And_Timeout_User::add_fd(mc_fd
, &mc_connection
, FD_EVENT_RD
);
263 TTCN_Logger::log_executor_runtime(
264 TitanLoggerApiSimple::ExecutorRuntime_reason::connected__to__mc
);
269 void TTCN_Communication::disconnect_mc()
276 recv_len
= recv(mc_fd
, buf
, sizeof(buf
), 0);
277 } while (recv_len
> 0);
279 close_mc_connection();
280 TTCN_Logger::log_executor_runtime(
281 TitanLoggerApiSimple::ExecutorRuntime_reason::disconnected__from__mc
);
285 void TTCN_Communication::close_mc_connection()
288 int tmp_mc_fd
= mc_fd
;
292 is_connected
= FALSE
;
293 incoming_buf
.reset();
294 // Removing the fd has to be done after closing the mc connection
295 // to prevent segmentation fault or broken pipe error
296 // in case remove_fd would try to print an error log.
297 Fd_And_Timeout_User::remove_fd(tmp_mc_fd
, &mc_connection
, FD_EVENT_RD
);
298 Fd_And_Timeout_User::set_timer(&mc_connection
, 0.0);
302 boolean
TTCN_Communication::transport_unix_stream_supported()
304 int fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
307 TTCN_Logger::log_executor_misc(
308 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets
,
312 TTCN_Logger::log_executor_misc(
313 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets
,
319 boolean
TTCN_Communication::set_close_on_exec(int fd
)
321 int flags
= fcntl(fd
, F_GETFD
);
323 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
324 TTCN_Logger::log_event("System call fcntl(F_GETFD) failed on file "
325 "descriptor %d.", fd
);
326 TTCN_Logger::OS_error();
327 TTCN_Logger::end_event();
333 if (fcntl(fd
, F_SETFD
, flags
) == -1) {
334 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
335 TTCN_Logger::log_event("System call fcntl(F_SETFD) failed on file "
336 "descriptor %d.", fd
);
337 TTCN_Logger::OS_error();
338 TTCN_Logger::end_event();
344 boolean
TTCN_Communication::set_non_blocking_mode(int fd
,
345 boolean enable_nonblock
)
347 int flags
= fcntl(fd
, F_GETFL
);
349 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
350 TTCN_Logger::log_event("System call fcntl(F_GETFL) failed on file "
351 "descriptor %d.", fd
);
352 TTCN_Logger::OS_error();
353 TTCN_Logger::end_event();
357 if (enable_nonblock
) flags
|= O_NONBLOCK
;
358 else flags
&= ~O_NONBLOCK
;
360 if (fcntl(fd
, F_SETFL
, flags
) == -1) {
361 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
362 TTCN_Logger::log_event("System call fcntl(F_SETFL) failed on file "
363 "descriptor %d.", fd
);
364 TTCN_Logger::OS_error();
365 TTCN_Logger::end_event();
371 boolean
TTCN_Communication::set_tcp_nodelay(int fd
)
374 if (setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (const char*)&on
,
376 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
377 TTCN_Logger::log_event("System call setsockopt(TCP_NODELAY) failed on "
378 "file descriptor %d.", fd
);
379 TTCN_Logger::OS_error();
380 TTCN_Logger::end_event();
386 boolean
TTCN_Communication::increase_send_buffer(int fd
,
387 int &old_size
, int& new_size
)
390 socklen_type optlen
= sizeof(old_size
);
391 // obtaining the current buffer size first
392 if (getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&old_size
, &optlen
))
393 goto getsockopt_failure
;
395 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
396 "System call getsockopt(SO_SNDBUF) returned invalid buffer size (%d) "
397 "on file descriptor %d.", old_size
, fd
);
400 // trying to double the buffer size
401 set_size
= 2 * old_size
;
402 if (set_size
> old_size
) {
403 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (const char*)&set_size
,
405 // the operation failed
412 // other error codes indicate a fatal error
413 goto setsockopt_failure
;
416 // the operation was successful
420 // trying to perform a binary search to determine the maximum buffer size
422 for (int size_step
= old_size
/ 2; size_step
> 0; size_step
/= 2) {
423 int tried_size
= set_size
+ size_step
;
424 if (tried_size
> set_size
) {
425 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (const char*)&tried_size
,
426 sizeof(tried_size
))) {
427 // the operation failed
434 // other error codes indicate a fatal error
435 goto setsockopt_failure
;
438 // the operation was successful
439 set_size
= tried_size
;
443 if (set_size
<= old_size
) return FALSE
;
445 // querying the new effective buffer size (it might be smaller
446 // than set_size but should not be smaller than old_size)
447 optlen
= sizeof(new_size
);
448 if (getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&new_size
,
449 &optlen
)) goto getsockopt_failure
;
450 if (new_size
> old_size
) return TRUE
;
452 if (new_size
< old_size
) TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
453 "System call getsockopt(SO_SNDBUF) returned unexpected buffer size "
454 "(%d, after increasing it from %d to %d) on file descriptor %d.",
455 new_size
, old_size
, set_size
, fd
);
459 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
460 TTCN_Logger::log_event("System call getsockopt(SO_SNDBUF) failed on file "
461 "descriptor %d.", fd
);
462 TTCN_Logger::OS_error();
463 TTCN_Logger::end_event();
466 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED
);
467 TTCN_Logger::log_event("System call setsockopt(SO_SNDBUF) failed on file "
468 "descriptor %d.", fd
);
469 TTCN_Logger::OS_error();
470 TTCN_Logger::end_event();
474 #define INITIAL_CALL_INTERVAL 1.0
475 #define CALL_INTERVAL_INCREMENT 2.0
477 void TTCN_Communication::enable_periodic_call()
479 call_interval
= INITIAL_CALL_INTERVAL
;
480 Fd_And_Timeout_User::set_timer(&mc_connection
, call_interval
, TRUE
,
481 FALSE
/*call_anyway*/);
484 void TTCN_Communication::increase_call_interval()
486 if (call_interval
<= 0.0) TTCN_error("Internal error: "
487 "TTCN_Communication::increase_call_interval() was called when call "
488 "interval is not set.");
489 call_interval
*= CALL_INTERVAL_INCREMENT
;
490 Fd_And_Timeout_User::set_timer(&mc_connection
, call_interval
, TRUE
,
491 FALSE
/*call_anyway*/);
494 void TTCN_Communication::disable_periodic_call()
496 Fd_And_Timeout_User::set_timer(&mc_connection
, 0.0);
500 void MC_Connection::Handle_Fd_Event(int fd
, boolean is_readable
, boolean
,
504 TTCN_error("MC_Connection::Fd_And_Timeout_Event_Handler: unexpected "
505 "file descriptor"); // not necessary - debugging
507 TTCN_warning("Error occurred on the control connection to MC");
511 incoming_buf
->get_end(buf_ptr
, buf_len
);
513 int recv_len
= recv(*mc_fd
, buf_ptr
, buf_len
, 0);
516 // reason: data has arrived
517 incoming_buf
->increase_length(recv_len
);
518 // If the component is idle the processing is done in the outer
519 // stack frame (i.e. in TTCN_Runtime::xxx_main()).
520 if (!TTCN_Runtime::is_idle())
521 TTCN_Communication::process_all_messages_tc();
523 // First closing the TCP connection to avoid EPIPE ("Broken pipe")
524 // errors and/or SIGPIPE signals when trying to send anything
525 // (e.g. log events or error messages) towards MC.
526 TTCN_Communication::close_mc_connection();
528 // reason: TCP connection was closed by peer
529 TTCN_error("Control connection was closed unexpectedly by MC.");
531 // reason: error occurred
532 TTCN_error("Receiving data on the control connection from MC "
539 void MC_Connection::Handle_Timeout(double /*time_since_last_call*/)
541 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_OVERLOADED
) {
542 // indicate the timeout to be handled in process_all_messages_hc()
543 TTCN_Runtime::set_state(TTCN_Runtime::HC_OVERLOADED_TIMEOUT
);
545 TTCN_warning("Unexpected timeout occurred on the control "
546 "connection to MC.");
547 TTCN_Communication::disable_periodic_call();
551 void MC_Connection::log() const
553 TTCN_Logger::log_event("mc connection");
556 void TTCN_Communication::process_all_messages_hc()
558 if (!TTCN_Runtime::is_hc()) TTCN_error("Internal error: "
559 "TTCN_Communication::process_all_messages_hc() was called in invalid "
561 TTCN_Runtime::wait_terminated_processes();
562 boolean wait_flag
= FALSE
;
563 boolean check_overload
= TTCN_Runtime::is_overloaded();
564 while (incoming_buf
.is_message()) {
566 int msg_len
= incoming_buf
.pull_int().get_val();
567 int msg_end
= incoming_buf
.get_pos() + msg_len
;
568 int msg_type
= incoming_buf
.pull_int().get_val();
569 // messages: MC -> HC
575 process_configure(msg_end
);
578 process_create_mtc();
579 TTCN_Runtime::wait_terminated_processes();
581 check_overload
= FALSE
;
584 process_create_ptc();
585 TTCN_Runtime::wait_terminated_processes();
587 check_overload
= FALSE
;
589 case MSG_KILL_PROCESS
:
590 process_kill_process();
591 TTCN_Runtime::wait_terminated_processes();
597 case MSG_DEBUG_COMMAND
:
598 process_debug_command();
601 process_unsupported_message(msg_type
, msg_end
);
604 if (wait_flag
) TTCN_Runtime::wait_terminated_processes();
605 if (check_overload
&& TTCN_Runtime::is_overloaded())
606 TTCN_Runtime::check_overload();
609 void TTCN_Communication::process_all_messages_tc()
611 if (!TTCN_Runtime::is_tc()) TTCN_error("Internal error: "
612 "TTCN_Communication::process_all_messages_tc() was called in invalid "
614 while (incoming_buf
.is_message()) {
615 int msg_len
= incoming_buf
.pull_int().get_val();
616 int msg_end
= incoming_buf
.get_pos() + msg_len
;
617 int msg_type
= incoming_buf
.pull_int().get_val();
618 // messages: MC -> TC
624 process_create_ack();
645 process_done_ack(msg_end
);
648 process_killed_ack();
650 case MSG_CANCEL_DONE
:
651 if (TTCN_Runtime::is_mtc()) process_cancel_done_mtc();
652 else process_cancel_done_ptc();
654 case MSG_COMPONENT_STATUS
:
655 if (TTCN_Runtime::is_mtc()) process_component_status_mtc(msg_end
);
656 else process_component_status_ptc(msg_end
);
658 case MSG_CONNECT_LISTEN
:
659 process_connect_listen();
664 case MSG_CONNECT_ACK
:
665 process_connect_ack();
668 process_disconnect();
670 case MSG_DISCONNECT_ACK
:
671 process_disconnect_ack();
685 case MSG_DEBUG_COMMAND
:
686 process_debug_command();
689 if (TTCN_Runtime::is_mtc()) {
690 // messages: MC -> MTC
692 case MSG_EXECUTE_CONTROL
:
693 process_execute_control();
695 case MSG_EXECUTE_TESTCASE
:
696 process_execute_testcase();
698 case MSG_PTC_VERDICT
:
699 process_ptc_verdict();
708 process_unsupported_message(msg_type
, msg_end
);
711 // messages: MC -> PTC
720 process_unsupported_message(msg_type
, msg_end
);
727 void TTCN_Communication::process_debug_messages()
729 // receives and processes messages from the MC, while test execution is halted
733 Text_Buf storage_buf
;
734 while (ttcn3_debugger
.is_halted()) {
735 incoming_buf
.get_end(buf_ptr
, buf_len
);
737 int recv_len
= recv(mc_fd
, buf_ptr
, buf_len
, 0);
740 incoming_buf
.increase_length(recv_len
);
742 while (incoming_buf
.is_message() && ttcn3_debugger
.is_halted()) {
743 int msg_len
= incoming_buf
.pull_int().get_val();
744 int msg_end
= incoming_buf
.get_pos() + msg_len
;
745 int msg_type
= incoming_buf
.pull_int().get_val();
746 // process only debug commands and 'stop' messages, store the rest
748 case MSG_DEBUG_COMMAND
:
749 process_debug_command();
755 // store all other messages in a different buffer
756 int data_len
= msg_end
- incoming_buf
.get_pos();
757 char* msg_data
= new char[data_len
];
758 incoming_buf
.pull_raw(data_len
, msg_data
);
759 incoming_buf
.cut_message();
760 storage_buf
.push_int(msg_type
);
761 storage_buf
.push_raw(data_len
, msg_data
);
763 storage_buf
.calculate_length();
769 // append the stored messages to the beginning of the main buffer and
771 if (storage_buf
.is_message()) {
772 incoming_buf
.push_raw_front(storage_buf
.get_len(), storage_buf
.get_data());
773 process_all_messages_tc();
777 void TTCN_Communication::send_version()
780 text_buf
.push_int(MSG_VERSION
);
781 text_buf
.push_int(TTCN3_MAJOR
);
782 text_buf
.push_int(TTCN3_MINOR
);
783 text_buf
.push_int(TTCN3_PATCHLEVEL
);
784 #ifdef TTCN3_BUILDNUMBER
785 text_buf
.push_int(TTCN3_BUILDNUMBER
);
787 text_buf
.push_int((RInt
)0);
789 Module_List::push_version(text_buf
);
791 if (uname(&uts
) < 0) TTCN_error("System call uname() failed.");
792 text_buf
.push_string(uts
.nodename
);
793 text_buf
.push_string(uts
.machine
);
794 text_buf
.push_string(uts
.sysname
);
795 text_buf
.push_string(uts
.release
);
796 text_buf
.push_string(uts
.version
);
797 boolean unix_stream_supported
= transport_unix_stream_supported();
799 // LOCAL (software loop) and INET_STREAM (TCP) transports are always
801 int n_supported_transports
= 2;
803 if (unix_stream_supported
) n_supported_transports
++;
804 text_buf
.push_int(n_supported_transports
);
805 text_buf
.push_int(TRANSPORT_LOCAL
);
806 text_buf
.push_int(TRANSPORT_INET_STREAM
);
807 if (unix_stream_supported
)
808 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
809 send_message(text_buf
);
812 void TTCN_Communication::send_configure_ack()
815 text_buf
.push_int(MSG_CONFIGURE_ACK
);
816 send_message(text_buf
);
819 void TTCN_Communication::send_configure_nak()
822 text_buf
.push_int(MSG_CONFIGURE_NAK
);
823 send_message(text_buf
);
826 void TTCN_Communication::send_create_nak(component component_reference
,
827 const char *fmt_str
, ...)
830 va_start(ap
, fmt_str
);
831 char *error_str
= mprintf_va_list(fmt_str
, ap
);
834 text_buf
.push_int(MSG_CREATE_NAK
);
835 text_buf
.push_int(component_reference
);
836 text_buf
.push_string(error_str
);
838 send_message(text_buf
);
841 void TTCN_Communication::send_hc_ready()
844 text_buf
.push_int(MSG_HC_READY
);
845 send_message(text_buf
);
848 void TTCN_Communication::send_create_req(const char *component_type_module
,
849 const char *component_type_name
, const char *component_name
,
850 const char *component_location
, boolean is_alive
)
853 text_buf
.push_int(MSG_CREATE_REQ
);
854 text_buf
.push_string(component_type_module
);
855 text_buf
.push_string(component_type_name
);
856 text_buf
.push_string(component_name
);
857 text_buf
.push_string(component_location
);
858 text_buf
.push_int(is_alive
? 1 : 0);
859 send_message(text_buf
);
862 void TTCN_Communication::prepare_start_req(Text_Buf
& text_buf
,
863 component component_reference
, const char *module_name
,
864 const char *function_name
)
866 text_buf
.push_int(MSG_START_REQ
);
867 text_buf
.push_int(component_reference
);
868 text_buf
.push_string(module_name
);
869 text_buf
.push_string(function_name
);
872 void TTCN_Communication::send_stop_req(component component_reference
)
875 text_buf
.push_int(MSG_STOP_REQ
);
876 text_buf
.push_int(component_reference
);
877 send_message(text_buf
);
880 void TTCN_Communication::send_kill_req(component component_reference
)
883 text_buf
.push_int(MSG_KILL_REQ
);
884 text_buf
.push_int(component_reference
);
885 send_message(text_buf
);
888 void TTCN_Communication::send_is_running(component component_reference
)
891 text_buf
.push_int(MSG_IS_RUNNING
);
892 text_buf
.push_int(component_reference
);
893 send_message(text_buf
);
896 void TTCN_Communication::send_is_alive(component component_reference
)
899 text_buf
.push_int(MSG_IS_ALIVE
);
900 text_buf
.push_int(component_reference
);
901 send_message(text_buf
);
904 void TTCN_Communication::send_done_req(component component_reference
)
907 text_buf
.push_int(MSG_DONE_REQ
);
908 text_buf
.push_int(component_reference
);
909 send_message(text_buf
);
912 void TTCN_Communication::send_killed_req(component component_reference
)
915 text_buf
.push_int(MSG_KILLED_REQ
);
916 text_buf
.push_int(component_reference
);
917 send_message(text_buf
);
920 void TTCN_Communication::send_cancel_done_ack(component component_reference
)
923 text_buf
.push_int(MSG_CANCEL_DONE_ACK
);
924 text_buf
.push_int(component_reference
);
925 send_message(text_buf
);
928 void TTCN_Communication::send_connect_req(component src_component
,
929 const char *src_port
, component dst_component
, const char *dst_port
)
932 text_buf
.push_int(MSG_CONNECT_REQ
);
933 text_buf
.push_int(src_component
);
934 text_buf
.push_string(src_port
);
935 text_buf
.push_int(dst_component
);
936 text_buf
.push_string(dst_port
);
937 send_message(text_buf
);
940 void TTCN_Communication::send_connect_listen_ack_inet_stream(
941 const char *local_port
, component remote_component
,
942 const char *remote_port
, const IPAddress
*local_address
)
945 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
946 text_buf
.push_string(local_port
);
947 text_buf
.push_int(remote_component
);
948 text_buf
.push_string(remote_port
);
949 text_buf
.push_int(TRANSPORT_INET_STREAM
);
950 local_address
->push_raw(text_buf
);
951 send_message(text_buf
);
954 void TTCN_Communication::send_connect_listen_ack_unix_stream(
955 const char *local_port
, component remote_component
,
956 const char *remote_port
, const struct sockaddr_un
*local_address
)
959 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
960 text_buf
.push_string(local_port
);
961 text_buf
.push_int(remote_component
);
962 text_buf
.push_string(remote_port
);
963 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
964 text_buf
.push_string(local_address
->sun_path
);
965 send_message(text_buf
);
968 void TTCN_Communication::send_connected(const char *local_port
,
969 component remote_component
, const char *remote_port
)
972 text_buf
.push_int(MSG_CONNECTED
);
973 text_buf
.push_string(local_port
);
974 text_buf
.push_int(remote_component
);
975 text_buf
.push_string(remote_port
);
976 send_message(text_buf
);
979 void TTCN_Communication::send_connect_error(const char *local_port
,
980 component remote_component
, const char *remote_port
,
981 const char *fmt_str
, ...)
984 va_start(ap
, fmt_str
);
985 char *error_str
= mprintf_va_list(fmt_str
, ap
);
988 text_buf
.push_int(MSG_CONNECT_ERROR
);
989 text_buf
.push_string(local_port
);
990 text_buf
.push_int(remote_component
);
991 text_buf
.push_string(remote_port
);
992 text_buf
.push_string(error_str
);
994 send_message(text_buf
);
997 void TTCN_Communication::send_disconnect_req(component src_component
,
998 const char *src_port
, component dst_component
, const char *dst_port
)
1001 text_buf
.push_int(MSG_DISCONNECT_REQ
);
1002 text_buf
.push_int(src_component
);
1003 text_buf
.push_string(src_port
);
1004 text_buf
.push_int(dst_component
);
1005 text_buf
.push_string(dst_port
);
1006 send_message(text_buf
);
1009 void TTCN_Communication::send_disconnected(const char *local_port
,
1010 component remote_component
, const char *remote_port
)
1013 text_buf
.push_int(MSG_DISCONNECTED
);
1014 text_buf
.push_string(local_port
);
1015 text_buf
.push_int(remote_component
);
1016 text_buf
.push_string(remote_port
);
1017 send_message(text_buf
);
1020 void TTCN_Communication::send_map_req(component src_component
,
1021 const char *src_port
, const char *system_port
)
1024 text_buf
.push_int(MSG_MAP_REQ
);
1025 text_buf
.push_int(src_component
);
1026 text_buf
.push_string(src_port
);
1027 text_buf
.push_string(system_port
);
1028 send_message(text_buf
);
1031 void TTCN_Communication::send_mapped(const char *local_port
,
1032 const char *system_port
)
1035 text_buf
.push_int(MSG_MAPPED
);
1036 text_buf
.push_string(local_port
);
1037 text_buf
.push_string(system_port
);
1038 send_message(text_buf
);
1041 void TTCN_Communication::send_unmap_req(component src_component
,
1042 const char *src_port
, const char *system_port
)
1045 text_buf
.push_int(MSG_UNMAP_REQ
);
1046 text_buf
.push_int(src_component
);
1047 text_buf
.push_string(src_port
);
1048 text_buf
.push_string(system_port
);
1049 send_message(text_buf
);
1052 void TTCN_Communication::send_unmapped(const char *local_port
,
1053 const char *system_port
)
1056 text_buf
.push_int(MSG_UNMAPPED
);
1057 text_buf
.push_string(local_port
);
1058 text_buf
.push_string(system_port
);
1059 send_message(text_buf
);
1062 void TTCN_Communication::send_mtc_created()
1065 text_buf
.push_int(MSG_MTC_CREATED
);
1066 send_message(text_buf
);
1069 void TTCN_Communication::send_testcase_started(const char *testcase_module
,
1070 const char *testcase_name
, const char *mtc_comptype_module
,
1071 const char *mtc_comptype_name
, const char *system_comptype_module
,
1072 const char *system_comptype_name
)
1075 text_buf
.push_int(MSG_TESTCASE_STARTED
);
1076 text_buf
.push_string(testcase_module
);
1077 text_buf
.push_string(testcase_name
);
1078 text_buf
.push_string(mtc_comptype_module
);
1079 text_buf
.push_string(mtc_comptype_name
);
1080 text_buf
.push_string(system_comptype_module
);
1081 text_buf
.push_string(system_comptype_name
);
1082 send_message(text_buf
);
1085 void TTCN_Communication::send_testcase_finished(verdicttype final_verdict
,
1089 text_buf
.push_int(MSG_TESTCASE_FINISHED
);
1090 text_buf
.push_int(final_verdict
);
1091 text_buf
.push_string(reason
);
1092 send_message(text_buf
);
1095 void TTCN_Communication::send_mtc_ready()
1098 text_buf
.push_int(MSG_MTC_READY
);
1099 send_message(text_buf
);
1102 void TTCN_Communication::send_ptc_created(component component_reference
)
1105 text_buf
.push_int(MSG_PTC_CREATED
);
1106 text_buf
.push_int(component_reference
);
1107 send_message(text_buf
);
1110 void TTCN_Communication::prepare_stopped(Text_Buf
& text_buf
,
1111 const char *return_type
)
1113 text_buf
.push_int(MSG_STOPPED
);
1114 text_buf
.push_string(return_type
);
1117 void TTCN_Communication::send_stopped()
1120 text_buf
.push_int(MSG_STOPPED
);
1121 // add an empty return type
1122 text_buf
.push_string(NULL
);
1123 send_message(text_buf
);
1126 void TTCN_Communication::prepare_stopped_killed(Text_Buf
& text_buf
,
1127 verdicttype final_verdict
, const char *return_type
, const char* reason
)
1129 text_buf
.push_int(MSG_STOPPED_KILLED
);
1130 text_buf
.push_int(final_verdict
);
1131 text_buf
.push_string(reason
);
1132 text_buf
.push_string(return_type
);
1135 void TTCN_Communication::send_stopped_killed(verdicttype final_verdict
,
1139 text_buf
.push_int(MSG_STOPPED_KILLED
);
1140 text_buf
.push_int(final_verdict
);
1141 text_buf
.push_string(reason
);
1142 // add an empty return type
1143 text_buf
.push_string(NULL
);
1144 send_message(text_buf
);
1147 void TTCN_Communication::send_killed(verdicttype final_verdict
,
1151 text_buf
.push_int(MSG_KILLED
);
1152 text_buf
.push_int(final_verdict
);
1153 text_buf
.push_string(reason
);
1154 send_message(text_buf
);
1157 void TTCN_Communication::send_debug_return_value(int return_type
, const char* message
)
1160 text_buf
.push_int(MSG_DEBUG_RETURN_VALUE
);
1161 text_buf
.push_int(return_type
);
1162 if (message
!= NULL
) {
1164 gettimeofday(&tv
, NULL
);
1165 text_buf
.push_int(tv
.tv_sec
);
1166 text_buf
.push_int(tv
.tv_usec
);
1167 text_buf
.push_string(message
);
1169 send_message(text_buf
);
1172 void TTCN_Communication::send_debug_halt_req()
1175 text_buf
.push_int(MSG_DEBUG_HALT_REQ
);
1176 send_message(text_buf
);
1179 void TTCN_Communication::send_debug_continue_req()
1182 text_buf
.push_int(MSG_DEBUG_CONTINUE_REQ
);
1183 send_message(text_buf
);
1186 void TTCN_Communication::send_debug_batch(const char* batch_file
)
1189 text_buf
.push_int(MSG_DEBUG_BATCH
);
1190 text_buf
.push_string(batch_file
);
1191 send_message(text_buf
);
1194 boolean
TTCN_Communication::send_log(time_t timestamp_sec
, long timestamp_usec
,
1195 unsigned int event_severity
, size_t message_text_len
,
1196 const char *message_text
)
1200 text_buf
.push_int(MSG_LOG
);
1201 text_buf
.push_int(timestamp_sec
);
1202 text_buf
.push_int(timestamp_usec
);
1203 text_buf
.push_int(event_severity
);
1204 text_buf
.push_int(message_text_len
);
1205 text_buf
.push_raw(message_text_len
, message_text
);
1206 send_message(text_buf
);
1207 /* If an ERROR message (indicating a version mismatch) arrives from MC
1208 in state HC_IDLE (i.e. before CONFIGURE) it shall be
1209 printed to the console as well. */
1210 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_IDLE
) return FALSE
;
1213 switch (TTCN_Runtime::get_state()) {
1214 case TTCN_Runtime::HC_EXIT
:
1215 case TTCN_Runtime::MTC_INITIAL
:
1216 case TTCN_Runtime::MTC_EXIT
:
1217 case TTCN_Runtime::PTC_INITIAL
:
1218 case TTCN_Runtime::PTC_EXIT
:
1219 /* Do not print the first/last few lines of logs to the console
1220 even if ConsoleMask is set to LOG_ALL */
1228 void TTCN_Communication::send_error(const char *fmt_str
, ...)
1231 va_start(ap
, fmt_str
);
1232 char *error_str
= mprintf_va_list(fmt_str
, ap
);
1235 text_buf
.push_int((RInt
)MSG_ERROR
);
1236 text_buf
.push_string(error_str
);
1238 send_message(text_buf
);
1241 void TTCN_Communication::send_message(Text_Buf
& text_buf
)
1243 if (!is_connected
) TTCN_error("Trying to send a message to MC, but the "
1244 "control connection is down.");
1245 text_buf
.calculate_length();
1246 const char *msg_ptr
= text_buf
.get_data();
1247 size_t msg_len
= text_buf
.get_len(), sent_len
= 0;
1248 while (sent_len
< msg_len
) {
1249 int ret_val
= send(mc_fd
, msg_ptr
+ sent_len
, msg_len
- sent_len
, 0);
1250 if (ret_val
> 0) sent_len
+= ret_val
;
1254 // a signal occurred: do nothing, just try again
1258 close_mc_connection();
1259 TTCN_error("Sending data on the control connection to MC "
1266 void TTCN_Communication::process_configure(int msg_end
)
1268 switch (TTCN_Runtime::get_state()) {
1269 case TTCN_Runtime::HC_IDLE
:
1270 case TTCN_Runtime::HC_ACTIVE
:
1271 case TTCN_Runtime::HC_OVERLOADED
:
1274 incoming_buf
.cut_message();
1275 send_error("Message CONFIGURE arrived in invalid state.");
1279 TTCN_Runtime::set_state(TTCN_Runtime::HC_CONFIGURING
);
1280 TTCN_Logger::log_configdata(TitanLoggerApiSimple::ExecutorConfigdata_reason::received__from__mc
);
1282 // take the config string directly from the buffer for efficiency reasons
1283 int config_str_len
= incoming_buf
.pull_int().get_val();
1284 int config_str_begin
= incoming_buf
.get_pos();
1285 if (config_str_begin
+ config_str_len
!= msg_end
) {
1286 incoming_buf
.cut_message();
1287 send_error("Malformed message CONFIGURE was received.");
1290 const char *config_str
= incoming_buf
.get_data() + config_str_begin
;
1291 boolean success
= process_config_string(config_str
, config_str_len
);
1293 // Only non component specific settings will be applied. The plug-ins need
1294 // to be loaded due to resetting.
1295 TTCN_Logger::load_plugins(NULL_COMPREF
, "");
1296 TTCN_Logger::set_plugin_parameters(NULL_COMPREF
, "");
1297 TTCN_Logger::open_file();
1300 Module_List::log_param();
1301 Module_List::post_init_modules();
1302 } catch (const TC_Error
& TC_error
) {
1303 TTCN_Logger::log_executor_runtime(
1304 TitanLoggerApiSimple::ExecutorRuntime_reason::initialization__of__modules__failed
);
1308 TTCN_Logger::log_configdata(
1309 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__failed
, NULL
);
1313 send_configure_ack();
1314 TTCN_Runtime::set_state(TTCN_Runtime::HC_ACTIVE
);
1315 TTCN_Logger::log_configdata(
1316 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__succeeded
);
1318 send_configure_nak();
1319 TTCN_Runtime::set_state(TTCN_Runtime::HC_IDLE
);
1322 incoming_buf
.cut_message();
1325 void TTCN_Communication::process_create_mtc()
1327 incoming_buf
.cut_message();
1328 TTCN_Runtime::process_create_mtc();
1331 void TTCN_Communication::process_create_ptc()
1333 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1334 if (component_reference
< FIRST_PTC_COMPREF
) {
1335 incoming_buf
.cut_message();
1336 send_error("Message CREATE_PTC refers to invalid "
1337 "component reference %d.", component_reference
);
1340 qualified_name component_type
;
1341 incoming_buf
.pull_qualified_name(component_type
);
1342 if (component_type
.module_name
== NULL
||
1343 component_type
.definition_name
== NULL
) {
1344 incoming_buf
.cut_message();
1345 delete [] component_type
.module_name
;
1346 delete [] component_type
.definition_name
;
1347 send_error("Message CREATE_PTC with component reference %d contains "
1348 "an invalid component type.", component_reference
);
1351 char *component_name
= incoming_buf
.pull_string();
1352 boolean is_alive
= incoming_buf
.pull_int().get_val();
1353 qualified_name current_testcase
;
1354 incoming_buf
.pull_qualified_name(current_testcase
);
1355 incoming_buf
.cut_message();
1358 TTCN_Runtime::process_create_ptc(component_reference
,
1359 component_type
.module_name
, component_type
.definition_name
,
1360 component_name
, is_alive
, current_testcase
.module_name
,
1361 current_testcase
.definition_name
);
1363 // to prevent from memory leaks
1364 delete [] component_type
.module_name
;
1365 delete [] component_type
.definition_name
;
1366 delete [] component_name
;
1367 delete [] current_testcase
.module_name
;
1368 delete [] current_testcase
.definition_name
;
1372 delete [] component_type
.module_name
;
1373 delete [] component_type
.definition_name
;
1374 delete [] component_name
;
1375 delete [] current_testcase
.module_name
;
1376 delete [] current_testcase
.definition_name
;
1379 void TTCN_Communication::process_kill_process()
1381 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1382 incoming_buf
.cut_message();
1383 TTCN_Runtime::process_kill_process(component_reference
);
1386 void TTCN_Communication::process_exit_hc()
1388 incoming_buf
.cut_message();
1389 TTCN_Logger::log_executor_runtime(
1390 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__hc
);
1391 TTCN_Runtime::set_state(TTCN_Runtime::HC_EXIT
);
1394 void TTCN_Communication::process_create_ack()
1396 component component_reference
= incoming_buf
.pull_int().get_val();
1397 incoming_buf
.cut_message();
1398 TTCN_Runtime::process_create_ack(component_reference
);
1401 void TTCN_Communication::process_start_ack()
1403 incoming_buf
.cut_message();
1405 switch (TTCN_Runtime::get_state()) {
1406 case TTCN_Runtime::MTC_START
:
1407 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1408 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1410 case TTCN_Runtime::PTC_START
:
1411 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1414 TTCN_error("Internal error: Message START_ACK arrived in invalid "
1419 void TTCN_Communication::process_stop()
1421 incoming_buf
.cut_message();
1422 switch (TTCN_Runtime::get_state()) {
1423 case TTCN_Runtime::MTC_IDLE
:
1424 TTCN_Logger::log_executor_runtime(
1425 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__mtc
);
1427 case TTCN_Runtime::MTC_PAUSED
:
1428 TTCN_Logger::log_executor_runtime(
1429 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1430 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TERMINATING_EXECUTION
);
1432 case TTCN_Runtime::PTC_IDLE
:
1433 case TTCN_Runtime::PTC_STOPPED
:
1434 TTCN_Logger::log_executor_runtime(
1435 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__ptc
);
1437 case TTCN_Runtime::PTC_EXIT
:
1441 TTCN_Logger::log_executor_runtime(
1442 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1443 TTCN_Runtime::stop_execution();
1448 void TTCN_Communication::process_stop_ack()
1450 incoming_buf
.cut_message();
1451 switch (TTCN_Runtime::get_state()) {
1452 case TTCN_Runtime::MTC_STOP
:
1453 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1454 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1456 case TTCN_Runtime::PTC_STOP
:
1457 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1460 TTCN_error("Internal error: Message STOP_ACK arrived in invalid "
1465 void TTCN_Communication::process_kill_ack()
1467 incoming_buf
.cut_message();
1468 switch (TTCN_Runtime::get_state()) {
1469 case TTCN_Runtime::MTC_KILL
:
1470 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1471 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1473 case TTCN_Runtime::PTC_KILL
:
1474 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1477 TTCN_error("Internal error: Message KILL_ACK arrived in invalid "
1482 void TTCN_Communication::process_running()
1484 boolean answer
= incoming_buf
.pull_int().get_val();
1485 incoming_buf
.cut_message();
1486 TTCN_Runtime::process_running(answer
);
1489 void TTCN_Communication::process_alive()
1491 boolean answer
= incoming_buf
.pull_int().get_val();
1492 incoming_buf
.cut_message();
1493 TTCN_Runtime::process_alive(answer
);
1496 void TTCN_Communication::process_done_ack(int msg_end
)
1498 // decoding the mandatory attributes
1499 boolean answer
= incoming_buf
.pull_int().get_val();
1500 char *return_type
= incoming_buf
.pull_string();
1501 // the return value starts here
1502 int return_value_begin
= incoming_buf
.get_pos();
1505 TTCN_Runtime::process_done_ack(answer
, return_type
,
1506 msg_end
- return_value_begin
,
1507 incoming_buf
.get_data() + return_value_begin
);
1509 // avoid memory leaks in case of error
1510 incoming_buf
.cut_message();
1511 delete [] return_type
;
1515 incoming_buf
.cut_message();
1516 delete [] return_type
;
1519 void TTCN_Communication::process_killed_ack()
1521 boolean answer
= incoming_buf
.pull_int().get_val();
1522 incoming_buf
.cut_message();
1523 TTCN_Runtime::process_killed_ack(answer
);
1526 void TTCN_Communication::process_cancel_done_mtc()
1528 component component_reference
= incoming_buf
.pull_int().get_val();
1529 boolean cancel_any
= incoming_buf
.pull_int().get_val();
1530 incoming_buf
.cut_message();
1531 TTCN_Runtime::cancel_component_done(component_reference
);
1532 if (cancel_any
) TTCN_Runtime::cancel_component_done(ANY_COMPREF
);
1533 send_cancel_done_ack(component_reference
);
1536 void TTCN_Communication::process_cancel_done_ptc()
1538 component component_reference
= incoming_buf
.pull_int().get_val();
1539 incoming_buf
.cut_message();
1540 TTCN_Runtime::cancel_component_done(component_reference
);
1541 send_cancel_done_ack(component_reference
);
1544 void TTCN_Communication::process_component_status_mtc(int msg_end
)
1546 // decoding the mandatory attributes
1547 component component_reference
= incoming_buf
.pull_int().get_val();
1548 boolean is_done
= incoming_buf
.pull_int().get_val();
1549 boolean is_killed
= incoming_buf
.pull_int().get_val();
1550 boolean is_any_done
= incoming_buf
.pull_int().get_val();
1551 boolean is_all_done
= incoming_buf
.pull_int().get_val();
1552 boolean is_any_killed
= incoming_buf
.pull_int().get_val();
1553 boolean is_all_killed
= incoming_buf
.pull_int().get_val();
1555 // the return type and value is valid
1556 char *return_type
= incoming_buf
.pull_string();
1557 int return_value_begin
= incoming_buf
.get_pos();
1559 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1560 msg_end
- return_value_begin
,
1561 incoming_buf
.get_data() + return_value_begin
);
1563 // avoid memory leaks
1564 incoming_buf
.cut_message();
1565 delete [] return_type
;
1568 delete [] return_type
;
1570 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1572 TTCN_Runtime::set_component_done(ANY_COMPREF
, NULL
, 0, NULL
);
1574 TTCN_Runtime::set_component_done(ALL_COMPREF
, NULL
, 0, NULL
);
1575 if (is_any_killed
) TTCN_Runtime::set_component_killed(ANY_COMPREF
);
1576 if (is_all_killed
) TTCN_Runtime::set_component_killed(ALL_COMPREF
);
1577 incoming_buf
.cut_message();
1578 if (!is_done
&& !is_killed
&& (component_reference
!= NULL_COMPREF
||
1579 (!is_any_done
&& !is_all_done
&& !is_any_killed
&& !is_all_killed
)))
1580 TTCN_error("Internal error: Malformed COMPONENT_STATUS message was "
1584 void TTCN_Communication::process_component_status_ptc(int msg_end
)
1586 // decoding the mandatory attributes
1587 component component_reference
= incoming_buf
.pull_int().get_val();
1588 boolean is_done
= incoming_buf
.pull_int().get_val();
1589 boolean is_killed
= incoming_buf
.pull_int().get_val();
1591 // the return type and value is valid
1592 char *return_type
= incoming_buf
.pull_string();
1593 int return_value_begin
= incoming_buf
.get_pos();
1595 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1596 msg_end
- return_value_begin
,
1597 incoming_buf
.get_data() + return_value_begin
);
1599 // avoid memory leaks
1600 incoming_buf
.cut_message();
1601 delete [] return_type
;
1604 delete [] return_type
;
1606 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1607 incoming_buf
.cut_message();
1608 if (!is_done
&& !is_killed
) TTCN_error("Internal error: Malformed "
1609 "COMPONENT_STATUS message was received.");
1612 void TTCN_Communication::process_connect_listen()
1614 char *local_port
= incoming_buf
.pull_string();
1615 component remote_component
= incoming_buf
.pull_int().get_val();
1616 char *remote_component_name
= incoming_buf
.pull_string();
1617 char *remote_port
= incoming_buf
.pull_string();
1618 transport_type_enum transport_type
=
1619 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1620 incoming_buf
.cut_message();
1623 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1624 COMPONENT::register_component_name(remote_component
,
1625 remote_component_name
);
1626 PORT::process_connect_listen(local_port
, remote_component
, remote_port
,
1629 delete [] local_port
;
1630 delete [] remote_component_name
;
1631 delete [] remote_port
;
1635 delete [] local_port
;
1636 delete [] remote_component_name
;
1637 delete [] remote_port
;
1640 void TTCN_Communication::process_connect()
1642 char *local_port
= incoming_buf
.pull_string();
1643 component remote_component
= incoming_buf
.pull_int().get_val();
1644 char *remote_component_name
= incoming_buf
.pull_string();
1645 char *remote_port
= incoming_buf
.pull_string();
1646 transport_type_enum transport_type
=
1647 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1650 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1651 COMPONENT::register_component_name(remote_component
,
1652 remote_component_name
);
1653 PORT::process_connect(local_port
, remote_component
, remote_port
,
1654 transport_type
, incoming_buf
);
1656 incoming_buf
.cut_message();
1657 delete [] local_port
;
1658 delete [] remote_component_name
;
1659 delete [] remote_port
;
1663 incoming_buf
.cut_message();
1664 delete [] local_port
;
1665 delete [] remote_component_name
;
1666 delete [] remote_port
;
1669 void TTCN_Communication::process_connect_ack()
1671 incoming_buf
.cut_message();
1673 switch (TTCN_Runtime::get_state()) {
1674 case TTCN_Runtime::MTC_CONNECT
:
1675 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1676 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1678 case TTCN_Runtime::PTC_CONNECT
:
1679 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1682 TTCN_error("Internal error: Message CONNECT_ACK arrived in invalid "
1687 void TTCN_Communication::process_disconnect()
1689 char *local_port
= incoming_buf
.pull_string();
1690 component remote_component
= incoming_buf
.pull_int().get_val();
1691 char *remote_port
= incoming_buf
.pull_string();
1692 incoming_buf
.cut_message();
1695 PORT::process_disconnect(local_port
, remote_component
, remote_port
);
1697 delete [] local_port
;
1698 delete [] remote_port
;
1702 delete [] local_port
;
1703 delete [] remote_port
;
1706 void TTCN_Communication::process_disconnect_ack()
1708 incoming_buf
.cut_message();
1710 switch (TTCN_Runtime::get_state()) {
1711 case TTCN_Runtime::MTC_DISCONNECT
:
1712 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1713 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1715 case TTCN_Runtime::PTC_DISCONNECT
:
1716 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1719 TTCN_error("Internal error: Message DISCONNECT_ACK arrived in invalid "
1724 void TTCN_Communication::process_map()
1726 char *local_port
= incoming_buf
.pull_string();
1727 char *system_port
= incoming_buf
.pull_string();
1728 incoming_buf
.cut_message();
1731 PORT::map_port(local_port
, system_port
);
1733 delete [] local_port
;
1734 delete [] system_port
;
1738 delete [] local_port
;
1739 delete [] system_port
;
1742 void TTCN_Communication::process_map_ack()
1744 incoming_buf
.cut_message();
1746 switch (TTCN_Runtime::get_state()) {
1747 case TTCN_Runtime::MTC_MAP
:
1748 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1749 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1751 case TTCN_Runtime::PTC_MAP
:
1752 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1755 TTCN_error("Internal error: Message MAP_ACK arrived in invalid state.");
1759 void TTCN_Communication::process_unmap()
1761 char *local_port
= incoming_buf
.pull_string();
1762 char *system_port
= incoming_buf
.pull_string();
1763 incoming_buf
.cut_message();
1766 PORT::unmap_port(local_port
, system_port
);
1768 delete [] local_port
;
1769 delete [] system_port
;
1773 delete [] local_port
;
1774 delete [] system_port
;
1777 void TTCN_Communication::process_unmap_ack()
1779 incoming_buf
.cut_message();
1781 switch(TTCN_Runtime::get_state()){
1782 case TTCN_Runtime::MTC_UNMAP
:
1783 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1784 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1786 case TTCN_Runtime::PTC_UNMAP
:
1787 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1790 TTCN_error("Internal error: Message UNMAP_ACK arrived in invalid "
1795 void TTCN_Communication::process_execute_control()
1797 char *module_name
= incoming_buf
.pull_string();
1798 incoming_buf
.cut_message();
1800 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1801 delete [] module_name
;
1802 TTCN_error("Internal error: Message EXECUTE_CONTROL arrived in "
1806 TTCN_Logger::log(TTCN_Logger::PARALLEL_UNQUALIFIED
,
1807 "Executing control part of module %s.", module_name
);
1809 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1812 Module_List::execute_control(module_name
);
1813 } catch (const TC_End
& TC_end
) {
1814 } catch (const TC_Error
& TC_error
) {
1817 delete [] module_name
;
1821 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1822 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1825 void TTCN_Communication::process_execute_testcase()
1827 char *module_name
= incoming_buf
.pull_string();
1828 char *testcase_name
= incoming_buf
.pull_string();
1829 incoming_buf
.cut_message();
1831 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1832 delete [] module_name
;
1833 delete [] testcase_name
;
1834 TTCN_error("Internal error: Message EXECUTE_TESTCASE arrived in "
1838 TTCN_Logger::log_testcase_exec(testcase_name
, module_name
);
1840 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1843 if (testcase_name
!= NULL
&& testcase_name
[0] != '\0')
1844 Module_List::execute_testcase(module_name
, testcase_name
);
1845 else Module_List::execute_all_testcases(module_name
);
1846 } catch (const TC_End
& TC_end
) {
1847 } catch (const TC_Error
& TC_error
) {
1852 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1853 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1855 delete [] module_name
;
1856 delete [] testcase_name
;
1859 void TTCN_Communication::process_ptc_verdict()
1861 TTCN_Runtime::process_ptc_verdict(incoming_buf
);
1862 incoming_buf
.cut_message();
1865 void TTCN_Communication::process_continue()
1867 incoming_buf
.cut_message();
1869 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_PAUSED
)
1870 TTCN_error("Internal error: Message CONTINUE arrived in invalid "
1873 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1876 void TTCN_Communication::process_exit_mtc()
1878 incoming_buf
.cut_message();
1879 TTCN_Runtime::log_verdict_statistics();
1880 TTCN_Logger::log_executor_runtime(
1881 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__mtc
);
1882 TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1885 void TTCN_Communication::process_start()
1887 qualified_name function_name
;
1888 incoming_buf
.pull_qualified_name(function_name
);
1889 if (function_name
.module_name
== NULL
||
1890 function_name
.definition_name
== NULL
) {
1891 incoming_buf
.cut_message();
1892 delete [] function_name
.module_name
;
1893 delete [] function_name
.definition_name
;
1894 TTCN_error("Internal error: Message START contains an invalid "
1899 TTCN_Runtime::start_function(function_name
.module_name
,
1900 function_name
.definition_name
, incoming_buf
);
1902 // avoid memory leaks
1903 delete [] function_name
.module_name
;
1904 delete [] function_name
.definition_name
;
1908 delete [] function_name
.module_name
;
1909 delete [] function_name
.definition_name
;
1912 void TTCN_Communication::process_kill()
1914 incoming_buf
.cut_message();
1915 TTCN_Runtime::process_kill();
1918 void TTCN_Communication::process_error()
1920 char *error_string
= incoming_buf
.pull_string();
1921 incoming_buf
.cut_message();
1924 TTCN_error("Error message was received from MC: %s", error_string
);
1926 delete [] error_string
;
1931 void TTCN_Communication::process_unsupported_message(int msg_type
, int msg_end
)
1933 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED
);
1934 TTCN_Logger::log_event("Unsupported message was received from MC: "
1935 "type (decimal): %d, data (hexadecimal): ", msg_type
);
1936 const unsigned char *msg_ptr
=
1937 (const unsigned char*)incoming_buf
.get_data();
1938 for (int i
= incoming_buf
.get_pos(); i
< msg_end
; i
++)
1939 TTCN_Logger::log_octet(msg_ptr
[i
]);
1940 TTCN_Logger::end_event();
1941 incoming_buf
.cut_message();
1944 void TTCN_Communication::process_debug_command()
1946 int command
= incoming_buf
.pull_int().get_val();
1947 int argument_count
= incoming_buf
.pull_int().get_val();
1948 char** arguments
= NULL
;
1949 if (argument_count
> 0) {
1950 arguments
= new char*[argument_count
];
1951 for (int i
= 0; i
< argument_count
; ++i
) {
1952 arguments
[i
] = incoming_buf
.pull_string();
1955 incoming_buf
.cut_message();
1956 ttcn3_debugger
.execute_command(command
, argument_count
, arguments
);
1957 if (argument_count
> 0) {
1958 for (int i
= 0; i
< argument_count
; ++i
) {
1959 delete [] arguments
[i
];
1961 delete [] arguments
;
1965 /* * * * Temporary squatting place because it includes version.h * * * */
1967 const struct runtime_version current_runtime_version
= {
1968 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
, TITAN_RUNTIME_NR
1971 static const char *runtime_name
[] = { 0, "load", "function " };
1973 RuntimeVersionChecker::RuntimeVersionChecker(
1974 int ver_major
, int ver_minor
, int patch_level
, int rt
)
1976 if ( TTCN3_MAJOR
!= ver_major
1977 || TTCN3_MINOR
!= ver_minor
1978 || TTCN3_PATCHLEVEL
!= patch_level
)
1981 "Version mismatch detected: generated code %d.%d.pl%d, "
1982 "runtime is %d.%d.pl%d",
1983 ver_major
, ver_minor
, patch_level
,
1984 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
);
1987 if (TITAN_RUNTIME_NR
!= rt
) {
1988 TTCN_error("Runtime mismatch detected: files compiled for the %stest"
1989 " runtime cannot be linked to %stest library",
1990 runtime_name
[TITAN_RUNTIME_NR
], runtime_name
[rt
]);
1994 reffer::reffer(const char*) {}