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
, false);
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_configure(msg_end
, true);
711 process_unsupported_message(msg_type
, msg_end
);
714 // messages: MC -> PTC
723 process_unsupported_message(msg_type
, msg_end
);
730 void TTCN_Communication::process_debug_messages()
732 // receives and processes messages from the MC, while test execution is halted
736 Text_Buf storage_buf
;
737 while (ttcn3_debugger
.is_halted()) {
738 incoming_buf
.get_end(buf_ptr
, buf_len
);
740 int recv_len
= recv(mc_fd
, buf_ptr
, buf_len
, 0);
743 incoming_buf
.increase_length(recv_len
);
745 while (incoming_buf
.is_message() && ttcn3_debugger
.is_halted()) {
746 int msg_len
= incoming_buf
.pull_int().get_val();
747 int msg_end
= incoming_buf
.get_pos() + msg_len
;
748 int msg_type
= incoming_buf
.pull_int().get_val();
749 // process only debug commands and 'stop' messages, store the rest
751 case MSG_DEBUG_COMMAND
:
752 process_debug_command();
758 // store all other messages in a different buffer
759 int data_len
= msg_end
- incoming_buf
.get_pos();
760 char* msg_data
= new char[data_len
];
761 incoming_buf
.pull_raw(data_len
, msg_data
);
762 incoming_buf
.cut_message();
763 storage_buf
.push_int(msg_type
);
764 storage_buf
.push_raw(data_len
, msg_data
);
766 storage_buf
.calculate_length();
772 // append the stored messages to the beginning of the main buffer and
774 if (storage_buf
.is_message()) {
775 incoming_buf
.push_raw_front(storage_buf
.get_len(), storage_buf
.get_data());
776 process_all_messages_tc();
780 void TTCN_Communication::send_version()
783 text_buf
.push_int(MSG_VERSION
);
784 text_buf
.push_int(TTCN3_MAJOR
);
785 text_buf
.push_int(TTCN3_MINOR
);
786 text_buf
.push_int(TTCN3_PATCHLEVEL
);
787 #ifdef TTCN3_BUILDNUMBER
788 text_buf
.push_int(TTCN3_BUILDNUMBER
);
790 text_buf
.push_int((RInt
)0);
792 Module_List::push_version(text_buf
);
794 if (uname(&uts
) < 0) TTCN_error("System call uname() failed.");
795 text_buf
.push_string(uts
.nodename
);
796 text_buf
.push_string(uts
.machine
);
797 text_buf
.push_string(uts
.sysname
);
798 text_buf
.push_string(uts
.release
);
799 text_buf
.push_string(uts
.version
);
800 boolean unix_stream_supported
= transport_unix_stream_supported();
802 // LOCAL (software loop) and INET_STREAM (TCP) transports are always
804 int n_supported_transports
= 2;
806 if (unix_stream_supported
) n_supported_transports
++;
807 text_buf
.push_int(n_supported_transports
);
808 text_buf
.push_int(TRANSPORT_LOCAL
);
809 text_buf
.push_int(TRANSPORT_INET_STREAM
);
810 if (unix_stream_supported
)
811 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
812 send_message(text_buf
);
815 void TTCN_Communication::send_configure_ack()
818 text_buf
.push_int(MSG_CONFIGURE_ACK
);
819 send_message(text_buf
);
822 void TTCN_Communication::send_configure_nak()
825 text_buf
.push_int(MSG_CONFIGURE_NAK
);
826 send_message(text_buf
);
829 void TTCN_Communication::send_create_nak(component component_reference
,
830 const char *fmt_str
, ...)
833 va_start(ap
, fmt_str
);
834 char *error_str
= mprintf_va_list(fmt_str
, ap
);
837 text_buf
.push_int(MSG_CREATE_NAK
);
838 text_buf
.push_int(component_reference
);
839 text_buf
.push_string(error_str
);
841 send_message(text_buf
);
844 void TTCN_Communication::send_hc_ready()
847 text_buf
.push_int(MSG_HC_READY
);
848 send_message(text_buf
);
851 void TTCN_Communication::send_create_req(const char *component_type_module
,
852 const char *component_type_name
, const char *component_name
,
853 const char *component_location
, boolean is_alive
)
856 text_buf
.push_int(MSG_CREATE_REQ
);
857 text_buf
.push_string(component_type_module
);
858 text_buf
.push_string(component_type_name
);
859 text_buf
.push_string(component_name
);
860 text_buf
.push_string(component_location
);
861 text_buf
.push_int(is_alive
? 1 : 0);
862 send_message(text_buf
);
865 void TTCN_Communication::prepare_start_req(Text_Buf
& text_buf
,
866 component component_reference
, const char *module_name
,
867 const char *function_name
)
869 text_buf
.push_int(MSG_START_REQ
);
870 text_buf
.push_int(component_reference
);
871 text_buf
.push_string(module_name
);
872 text_buf
.push_string(function_name
);
875 void TTCN_Communication::send_stop_req(component component_reference
)
878 text_buf
.push_int(MSG_STOP_REQ
);
879 text_buf
.push_int(component_reference
);
880 send_message(text_buf
);
883 void TTCN_Communication::send_kill_req(component component_reference
)
886 text_buf
.push_int(MSG_KILL_REQ
);
887 text_buf
.push_int(component_reference
);
888 send_message(text_buf
);
891 void TTCN_Communication::send_is_running(component component_reference
)
894 text_buf
.push_int(MSG_IS_RUNNING
);
895 text_buf
.push_int(component_reference
);
896 send_message(text_buf
);
899 void TTCN_Communication::send_is_alive(component component_reference
)
902 text_buf
.push_int(MSG_IS_ALIVE
);
903 text_buf
.push_int(component_reference
);
904 send_message(text_buf
);
907 void TTCN_Communication::send_done_req(component component_reference
)
910 text_buf
.push_int(MSG_DONE_REQ
);
911 text_buf
.push_int(component_reference
);
912 send_message(text_buf
);
915 void TTCN_Communication::send_killed_req(component component_reference
)
918 text_buf
.push_int(MSG_KILLED_REQ
);
919 text_buf
.push_int(component_reference
);
920 send_message(text_buf
);
923 void TTCN_Communication::send_cancel_done_ack(component component_reference
)
926 text_buf
.push_int(MSG_CANCEL_DONE_ACK
);
927 text_buf
.push_int(component_reference
);
928 send_message(text_buf
);
931 void TTCN_Communication::send_connect_req(component src_component
,
932 const char *src_port
, component dst_component
, const char *dst_port
)
935 text_buf
.push_int(MSG_CONNECT_REQ
);
936 text_buf
.push_int(src_component
);
937 text_buf
.push_string(src_port
);
938 text_buf
.push_int(dst_component
);
939 text_buf
.push_string(dst_port
);
940 send_message(text_buf
);
943 void TTCN_Communication::send_connect_listen_ack_inet_stream(
944 const char *local_port
, component remote_component
,
945 const char *remote_port
, const IPAddress
*local_address
)
948 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
949 text_buf
.push_string(local_port
);
950 text_buf
.push_int(remote_component
);
951 text_buf
.push_string(remote_port
);
952 text_buf
.push_int(TRANSPORT_INET_STREAM
);
953 local_address
->push_raw(text_buf
);
954 send_message(text_buf
);
957 void TTCN_Communication::send_connect_listen_ack_unix_stream(
958 const char *local_port
, component remote_component
,
959 const char *remote_port
, const struct sockaddr_un
*local_address
)
962 text_buf
.push_int(MSG_CONNECT_LISTEN_ACK
);
963 text_buf
.push_string(local_port
);
964 text_buf
.push_int(remote_component
);
965 text_buf
.push_string(remote_port
);
966 text_buf
.push_int(TRANSPORT_UNIX_STREAM
);
967 text_buf
.push_string(local_address
->sun_path
);
968 send_message(text_buf
);
971 void TTCN_Communication::send_connected(const char *local_port
,
972 component remote_component
, const char *remote_port
)
975 text_buf
.push_int(MSG_CONNECTED
);
976 text_buf
.push_string(local_port
);
977 text_buf
.push_int(remote_component
);
978 text_buf
.push_string(remote_port
);
979 send_message(text_buf
);
982 void TTCN_Communication::send_connect_error(const char *local_port
,
983 component remote_component
, const char *remote_port
,
984 const char *fmt_str
, ...)
987 va_start(ap
, fmt_str
);
988 char *error_str
= mprintf_va_list(fmt_str
, ap
);
991 text_buf
.push_int(MSG_CONNECT_ERROR
);
992 text_buf
.push_string(local_port
);
993 text_buf
.push_int(remote_component
);
994 text_buf
.push_string(remote_port
);
995 text_buf
.push_string(error_str
);
997 send_message(text_buf
);
1000 void TTCN_Communication::send_disconnect_req(component src_component
,
1001 const char *src_port
, component dst_component
, const char *dst_port
)
1004 text_buf
.push_int(MSG_DISCONNECT_REQ
);
1005 text_buf
.push_int(src_component
);
1006 text_buf
.push_string(src_port
);
1007 text_buf
.push_int(dst_component
);
1008 text_buf
.push_string(dst_port
);
1009 send_message(text_buf
);
1012 void TTCN_Communication::send_disconnected(const char *local_port
,
1013 component remote_component
, const char *remote_port
)
1016 text_buf
.push_int(MSG_DISCONNECTED
);
1017 text_buf
.push_string(local_port
);
1018 text_buf
.push_int(remote_component
);
1019 text_buf
.push_string(remote_port
);
1020 send_message(text_buf
);
1023 void TTCN_Communication::send_map_req(component src_component
,
1024 const char *src_port
, const char *system_port
)
1027 text_buf
.push_int(MSG_MAP_REQ
);
1028 text_buf
.push_int(src_component
);
1029 text_buf
.push_string(src_port
);
1030 text_buf
.push_string(system_port
);
1031 send_message(text_buf
);
1034 void TTCN_Communication::send_mapped(const char *local_port
,
1035 const char *system_port
)
1038 text_buf
.push_int(MSG_MAPPED
);
1039 text_buf
.push_string(local_port
);
1040 text_buf
.push_string(system_port
);
1041 send_message(text_buf
);
1044 void TTCN_Communication::send_unmap_req(component src_component
,
1045 const char *src_port
, const char *system_port
)
1048 text_buf
.push_int(MSG_UNMAP_REQ
);
1049 text_buf
.push_int(src_component
);
1050 text_buf
.push_string(src_port
);
1051 text_buf
.push_string(system_port
);
1052 send_message(text_buf
);
1055 void TTCN_Communication::send_unmapped(const char *local_port
,
1056 const char *system_port
)
1059 text_buf
.push_int(MSG_UNMAPPED
);
1060 text_buf
.push_string(local_port
);
1061 text_buf
.push_string(system_port
);
1062 send_message(text_buf
);
1065 void TTCN_Communication::send_mtc_created()
1068 text_buf
.push_int(MSG_MTC_CREATED
);
1069 send_message(text_buf
);
1072 void TTCN_Communication::send_testcase_started(const char *testcase_module
,
1073 const char *testcase_name
, const char *mtc_comptype_module
,
1074 const char *mtc_comptype_name
, const char *system_comptype_module
,
1075 const char *system_comptype_name
)
1078 text_buf
.push_int(MSG_TESTCASE_STARTED
);
1079 text_buf
.push_string(testcase_module
);
1080 text_buf
.push_string(testcase_name
);
1081 text_buf
.push_string(mtc_comptype_module
);
1082 text_buf
.push_string(mtc_comptype_name
);
1083 text_buf
.push_string(system_comptype_module
);
1084 text_buf
.push_string(system_comptype_name
);
1085 send_message(text_buf
);
1088 void TTCN_Communication::send_testcase_finished(verdicttype final_verdict
,
1092 text_buf
.push_int(MSG_TESTCASE_FINISHED
);
1093 text_buf
.push_int(final_verdict
);
1094 text_buf
.push_string(reason
);
1095 send_message(text_buf
);
1098 void TTCN_Communication::send_mtc_ready()
1101 text_buf
.push_int(MSG_MTC_READY
);
1102 send_message(text_buf
);
1105 void TTCN_Communication::send_ptc_created(component component_reference
)
1108 text_buf
.push_int(MSG_PTC_CREATED
);
1109 text_buf
.push_int(component_reference
);
1110 send_message(text_buf
);
1113 void TTCN_Communication::prepare_stopped(Text_Buf
& text_buf
,
1114 const char *return_type
)
1116 text_buf
.push_int(MSG_STOPPED
);
1117 text_buf
.push_string(return_type
);
1120 void TTCN_Communication::send_stopped()
1123 text_buf
.push_int(MSG_STOPPED
);
1124 // add an empty return type
1125 text_buf
.push_string(NULL
);
1126 send_message(text_buf
);
1129 void TTCN_Communication::prepare_stopped_killed(Text_Buf
& text_buf
,
1130 verdicttype final_verdict
, const char *return_type
, const char* reason
)
1132 text_buf
.push_int(MSG_STOPPED_KILLED
);
1133 text_buf
.push_int(final_verdict
);
1134 text_buf
.push_string(reason
);
1135 text_buf
.push_string(return_type
);
1138 void TTCN_Communication::send_stopped_killed(verdicttype final_verdict
,
1142 text_buf
.push_int(MSG_STOPPED_KILLED
);
1143 text_buf
.push_int(final_verdict
);
1144 text_buf
.push_string(reason
);
1145 // add an empty return type
1146 text_buf
.push_string(NULL
);
1147 send_message(text_buf
);
1150 void TTCN_Communication::send_killed(verdicttype final_verdict
,
1154 text_buf
.push_int(MSG_KILLED
);
1155 text_buf
.push_int(final_verdict
);
1156 text_buf
.push_string(reason
);
1157 send_message(text_buf
);
1160 void TTCN_Communication::send_debug_return_value(int return_type
, const char* message
)
1163 text_buf
.push_int(MSG_DEBUG_RETURN_VALUE
);
1164 text_buf
.push_int(return_type
);
1165 if (message
!= NULL
) {
1167 gettimeofday(&tv
, NULL
);
1168 text_buf
.push_int(tv
.tv_sec
);
1169 text_buf
.push_int(tv
.tv_usec
);
1170 text_buf
.push_string(message
);
1172 send_message(text_buf
);
1175 void TTCN_Communication::send_debug_halt_req()
1178 text_buf
.push_int(MSG_DEBUG_HALT_REQ
);
1179 send_message(text_buf
);
1182 void TTCN_Communication::send_debug_continue_req()
1185 text_buf
.push_int(MSG_DEBUG_CONTINUE_REQ
);
1186 send_message(text_buf
);
1189 void TTCN_Communication::send_debug_batch(const char* batch_file
)
1192 text_buf
.push_int(MSG_DEBUG_BATCH
);
1193 text_buf
.push_string(batch_file
);
1194 send_message(text_buf
);
1197 boolean
TTCN_Communication::send_log(time_t timestamp_sec
, long timestamp_usec
,
1198 unsigned int event_severity
, size_t message_text_len
,
1199 const char *message_text
)
1203 text_buf
.push_int(MSG_LOG
);
1204 text_buf
.push_int(timestamp_sec
);
1205 text_buf
.push_int(timestamp_usec
);
1206 text_buf
.push_int(event_severity
);
1207 text_buf
.push_int(message_text_len
);
1208 text_buf
.push_raw(message_text_len
, message_text
);
1209 send_message(text_buf
);
1210 /* If an ERROR message (indicating a version mismatch) arrives from MC
1211 in state HC_IDLE (i.e. before CONFIGURE) it shall be
1212 printed to the console as well. */
1213 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_IDLE
) return FALSE
;
1216 switch (TTCN_Runtime::get_state()) {
1217 case TTCN_Runtime::HC_EXIT
:
1218 case TTCN_Runtime::MTC_INITIAL
:
1219 case TTCN_Runtime::MTC_EXIT
:
1220 case TTCN_Runtime::PTC_INITIAL
:
1221 case TTCN_Runtime::PTC_EXIT
:
1222 /* Do not print the first/last few lines of logs to the console
1223 even if ConsoleMask is set to LOG_ALL */
1231 void TTCN_Communication::send_error(const char *fmt_str
, ...)
1234 va_start(ap
, fmt_str
);
1235 char *error_str
= mprintf_va_list(fmt_str
, ap
);
1238 text_buf
.push_int((RInt
)MSG_ERROR
);
1239 text_buf
.push_string(error_str
);
1241 send_message(text_buf
);
1244 void TTCN_Communication::send_message(Text_Buf
& text_buf
)
1246 if (!is_connected
) TTCN_error("Trying to send a message to MC, but the "
1247 "control connection is down.");
1248 text_buf
.calculate_length();
1249 const char *msg_ptr
= text_buf
.get_data();
1250 size_t msg_len
= text_buf
.get_len(), sent_len
= 0;
1251 while (sent_len
< msg_len
) {
1252 int ret_val
= send(mc_fd
, msg_ptr
+ sent_len
, msg_len
- sent_len
, 0);
1253 if (ret_val
> 0) sent_len
+= ret_val
;
1257 // a signal occurred: do nothing, just try again
1261 close_mc_connection();
1262 TTCN_error("Sending data on the control connection to MC "
1269 void TTCN_Communication::process_configure(int msg_end
, bool to_mtc
)
1271 switch (TTCN_Runtime::get_state()) {
1272 case TTCN_Runtime::HC_IDLE
:
1273 case TTCN_Runtime::HC_ACTIVE
:
1274 case TTCN_Runtime::HC_OVERLOADED
:
1279 case TTCN_Runtime::MTC_IDLE
:
1285 incoming_buf
.cut_message();
1286 send_error("Message CONFIGURE arrived in invalid state.");
1290 TTCN_Runtime::set_state(to_mtc
? TTCN_Runtime::MTC_CONFIGURING
: TTCN_Runtime::HC_CONFIGURING
);
1291 TTCN_Logger::log_configdata(TitanLoggerApiSimple::ExecutorConfigdata_reason::received__from__mc
);
1293 // take the config string directly from the buffer for efficiency reasons
1294 int config_str_len
= incoming_buf
.pull_int().get_val();
1295 int config_str_begin
= incoming_buf
.get_pos();
1296 if (config_str_begin
+ config_str_len
!= msg_end
) {
1297 incoming_buf
.cut_message();
1298 send_error("Malformed message CONFIGURE was received.");
1301 const char *config_str
= incoming_buf
.get_data() + config_str_begin
;
1302 boolean success
= process_config_string(config_str
, config_str_len
);
1304 // Only non component specific settings will be applied. The plug-ins need
1305 // to be loaded due to resetting.
1306 TTCN_Logger::load_plugins(NULL_COMPREF
, "");
1307 TTCN_Logger::set_plugin_parameters(NULL_COMPREF
, "");
1308 TTCN_Logger::open_file();
1311 Module_List::log_param();
1312 Module_List::post_init_modules();
1313 } catch (const TC_Error
& TC_error
) {
1314 TTCN_Logger::log_executor_runtime(
1315 TitanLoggerApiSimple::ExecutorRuntime_reason::initialization__of__modules__failed
);
1319 TTCN_Logger::log_configdata(
1320 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__failed
, NULL
);
1324 send_configure_ack();
1325 TTCN_Runtime::set_state(to_mtc
? TTCN_Runtime::MTC_IDLE
: TTCN_Runtime::HC_ACTIVE
);
1326 TTCN_Logger::log_configdata(
1327 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__succeeded
);
1329 send_configure_nak();
1330 TTCN_Runtime::set_state(to_mtc
? TTCN_Runtime::MTC_IDLE
: TTCN_Runtime::HC_IDLE
);
1333 incoming_buf
.cut_message();
1336 void TTCN_Communication::process_create_mtc()
1338 incoming_buf
.cut_message();
1339 TTCN_Runtime::process_create_mtc();
1342 void TTCN_Communication::process_create_ptc()
1344 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1345 if (component_reference
< FIRST_PTC_COMPREF
) {
1346 incoming_buf
.cut_message();
1347 send_error("Message CREATE_PTC refers to invalid "
1348 "component reference %d.", component_reference
);
1351 qualified_name component_type
;
1352 incoming_buf
.pull_qualified_name(component_type
);
1353 if (component_type
.module_name
== NULL
||
1354 component_type
.definition_name
== NULL
) {
1355 incoming_buf
.cut_message();
1356 delete [] component_type
.module_name
;
1357 delete [] component_type
.definition_name
;
1358 send_error("Message CREATE_PTC with component reference %d contains "
1359 "an invalid component type.", component_reference
);
1362 char *component_name
= incoming_buf
.pull_string();
1363 boolean is_alive
= incoming_buf
.pull_int().get_val();
1364 qualified_name current_testcase
;
1365 incoming_buf
.pull_qualified_name(current_testcase
);
1366 incoming_buf
.cut_message();
1369 TTCN_Runtime::process_create_ptc(component_reference
,
1370 component_type
.module_name
, component_type
.definition_name
,
1371 component_name
, is_alive
, current_testcase
.module_name
,
1372 current_testcase
.definition_name
);
1374 // to prevent from memory leaks
1375 delete [] component_type
.module_name
;
1376 delete [] component_type
.definition_name
;
1377 delete [] component_name
;
1378 delete [] current_testcase
.module_name
;
1379 delete [] current_testcase
.definition_name
;
1383 delete [] component_type
.module_name
;
1384 delete [] component_type
.definition_name
;
1385 delete [] component_name
;
1386 delete [] current_testcase
.module_name
;
1387 delete [] current_testcase
.definition_name
;
1390 void TTCN_Communication::process_kill_process()
1392 component component_reference
= (component
)incoming_buf
.pull_int().get_val();
1393 incoming_buf
.cut_message();
1394 TTCN_Runtime::process_kill_process(component_reference
);
1397 void TTCN_Communication::process_exit_hc()
1399 incoming_buf
.cut_message();
1400 TTCN_Logger::log_executor_runtime(
1401 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__hc
);
1402 TTCN_Runtime::set_state(TTCN_Runtime::HC_EXIT
);
1405 void TTCN_Communication::process_create_ack()
1407 component component_reference
= incoming_buf
.pull_int().get_val();
1408 incoming_buf
.cut_message();
1409 TTCN_Runtime::process_create_ack(component_reference
);
1412 void TTCN_Communication::process_start_ack()
1414 incoming_buf
.cut_message();
1416 switch (TTCN_Runtime::get_state()) {
1417 case TTCN_Runtime::MTC_START
:
1418 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1419 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1421 case TTCN_Runtime::PTC_START
:
1422 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1425 TTCN_error("Internal error: Message START_ACK arrived in invalid "
1430 void TTCN_Communication::process_stop()
1432 incoming_buf
.cut_message();
1433 switch (TTCN_Runtime::get_state()) {
1434 case TTCN_Runtime::MTC_IDLE
:
1435 TTCN_Logger::log_executor_runtime(
1436 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__mtc
);
1438 case TTCN_Runtime::MTC_PAUSED
:
1439 TTCN_Logger::log_executor_runtime(
1440 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1441 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TERMINATING_EXECUTION
);
1443 case TTCN_Runtime::PTC_IDLE
:
1444 case TTCN_Runtime::PTC_STOPPED
:
1445 TTCN_Logger::log_executor_runtime(
1446 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__ptc
);
1448 case TTCN_Runtime::PTC_EXIT
:
1452 TTCN_Logger::log_executor_runtime(
1453 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc
);
1454 TTCN_Runtime::stop_execution();
1459 void TTCN_Communication::process_stop_ack()
1461 incoming_buf
.cut_message();
1462 switch (TTCN_Runtime::get_state()) {
1463 case TTCN_Runtime::MTC_STOP
:
1464 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1465 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1467 case TTCN_Runtime::PTC_STOP
:
1468 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1471 TTCN_error("Internal error: Message STOP_ACK arrived in invalid "
1476 void TTCN_Communication::process_kill_ack()
1478 incoming_buf
.cut_message();
1479 switch (TTCN_Runtime::get_state()) {
1480 case TTCN_Runtime::MTC_KILL
:
1481 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1482 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1484 case TTCN_Runtime::PTC_KILL
:
1485 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1488 TTCN_error("Internal error: Message KILL_ACK arrived in invalid "
1493 void TTCN_Communication::process_running()
1495 boolean answer
= incoming_buf
.pull_int().get_val();
1496 incoming_buf
.cut_message();
1497 TTCN_Runtime::process_running(answer
);
1500 void TTCN_Communication::process_alive()
1502 boolean answer
= incoming_buf
.pull_int().get_val();
1503 incoming_buf
.cut_message();
1504 TTCN_Runtime::process_alive(answer
);
1507 void TTCN_Communication::process_done_ack(int msg_end
)
1509 // decoding the mandatory attributes
1510 boolean answer
= incoming_buf
.pull_int().get_val();
1511 char *return_type
= incoming_buf
.pull_string();
1512 // the return value starts here
1513 int return_value_begin
= incoming_buf
.get_pos();
1516 TTCN_Runtime::process_done_ack(answer
, return_type
,
1517 msg_end
- return_value_begin
,
1518 incoming_buf
.get_data() + return_value_begin
);
1520 // avoid memory leaks in case of error
1521 incoming_buf
.cut_message();
1522 delete [] return_type
;
1526 incoming_buf
.cut_message();
1527 delete [] return_type
;
1530 void TTCN_Communication::process_killed_ack()
1532 boolean answer
= incoming_buf
.pull_int().get_val();
1533 incoming_buf
.cut_message();
1534 TTCN_Runtime::process_killed_ack(answer
);
1537 void TTCN_Communication::process_cancel_done_mtc()
1539 component component_reference
= incoming_buf
.pull_int().get_val();
1540 boolean cancel_any
= incoming_buf
.pull_int().get_val();
1541 incoming_buf
.cut_message();
1542 TTCN_Runtime::cancel_component_done(component_reference
);
1543 if (cancel_any
) TTCN_Runtime::cancel_component_done(ANY_COMPREF
);
1544 send_cancel_done_ack(component_reference
);
1547 void TTCN_Communication::process_cancel_done_ptc()
1549 component component_reference
= incoming_buf
.pull_int().get_val();
1550 incoming_buf
.cut_message();
1551 TTCN_Runtime::cancel_component_done(component_reference
);
1552 send_cancel_done_ack(component_reference
);
1555 void TTCN_Communication::process_component_status_mtc(int msg_end
)
1557 // decoding the mandatory attributes
1558 component component_reference
= incoming_buf
.pull_int().get_val();
1559 boolean is_done
= incoming_buf
.pull_int().get_val();
1560 boolean is_killed
= incoming_buf
.pull_int().get_val();
1561 boolean is_any_done
= incoming_buf
.pull_int().get_val();
1562 boolean is_all_done
= incoming_buf
.pull_int().get_val();
1563 boolean is_any_killed
= incoming_buf
.pull_int().get_val();
1564 boolean is_all_killed
= incoming_buf
.pull_int().get_val();
1566 // the return type and value is valid
1567 char *return_type
= incoming_buf
.pull_string();
1568 int return_value_begin
= incoming_buf
.get_pos();
1570 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1571 msg_end
- return_value_begin
,
1572 incoming_buf
.get_data() + return_value_begin
);
1574 // avoid memory leaks
1575 incoming_buf
.cut_message();
1576 delete [] return_type
;
1579 delete [] return_type
;
1581 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1583 TTCN_Runtime::set_component_done(ANY_COMPREF
, NULL
, 0, NULL
);
1585 TTCN_Runtime::set_component_done(ALL_COMPREF
, NULL
, 0, NULL
);
1586 if (is_any_killed
) TTCN_Runtime::set_component_killed(ANY_COMPREF
);
1587 if (is_all_killed
) TTCN_Runtime::set_component_killed(ALL_COMPREF
);
1588 incoming_buf
.cut_message();
1589 if (!is_done
&& !is_killed
&& (component_reference
!= NULL_COMPREF
||
1590 (!is_any_done
&& !is_all_done
&& !is_any_killed
&& !is_all_killed
)))
1591 TTCN_error("Internal error: Malformed COMPONENT_STATUS message was "
1595 void TTCN_Communication::process_component_status_ptc(int msg_end
)
1597 // decoding the mandatory attributes
1598 component component_reference
= incoming_buf
.pull_int().get_val();
1599 boolean is_done
= incoming_buf
.pull_int().get_val();
1600 boolean is_killed
= incoming_buf
.pull_int().get_val();
1602 // the return type and value is valid
1603 char *return_type
= incoming_buf
.pull_string();
1604 int return_value_begin
= incoming_buf
.get_pos();
1606 TTCN_Runtime::set_component_done(component_reference
, return_type
,
1607 msg_end
- return_value_begin
,
1608 incoming_buf
.get_data() + return_value_begin
);
1610 // avoid memory leaks
1611 incoming_buf
.cut_message();
1612 delete [] return_type
;
1615 delete [] return_type
;
1617 if (is_killed
) TTCN_Runtime::set_component_killed(component_reference
);
1618 incoming_buf
.cut_message();
1619 if (!is_done
&& !is_killed
) TTCN_error("Internal error: Malformed "
1620 "COMPONENT_STATUS message was received.");
1623 void TTCN_Communication::process_connect_listen()
1625 char *local_port
= incoming_buf
.pull_string();
1626 component remote_component
= incoming_buf
.pull_int().get_val();
1627 char *remote_component_name
= incoming_buf
.pull_string();
1628 char *remote_port
= incoming_buf
.pull_string();
1629 transport_type_enum transport_type
=
1630 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1631 incoming_buf
.cut_message();
1634 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1635 COMPONENT::register_component_name(remote_component
,
1636 remote_component_name
);
1637 PORT::process_connect_listen(local_port
, remote_component
, remote_port
,
1640 delete [] local_port
;
1641 delete [] remote_component_name
;
1642 delete [] remote_port
;
1646 delete [] local_port
;
1647 delete [] remote_component_name
;
1648 delete [] remote_port
;
1651 void TTCN_Communication::process_connect()
1653 char *local_port
= incoming_buf
.pull_string();
1654 component remote_component
= incoming_buf
.pull_int().get_val();
1655 char *remote_component_name
= incoming_buf
.pull_string();
1656 char *remote_port
= incoming_buf
.pull_string();
1657 transport_type_enum transport_type
=
1658 (transport_type_enum
)incoming_buf
.pull_int().get_val();
1661 if (remote_component
!= MTC_COMPREF
&& self
!= remote_component
)
1662 COMPONENT::register_component_name(remote_component
,
1663 remote_component_name
);
1664 PORT::process_connect(local_port
, remote_component
, remote_port
,
1665 transport_type
, incoming_buf
);
1667 incoming_buf
.cut_message();
1668 delete [] local_port
;
1669 delete [] remote_component_name
;
1670 delete [] remote_port
;
1674 incoming_buf
.cut_message();
1675 delete [] local_port
;
1676 delete [] remote_component_name
;
1677 delete [] remote_port
;
1680 void TTCN_Communication::process_connect_ack()
1682 incoming_buf
.cut_message();
1684 switch (TTCN_Runtime::get_state()) {
1685 case TTCN_Runtime::MTC_CONNECT
:
1686 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1687 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1689 case TTCN_Runtime::PTC_CONNECT
:
1690 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1693 TTCN_error("Internal error: Message CONNECT_ACK arrived in invalid "
1698 void TTCN_Communication::process_disconnect()
1700 char *local_port
= incoming_buf
.pull_string();
1701 component remote_component
= incoming_buf
.pull_int().get_val();
1702 char *remote_port
= incoming_buf
.pull_string();
1703 incoming_buf
.cut_message();
1706 PORT::process_disconnect(local_port
, remote_component
, remote_port
);
1708 delete [] local_port
;
1709 delete [] remote_port
;
1713 delete [] local_port
;
1714 delete [] remote_port
;
1717 void TTCN_Communication::process_disconnect_ack()
1719 incoming_buf
.cut_message();
1721 switch (TTCN_Runtime::get_state()) {
1722 case TTCN_Runtime::MTC_DISCONNECT
:
1723 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1724 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1726 case TTCN_Runtime::PTC_DISCONNECT
:
1727 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1730 TTCN_error("Internal error: Message DISCONNECT_ACK arrived in invalid "
1735 void TTCN_Communication::process_map()
1737 char *local_port
= incoming_buf
.pull_string();
1738 char *system_port
= incoming_buf
.pull_string();
1739 incoming_buf
.cut_message();
1742 PORT::map_port(local_port
, system_port
);
1744 delete [] local_port
;
1745 delete [] system_port
;
1749 delete [] local_port
;
1750 delete [] system_port
;
1753 void TTCN_Communication::process_map_ack()
1755 incoming_buf
.cut_message();
1757 switch (TTCN_Runtime::get_state()) {
1758 case TTCN_Runtime::MTC_MAP
:
1759 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1760 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1762 case TTCN_Runtime::PTC_MAP
:
1763 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1766 TTCN_error("Internal error: Message MAP_ACK arrived in invalid state.");
1770 void TTCN_Communication::process_unmap()
1772 char *local_port
= incoming_buf
.pull_string();
1773 char *system_port
= incoming_buf
.pull_string();
1774 incoming_buf
.cut_message();
1777 PORT::unmap_port(local_port
, system_port
);
1779 delete [] local_port
;
1780 delete [] system_port
;
1784 delete [] local_port
;
1785 delete [] system_port
;
1788 void TTCN_Communication::process_unmap_ack()
1790 incoming_buf
.cut_message();
1792 switch(TTCN_Runtime::get_state()){
1793 case TTCN_Runtime::MTC_UNMAP
:
1794 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE
);
1795 case TTCN_Runtime::MTC_TERMINATING_TESTCASE
:
1797 case TTCN_Runtime::PTC_UNMAP
:
1798 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION
);
1801 TTCN_error("Internal error: Message UNMAP_ACK arrived in invalid "
1806 void TTCN_Communication::process_execute_control()
1808 char *module_name
= incoming_buf
.pull_string();
1809 incoming_buf
.cut_message();
1811 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1812 delete [] module_name
;
1813 TTCN_error("Internal error: Message EXECUTE_CONTROL arrived in "
1817 TTCN_Logger::log(TTCN_Logger::PARALLEL_UNQUALIFIED
,
1818 "Executing control part of module %s.", module_name
);
1820 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1823 Module_List::execute_control(module_name
);
1824 } catch (const TC_End
& TC_end
) {
1825 } catch (const TC_Error
& TC_error
) {
1828 delete [] module_name
;
1832 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1833 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1836 void TTCN_Communication::process_execute_testcase()
1838 char *module_name
= incoming_buf
.pull_string();
1839 char *testcase_name
= incoming_buf
.pull_string();
1840 incoming_buf
.cut_message();
1842 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE
) {
1843 delete [] module_name
;
1844 delete [] testcase_name
;
1845 TTCN_error("Internal error: Message EXECUTE_TESTCASE arrived in "
1849 TTCN_Logger::log_testcase_exec(testcase_name
, module_name
);
1851 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1854 if (testcase_name
!= NULL
&& testcase_name
[0] != '\0')
1855 Module_List::execute_testcase(module_name
, testcase_name
);
1856 else Module_List::execute_all_testcases(module_name
);
1857 } catch (const TC_End
& TC_end
) {
1858 } catch (const TC_Error
& TC_error
) {
1863 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE
);
1864 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1866 delete [] module_name
;
1867 delete [] testcase_name
;
1870 void TTCN_Communication::process_ptc_verdict()
1872 TTCN_Runtime::process_ptc_verdict(incoming_buf
);
1873 incoming_buf
.cut_message();
1876 void TTCN_Communication::process_continue()
1878 incoming_buf
.cut_message();
1880 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_PAUSED
)
1881 TTCN_error("Internal error: Message CONTINUE arrived in invalid "
1884 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART
);
1887 void TTCN_Communication::process_exit_mtc()
1889 incoming_buf
.cut_message();
1890 TTCN_Runtime::log_verdict_statistics();
1891 TTCN_Logger::log_executor_runtime(
1892 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__mtc
);
1893 TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT
);
1896 void TTCN_Communication::process_start()
1898 qualified_name function_name
;
1899 incoming_buf
.pull_qualified_name(function_name
);
1900 if (function_name
.module_name
== NULL
||
1901 function_name
.definition_name
== NULL
) {
1902 incoming_buf
.cut_message();
1903 delete [] function_name
.module_name
;
1904 delete [] function_name
.definition_name
;
1905 TTCN_error("Internal error: Message START contains an invalid "
1910 TTCN_Runtime::start_function(function_name
.module_name
,
1911 function_name
.definition_name
, incoming_buf
);
1913 // avoid memory leaks
1914 delete [] function_name
.module_name
;
1915 delete [] function_name
.definition_name
;
1919 delete [] function_name
.module_name
;
1920 delete [] function_name
.definition_name
;
1923 void TTCN_Communication::process_kill()
1925 incoming_buf
.cut_message();
1926 TTCN_Runtime::process_kill();
1929 void TTCN_Communication::process_error()
1931 char *error_string
= incoming_buf
.pull_string();
1932 incoming_buf
.cut_message();
1935 TTCN_error("Error message was received from MC: %s", error_string
);
1937 delete [] error_string
;
1942 void TTCN_Communication::process_unsupported_message(int msg_type
, int msg_end
)
1944 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED
);
1945 TTCN_Logger::log_event("Unsupported message was received from MC: "
1946 "type (decimal): %d, data (hexadecimal): ", msg_type
);
1947 const unsigned char *msg_ptr
=
1948 (const unsigned char*)incoming_buf
.get_data();
1949 for (int i
= incoming_buf
.get_pos(); i
< msg_end
; i
++)
1950 TTCN_Logger::log_octet(msg_ptr
[i
]);
1951 TTCN_Logger::end_event();
1952 incoming_buf
.cut_message();
1955 void TTCN_Communication::process_debug_command()
1957 int command
= incoming_buf
.pull_int().get_val();
1958 int argument_count
= incoming_buf
.pull_int().get_val();
1959 char** arguments
= NULL
;
1960 if (argument_count
> 0) {
1961 arguments
= new char*[argument_count
];
1962 for (int i
= 0; i
< argument_count
; ++i
) {
1963 arguments
[i
] = incoming_buf
.pull_string();
1966 incoming_buf
.cut_message();
1967 ttcn3_debugger
.execute_command(command
, argument_count
, arguments
);
1968 if (argument_count
> 0) {
1969 for (int i
= 0; i
< argument_count
; ++i
) {
1970 delete [] arguments
[i
];
1972 delete [] arguments
;
1976 /* * * * Temporary squatting place because it includes version.h * * * */
1978 const struct runtime_version current_runtime_version
= {
1979 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
, TITAN_RUNTIME_NR
1982 static const char *runtime_name
[] = { 0, "load", "function " };
1984 RuntimeVersionChecker::RuntimeVersionChecker(
1985 int ver_major
, int ver_minor
, int patch_level
, int rt
)
1987 if ( TTCN3_MAJOR
!= ver_major
1988 || TTCN3_MINOR
!= ver_minor
1989 || TTCN3_PATCHLEVEL
!= patch_level
)
1992 "Version mismatch detected: generated code %d.%d.pl%d, "
1993 "runtime is %d.%d.pl%d",
1994 ver_major
, ver_minor
, patch_level
,
1995 TTCN3_MAJOR
, TTCN3_MINOR
, TTCN3_PATCHLEVEL
);
1998 if (TITAN_RUNTIME_NR
!= rt
) {
1999 TTCN_error("Runtime mismatch detected: files compiled for the %stest"
2000 " runtime cannot be linked to %stest library",
2001 runtime_name
[TITAN_RUNTIME_NR
], runtime_name
[rt
]);
2005 reffer::reffer(const char*) {}