Sync with 5.4.0
[deliverable/titan.core.git] / core / Communication.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "Communication.hh"
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <netdb.h>
17
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/utsname.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <arpa/inet.h>
24 #include <sys/un.h>
25
26 #include "../common/dbgnew.hh"
27 #include "Types.h"
28 #include "Message_types.hh"
29 #include "Module_list.hh"
30 #include "Verdicttype.hh"
31 #include "Fd_And_Timeout_User.hh"
32 #include "Runtime.hh"
33 #include "Logger.hh"
34 #include "Port.hh"
35 #include "Component.hh"
36
37 #include "TitanLoggerApiSimple.hh"
38 #include "../common/version.h"
39
40 #include "Event_Handler.hh"
41
42 class MC_Connection : public Fd_And_Timeout_Event_Handler {
43 virtual void Handle_Fd_Event(int fd,
44 boolean is_readable, boolean is_writable, boolean is_error);
45 virtual void Handle_Timeout(double time_since_last_call);
46 public:
47 MC_Connection(const int * fd, Text_Buf * buf) :
48 Fd_And_Timeout_Event_Handler(), mc_fd(fd), incoming_buf(buf) {}
49 virtual void log() const;
50 private:
51 const int * mc_fd;
52 Text_Buf * incoming_buf;
53 };
54
55 int TTCN_Communication::mc_fd = -1;
56 HCNetworkHandler TTCN_Communication::hcnh;
57 boolean TTCN_Communication::local_addr_set = FALSE,
58 TTCN_Communication::mc_addr_set = FALSE,
59 TTCN_Communication::is_connected = FALSE;
60 Text_Buf TTCN_Communication::incoming_buf;
61 MC_Connection TTCN_Communication::mc_connection(
62 &TTCN_Communication::mc_fd, &TTCN_Communication::incoming_buf);
63 double TTCN_Communication::call_interval = 0.0;
64
65 void TTCN_Communication::set_local_address(const char *host_name)
66 {
67 if (local_addr_set)
68 TTCN_warning("The local address has already been set.");
69 if (is_connected)
70 TTCN_error("Trying to change the local address, but there is an existing "
71 "control connection to MC.");
72 if (host_name == NULL){
73 fprintf(stderr,"TTCN_Communication::set_local_address: internal error: " // There is no connection to the MC
74 "invalid host name.\r\n"); // We should log to the console also
75 TTCN_error("TTCN_Communication::set_local_address: internal error: "
76 "invalid host name.");
77 }
78 if (!hcnh.set_local_addr(host_name, 0)){
79 fprintf(stderr,"Could not get the IP address for the local address " // There is no connection to the MC
80 "(%s): Host name lookup failure.\r\n", host_name); // We should log to the console also
81 TTCN_error("Could not get the IP address for the local address "
82 "(%s): Host name lookup failure.", host_name);
83 }
84 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::local__address__was__set,
85 hcnh.get_local_host_str(), hcnh.get_local_addr_str(), 0);
86 local_addr_set = TRUE;
87 }
88
89 const IPAddress *TTCN_Communication::get_local_address()
90 {
91 if (!local_addr_set)
92 TTCN_error("TTCN_Communication::get_local_address: internal error: the "
93 "local address has not been set.");
94 return hcnh.get_local_addr();
95 }
96
97 void TTCN_Communication::set_mc_address(const char *host_name,
98 unsigned short tcp_port)
99 {
100 if (mc_addr_set)
101 TTCN_warning("The address of MC has already been set.");
102 if (is_connected)
103 TTCN_error("Trying to change the address of MC, but there is an existing connection.");
104 if (host_name == NULL){
105 fprintf(stderr,"TTCN_Communication::set_mc_address: internal error: invalid host name.\r\n");
106 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid host name.");
107 }
108 if (tcp_port <= 0){
109 fprintf(stderr,"TTCN_Communication::set_mc_address: internal error: invalid TCP port. %hu\r\n",tcp_port);
110 TTCN_error("TTCN_Communication::set_mc_address: internal error: invalid TCP port.");
111 }
112 hcnh.set_family(host_name);
113 if (!hcnh.set_mc_addr(host_name, tcp_port)){
114 fprintf(stderr,"Could not get the IP address of MC (%s): Host name lookup "
115 "failure.\r\n", host_name);
116 TTCN_error("Could not get the IP address of MC (%s): Host name lookup "
117 "failure.", host_name);
118 }
119 if ((hcnh.get_mc_addr())->is_local()){
120 fprintf(stderr,"The address of MC was set to a local IP address. This may "
121 "cause incorrect behavior if a HC from a remote host also "
122 "connects to MC.\r\n");
123 TTCN_warning("The address of MC was set to a local IP address. This may "
124 "cause incorrect behavior if a HC from a remote host also "
125 "connects to MC.");
126 }
127 TTCN_Logger::log_executor_misc(TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__mc__was__set,
128 hcnh.get_mc_host_str(), hcnh.get_mc_addr_str(), 0);
129 mc_addr_set = TRUE;
130 }
131
132 const IPAddress *TTCN_Communication::get_mc_address()
133 {
134 if (!mc_addr_set)
135 TTCN_error("TTCN_Communication::get_mc_address: internal error: the "
136 "address of MC has not been set.");
137 return hcnh.get_mc_addr();
138 }
139
140 bool TTCN_Communication::is_mc_connected()
141 {
142 return is_connected;
143 }
144
145 void TTCN_Communication::connect_mc()
146 {
147 if (is_connected) TTCN_error("Trying to re-connect to MC, but there is an "
148 "existing connection.");
149 if (!mc_addr_set) TTCN_error("Trying to connect to MC, but the address of "
150 "MC has not yet been set.");
151
152 // Trying to connect to local mc through unix domain socket
153 // TODO: Disable if config file parameter is set
154 if ((hcnh.get_mc_addr())->is_local()
155 || (local_addr_set && *(hcnh.get_mc_addr()) == *(hcnh.get_local_addr()))) {
156 sockaddr_un localaddr_unix;
157 memset(&localaddr_unix, 0, sizeof(localaddr_unix));
158 localaddr_unix.sun_family = AF_UNIX;
159 snprintf(localaddr_unix.sun_path, sizeof(localaddr_unix.sun_path),
160 "/tmp/ttcn3-mctr-%u", hcnh.get_mc_port());
161 mc_fd = socket(PF_UNIX, SOCK_STREAM, 0);
162 if (mc_fd >= (int)FD_SETSIZE) {
163 close(mc_fd);
164 } else if (mc_fd >= 0) {
165 if (connect(mc_fd, (struct sockaddr*)&localaddr_unix,
166 sizeof(localaddr_unix)) == 0) {
167 goto unix_end; // connected successfully
168 } else {
169 close(mc_fd);
170 }
171 }
172 }
173
174 #ifdef WIN32
175 again:
176 #endif
177 mc_fd = hcnh.socket();
178 if (mc_fd < 0) {
179 fprintf(stderr,"Socket creation failed when connecting to MC.");
180 TTCN_error("Socket creation failed when connecting to MC.");
181 }
182 else if (mc_fd >= (int)FD_SETSIZE) {
183 close(mc_fd);
184 fprintf(stderr,"When connecting to MC: "
185 "The file descriptor returned by the operating system (%d) is "
186 "too large for use with the select() system call.\r\n", mc_fd);
187 TTCN_error("When connecting to MC: "
188 "The file descriptor returned by the operating system (%d) is "
189 "too large for use with the select() system call.", mc_fd);
190 }
191
192 if (local_addr_set) {
193 if (hcnh.bind_local_addr(mc_fd)) {
194 fprintf(stderr,"Binding IP address %s to the local endpoint of the "
195 "control connection failed when connecting to MC.\r\n", hcnh.get_local_addr_str());
196 TTCN_error("Binding IP address %s to the local endpoint of the "
197 "control connection failed when connecting to MC.",
198 hcnh.get_local_addr_str());
199 close(mc_fd);
200 }
201 }
202
203 if (hcnh.connect_to_mc(mc_fd)) {
204 #ifdef WIN32
205 if (errno == EADDRINUSE) {
206 close(mc_fd);
207 errno = 0;
208 TTCN_warning("connect() returned error code EADDRINUSE. "
209 "Perhaps this is a Cygwin bug. Trying to connect again.");
210 goto again;
211 }
212 #endif
213 fprintf(stderr,"Connecting to MC failed. MC address: %s:%hu %s\r\n",hcnh.get_mc_addr_str(),hcnh.get_mc_port(),strerror(errno));
214 TTCN_error("Connecting to MC failed.");
215 close(mc_fd);
216 }
217
218 if (!local_addr_set) {
219 if (hcnh.getsockname_local_addr(mc_fd)) {
220 close(mc_fd);
221 TTCN_error("getsockname() system call failed on the socket of the "
222 "control connection to MC.");
223 }
224 TTCN_Logger::log_executor_misc(
225 TitanLoggerApiSimple::ExecutorUnqualified_reason::address__of__control__connection,
226 NULL, hcnh.get_local_addr_str(), 0);
227 local_addr_set = TRUE;
228 }
229
230 if (!set_tcp_nodelay(mc_fd)) {
231 close(mc_fd);
232 TTCN_error("Setting the TCP_NODELAY flag failed on the socket of "
233 "the control connection to MC.");
234 }
235
236 unix_end:
237
238 if (!set_close_on_exec(mc_fd)) {
239 close(mc_fd);
240 TTCN_error("Setting the close-on-exec flag failed on the socket of "
241 "the control connection to MC.");
242 }
243
244 Fd_And_Timeout_User::add_fd(mc_fd, &mc_connection, FD_EVENT_RD);
245
246 TTCN_Logger::log_executor_runtime(
247 TitanLoggerApiSimple::ExecutorRuntime_reason::connected__to__mc);
248
249 is_connected = TRUE;
250 }
251
252 void TTCN_Communication::disconnect_mc()
253 {
254 if (is_connected) {
255 shutdown(mc_fd, 1);
256 int recv_len;
257 do {
258 char buf[1024];
259 recv_len = recv(mc_fd, buf, sizeof(buf), 0);
260 } while (recv_len > 0);
261 errno = 0;
262 close_mc_connection();
263 TTCN_Logger::log_executor_runtime(
264 TitanLoggerApiSimple::ExecutorRuntime_reason::disconnected__from__mc);
265 }
266 }
267
268 void TTCN_Communication::close_mc_connection()
269 {
270 if (is_connected) {
271 int tmp_mc_fd = mc_fd;
272 call_interval = 0.0;
273 close(mc_fd);
274 mc_fd = -1;
275 is_connected = FALSE;
276 incoming_buf.reset();
277 // Removing the fd has to be done after closing the mc connection
278 // to prevent segmentation fault or broken pipe error
279 // in case remove_fd would try to print an error log.
280 Fd_And_Timeout_User::remove_fd(tmp_mc_fd, &mc_connection, FD_EVENT_RD);
281 Fd_And_Timeout_User::set_timer(&mc_connection, 0.0);
282 }
283 }
284
285 boolean TTCN_Communication::transport_unix_stream_supported()
286 {
287 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
288 if (fd >= 0) {
289 close(fd);
290 TTCN_Logger::log_executor_misc(
291 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets,
292 NULL, NULL, 0);
293 return TRUE;
294 } else {
295 TTCN_Logger::log_executor_misc(
296 TitanLoggerApiSimple::ExecutorUnqualified_reason::host__support__unix__domain__sockets,
297 NULL, NULL, errno);
298 return FALSE;
299 }
300 }
301
302 boolean TTCN_Communication::set_close_on_exec(int fd)
303 {
304 int flags = fcntl(fd, F_GETFD);
305 if (flags < 0) {
306 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
307 TTCN_Logger::log_event("System call fcntl(F_GETFD) failed on file "
308 "descriptor %d.", fd);
309 TTCN_Logger::OS_error();
310 TTCN_Logger::end_event();
311 return FALSE;
312 }
313
314 flags |= FD_CLOEXEC;
315
316 if (fcntl(fd, F_SETFD, flags) == -1) {
317 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
318 TTCN_Logger::log_event("System call fcntl(F_SETFD) failed on file "
319 "descriptor %d.", fd);
320 TTCN_Logger::OS_error();
321 TTCN_Logger::end_event();
322 return FALSE;
323 }
324 return TRUE;
325 }
326
327 boolean TTCN_Communication::set_non_blocking_mode(int fd,
328 boolean enable_nonblock)
329 {
330 int flags = fcntl(fd, F_GETFL);
331 if (flags < 0) {
332 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
333 TTCN_Logger::log_event("System call fcntl(F_GETFL) failed on file "
334 "descriptor %d.", fd);
335 TTCN_Logger::OS_error();
336 TTCN_Logger::end_event();
337 return FALSE;
338 }
339
340 if (enable_nonblock) flags |= O_NONBLOCK;
341 else flags &= ~O_NONBLOCK;
342
343 if (fcntl(fd, F_SETFL, flags) == -1) {
344 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
345 TTCN_Logger::log_event("System call fcntl(F_SETFL) failed on file "
346 "descriptor %d.", fd);
347 TTCN_Logger::OS_error();
348 TTCN_Logger::end_event();
349 return FALSE;
350 }
351 return TRUE;
352 }
353
354 boolean TTCN_Communication::set_tcp_nodelay(int fd)
355 {
356 const int on = 1;
357 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on,
358 sizeof(on))) {
359 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
360 TTCN_Logger::log_event("System call setsockopt(TCP_NODELAY) failed on "
361 "file descriptor %d.", fd);
362 TTCN_Logger::OS_error();
363 TTCN_Logger::end_event();
364 return FALSE;
365 }
366 return TRUE;
367 }
368
369 boolean TTCN_Communication::increase_send_buffer(int fd,
370 int &old_size, int& new_size)
371 {
372 int set_size;
373 socklen_type optlen = sizeof(old_size);
374 // obtaining the current buffer size first
375 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&old_size, &optlen))
376 goto getsockopt_failure;
377 if (old_size <= 0) {
378 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED,
379 "System call getsockopt(SO_SNDBUF) returned invalid buffer size (%d) "
380 "on file descriptor %d.", old_size, fd);
381 return FALSE;
382 }
383 // trying to double the buffer size
384 set_size = 2 * old_size;
385 if (set_size > old_size) {
386 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char*)&set_size,
387 sizeof(set_size))) {
388 // the operation failed
389 switch (errno) {
390 case ENOMEM:
391 case ENOBUFS:
392 errno = 0;
393 break;
394 default:
395 // other error codes indicate a fatal error
396 goto setsockopt_failure;
397 }
398 } else {
399 // the operation was successful
400 goto success;
401 }
402 }
403 // trying to perform a binary search to determine the maximum buffer size
404 set_size = old_size;
405 for (int size_step = old_size / 2; size_step > 0; size_step /= 2) {
406 int tried_size = set_size + size_step;
407 if (tried_size > set_size) {
408 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char*)&tried_size,
409 sizeof(tried_size))) {
410 // the operation failed
411 switch (errno) {
412 case ENOMEM:
413 case ENOBUFS:
414 errno = 0;
415 break;
416 default:
417 // other error codes indicate a fatal error
418 goto setsockopt_failure;
419 }
420 } else {
421 // the operation was successful
422 set_size = tried_size;
423 }
424 }
425 }
426 if (set_size <= old_size) return FALSE;
427 success:
428 // querying the new effective buffer size (it might be smaller
429 // than set_size but should not be smaller than old_size)
430 optlen = sizeof(new_size);
431 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&new_size,
432 &optlen)) goto getsockopt_failure;
433 if (new_size > old_size) return TRUE;
434 else {
435 if (new_size < old_size) TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED,
436 "System call getsockopt(SO_SNDBUF) returned unexpected buffer size "
437 "(%d, after increasing it from %d to %d) on file descriptor %d.",
438 new_size, old_size, set_size, fd);
439 return FALSE;
440 }
441 getsockopt_failure:
442 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
443 TTCN_Logger::log_event("System call getsockopt(SO_SNDBUF) failed on file "
444 "descriptor %d.", fd);
445 TTCN_Logger::OS_error();
446 TTCN_Logger::end_event();
447 return FALSE;
448 setsockopt_failure:
449 TTCN_Logger::begin_event(TTCN_Logger::ERROR_UNQUALIFIED);
450 TTCN_Logger::log_event("System call setsockopt(SO_SNDBUF) failed on file "
451 "descriptor %d.", fd);
452 TTCN_Logger::OS_error();
453 TTCN_Logger::end_event();
454 return FALSE;
455 }
456
457 #define INITIAL_CALL_INTERVAL 1.0
458 #define CALL_INTERVAL_INCREMENT 2.0
459
460 void TTCN_Communication::enable_periodic_call()
461 {
462 call_interval = INITIAL_CALL_INTERVAL;
463 Fd_And_Timeout_User::set_timer(&mc_connection, call_interval, TRUE,
464 FALSE /*call_anyway*/);
465 }
466
467 void TTCN_Communication::increase_call_interval()
468 {
469 if (call_interval <= 0.0) TTCN_error("Internal error: "
470 "TTCN_Communication::increase_call_interval() was called when call "
471 "interval is not set.");
472 call_interval *= CALL_INTERVAL_INCREMENT;
473 Fd_And_Timeout_User::set_timer(&mc_connection, call_interval, TRUE,
474 FALSE /*call_anyway*/);
475 }
476
477 void TTCN_Communication::disable_periodic_call()
478 {
479 Fd_And_Timeout_User::set_timer(&mc_connection, 0.0);
480 call_interval = 0.0;
481 }
482
483 void MC_Connection::Handle_Fd_Event(int fd, boolean is_readable, boolean,
484 boolean is_error)
485 {
486 if (fd != *mc_fd)
487 TTCN_error("MC_Connection::Fd_And_Timeout_Event_Handler: unexpected "
488 "file descriptor"); // not necessary - debugging
489 if (is_error)
490 TTCN_warning("Error occurred on the control connection to MC");
491 if (is_readable) {
492 char *buf_ptr;
493 int buf_len;
494 incoming_buf->get_end(buf_ptr, buf_len);
495
496 int recv_len = recv(*mc_fd, buf_ptr, buf_len, 0);
497
498 if (recv_len > 0) {
499 // reason: data has arrived
500 incoming_buf->increase_length(recv_len);
501 // If the component is idle the processing is done in the outer
502 // stack frame (i.e. in TTCN_Runtime::xxx_main()).
503 if (!TTCN_Runtime::is_idle())
504 TTCN_Communication::process_all_messages_tc();
505 } else {
506 // First closing the TCP connection to avoid EPIPE ("Broken pipe")
507 // errors and/or SIGPIPE signals when trying to send anything
508 // (e.g. log events or error messages) towards MC.
509 TTCN_Communication::close_mc_connection();
510 if (recv_len == 0) {
511 // reason: TCP connection was closed by peer
512 TTCN_error("Control connection was closed unexpectedly by MC.");
513 } else {
514 // reason: error occurred
515 TTCN_error("Receiving data on the control connection from MC "
516 "failed.");
517 }
518 }
519 }
520 }
521
522 void MC_Connection::Handle_Timeout(double /*time_since_last_call*/)
523 {
524 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_OVERLOADED) {
525 // indicate the timeout to be handled in process_all_messages_hc()
526 TTCN_Runtime::set_state(TTCN_Runtime::HC_OVERLOADED_TIMEOUT);
527 } else {
528 TTCN_warning("Unexpected timeout occurred on the control "
529 "connection to MC.");
530 TTCN_Communication::disable_periodic_call();
531 }
532 }
533
534 void MC_Connection::log() const
535 {
536 TTCN_Logger::log_event("mc connection");
537 }
538
539 void TTCN_Communication::process_all_messages_hc()
540 {
541 if (!TTCN_Runtime::is_hc()) TTCN_error("Internal error: "
542 "TTCN_Communication::process_all_messages_hc() was called in invalid "
543 "state.");
544 TTCN_Runtime::wait_terminated_processes();
545 boolean wait_flag = FALSE;
546 boolean check_overload = TTCN_Runtime::is_overloaded();
547 while (incoming_buf.is_message()) {
548 wait_flag = TRUE;
549 int msg_len = incoming_buf.pull_int().get_val();
550 int msg_end = incoming_buf.get_pos() + msg_len;
551 int msg_type = incoming_buf.pull_int().get_val();
552 // messages: MC -> HC
553 switch (msg_type) {
554 case MSG_ERROR:
555 process_error();
556 break;
557 case MSG_CONFIGURE:
558 process_configure(msg_end);
559 break;
560 case MSG_CREATE_MTC:
561 process_create_mtc();
562 TTCN_Runtime::wait_terminated_processes();
563 wait_flag = FALSE;
564 check_overload = FALSE;
565 break;
566 case MSG_CREATE_PTC:
567 process_create_ptc();
568 TTCN_Runtime::wait_terminated_processes();
569 wait_flag = FALSE;
570 check_overload = FALSE;
571 break;
572 case MSG_KILL_PROCESS:
573 process_kill_process();
574 TTCN_Runtime::wait_terminated_processes();
575 wait_flag = FALSE;
576 break;
577 case MSG_EXIT_HC:
578 process_exit_hc();
579 break;
580 default:
581 process_unsupported_message(msg_type, msg_end);
582 }
583 }
584 if (wait_flag) TTCN_Runtime::wait_terminated_processes();
585 if (check_overload && TTCN_Runtime::is_overloaded())
586 TTCN_Runtime::check_overload();
587 }
588
589 void TTCN_Communication::process_all_messages_tc()
590 {
591 if (!TTCN_Runtime::is_tc()) TTCN_error("Internal error: "
592 "TTCN_Communication::process_all_messages_tc() was called in invalid "
593 "state.");
594 while (incoming_buf.is_message()) {
595 int msg_len = incoming_buf.pull_int().get_val();
596 int msg_end = incoming_buf.get_pos() + msg_len;
597 int msg_type = incoming_buf.pull_int().get_val();
598 // messages: MC -> TC
599 switch (msg_type) {
600 case MSG_ERROR:
601 process_error();
602 break;
603 case MSG_CREATE_ACK:
604 process_create_ack();
605 break;
606 case MSG_START_ACK:
607 process_start_ack();
608 break;
609 case MSG_STOP:
610 process_stop();
611 break;
612 case MSG_STOP_ACK:
613 process_stop_ack();
614 break;
615 case MSG_KILL_ACK:
616 process_kill_ack();
617 break;
618 case MSG_RUNNING:
619 process_running();
620 break;
621 case MSG_ALIVE:
622 process_alive();
623 break;
624 case MSG_DONE_ACK:
625 process_done_ack(msg_end);
626 break;
627 case MSG_KILLED_ACK:
628 process_killed_ack();
629 break;
630 case MSG_CANCEL_DONE:
631 if (TTCN_Runtime::is_mtc()) process_cancel_done_mtc();
632 else process_cancel_done_ptc();
633 break;
634 case MSG_COMPONENT_STATUS:
635 if (TTCN_Runtime::is_mtc()) process_component_status_mtc(msg_end);
636 else process_component_status_ptc(msg_end);
637 break;
638 case MSG_CONNECT_LISTEN:
639 process_connect_listen();
640 break;
641 case MSG_CONNECT:
642 process_connect();
643 break;
644 case MSG_CONNECT_ACK:
645 process_connect_ack();
646 break;
647 case MSG_DISCONNECT:
648 process_disconnect();
649 break;
650 case MSG_DISCONNECT_ACK:
651 process_disconnect_ack();
652 break;
653 case MSG_MAP:
654 process_map();
655 break;
656 case MSG_MAP_ACK:
657 process_map_ack();
658 break;
659 case MSG_UNMAP:
660 process_unmap();
661 break;
662 case MSG_UNMAP_ACK:
663 process_unmap_ack();
664 break;
665 default:
666 if (TTCN_Runtime::is_mtc()) {
667 // messages: MC -> MTC
668 switch (msg_type) {
669 case MSG_EXECUTE_CONTROL:
670 process_execute_control();
671 break;
672 case MSG_EXECUTE_TESTCASE:
673 process_execute_testcase();
674 break;
675 case MSG_PTC_VERDICT:
676 process_ptc_verdict();
677 break;
678 case MSG_CONTINUE:
679 process_continue();
680 break;
681 case MSG_EXIT_MTC:
682 process_exit_mtc();
683 break;
684 default:
685 process_unsupported_message(msg_type, msg_end);
686 }
687 } else {
688 // messages: MC -> PTC
689 switch (msg_type) {
690 case MSG_START:
691 process_start();
692 break;
693 case MSG_KILL:
694 process_kill();
695 break;
696 default:
697 process_unsupported_message(msg_type, msg_end);
698 }
699 }
700 }
701 }
702 }
703
704 void TTCN_Communication::send_version()
705 {
706 Text_Buf text_buf;
707 text_buf.push_int(MSG_VERSION);
708 text_buf.push_int(TTCN3_MAJOR);
709 text_buf.push_int(TTCN3_MINOR);
710 text_buf.push_int(TTCN3_PATCHLEVEL);
711 #ifdef TTCN3_BUILDNUMBER
712 text_buf.push_int(TTCN3_BUILDNUMBER);
713 #else
714 text_buf.push_int((RInt)0);
715 #endif
716 Module_List::push_version(text_buf);
717 struct utsname uts;
718 if (uname(&uts) < 0) TTCN_error("System call uname() failed.");
719 text_buf.push_string(uts.nodename);
720 text_buf.push_string(uts.machine);
721 text_buf.push_string(uts.sysname);
722 text_buf.push_string(uts.release);
723 text_buf.push_string(uts.version);
724 boolean unix_stream_supported = transport_unix_stream_supported();
725
726 // LOCAL (software loop) and INET_STREAM (TCP) transports are always
727 // supported
728 int n_supported_transports = 2;
729
730 if (unix_stream_supported) n_supported_transports++;
731 text_buf.push_int(n_supported_transports);
732 text_buf.push_int(TRANSPORT_LOCAL);
733 text_buf.push_int(TRANSPORT_INET_STREAM);
734 if (unix_stream_supported)
735 text_buf.push_int(TRANSPORT_UNIX_STREAM);
736 send_message(text_buf);
737 }
738
739 void TTCN_Communication::send_configure_ack()
740 {
741 Text_Buf text_buf;
742 text_buf.push_int(MSG_CONFIGURE_ACK);
743 send_message(text_buf);
744 }
745
746 void TTCN_Communication::send_configure_nak()
747 {
748 Text_Buf text_buf;
749 text_buf.push_int(MSG_CONFIGURE_NAK);
750 send_message(text_buf);
751 }
752
753 void TTCN_Communication::send_create_nak(component component_reference,
754 const char *fmt_str, ...)
755 {
756 va_list ap;
757 va_start(ap, fmt_str);
758 char *error_str = mprintf_va_list(fmt_str, ap);
759 va_end(ap);
760 Text_Buf text_buf;
761 text_buf.push_int(MSG_CREATE_NAK);
762 text_buf.push_int(component_reference);
763 text_buf.push_string(error_str);
764 Free(error_str);
765 send_message(text_buf);
766 }
767
768 void TTCN_Communication::send_hc_ready()
769 {
770 Text_Buf text_buf;
771 text_buf.push_int(MSG_HC_READY);
772 send_message(text_buf);
773 }
774
775 void TTCN_Communication::send_create_req(const char *component_type_module,
776 const char *component_type_name, const char *component_name,
777 const char *component_location, boolean is_alive)
778 {
779 Text_Buf text_buf;
780 text_buf.push_int(MSG_CREATE_REQ);
781 text_buf.push_string(component_type_module);
782 text_buf.push_string(component_type_name);
783 text_buf.push_string(component_name);
784 text_buf.push_string(component_location);
785 text_buf.push_int(is_alive ? 1 : 0);
786 send_message(text_buf);
787 }
788
789 void TTCN_Communication::prepare_start_req(Text_Buf& text_buf,
790 component component_reference, const char *module_name,
791 const char *function_name)
792 {
793 text_buf.push_int(MSG_START_REQ);
794 text_buf.push_int(component_reference);
795 text_buf.push_string(module_name);
796 text_buf.push_string(function_name);
797 }
798
799 void TTCN_Communication::send_stop_req(component component_reference)
800 {
801 Text_Buf text_buf;
802 text_buf.push_int(MSG_STOP_REQ);
803 text_buf.push_int(component_reference);
804 send_message(text_buf);
805 }
806
807 void TTCN_Communication::send_kill_req(component component_reference)
808 {
809 Text_Buf text_buf;
810 text_buf.push_int(MSG_KILL_REQ);
811 text_buf.push_int(component_reference);
812 send_message(text_buf);
813 }
814
815 void TTCN_Communication::send_is_running(component component_reference)
816 {
817 Text_Buf text_buf;
818 text_buf.push_int(MSG_IS_RUNNING);
819 text_buf.push_int(component_reference);
820 send_message(text_buf);
821 }
822
823 void TTCN_Communication::send_is_alive(component component_reference)
824 {
825 Text_Buf text_buf;
826 text_buf.push_int(MSG_IS_ALIVE);
827 text_buf.push_int(component_reference);
828 send_message(text_buf);
829 }
830
831 void TTCN_Communication::send_done_req(component component_reference)
832 {
833 Text_Buf text_buf;
834 text_buf.push_int(MSG_DONE_REQ);
835 text_buf.push_int(component_reference);
836 send_message(text_buf);
837 }
838
839 void TTCN_Communication::send_killed_req(component component_reference)
840 {
841 Text_Buf text_buf;
842 text_buf.push_int(MSG_KILLED_REQ);
843 text_buf.push_int(component_reference);
844 send_message(text_buf);
845 }
846
847 void TTCN_Communication::send_cancel_done_ack(component component_reference)
848 {
849 Text_Buf text_buf;
850 text_buf.push_int(MSG_CANCEL_DONE_ACK);
851 text_buf.push_int(component_reference);
852 send_message(text_buf);
853 }
854
855 void TTCN_Communication::send_connect_req(component src_component,
856 const char *src_port, component dst_component, const char *dst_port)
857 {
858 Text_Buf text_buf;
859 text_buf.push_int(MSG_CONNECT_REQ);
860 text_buf.push_int(src_component);
861 text_buf.push_string(src_port);
862 text_buf.push_int(dst_component);
863 text_buf.push_string(dst_port);
864 send_message(text_buf);
865 }
866
867 void TTCN_Communication::send_connect_listen_ack_inet_stream(
868 const char *local_port, component remote_component,
869 const char *remote_port, const IPAddress *local_address)
870 {
871 Text_Buf text_buf;
872 text_buf.push_int(MSG_CONNECT_LISTEN_ACK);
873 text_buf.push_string(local_port);
874 text_buf.push_int(remote_component);
875 text_buf.push_string(remote_port);
876 text_buf.push_int(TRANSPORT_INET_STREAM);
877 local_address->push_raw(text_buf);
878 send_message(text_buf);
879 }
880
881 void TTCN_Communication::send_connect_listen_ack_unix_stream(
882 const char *local_port, component remote_component,
883 const char *remote_port, const struct sockaddr_un *local_address)
884 {
885 Text_Buf text_buf;
886 text_buf.push_int(MSG_CONNECT_LISTEN_ACK);
887 text_buf.push_string(local_port);
888 text_buf.push_int(remote_component);
889 text_buf.push_string(remote_port);
890 text_buf.push_int(TRANSPORT_UNIX_STREAM);
891 text_buf.push_string(local_address->sun_path);
892 send_message(text_buf);
893 }
894
895 void TTCN_Communication::send_connected(const char *local_port,
896 component remote_component, const char *remote_port)
897 {
898 Text_Buf text_buf;
899 text_buf.push_int(MSG_CONNECTED);
900 text_buf.push_string(local_port);
901 text_buf.push_int(remote_component);
902 text_buf.push_string(remote_port);
903 send_message(text_buf);
904 }
905
906 void TTCN_Communication::send_connect_error(const char *local_port,
907 component remote_component, const char *remote_port,
908 const char *fmt_str, ...)
909 {
910 va_list ap;
911 va_start(ap, fmt_str);
912 char *error_str = mprintf_va_list(fmt_str, ap);
913 va_end(ap);
914 Text_Buf text_buf;
915 text_buf.push_int(MSG_CONNECT_ERROR);
916 text_buf.push_string(local_port);
917 text_buf.push_int(remote_component);
918 text_buf.push_string(remote_port);
919 text_buf.push_string(error_str);
920 Free(error_str);
921 send_message(text_buf);
922 }
923
924 void TTCN_Communication::send_disconnect_req(component src_component,
925 const char *src_port, component dst_component, const char *dst_port)
926 {
927 Text_Buf text_buf;
928 text_buf.push_int(MSG_DISCONNECT_REQ);
929 text_buf.push_int(src_component);
930 text_buf.push_string(src_port);
931 text_buf.push_int(dst_component);
932 text_buf.push_string(dst_port);
933 send_message(text_buf);
934 }
935
936 void TTCN_Communication::send_disconnected(const char *local_port,
937 component remote_component, const char *remote_port)
938 {
939 Text_Buf text_buf;
940 text_buf.push_int(MSG_DISCONNECTED);
941 text_buf.push_string(local_port);
942 text_buf.push_int(remote_component);
943 text_buf.push_string(remote_port);
944 send_message(text_buf);
945 }
946
947 void TTCN_Communication::send_map_req(component src_component,
948 const char *src_port, const char *system_port)
949 {
950 Text_Buf text_buf;
951 text_buf.push_int(MSG_MAP_REQ);
952 text_buf.push_int(src_component);
953 text_buf.push_string(src_port);
954 text_buf.push_string(system_port);
955 send_message(text_buf);
956 }
957
958 void TTCN_Communication::send_mapped(const char *local_port,
959 const char *system_port)
960 {
961 Text_Buf text_buf;
962 text_buf.push_int(MSG_MAPPED);
963 text_buf.push_string(local_port);
964 text_buf.push_string(system_port);
965 send_message(text_buf);
966 }
967
968 void TTCN_Communication::send_unmap_req(component src_component,
969 const char *src_port, const char *system_port)
970 {
971 Text_Buf text_buf;
972 text_buf.push_int(MSG_UNMAP_REQ);
973 text_buf.push_int(src_component);
974 text_buf.push_string(src_port);
975 text_buf.push_string(system_port);
976 send_message(text_buf);
977 }
978
979 void TTCN_Communication::send_unmapped(const char *local_port,
980 const char *system_port)
981 {
982 Text_Buf text_buf;
983 text_buf.push_int(MSG_UNMAPPED);
984 text_buf.push_string(local_port);
985 text_buf.push_string(system_port);
986 send_message(text_buf);
987 }
988
989 void TTCN_Communication::send_mtc_created()
990 {
991 Text_Buf text_buf;
992 text_buf.push_int(MSG_MTC_CREATED);
993 send_message(text_buf);
994 }
995
996 void TTCN_Communication::send_testcase_started(const char *testcase_module,
997 const char *testcase_name, const char *mtc_comptype_module,
998 const char *mtc_comptype_name, const char *system_comptype_module,
999 const char *system_comptype_name)
1000 {
1001 Text_Buf text_buf;
1002 text_buf.push_int(MSG_TESTCASE_STARTED);
1003 text_buf.push_string(testcase_module);
1004 text_buf.push_string(testcase_name);
1005 text_buf.push_string(mtc_comptype_module);
1006 text_buf.push_string(mtc_comptype_name);
1007 text_buf.push_string(system_comptype_module);
1008 text_buf.push_string(system_comptype_name);
1009 send_message(text_buf);
1010 }
1011
1012 void TTCN_Communication::send_testcase_finished(verdicttype final_verdict,
1013 const char* reason)
1014 {
1015 Text_Buf text_buf;
1016 text_buf.push_int(MSG_TESTCASE_FINISHED);
1017 text_buf.push_int(final_verdict);
1018 text_buf.push_string(reason);
1019 send_message(text_buf);
1020 }
1021
1022 void TTCN_Communication::send_mtc_ready()
1023 {
1024 Text_Buf text_buf;
1025 text_buf.push_int(MSG_MTC_READY);
1026 send_message(text_buf);
1027 }
1028
1029 void TTCN_Communication::send_ptc_created(component component_reference)
1030 {
1031 Text_Buf text_buf;
1032 text_buf.push_int(MSG_PTC_CREATED);
1033 text_buf.push_int(component_reference);
1034 send_message(text_buf);
1035 }
1036
1037 void TTCN_Communication::prepare_stopped(Text_Buf& text_buf,
1038 const char *return_type)
1039 {
1040 text_buf.push_int(MSG_STOPPED);
1041 text_buf.push_string(return_type);
1042 }
1043
1044 void TTCN_Communication::send_stopped()
1045 {
1046 Text_Buf text_buf;
1047 text_buf.push_int(MSG_STOPPED);
1048 // add an empty return type
1049 text_buf.push_string(NULL);
1050 send_message(text_buf);
1051 }
1052
1053 void TTCN_Communication::prepare_stopped_killed(Text_Buf& text_buf,
1054 verdicttype final_verdict, const char *return_type, const char* reason)
1055 {
1056 text_buf.push_int(MSG_STOPPED_KILLED);
1057 text_buf.push_int(final_verdict);
1058 text_buf.push_string(reason);
1059 text_buf.push_string(return_type);
1060 }
1061
1062 void TTCN_Communication::send_stopped_killed(verdicttype final_verdict,
1063 const char* reason)
1064 {
1065 Text_Buf text_buf;
1066 text_buf.push_int(MSG_STOPPED_KILLED);
1067 text_buf.push_int(final_verdict);
1068 text_buf.push_string(reason);
1069 // add an empty return type
1070 text_buf.push_string(NULL);
1071 send_message(text_buf);
1072 }
1073
1074 void TTCN_Communication::send_killed(verdicttype final_verdict,
1075 const char* reason)
1076 {
1077 Text_Buf text_buf;
1078 text_buf.push_int(MSG_KILLED);
1079 text_buf.push_int(final_verdict);
1080 text_buf.push_string(reason);
1081 send_message(text_buf);
1082 }
1083
1084 boolean TTCN_Communication::send_log(time_t timestamp_sec, long timestamp_usec,
1085 unsigned int event_severity, size_t message_text_len,
1086 const char *message_text)
1087 {
1088 if (is_connected) {
1089 Text_Buf text_buf;
1090 text_buf.push_int(MSG_LOG);
1091 text_buf.push_int(timestamp_sec);
1092 text_buf.push_int(timestamp_usec);
1093 text_buf.push_int(event_severity);
1094 text_buf.push_int(message_text_len);
1095 text_buf.push_raw(message_text_len, message_text);
1096 send_message(text_buf);
1097 /* If an ERROR message (indicating a version mismatch) arrives from MC
1098 in state HC_IDLE (i.e. before CONFIGURE) it shall be
1099 printed to the console as well. */
1100 if (TTCN_Runtime::get_state() == TTCN_Runtime::HC_IDLE) return FALSE;
1101 else return TRUE;
1102 } else {
1103 switch (TTCN_Runtime::get_state()) {
1104 case TTCN_Runtime::HC_EXIT:
1105 case TTCN_Runtime::MTC_INITIAL:
1106 case TTCN_Runtime::MTC_EXIT:
1107 case TTCN_Runtime::PTC_INITIAL:
1108 case TTCN_Runtime::PTC_EXIT:
1109 /* Do not print the first/last few lines of logs to the console
1110 even if ConsoleMask is set to LOG_ALL */
1111 return TRUE;
1112 default:
1113 return FALSE;
1114 }
1115 }
1116 }
1117
1118 void TTCN_Communication::send_error(const char *fmt_str, ...)
1119 {
1120 va_list ap;
1121 va_start(ap, fmt_str);
1122 char *error_str = mprintf_va_list(fmt_str, ap);
1123 va_end(ap);
1124 Text_Buf text_buf;
1125 text_buf.push_int((RInt)MSG_ERROR);
1126 text_buf.push_string(error_str);
1127 Free(error_str);
1128 send_message(text_buf);
1129 }
1130
1131 void TTCN_Communication::send_message(Text_Buf& text_buf)
1132 {
1133 if (!is_connected) TTCN_error("Trying to send a message to MC, but the "
1134 "control connection is down.");
1135 text_buf.calculate_length();
1136 const char *msg_ptr = text_buf.get_data();
1137 size_t msg_len = text_buf.get_len(), sent_len = 0;
1138 while (sent_len < msg_len) {
1139 int ret_val = send(mc_fd, msg_ptr + sent_len, msg_len - sent_len, 0);
1140 if (ret_val > 0) sent_len += ret_val;
1141 else {
1142 switch (errno) {
1143 case EINTR:
1144 // a signal occurred: do nothing, just try again
1145 errno = 0;
1146 break;
1147 default:
1148 close_mc_connection();
1149 TTCN_error("Sending data on the control connection to MC "
1150 "failed.");
1151 }
1152 }
1153 }
1154 }
1155
1156 void TTCN_Communication::process_configure(int msg_end)
1157 {
1158 switch (TTCN_Runtime::get_state()) {
1159 case TTCN_Runtime::HC_IDLE:
1160 case TTCN_Runtime::HC_ACTIVE:
1161 case TTCN_Runtime::HC_OVERLOADED:
1162 break;
1163 default:
1164 incoming_buf.cut_message();
1165 send_error("Message CONFIGURE arrived in invalid state.");
1166 return;
1167 }
1168
1169 TTCN_Runtime::set_state(TTCN_Runtime::HC_CONFIGURING);
1170 TTCN_Logger::log_configdata(TitanLoggerApiSimple::ExecutorConfigdata_reason::received__from__mc);
1171
1172 // take the config string directly from the buffer for efficiency reasons
1173 int config_str_len = incoming_buf.pull_int().get_val();
1174 int config_str_begin = incoming_buf.get_pos();
1175 if (config_str_begin + config_str_len != msg_end) {
1176 incoming_buf.cut_message();
1177 send_error("Malformed message CONFIGURE was received.");
1178 return;
1179 }
1180 const char *config_str = incoming_buf.get_data() + config_str_begin;
1181 boolean success = process_config_string(config_str, config_str_len);
1182
1183 // Only non component specific settings will be applied. The plug-ins need
1184 // to be loaded due to resetting.
1185 TTCN_Logger::load_plugins(NULL_COMPREF, "");
1186 TTCN_Logger::set_plugin_parameters(NULL_COMPREF, "");
1187 TTCN_Logger::open_file();
1188 if (success) {
1189 try {
1190 Module_List::log_param();
1191 Module_List::post_init_modules();
1192 } catch (const TC_Error& TC_error) {
1193 TTCN_Logger::log_executor_runtime(
1194 TitanLoggerApiSimple::ExecutorRuntime_reason::initialization__of__modules__failed);
1195 success = FALSE;
1196 }
1197 } else {
1198 TTCN_Logger::log_configdata(
1199 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__failed, NULL);
1200 }
1201
1202 if (success) {
1203 send_configure_ack();
1204 TTCN_Runtime::set_state(TTCN_Runtime::HC_ACTIVE);
1205 TTCN_Logger::log_configdata(
1206 TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__succeeded);
1207 } else {
1208 send_configure_nak();
1209 TTCN_Runtime::set_state(TTCN_Runtime::HC_IDLE);
1210 }
1211
1212 incoming_buf.cut_message();
1213 }
1214
1215 void TTCN_Communication::process_create_mtc()
1216 {
1217 incoming_buf.cut_message();
1218 TTCN_Runtime::process_create_mtc();
1219 }
1220
1221 void TTCN_Communication::process_create_ptc()
1222 {
1223 component component_reference = (component)incoming_buf.pull_int().get_val();
1224 if (component_reference < FIRST_PTC_COMPREF) {
1225 incoming_buf.cut_message();
1226 send_error("Message CREATE_PTC refers to invalid "
1227 "component reference %d.", component_reference);
1228 return;
1229 }
1230 qualified_name component_type;
1231 incoming_buf.pull_qualified_name(component_type);
1232 if (component_type.module_name == NULL ||
1233 component_type.definition_name == NULL) {
1234 incoming_buf.cut_message();
1235 delete [] component_type.module_name;
1236 delete [] component_type.definition_name;
1237 send_error("Message CREATE_PTC with component reference %d contains "
1238 "an invalid component type.", component_reference);
1239 return;
1240 }
1241 char *component_name = incoming_buf.pull_string();
1242 boolean is_alive = incoming_buf.pull_int().get_val();
1243 qualified_name current_testcase;
1244 incoming_buf.pull_qualified_name(current_testcase);
1245 incoming_buf.cut_message();
1246
1247 try {
1248 TTCN_Runtime::process_create_ptc(component_reference,
1249 component_type.module_name, component_type.definition_name,
1250 component_name, is_alive, current_testcase.module_name,
1251 current_testcase.definition_name);
1252 } catch (...) {
1253 // to prevent from memory leaks
1254 delete [] component_type.module_name;
1255 delete [] component_type.definition_name;
1256 delete [] component_name;
1257 delete [] current_testcase.module_name;
1258 delete [] current_testcase.definition_name;
1259 throw;
1260 }
1261
1262 delete [] component_type.module_name;
1263 delete [] component_type.definition_name;
1264 delete [] component_name;
1265 delete [] current_testcase.module_name;
1266 delete [] current_testcase.definition_name;
1267 }
1268
1269 void TTCN_Communication::process_kill_process()
1270 {
1271 component component_reference = (component)incoming_buf.pull_int().get_val();
1272 incoming_buf.cut_message();
1273 TTCN_Runtime::process_kill_process(component_reference);
1274 }
1275
1276 void TTCN_Communication::process_exit_hc()
1277 {
1278 incoming_buf.cut_message();
1279 TTCN_Logger::log_executor_runtime(
1280 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__hc);
1281 TTCN_Runtime::set_state(TTCN_Runtime::HC_EXIT);
1282 }
1283
1284 void TTCN_Communication::process_create_ack()
1285 {
1286 component component_reference = incoming_buf.pull_int().get_val();
1287 incoming_buf.cut_message();
1288 TTCN_Runtime::process_create_ack(component_reference);
1289 }
1290
1291 void TTCN_Communication::process_start_ack()
1292 {
1293 incoming_buf.cut_message();
1294
1295 switch (TTCN_Runtime::get_state()) {
1296 case TTCN_Runtime::MTC_START:
1297 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1298 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1299 break;
1300 case TTCN_Runtime::PTC_START:
1301 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1302 break;
1303 default:
1304 TTCN_error("Internal error: Message START_ACK arrived in invalid "
1305 "state.");
1306 }
1307 }
1308
1309 void TTCN_Communication::process_stop()
1310 {
1311 incoming_buf.cut_message();
1312 switch (TTCN_Runtime::get_state()) {
1313 case TTCN_Runtime::MTC_IDLE:
1314 TTCN_Logger::log_executor_runtime(
1315 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__mtc);
1316 break;
1317 case TTCN_Runtime::MTC_PAUSED:
1318 TTCN_Logger::log_executor_runtime(
1319 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc);
1320 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TERMINATING_EXECUTION);
1321 break;
1322 case TTCN_Runtime::PTC_IDLE:
1323 case TTCN_Runtime::PTC_STOPPED:
1324 TTCN_Logger::log_executor_runtime(
1325 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc__ignored__on__idle__ptc);
1326 break;
1327 case TTCN_Runtime::PTC_EXIT:
1328 // silently ignore
1329 break;
1330 default:
1331 TTCN_Logger::log_executor_runtime(
1332 TitanLoggerApiSimple::ExecutorRuntime_reason::stop__was__requested__from__mc);
1333 TTCN_Runtime::stop_execution();
1334 break;
1335 }
1336 }
1337
1338 void TTCN_Communication::process_stop_ack()
1339 {
1340 incoming_buf.cut_message();
1341 switch (TTCN_Runtime::get_state()) {
1342 case TTCN_Runtime::MTC_STOP:
1343 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1344 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1345 break;
1346 case TTCN_Runtime::PTC_STOP:
1347 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1348 break;
1349 default:
1350 TTCN_error("Internal error: Message STOP_ACK arrived in invalid "
1351 "state.");
1352 }
1353 }
1354
1355 void TTCN_Communication::process_kill_ack()
1356 {
1357 incoming_buf.cut_message();
1358 switch (TTCN_Runtime::get_state()) {
1359 case TTCN_Runtime::MTC_KILL:
1360 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1361 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1362 break;
1363 case TTCN_Runtime::PTC_KILL:
1364 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1365 break;
1366 default:
1367 TTCN_error("Internal error: Message KILL_ACK arrived in invalid "
1368 "state.");
1369 }
1370 }
1371
1372 void TTCN_Communication::process_running()
1373 {
1374 boolean answer = incoming_buf.pull_int().get_val();
1375 incoming_buf.cut_message();
1376 TTCN_Runtime::process_running(answer);
1377 }
1378
1379 void TTCN_Communication::process_alive()
1380 {
1381 boolean answer = incoming_buf.pull_int().get_val();
1382 incoming_buf.cut_message();
1383 TTCN_Runtime::process_alive(answer);
1384 }
1385
1386 void TTCN_Communication::process_done_ack(int msg_end)
1387 {
1388 // decoding the mandatory attributes
1389 boolean answer = incoming_buf.pull_int().get_val();
1390 char *return_type = incoming_buf.pull_string();
1391 // the return value starts here
1392 int return_value_begin = incoming_buf.get_pos();
1393
1394 try {
1395 TTCN_Runtime::process_done_ack(answer, return_type,
1396 msg_end - return_value_begin,
1397 incoming_buf.get_data() + return_value_begin);
1398 } catch (...) {
1399 // avoid memory leaks in case of error
1400 incoming_buf.cut_message();
1401 delete [] return_type;
1402 throw;
1403 }
1404
1405 incoming_buf.cut_message();
1406 delete [] return_type;
1407 }
1408
1409 void TTCN_Communication::process_killed_ack()
1410 {
1411 boolean answer = incoming_buf.pull_int().get_val();
1412 incoming_buf.cut_message();
1413 TTCN_Runtime::process_killed_ack(answer);
1414 }
1415
1416 void TTCN_Communication::process_cancel_done_mtc()
1417 {
1418 component component_reference = incoming_buf.pull_int().get_val();
1419 boolean cancel_any = incoming_buf.pull_int().get_val();
1420 incoming_buf.cut_message();
1421 TTCN_Runtime::cancel_component_done(component_reference);
1422 if (cancel_any) TTCN_Runtime::cancel_component_done(ANY_COMPREF);
1423 send_cancel_done_ack(component_reference);
1424 }
1425
1426 void TTCN_Communication::process_cancel_done_ptc()
1427 {
1428 component component_reference = incoming_buf.pull_int().get_val();
1429 incoming_buf.cut_message();
1430 TTCN_Runtime::cancel_component_done(component_reference);
1431 send_cancel_done_ack(component_reference);
1432 }
1433
1434 void TTCN_Communication::process_component_status_mtc(int msg_end)
1435 {
1436 // decoding the mandatory attributes
1437 component component_reference = incoming_buf.pull_int().get_val();
1438 boolean is_done = incoming_buf.pull_int().get_val();
1439 boolean is_killed = incoming_buf.pull_int().get_val();
1440 boolean is_any_done = incoming_buf.pull_int().get_val();
1441 boolean is_all_done = incoming_buf.pull_int().get_val();
1442 boolean is_any_killed = incoming_buf.pull_int().get_val();
1443 boolean is_all_killed = incoming_buf.pull_int().get_val();
1444 if (is_done) {
1445 // the return type and value is valid
1446 char *return_type = incoming_buf.pull_string();
1447 int return_value_begin = incoming_buf.get_pos();
1448 try {
1449 TTCN_Runtime::set_component_done(component_reference, return_type,
1450 msg_end - return_value_begin,
1451 incoming_buf.get_data() + return_value_begin);
1452 } catch (...) {
1453 // avoid memory leaks
1454 incoming_buf.cut_message();
1455 delete [] return_type;
1456 throw;
1457 }
1458 delete [] return_type;
1459 }
1460 if (is_killed) TTCN_Runtime::set_component_killed(component_reference);
1461 if (is_any_done)
1462 TTCN_Runtime::set_component_done(ANY_COMPREF, NULL, 0, NULL);
1463 if (is_all_done)
1464 TTCN_Runtime::set_component_done(ALL_COMPREF, NULL, 0, NULL);
1465 if (is_any_killed) TTCN_Runtime::set_component_killed(ANY_COMPREF);
1466 if (is_all_killed) TTCN_Runtime::set_component_killed(ALL_COMPREF);
1467 incoming_buf.cut_message();
1468 if (!is_done && !is_killed && (component_reference != NULL_COMPREF ||
1469 (!is_any_done && !is_all_done && !is_any_killed && !is_all_killed)))
1470 TTCN_error("Internal error: Malformed COMPONENT_STATUS message was "
1471 "received.");
1472 }
1473
1474 void TTCN_Communication::process_component_status_ptc(int msg_end)
1475 {
1476 // decoding the mandatory attributes
1477 component component_reference = incoming_buf.pull_int().get_val();
1478 boolean is_done = incoming_buf.pull_int().get_val();
1479 boolean is_killed = incoming_buf.pull_int().get_val();
1480 if (is_done) {
1481 // the return type and value is valid
1482 char *return_type = incoming_buf.pull_string();
1483 int return_value_begin = incoming_buf.get_pos();
1484 try {
1485 TTCN_Runtime::set_component_done(component_reference, return_type,
1486 msg_end - return_value_begin,
1487 incoming_buf.get_data() + return_value_begin);
1488 } catch (...) {
1489 // avoid memory leaks
1490 incoming_buf.cut_message();
1491 delete [] return_type;
1492 throw;
1493 }
1494 delete [] return_type;
1495 }
1496 if (is_killed) TTCN_Runtime::set_component_killed(component_reference);
1497 incoming_buf.cut_message();
1498 if (!is_done && !is_killed) TTCN_error("Internal error: Malformed "
1499 "COMPONENT_STATUS message was received.");
1500 }
1501
1502 void TTCN_Communication::process_connect_listen()
1503 {
1504 char *local_port = incoming_buf.pull_string();
1505 component remote_component = incoming_buf.pull_int().get_val();
1506 char *remote_component_name = incoming_buf.pull_string();
1507 char *remote_port = incoming_buf.pull_string();
1508 transport_type_enum transport_type =
1509 (transport_type_enum)incoming_buf.pull_int().get_val();
1510 incoming_buf.cut_message();
1511
1512 try {
1513 if (remote_component != MTC_COMPREF && self != remote_component)
1514 COMPONENT::register_component_name(remote_component,
1515 remote_component_name);
1516 PORT::process_connect_listen(local_port, remote_component, remote_port,
1517 transport_type);
1518 } catch (...) {
1519 delete [] local_port;
1520 delete [] remote_component_name;
1521 delete [] remote_port;
1522 throw;
1523 }
1524
1525 delete [] local_port;
1526 delete [] remote_component_name;
1527 delete [] remote_port;
1528 }
1529
1530 void TTCN_Communication::process_connect()
1531 {
1532 char *local_port = incoming_buf.pull_string();
1533 component remote_component = incoming_buf.pull_int().get_val();
1534 char *remote_component_name = incoming_buf.pull_string();
1535 char *remote_port = incoming_buf.pull_string();
1536 transport_type_enum transport_type =
1537 (transport_type_enum)incoming_buf.pull_int().get_val();
1538
1539 try {
1540 if (remote_component != MTC_COMPREF && self != remote_component)
1541 COMPONENT::register_component_name(remote_component,
1542 remote_component_name);
1543 PORT::process_connect(local_port, remote_component, remote_port,
1544 transport_type, incoming_buf);
1545 } catch (...) {
1546 incoming_buf.cut_message();
1547 delete [] local_port;
1548 delete [] remote_component_name;
1549 delete [] remote_port;
1550 throw;
1551 }
1552
1553 incoming_buf.cut_message();
1554 delete [] local_port;
1555 delete [] remote_component_name;
1556 delete [] remote_port;
1557 }
1558
1559 void TTCN_Communication::process_connect_ack()
1560 {
1561 incoming_buf.cut_message();
1562
1563 switch (TTCN_Runtime::get_state()) {
1564 case TTCN_Runtime::MTC_CONNECT:
1565 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1566 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1567 break;
1568 case TTCN_Runtime::PTC_CONNECT:
1569 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1570 break;
1571 default:
1572 TTCN_error("Internal error: Message CONNECT_ACK arrived in invalid "
1573 "state.");
1574 }
1575 }
1576
1577 void TTCN_Communication::process_disconnect()
1578 {
1579 char *local_port = incoming_buf.pull_string();
1580 component remote_component = incoming_buf.pull_int().get_val();
1581 char *remote_port = incoming_buf.pull_string();
1582 incoming_buf.cut_message();
1583
1584 try {
1585 PORT::process_disconnect(local_port, remote_component, remote_port);
1586 } catch (...) {
1587 delete [] local_port;
1588 delete [] remote_port;
1589 throw;
1590 }
1591
1592 delete [] local_port;
1593 delete [] remote_port;
1594 }
1595
1596 void TTCN_Communication::process_disconnect_ack()
1597 {
1598 incoming_buf.cut_message();
1599
1600 switch (TTCN_Runtime::get_state()) {
1601 case TTCN_Runtime::MTC_DISCONNECT:
1602 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1603 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1604 break;
1605 case TTCN_Runtime::PTC_DISCONNECT:
1606 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1607 break;
1608 default:
1609 TTCN_error("Internal error: Message DISCONNECT_ACK arrived in invalid "
1610 "state.");
1611 }
1612 }
1613
1614 void TTCN_Communication::process_map()
1615 {
1616 char *local_port = incoming_buf.pull_string();
1617 char *system_port = incoming_buf.pull_string();
1618 incoming_buf.cut_message();
1619
1620 try {
1621 PORT::map_port(local_port, system_port);
1622 } catch (...) {
1623 delete [] local_port;
1624 delete [] system_port;
1625 throw;
1626 }
1627
1628 delete [] local_port;
1629 delete [] system_port;
1630 }
1631
1632 void TTCN_Communication::process_map_ack()
1633 {
1634 incoming_buf.cut_message();
1635
1636 switch (TTCN_Runtime::get_state()) {
1637 case TTCN_Runtime::MTC_MAP:
1638 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1639 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1640 break;
1641 case TTCN_Runtime::PTC_MAP:
1642 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1643 break;
1644 default:
1645 TTCN_error("Internal error: Message MAP_ACK arrived in invalid state.");
1646 }
1647 }
1648
1649 void TTCN_Communication::process_unmap()
1650 {
1651 char *local_port = incoming_buf.pull_string();
1652 char *system_port = incoming_buf.pull_string();
1653 incoming_buf.cut_message();
1654
1655 try {
1656 PORT::unmap_port(local_port, system_port);
1657 } catch (...) {
1658 delete [] local_port;
1659 delete [] system_port;
1660 throw;
1661 }
1662
1663 delete [] local_port;
1664 delete [] system_port;
1665 }
1666
1667 void TTCN_Communication::process_unmap_ack()
1668 {
1669 incoming_buf.cut_message();
1670
1671 switch(TTCN_Runtime::get_state()){
1672 case TTCN_Runtime::MTC_UNMAP:
1673 TTCN_Runtime::set_state(TTCN_Runtime::MTC_TESTCASE);
1674 case TTCN_Runtime::MTC_TERMINATING_TESTCASE:
1675 break;
1676 case TTCN_Runtime::PTC_UNMAP:
1677 TTCN_Runtime::set_state(TTCN_Runtime::PTC_FUNCTION);
1678 break;
1679 default:
1680 TTCN_error("Internal error: Message UNMAP_ACK arrived in invalid "
1681 "state.");
1682 }
1683 }
1684
1685 void TTCN_Communication::process_execute_control()
1686 {
1687 char *module_name = incoming_buf.pull_string();
1688 incoming_buf.cut_message();
1689
1690 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE) {
1691 delete [] module_name;
1692 TTCN_error("Internal error: Message EXECUTE_CONTROL arrived in "
1693 "invalid state.");
1694 }
1695
1696 TTCN_Logger::log(TTCN_Logger::PARALLEL_UNQUALIFIED,
1697 "Executing control part of module %s.", module_name);
1698
1699 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART);
1700
1701 try {
1702 Module_List::execute_control(module_name);
1703 } catch (const TC_End& TC_end) {
1704 } catch (const TC_Error& TC_error) {
1705 }
1706
1707 delete [] module_name;
1708
1709 if (is_connected) {
1710 send_mtc_ready();
1711 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE);
1712 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT);
1713 }
1714
1715 void TTCN_Communication::process_execute_testcase()
1716 {
1717 char *module_name = incoming_buf.pull_string();
1718 char *testcase_name = incoming_buf.pull_string();
1719 incoming_buf.cut_message();
1720
1721 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_IDLE) {
1722 delete [] module_name;
1723 delete [] testcase_name;
1724 TTCN_error("Internal error: Message EXECUTE_TESTCASE arrived in "
1725 "invalid state.");
1726 }
1727
1728 TTCN_Logger::log_testcase_exec(testcase_name, module_name);
1729
1730 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART);
1731
1732 try {
1733 if (testcase_name != NULL && testcase_name[0] != '\0')
1734 Module_List::execute_testcase(module_name, testcase_name);
1735 else Module_List::execute_all_testcases(module_name);
1736 } catch (const TC_End& TC_end) {
1737 } catch (const TC_Error& TC_error) {
1738 }
1739
1740 if (is_connected) {
1741 send_mtc_ready();
1742 TTCN_Runtime::set_state(TTCN_Runtime::MTC_IDLE);
1743 } else TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT);
1744
1745 delete [] module_name;
1746 delete [] testcase_name;
1747 }
1748
1749 void TTCN_Communication::process_ptc_verdict()
1750 {
1751 TTCN_Runtime::process_ptc_verdict(incoming_buf);
1752 incoming_buf.cut_message();
1753 }
1754
1755 void TTCN_Communication::process_continue()
1756 {
1757 incoming_buf.cut_message();
1758
1759 if (TTCN_Runtime::get_state() != TTCN_Runtime::MTC_PAUSED)
1760 TTCN_error("Internal error: Message CONTINUE arrived in invalid "
1761 "state.");
1762
1763 TTCN_Runtime::set_state(TTCN_Runtime::MTC_CONTROLPART);
1764 }
1765
1766 void TTCN_Communication::process_exit_mtc()
1767 {
1768 incoming_buf.cut_message();
1769 TTCN_Runtime::log_verdict_statistics();
1770 TTCN_Logger::log_executor_runtime(
1771 TitanLoggerApiSimple::ExecutorRuntime_reason::exit__requested__from__mc__mtc);
1772 TTCN_Runtime::set_state(TTCN_Runtime::MTC_EXIT);
1773 }
1774
1775 void TTCN_Communication::process_start()
1776 {
1777 qualified_name function_name;
1778 incoming_buf.pull_qualified_name(function_name);
1779 if (function_name.module_name == NULL ||
1780 function_name.definition_name == NULL) {
1781 incoming_buf.cut_message();
1782 delete [] function_name.module_name;
1783 delete [] function_name.definition_name;
1784 TTCN_error("Internal error: Message START contains an invalid "
1785 "function name.");
1786 }
1787
1788 try {
1789 TTCN_Runtime::start_function(function_name.module_name,
1790 function_name.definition_name, incoming_buf);
1791 } catch (...) {
1792 // avoid memory leaks
1793 delete [] function_name.module_name;
1794 delete [] function_name.definition_name;
1795 throw;
1796 }
1797
1798 delete [] function_name.module_name;
1799 delete [] function_name.definition_name;
1800 }
1801
1802 void TTCN_Communication::process_kill()
1803 {
1804 incoming_buf.cut_message();
1805 TTCN_Runtime::process_kill();
1806 }
1807
1808 void TTCN_Communication::process_error()
1809 {
1810 char *error_string = incoming_buf.pull_string();
1811 incoming_buf.cut_message();
1812
1813 try {
1814 TTCN_error("Error message was received from MC: %s", error_string);
1815 } catch (...) {
1816 delete [] error_string;
1817 throw;
1818 }
1819 }
1820
1821 void TTCN_Communication::process_unsupported_message(int msg_type, int msg_end)
1822 {
1823 TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED);
1824 TTCN_Logger::log_event("Unsupported message was received from MC: "
1825 "type (decimal): %d, data (hexadecimal): ", msg_type);
1826 const unsigned char *msg_ptr =
1827 (const unsigned char*)incoming_buf.get_data();
1828 for (int i = incoming_buf.get_pos(); i < msg_end; i++)
1829 TTCN_Logger::log_octet(msg_ptr[i]);
1830 TTCN_Logger::end_event();
1831 incoming_buf.cut_message();
1832 }
1833
1834 /* * * * Temporary squatting place because it includes version.h * * * */
1835
1836 const struct runtime_version current_runtime_version = {
1837 TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL, TITAN_RUNTIME_NR
1838 };
1839
1840 static const char *runtime_name[] = { 0, "load", "function " };
1841
1842 RuntimeVersionChecker::RuntimeVersionChecker(
1843 int ver_major, int ver_minor, int patch_level, int rt)
1844 {
1845 if ( TTCN3_MAJOR != ver_major
1846 || TTCN3_MINOR != ver_minor
1847 || TTCN3_PATCHLEVEL != patch_level)
1848 {
1849 TTCN_error(
1850 "Version mismatch detected: generated code %d.%d.pl%d, "
1851 "runtime is %d.%d.pl%d",
1852 ver_major, ver_minor, patch_level,
1853 TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL);
1854 }
1855
1856 if (TITAN_RUNTIME_NR != rt) {
1857 TTCN_error("Runtime mismatch detected: files compiled for the %stest"
1858 " runtime cannot be linked to %stest library",
1859 runtime_name[TITAN_RUNTIME_NR], runtime_name[rt]);
1860 }
1861 }
1862
1863 reffer::reffer(const char*) {}
1864
This page took 0.088707 seconds and 5 git commands to generate.