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