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