1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Robert Galkowski
5 : * Contact e-mail: DG.MIN-Support@nokia.com
6 : *
7 : * This program is free software: you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the Free
9 : * Software Foundation, version 2 of the License.
10 : *
11 : * This program is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : * more details. You should have received a copy of the GNU General Public
15 : * License along with this program. If not, see
16 : * <http://www.gnu.org/licenses/>.
17 : */
18 :
19 :
20 : /**
21 : * @file tec_rcp_handling.c
22 : * @version 0.1
23 : * @brief This file contains implementation of min RCP message handling
24 : */
25 :
26 : /* ------------------------------------------------------------------------- */
27 : /* INCLUDE FILES */
28 : #include <tec.h>
29 : #include <tec_events.h>
30 : #include <data_api.h>
31 : #include <string.h>
32 : #include <scripter_keyword.h>
33 : #include <mintfwif.h>
34 : #include <min_engine_api.h>
35 : #ifndef MIN_EXTIF
36 : #include <sys/socket.h>
37 : #include <netinet/in.h>
38 : #include <arpa/inet.h>
39 : #include <tec_tcp_handling.h>
40 : #endif
41 :
42 : /* ------------------------------------------------------------------------- */
43 : /* EXTERNAL DATA STRUCTURES */
44 : #ifdef MIN_EXTIF
45 : extern tfwif_callbacks_s tfwif_callbacks;
46 : #endif
47 : extern eapiIn_t *in;
48 :
49 : /* ------------------------------------------------------------------------- */
50 : /* EXTERNAL GLOBAL VARIABLES */
51 : extern pthread_mutex_t tec_mutex_;
52 :
53 : /* ------------------------------------------------------------------------- */
54 : /* EXTERNAL FUNCTION PROTOTYPES */
55 : /* ------------------------------------------------------------------------- */
56 : extern char *strcasestr (__const char *__haystack, __const char *__needle);
57 :
58 : /* GLOBAL VARIABLES */
59 : /** List containing association data for master - slave system
60 : (slave_info structures)*/
61 : DLList *ms_assoc;
62 : DLList *EXTIF_received_data;
63 : #ifdef MIN_EXTIF
64 : min_case_complete_func original_complete_callback;
65 : #endif
66 : TSBool ok_to_break; /*flag stating if it is ok to revert back to
67 : * normal external controller communication
68 : * instead of slave mode */
69 : /* ------------------------------------------------------------------------- */
70 : /* CONSTANTS */
71 : /* None */
72 :
73 : /* ------------------------------------------------------------------------- */
74 : /* MACROS */
75 : /* None */
76 :
77 : /* ------------------------------------------------------------------------- */
78 : /* LOCAL GLOBAL VARIABLES */
79 : /* None */
80 :
81 : /* ------------------------------------------------------------------------- */
82 : /* LOCAL CONSTANTS AND MACROS */
83 : /* None */
84 :
85 : /* ------------------------------------------------------------------------- */
86 : /* MODULE DATA STRUCTURES */
87 : /* None */
88 : /* ------------------------------------------------------------------------- */
89 : /* LOCAL FUNCTION PROTOTYPES */
90 : /* ------------------------------------------------------------------------- */
91 : LOCAL int min_if_dispatch_extif_msg (MinItemParser * extif_message);
92 : /* ------------------------------------------------------------------------- */
93 : LOCAL int extif_msg_handle_reserve (MinItemParser * extif_message);
94 : /* ------------------------------------------------------------------------- */
95 : LOCAL int extif_msg_handle_release (MinItemParser * extif_message);
96 : /* ------------------------------------------------------------------------- */
97 : #ifdef MIN_EXTIF
98 : LOCAL int extif_msg_handle_response (MinItemParser * extif_message);
99 : #endif
100 : /* ------------------------------------------------------------------------- */
101 : LOCAL int extif_msg_handle_command (MinItemParser * extif_message);
102 : /* ------------------------------------------------------------------------- */
103 : LOCAL int handle_remote_run (MinItemParser * extif_message);
104 : /* ------------------------------------------------------------------------- */
105 : LOCAL int handle_remote_pause (MinItemParser * extif_message,
106 : int case_id);
107 : /* ------------------------------------------------------------------------- */
108 : LOCAL int handle_remote_cancel (MinItemParser * extif_message,
109 : int case_id);
110 : /* ------------------------------------------------------------------------- */
111 : LOCAL int splithex (char *hex, int *dev_id, int *case_id);
112 : /* ------------------------------------------------------------------------- */
113 : LOCAL int handle_remote_sendreceive (MinItemParser * extif_message,
114 : int dev_id);
115 : /* ------------------------------------------------------------------------- */
116 : LOCAL slave_info *find_slave_by_addrinfo (struct addrinfo *ai,
117 : DLListIterator *itp);
118 : /* ------------------------------------------------------------------------- */
119 :
120 : /* ------------------------------------------------------------------------- */
121 : /* FORWARD DECLARATIONS */
122 : void master_report (int run_id, int execution_result,
123 : int test_result, char *desc);
124 : /* ==================== LOCAL FUNCTIONS ==================================== */
125 : /** Function used to split string looking like name=value into 2 parts.
126 : * It was necessary, because parser has only functionality to extract value
127 : * only if name is known. Remember to deallocate "name" and "value" after
128 : * they are not needed.
129 : * @param input [in] string to be split
130 : * @param name [out] points to string containing part before "=" sign
131 : * @param var [out] points to string containing part after "=" sign
132 : * @return result of operation (0 if ok, -1 in case of problems); "name"
133 : * and "value" will be NULL if splitting fails.
134 : */
135 : LOCAL int split_string_eq (char *input, char **name, char **var)
136 1 : {
137 :
138 : char *delimiter;
139 : int name_size;
140 : int var_size;
141 :
142 1 : delimiter = strchr (input, '=');
143 1 : if (delimiter == NULL) {
144 0 : name = NULL;
145 0 : var = NULL;
146 0 : return -1;
147 : }
148 :
149 1 : var_size = strlen (delimiter + 1) + 1;
150 1 : name_size = strlen (input) - strlen (delimiter) + 1;
151 :
152 1 : *name = NEW2 (char, name_size);
153 1 : snprintf (*name, name_size, "%s", input);
154 1 : *var = NEW2 (char, var_size);
155 1 : sprintf (*var, "%s", delimiter + 1);
156 1 : MIN_DEBUG ("name = %s, var = %s", *name, *var);
157 :
158 1 : return 0;
159 :
160 : }
161 : /* ------------------------------------------------------------------------- */
162 : LOCAL int
163 : extif_send_ipc_sendrcv (long receipent, char *data_name, char *data_value)
164 1 : {
165 : MsgBuffer data_message;
166 1 : data_message.type_ = MSG_SNDRCV;
167 1 : data_message.sender_ = getpid ();
168 1 : data_message.receiver_ = receipent;
169 1 : sprintf (data_message.message_, "%s", data_name);
170 1 : sprintf (data_message.desc_, "%s", data_value);
171 :
172 1 : return mq_send_message (mq_id, &data_message);
173 : }
174 : /* ------------------------------------------------------------------------- */
175 : LOCAL int get_id_from_slavename (char *slavename)
176 1 : {
177 1 : DLListIterator work_slave_item = DLListNULLIterator;
178 : slave_info *work_slave_entry;
179 1 : work_slave_item = dl_list_head (ms_assoc);
180 1 : int retval = -1;
181 1 : if (strcmp (slavename, "master") == 0)
182 0 : retval = 0xdead;
183 : else {
184 2 : while (work_slave_item != DLListNULLIterator) {
185 1 : work_slave_entry =
186 : (slave_info *) dl_list_data (work_slave_item);
187 1 : if (strcasecmp
188 : (tx_share_buf (work_slave_entry->slave_name_),
189 : slavename) == 0) {
190 1 : retval = work_slave_entry->slave_id_;
191 1 : break;
192 : }
193 0 : work_slave_item = dl_list_next (work_slave_item);
194 : }
195 : }
196 1 : return retval;
197 : }
198 : /* ------------------------------------------------------------------------- */
199 : LOCAL int extif_msg_handle_release (MinItemParser * extif_message)
200 1 : {
201 : /*restore original "complete" callback if allowed, otherwise mark that
202 : it's allowed */
203 1 : send_to_master (0, "release 0");
204 :
205 1 : if (ok_to_break == ESTrue) {
206 : #ifdef MIN_EXTIF
207 0 : tfwif_callbacks.complete_callback_ = original_complete_callback;
208 : #else
209 : ;
210 : #endif
211 : } else
212 1 : ok_to_break = ESTrue;
213 :
214 1 : return 0;
215 : }
216 : /* ------------------------------------------------------------------------- */
217 : LOCAL void
218 : tec_ms_handle_data_request (int slave_id, char *varname, long requester)
219 1 : {
220 1 : DLListIterator work_data_item = DLListNULLIterator;
221 : received_data *work_data_entry;
222 : MsgBuffer ipc_message;
223 1 : pthread_mutex_lock (&tec_mutex_);
224 :
225 1 : work_data_item = dl_list_head (EXTIF_received_data);
226 2 : while (work_data_item != DLListNULLIterator) {
227 0 : work_data_entry =
228 : (received_data *) dl_list_data (work_data_item);
229 0 : MIN_DEBUG (" > %d : %d < ", work_data_entry->sender_id_,
230 : slave_id);
231 0 : MIN_DEBUG (" > %s : %s < ", work_data_entry->data_name_,
232 : varname);
233 :
234 0 : if ((work_data_entry->sender_id_ == slave_id) &&
235 : (strcmp (work_data_entry->data_name_, varname) == 0)) {
236 : /*data entry exists already - data was received */
237 0 : MIN_DEBUG ("FOUND SOME DATA ENTRY");
238 0 : break;
239 : }
240 0 : work_data_item = dl_list_next (work_data_item);
241 : }
242 1 : if (work_data_item != DLListNULLIterator) {
243 0 : work_data_entry->requested_by_ = requester;
244 0 : ipc_message.type_ = MSG_SNDRCV;
245 0 : ipc_message.sender_ = getpid ();
246 0 : ipc_message.receiver_ = work_data_entry->requested_by_;
247 0 : sprintf (ipc_message.message_, "%s",
248 : work_data_entry->data_name_);
249 0 : sprintf (ipc_message.desc_, "%s", work_data_entry->data_);
250 0 : MIN_DEBUG ("returning data");
251 0 : mq_send_message (mq_id, &ipc_message);
252 : } else {
253 1 : work_data_entry = NEW (received_data);
254 1 : work_data_entry->sender_id_ = slave_id;
255 1 : sprintf (work_data_entry->data_name_, "%s", varname);
256 1 : work_data_entry->requested_by_ = requester;
257 1 : MIN_DEBUG ("Caching request:");
258 1 : MIN_DEBUG ("sender_id_ = %d", work_data_entry->sender_id_);
259 1 : MIN_DEBUG ("varname = %s", work_data_entry->data_name_);
260 1 : dl_list_add (EXTIF_received_data, (void *)work_data_entry);
261 : }
262 1 : pthread_mutex_unlock (&tec_mutex_);
263 1 : }
264 : /* ------------------------------------------------------------------------- */
265 : LOCAL int extif_msg_handle_command (MinItemParser * extif_message)
266 2 : {
267 :
268 2 : char *srcaddr = NULL;
269 2 : char *destaddr = NULL;
270 2 : char *token = NULL;
271 2 : int dev_id = 0;
272 2 : int case_id = -1;
273 2 : int retval = 0;
274 : TScripterKeyword kw;
275 :
276 2 : mip_get_next_string (extif_message, &srcaddr);
277 2 : mip_get_next_string (extif_message, &destaddr);
278 2 : splithex (destaddr, &dev_id, &case_id);
279 2 : MIN_DEBUG (">>destaddr = %s<<", destaddr);
280 2 : MIN_DEBUG (">> dev_id = %d, case_id = %d<<", dev_id, case_id);
281 2 : mip_get_next_string (extif_message, &token);
282 :
283 2 : MIN_DEBUG ("%s: Keyword %s", __FUNCTION__,
284 : token != INITPTR ? token : "NULL");
285 :
286 2 : kw = get_keyword (token);
287 2 : switch (kw) {
288 : case EKeywordRequest:
289 : case EKeywordRelease:
290 : case EKeywordSet:
291 : case EKeywordUnset:
292 0 : retval = handle_remote_event (kw, extif_message);
293 0 : goto EXIT;
294 : break;
295 : case EKeywordRun:
296 1 : retval = handle_remote_run (extif_message);
297 0 : goto EXIT;
298 : break;
299 : case EKeywordResume:
300 0 : break;
301 : case EKeywordCancel:
302 0 : retval = handle_remote_cancel (extif_message, case_id);
303 0 : goto EXIT;
304 : break;
305 : case EKeywordPause:
306 0 : retval = handle_remote_pause (extif_message, case_id);
307 0 : goto EXIT;
308 : break;
309 : case EKeywordCancelIfError:
310 0 : break;
311 : case EKeywordSendreceive:
312 1 : splithex (srcaddr, &dev_id, &case_id);
313 1 : MIN_DEBUG (">>> %s : %d <<<", srcaddr, dev_id);
314 1 : retval = handle_remote_sendreceive (extif_message, dev_id);
315 1 : goto EXIT;
316 : break;
317 : default:
318 : case EKeywordUnknown:
319 0 : MIN_WARN ("%s: unhandled keyword %s", __FUNCTION__, token);
320 : break;
321 : }
322 1 : EXIT:
323 1 : return retval;
324 : }
325 : /* ------------------------------------------------------------------------- */
326 : /** Function handles RCP message containing sendreceive command
327 : */
328 : LOCAL int handle_remote_sendreceive (MinItemParser * extif_message, int dev_id)
329 1 : {
330 :
331 1 : char *data = NULL;
332 1 : char *data_value = NULL;
333 1 : char *data_name = NULL;
334 1 : int retval = 0;
335 : DLListIterator work_data_item;
336 : received_data *work_data_entry;
337 :
338 : /*check if data entry exists in list, i. e. it was
339 : already requested */
340 1 : mip_get_next_string (extif_message, &data);
341 :
342 1 : retval = split_string_eq (data, &data_name, &data_value);
343 1 : if (retval != 0) {
344 0 : MIN_WARN ("Faulty message format");
345 0 : return -1;
346 : }
347 :
348 1 : pthread_mutex_lock (&tec_mutex_);
349 1 : work_data_item = dl_list_head (EXTIF_received_data);
350 2 : while (work_data_item != DLListNULLIterator) {
351 1 : work_data_entry =
352 : (received_data *) dl_list_data (work_data_item);
353 1 : if ((work_data_entry->sender_id_ == dev_id)
354 : && ((strcasecmp (work_data_entry->data_name_, data_name))
355 : == 0)) {
356 1 : MIN_DEBUG (" > %d : %d < ",
357 : work_data_entry->sender_id_, dev_id);
358 1 : MIN_DEBUG (" > %s : %s < ",
359 : work_data_entry->data_name_, data_name);
360 1 : break;
361 : }
362 0 : work_data_item = dl_list_next (work_data_item);
363 : }
364 :
365 1 : if (work_data_item == DLListNULLIterator) {
366 : /*no-one mentioned this data yet, create an entry */
367 0 : work_data_entry = NEW (received_data);
368 0 : work_data_entry->sender_id_ = dev_id;
369 0 : sprintf (work_data_entry->data_name_, "%s", data_name);
370 0 : sprintf (work_data_entry->data_, "%s", data_value);
371 0 : work_data_entry->requested_by_ = 0;
372 0 : dl_list_add (EXTIF_received_data, (void *)work_data_entry);
373 0 : MIN_DEBUG ("sender_id_ = %d", work_data_entry->sender_id_);
374 0 : MIN_DEBUG ("varname = %s", work_data_entry->data_name_);
375 0 : MIN_DEBUG ("EXTIF received data has now %d entries",
376 : dl_list_size (EXTIF_received_data));
377 : } else {
378 1 : MIN_DEBUG ("data entry found");
379 1 : sprintf (work_data_entry->data_, "%s", data_value);
380 1 : extif_send_ipc_sendrcv (work_data_entry->requested_by_,
381 : data_name, data_value);
382 : /* removing used variable from buffer */
383 1 : DELETE ( work_data_entry );
384 1 : dl_list_remove_it(work_data_item);
385 : }
386 1 : pthread_mutex_unlock (&tec_mutex_);
387 1 : return 0;
388 : }
389 : /* ------------------------------------------------------------------------- */
390 : /**Function handles RCP message containing "remote run" command.
391 : * @param extif_message - pointer to item parser containing received message.
392 : * Assume that get_next_string was called several times, until "run" command
393 : * was extracted - so next get_string will give first parameter to run keyword.
394 : * @return result of operation - 0 if ok.
395 : */
396 : LOCAL int handle_remote_run (MinItemParser * extif_message)
397 1 : {
398 1 : char *module = NULL;
399 : filename_t module_filename;
400 1 : char *casefile = NULL;
401 1 : char *casefile_con = NULL; /*test case's config */
402 1 : char *temp_string = NULL;
403 1 : int caseid = 0;
404 1 : int result = 0;
405 1 : int cont_flag = 0;
406 1 : int check_result = 0;
407 1 : int i = 0; /*general purpose loop iterator */
408 1 : int mod_found = 0, conf_found = 0;
409 1 : DLListIterator work_module_item = DLListNULLIterator, it;
410 1 : test_module_info_s *work_module = INITPTR;
411 1 : DLListIterator work_case_item = DLListNULLIterator;
412 : char *message;
413 1 : int error_code = 0;
414 1 : DLList *conf_list = dl_list_create (); /* helper list for
415 : * adding module */
416 : title_string_t tc_title;
417 1 : TParsingType parsing = ENormalParsing;
418 1 : char *casetitle = NULL;
419 : filename_t name;
420 : #ifndef MIN_EXTIF
421 : test_case_s *work_case;
422 : #endif
423 1 : result = mip_get_string (extif_message, "module=", &module);
424 1 : if (result != 0) {
425 0 : MIN_WARN ("remote module not specified");
426 0 : goto FAULT;
427 : }
428 :
429 1 : result = mip_get_string (extif_message, "testcasefile=", &casefile);
430 1 : if (result != 0) {
431 1 : MIN_WARN ("test case file not specified");
432 1 : error_code = -1;
433 1 : casefile = NULL;
434 : }
435 1 : result = mip_get_int (extif_message, "testcasenum=", &caseid);
436 1 : if (result != 0) {
437 0 : MIN_WARN ("Faulty command: %s",
438 : extif_message->item_line_section_);
439 0 : MIN_WARN ("test case id not specified");
440 0 : error_code = -1;
441 0 : goto FAULT;
442 : }
443 :
444 : /*
445 : ** Check if we have the module already instantiated
446 : */
447 1 : if (!strcmp (casefile, "dummy.cfg"))
448 0 : conf_found = 1;
449 0 : for (work_module_item = dl_list_head (instantiated_modules);
450 0 : work_module_item != DLListNULLIterator;
451 0 : work_module_item = dl_list_next (work_module_item))
452 : {
453 0 : tm_get_module_filename (work_module_item, name);
454 0 : if (strcmp (module, name) == 0) {
455 0 : mod_found = 1;
456 : /*
457 : ** The module is already instantiated.
458 : ** Next check the configuration file.
459 : */
460 : for (it = dl_list_head (tm_get_cfg_filenames
461 0 : (work_module_item));
462 0 : it != DLListNULLIterator;
463 0 : it = dl_list_next (it)) {
464 0 : if (strcmp (dl_list_data (it),
465 : casefile) == 0) {
466 0 : conf_found = 1;
467 : }
468 : }
469 0 : if (conf_found && mod_found)
470 0 : goto MODULE_PRESENT;
471 : }
472 :
473 :
474 : }
475 :
476 : /*adding module specified in run command here */
477 0 : temp_string = NEW2 (char, strlen (casefile) + 1);
478 0 : sprintf (temp_string, "%s", casefile);
479 : /*add specified testcase file only if it is
480 : specified as absolute path or exists in lib directories*/
481 0 : if (((*temp_string)=='/')||
482 :
483 : (ec_search_lib(temp_string)) != -1){
484 0 : dl_list_add (conf_list, (void *)temp_string);
485 : } else {
486 0 : MIN_WARN ("test case file %s not found", temp_string);
487 : }
488 : #ifdef MIN_EXTIF
489 0 : min_if_module_add (module, !strcmp (casefile, "dummy.cfg") ?
490 : "" : temp_string);
491 : #else
492 0 : ec_add_module (module, conf_list, 0, 0);
493 : #endif
494 : /*wait for module to return testcases */
495 0 : MODULE_PRESENT:
496 0 : while (cont_flag == 0) {
497 0 : usleep (500000);
498 0 : i++;
499 0 : work_module_item = dl_list_head (instantiated_modules);
500 0 : cont_flag = 1;
501 0 : while (work_module_item != DLListNULLIterator) {
502 0 : check_result = tm_get_status (work_module_item);
503 0 : if (check_result == TEST_MODULE_READY)
504 0 : cont_flag = cont_flag | 1;
505 : else
506 0 : cont_flag = 0;
507 0 : work_module_item = dl_list_next (work_module_item);
508 : }
509 0 : if (i > 20) {
510 0 : MIN_WARN ("timeout on module instantiation");
511 0 : goto FAULT;
512 : }
513 : }
514 : /*Now fetch correct testcase */
515 0 : work_module_item = dl_list_head (instantiated_modules);
516 0 : while (work_module_item != DLListNULLIterator) {
517 0 : work_module =
518 : (test_module_info_s *) dl_list_data (work_module_item);
519 0 : tm_get_module_filename (work_module_item, module_filename);
520 0 : if (strcmp (module_filename, module) == 0)
521 0 : break;
522 0 : work_module_item = dl_list_next (work_module_item);
523 : }
524 :
525 0 : if (work_module_item == DLListNULLIterator) {
526 0 : MIN_WARN ("Specified module not configured");
527 0 : error_code = -2;
528 0 : goto FAULT;
529 : }
530 :
531 : /* test case title may contain whitespaces, that's why parsing type
532 : * is changed to QuoteStyle. if passing this optional value, it
533 : * must be quoted */
534 0 : parsing=mip_get_parsing_type(extif_message);
535 0 : mip_set_parsing_type (extif_message, EQuoteStyleParsing);
536 0 : result = mip_get_string (extif_message, "testcasetitle=", &casetitle);
537 0 : mip_set_parsing_type (extif_message, parsing);
538 0 : if (result == 0) {
539 0 : MIN_INFO ("test case title specified, omitting id");
540 :
541 0 : work_case_item = dl_list_head (tm_get_tclist (work_module_item));
542 0 : while (work_case_item != DLListNULLIterator) {
543 0 : tc_get_title (work_case_item, tc_title);
544 0 : if (strcmp(tc_title, casetitle) == 0) {
545 0 : if (dl_list_size
546 : (tm_get_cfg_filenames (work_module_item)) < 2)
547 0 : break;
548 : /*if module has 0 or 1 config file,
549 : * we have already found case */
550 : else {
551 0 : tc_get_cfg_filename (work_case_item,
552 : casefile_con);
553 0 : check_result =
554 : strcmp (casefile_con, casefile);
555 0 : DELETE (casefile_con);
556 0 : if (check_result == 0)
557 0 : break;
558 : /*id and testcase file match */
559 : }
560 : }
561 0 : work_case_item = dl_list_next (work_case_item);
562 : }
563 :
564 : } else {
565 0 : MIN_INFO ("test case title not specified, using id");
566 0 : work_case_item = dl_list_head (tm_get_tclist (work_module_item));
567 0 : while (work_case_item != DLListNULLIterator) {
568 0 : if (tc_get_id (work_case_item) == caseid) {
569 0 : if (dl_list_size
570 : (tm_get_cfg_filenames (work_module_item)) < 2)
571 0 : break;
572 : /*if module has 0 or 1 config file,
573 : * we have already found case */
574 : else {
575 0 : tc_get_cfg_filename (work_case_item,
576 : casefile_con);
577 0 : check_result =
578 : strcmp (casefile_con, casefile);
579 0 : DELETE (casefile_con);
580 0 : if (check_result == 0)
581 0 : break;
582 : /*id and testcase file match */
583 : }
584 : }
585 0 : work_case_item = dl_list_next (work_case_item);
586 : }
587 : }
588 :
589 0 : if (work_case_item == DLListNULLIterator) {
590 0 : MIN_WARN ("Wrong case id");
591 0 : error_code = -2;
592 0 : goto FAULT;
593 : }
594 :
595 0 : result = ec_exec_test_case (work_case_item);
596 0 : caseid = dl_list_size (selected_cases);
597 : #ifndef MIN_EXTIF
598 0 : work_case_item = dl_list_tail (selected_cases);
599 0 : work_case = dl_list_data (work_case_item);
600 0 : work_case->ip_slave_case_ = 1;
601 : #endif
602 :
603 0 : if (result != 0) {
604 0 : error_code = -2;
605 0 : MIN_WARN ("Error in test case execution");
606 0 : goto FAULT;
607 : }
608 0 : ok_to_break = ESFalse;
609 0 : send_to_master (caseid, "remote run started");
610 0 : return 0;
611 :
612 0 : FAULT:
613 : /*test case could not be started for some reason */
614 0 : message = NEW2 (char, 30);
615 0 : sprintf (message, "remote run error result=%d", error_code);
616 0 : send_to_master (0, message);
617 0 : DELETE (module);
618 0 : DELETE (message);
619 0 : DELETE (casefile);
620 0 : return 0;
621 : }
622 : /* ------------------------------------------------------------------------- */
623 : /**Function implemens handling of "remote pause" command
624 : * @param extif_message - pointer to item parser containing received message.
625 : * Assume that get_next_string was called several times, until "pause"
626 : * command was extracted
627 : * @param case_id - dev id extracted from external controller address field
628 : * @return result of operation - 0 if ok.
629 : */
630 : LOCAL int handle_remote_pause (MinItemParser * extif_message, int case_id)
631 0 : {
632 0 : return 0;
633 : }
634 : /* ------------------------------------------------------------------------- */
635 : /**Function implemens handling of "remote cancel" command
636 : * @param extif_message - pointer to item parser containing received message.
637 : * Assume that get_next_string was called several times, until "cancel"
638 : * command was extracted
639 : * @param case_id - dev id extracted from external controller address field
640 : * @return result of operation - 0 if ok.
641 : */
642 : LOCAL int handle_remote_cancel (MinItemParser * extif_message, int case_id)
643 0 : {
644 0 : DLListIterator work_case_item = DLListNULLIterator;
645 0 : int result = 0;
646 :
647 0 : work_case_item = dl_list_at (selected_cases, case_id - 1);
648 :
649 0 : if (work_case_item != DLListNULLIterator) {
650 0 : result = ec_abort_test_case (work_case_item);
651 : } else {
652 0 : result = -1;
653 : }
654 :
655 0 : if (result == 0) {
656 0 : send_to_master (case_id, "remote cancel");
657 : }
658 : /* Protocol specification describes only response to successfull
659 : * remote pause. If the pause was not successfull, master test
660 : * case should fail. Based on that, if remote pause fails for whatever
661 : * reason, response will not be sent - what should cause master test
662 : * case fo fail.
663 : */
664 0 : return result;
665 : }
666 : /* ------------------------------------------------------------------------- */
667 : /**Function splits RCP's adress string fields into two ints.
668 : * @param hex [in] string to be split, has to be 8 characters, otherwise
669 : * function fails
670 : * @param dev_id [out] pointer to int that will hold device id
671 : * @param case_id [out] pointer to int that will hold case id
672 : * @return result of operation, 0 if ok
673 : */
674 : LOCAL int splithex (char *hex, int *dev_id, int *case_id)
675 5 : {
676 : char dev_id_c[5];
677 : char case_id_c[5];
678 : char *endptr;
679 :
680 5 : if (strlen (hex) != 8) {
681 0 : return -1;
682 : }
683 :
684 5 : snprintf (dev_id_c, 5, "%s", hex);
685 5 : snprintf (case_id_c, 5, "%s", hex + 4);
686 5 : *dev_id = strtol (dev_id_c, &endptr, 16);
687 5 : *case_id = strtol (case_id_c, &endptr, 16);
688 :
689 5 : return 0;
690 : }
691 : /* ------------------------------------------------------------------------- */
692 : /** Function writes text representation of slave adress, in hexadecimal with
693 : * leading zeros
694 : * @param deviceid identifier of device
695 : * @param caseid id of testcase
696 : * @return string containing proper representation, or INITPTR
697 : * in case of problem.
698 : */
699 :
700 : LOCAL char *writehex (int devid, int caseid)
701 9 : {
702 9 : char *hex = NEW2 (char, 9);
703 9 : int val = devid * 0x10000 + caseid;
704 :
705 : if (val > 0xffffffff) {
706 : DELETE (hex);
707 : } else {
708 9 : sprintf (hex, "%.8x", val);
709 : }
710 :
711 9 : return hex;
712 : }
713 : /* ------------------------------------------------------------------------- */
714 : /**Function recognizes message received from external controller and calls
715 : * apropriate handler
716 : * @param extif_message pointer to MinItemParser with parser created
717 : * from message string.
718 : * @return result of operation, 0 if successfull.
719 : */
720 : LOCAL int min_if_dispatch_extif_msg (MinItemParser * extif_message)
721 12 : {
722 : /*strings used to parse fields of RCP message */
723 12 : char *messtype = NULL;
724 :
725 12 : int result = 666;
726 :
727 12 : result = mip_get_string (extif_message, "", &messtype);
728 :
729 12 : if (result != 0) {
730 0 : MIN_WARN ("Could not get EXTIF message type");
731 0 : goto DISPATCH_EXIT;
732 : }
733 :
734 12 : if (strcasestr (messtype, "reserve") != NULL) {
735 :
736 3 : result = extif_msg_handle_reserve (extif_message);
737 3 : goto DISPATCH_EXIT;
738 : }
739 :
740 9 : if (strcasestr (messtype, "release") != NULL) {
741 1 : result = extif_msg_handle_release (extif_message);
742 1 : goto DISPATCH_EXIT;
743 : }
744 :
745 8 : if (strcasestr (messtype, "response") != NULL) {
746 : #ifdef MIN_EXTIF
747 2 : result = extif_msg_handle_response (extif_message);
748 : #else
749 4 : result = tcp_msg_handle_response (extif_message);
750 :
751 : #endif
752 6 : goto DISPATCH_EXIT;
753 : }
754 :
755 2 : if (strcasestr (messtype, "remote") != NULL) {
756 2 : result = extif_msg_handle_command (extif_message);
757 1 : goto DISPATCH_EXIT;
758 : }
759 :
760 11 : DISPATCH_EXIT:
761 11 : DELETE (messtype);
762 :
763 11 : return result;
764 : }
765 : /* ------------------------------------------------------------------------- */
766 : /**Function handles "response" message coming from external controller
767 : * @param extif_message pointer to item parser. It is assumed that
768 : * mip_get_string was executed once for this parser to get first "word"
769 : * @return result of operation, 0 if ok.
770 : */
771 : #ifdef MIN_EXTIF
772 : LOCAL int extif_msg_handle_response (MinItemParser * extif_message)
773 2 : {
774 2 : char *command = INITPTR;
775 2 : char *param1 = NULL;
776 2 : char *srcid = INITPTR;
777 2 : char *destid = INITPTR;
778 2 : int result = 666;
779 2 : int retval = 666;
780 2 : int slave_id = 0;
781 2 : int case_id = 0;
782 : MsgBuffer ipc_message;
783 2 : slave_info *slave_entry = INITPTR;
784 2 : char *slave_name = NULL;
785 : DLListIterator slave_entry_item;
786 :
787 2 : mip_get_next_string (extif_message, &srcid);
788 :
789 2 : mip_get_next_string (extif_message, &destid);
790 :
791 2 : mip_get_next_string (extif_message, &command);
792 :
793 2 : if (strcasecmp (command, "reserve") == 0) {
794 1 : retval =
795 : mip_get_next_tagged_int (extif_message, "result=", &result);
796 :
797 1 : if (retval == -1)
798 1 : mip_get_next_int (extif_message, &result);
799 : /*result was not tagged int */
800 1 : if (retval == -1)
801 1 : result = 0;
802 :
803 : /*it seems that result was not send, assume success */
804 :
805 : /* now find slave entry without device id. Currently
806 : * external controller picks first available slave during
807 : * allocation, so we do the same */
808 1 : slave_entry_item = dl_list_head (ms_assoc);
809 2 : while (slave_entry_item != INITPTR) {
810 1 : slave_entry =
811 : (slave_info *) dl_list_data (slave_entry_item);
812 1 : MIN_DEBUG (" slave: %d, %s", slave_entry->slave_id_,
813 : tx_share_buf (slave_entry->slave_name_));
814 1 : if (slave_entry->slave_id_ == 0) {
815 1 : slave_name = tx_get_buf
816 : (slave_entry->slave_name_);
817 1 : break;
818 : }
819 0 : slave_entry_item = dl_list_next (slave_entry_item);
820 : }
821 1 : if (slave_name == NULL) {
822 0 : MIN_WARN ("Unrequested response ?");
823 0 : retval = -1;
824 0 : goto out;
825 : }
826 1 : splithex (srcid, &slave_id, &case_id);
827 1 : slave_entry->slave_id_ = slave_id;
828 1 : if (retval == -1)
829 1 : result = 0;
830 : /*it seems that result was not sent, assume success */
831 1 : ipc_message.sender_ = ec_settings.engine_pid_;
832 1 : ipc_message.receiver_ = own_id;
833 1 : ipc_message.type_ = MSG_EXTIF;
834 1 : ipc_message.special_ = 0;
835 1 : ipc_message.extif_msg_type_ = EResponseSlave;
836 1 : ipc_message.param_ = result;
837 1 : MIN_DEBUG ("ipc sending with result %d", result);
838 1 : mq_send_message (mq_id, &ipc_message);
839 1 : DELETE (slave_name);
840 1 : retval = 0;
841 1 : } else if (strcasecmp (command, "release") == 0) {
842 1 : retval =
843 : mip_get_next_tagged_int (extif_message, "result=", &result);
844 1 : if (retval == -1)
845 1 : mip_get_next_int (extif_message, &result);
846 : /*result was not tagged int */
847 1 : if (retval == -1)
848 1 : result = 0;
849 : /*it seems that result was not send, assume success */
850 1 : ipc_message.sender_ = ec_settings.engine_pid_;
851 1 : ipc_message.receiver_ = own_id;
852 1 : ipc_message.type_ = MSG_EXTIF;
853 1 : ipc_message.param_ = result;
854 1 : ipc_message.special_ = 0;
855 1 : ipc_message.extif_msg_type_ = EResponseSlave;
856 1 : MIN_DEBUG ("ipc sending with result %d", result);
857 1 : mq_send_message (mq_id, &ipc_message);
858 : /*slave released, remove it from ms_assoc */
859 1 : splithex (srcid, &slave_id, &case_id);
860 1 : slave_entry_item = dl_list_head (ms_assoc);
861 2 : while (slave_entry_item != DLListNULLIterator) {
862 :
863 1 : slave_entry =
864 : (slave_info *) dl_list_data (slave_entry_item);
865 1 : if (slave_entry->slave_id_ == slave_id) {
866 1 : DELETE (slave_entry);
867 1 : dl_list_remove_it (slave_entry_item);
868 1 : break;
869 : }
870 :
871 : }
872 1 : retval = 0;
873 0 : } else if (strcasecmp (command, "remote") == 0) {
874 0 : mip_get_next_string (extif_message, &command);
875 0 : if (strcasecmp (command, "run") == 0) {
876 0 : splithex (srcid, &slave_id, &case_id);
877 : /*translate received caseid into proper
878 : number that can be stored in scripter*/
879 0 : case_id = (slave_id<<16) + case_id;
880 0 : mip_get_next_string (extif_message, ¶m1);
881 0 : if (strcasecmp (param1, "started") == 0) {
882 0 : ipc_message.sender_ = ec_settings.engine_pid_;
883 0 : ipc_message.receiver_ = own_id;
884 0 : ipc_message.type_ = MSG_EXTIF;
885 0 : ipc_message.special_ = case_id;
886 0 : ipc_message.param_ = 0;
887 0 : ipc_message.extif_msg_type_ = EResponseSlave;
888 0 : MIN_DEBUG ("ipc sending with result 0");
889 0 : mq_send_message (mq_id, &ipc_message);
890 0 : retval = 0;
891 0 : } else if (strcasecmp (param1, "ready") == 0) {
892 0 : mip_get_int (extif_message, "result=", &result);
893 0 : ipc_message.sender_ = ec_settings.engine_pid_;
894 0 : ipc_message.receiver_ = own_id;
895 0 : ipc_message.type_ = MSG_EXTIF;
896 0 : ipc_message.special_ = case_id;
897 0 : ipc_message.param_ = result;
898 0 : ipc_message.extif_msg_type_ =
899 : ERemoteSlaveResponse;
900 0 : MIN_DEBUG ("ipc sending with result %d",
901 : result);
902 0 : mq_send_message (mq_id, &ipc_message);
903 0 : retval = 0;
904 :
905 0 : } else if (strcasecmp (param1, "error") == 0) {
906 0 : mip_get_int (extif_message, "result=", &result);
907 0 : ipc_message.sender_ = ec_settings.engine_pid_;
908 0 : ipc_message.receiver_ = own_id;
909 0 : ipc_message.type_ = MSG_EXTIF;
910 0 : ipc_message.special_ = case_id;
911 0 : ipc_message.param_ = result;
912 0 : ipc_message.extif_msg_type_ = EResponseSlave;
913 0 : MIN_DEBUG ("ipc sending with result %d",
914 : result);
915 0 : mq_send_message (mq_id, &ipc_message);
916 0 : retval = 0;
917 : }
918 0 : } else if (strcasecmp (command, "request") == 0) {
919 0 : retval =
920 : handle_remote_event_request_resp (extif_message);
921 0 : } else if (strcasecmp (command, "release") == 0)
922 : /*TEMPORARY SOLUTION, INVESTIGATE EVENT SYSTEM */
923 0 : retval = 0;
924 : }
925 2 : out:
926 2 : DELETE (command);
927 2 : DELETE (param1);
928 2 : DELETE (srcid);
929 2 : DELETE (destid);
930 :
931 2 : return retval;
932 : }
933 : #endif
934 : /* ------------------------------------------------------------------------- */
935 : /** Function handles external controller "reserve" message
936 : * @param extif_message pointer to item parser. It is assumed that
937 : * mip_get_string was executed once for this parser to get first "word"
938 : * @return result of operation, 0 if ok.
939 : */
940 : LOCAL int extif_msg_handle_reserve (MinItemParser * extif_message)
941 3 : {
942 : char rtype[11];
943 : #ifndef MIN_EXTIF
944 :
945 0 : char *srcid = INITPTR;
946 0 : char *destid = INITPTR;
947 0 : int dev_id = 0;
948 0 : int case_id = -1;
949 : #endif
950 : /*change "complete case" callback */
951 3 : pthread_mutex_lock (&tec_mutex_);
952 3 : ok_to_break = ESFalse;
953 :
954 : #ifdef MIN_EXTIF
955 3 : original_complete_callback = tfwif_callbacks.complete_callback_;
956 3 : MIN_DEBUG ("old callback = %x ", tfwif_callbacks.complete_callback_);
957 3 : MIN_DEBUG ("master report = %x ", master_report);
958 3 : tfwif_callbacks.complete_callback_ = master_report;
959 3 : MIN_DEBUG ("new callback = %x ", tfwif_callbacks.complete_callback_);
960 : #else
961 0 : mip_get_next_string (extif_message, &srcid);
962 0 : mip_get_next_string (extif_message, &destid);
963 0 : splithex (destid, &dev_id, &case_id);
964 0 : own_id = dev_id;
965 : #endif
966 :
967 3 : pthread_mutex_unlock (&tec_mutex_);
968 3 : sprintf (rtype, "reserve 0");
969 3 : send_to_master (0, rtype);
970 :
971 3 : return 0;
972 : }
973 : /* ------------------------------------------------------------------------- */
974 : /** Searches for slave based on address
975 : * @param ai address information
976 : * @param itp OUT used to pass the DLListIterator to caller
977 : * @return slave_info if found, otherwise INITPTR
978 : */
979 : LOCAL slave_info *find_slave_by_addrinfo (struct addrinfo *ai,
980 : DLListIterator *itp)
981 16 : {
982 : DLListIterator it;
983 : slave_info *ips;
984 :
985 16 : *itp = INITPTR;
986 :
987 39 : for (it = dl_list_head (ms_assoc); it != INITPTR;
988 7 : it = dl_list_next (it)) {
989 7 : ips = dl_list_data (it);
990 7 : if (!memcmp (ai, ips->addrinfo_, sizeof (struct addrinfo))) {
991 0 : *itp = it;
992 0 : return ips;
993 : }
994 : }
995 :
996 16 : return INITPTR;
997 : }
998 :
999 : /* ======================== FUNCTIONS ===================================== */
1000 :
1001 : /*---------------------------------------------------------------------------*/
1002 : /** Function called to intitialize rcp handling
1003 : */
1004 : void rcp_handling_init ()
1005 124 : {
1006 124 : ms_assoc = dl_list_create();
1007 124 : EXTIF_received_data = dl_list_create();
1008 124 : }
1009 : /*---------------------------------------------------------------------------*/
1010 : /** Clean up
1011 : */
1012 : void rcp_handling_cleanup ()
1013 19 : {
1014 : DLListIterator work_slave_item;
1015 : DLListIterator work_data_item;
1016 : received_data *work_data_entry;
1017 : slave_info *slave;
1018 19 : work_slave_item = dl_list_head (ms_assoc);
1019 50 : while (work_slave_item != DLListNULLIterator) {
1020 12 : slave = dl_list_data (work_slave_item);
1021 12 : if (slave->write_queue_)
1022 12 : dl_list_free (&slave->write_queue_);
1023 12 : if (slave->slave_name_)
1024 12 : tx_destroy (&slave->slave_name_);
1025 12 : if (slave->slave_type_)
1026 12 : tx_destroy (&slave->slave_type_);
1027 12 : if (slave->addrinfo_)
1028 12 : freeaddrinfo (slave->addrinfo_);
1029 12 : DELETE (slave);
1030 12 : dl_list_remove_it (work_slave_item);
1031 12 : work_slave_item = dl_list_head (ms_assoc);
1032 : }
1033 19 : dl_list_free (&ms_assoc);
1034 :
1035 19 : work_data_item = dl_list_head (EXTIF_received_data);
1036 38 : while (work_data_item != DLListNULLIterator) {
1037 0 : work_data_entry =
1038 : (received_data *) dl_list_data (work_data_item);
1039 0 : DELETE (work_data_entry);
1040 0 : dl_list_remove_it (work_data_item);
1041 0 : work_data_item = dl_list_head (EXTIF_received_data);
1042 : }
1043 19 : dl_list_free (&EXTIF_received_data);
1044 :
1045 19 : }
1046 :
1047 : /* ------------------------------------------------------------------------- */
1048 : /** Function called to send external controller message to master device.
1049 : * @param tc_id id of slave's test case
1050 : * @param msg NULL-terminated string containing body of message
1051 : * (everything following adresses)
1052 : */
1053 : void send_to_master (int tc_id, char *msg)
1054 4 : {
1055 :
1056 : char *hex;
1057 :
1058 4 : if (tc_id != 0) {
1059 0 : tc_id = dl_list_size (selected_cases);
1060 : }
1061 4 : hex = writehex (own_id, tc_id);
1062 4 : in->send_rcp ("response", hex, "deadbeef", msg, 0);
1063 :
1064 4 : DELETE (hex);
1065 4 : }
1066 :
1067 : /*---------------------------------------------------------------------------*/
1068 : /** Function called to send external controller message to slave device.
1069 : * @param slave_name NULL-terminated string containing slave's name
1070 : * @param tc_id id of slave's test case
1071 : * @param msg NULL-terminated string containing body of message
1072 : * (everything following adresses)
1073 : */
1074 : void
1075 : send_to_slave (TMSCommand command, char *slave_name, int tc_id, char *message)
1076 5 : {
1077 5 : DLListIterator slave_entry_item = DLListNULLIterator;
1078 5 : slave_info *slave_entry = INITPTR;
1079 5 : int slave_id = 0;
1080 : char *hex;
1081 :
1082 5 : slave_entry_item = dl_list_head (ms_assoc);
1083 10 : while (slave_entry_item != DLListNULLIterator) {
1084 5 : slave_entry = (slave_info *) dl_list_data (slave_entry_item);
1085 5 : if (slave_entry->slave_name_ != INITPTR &&
1086 : strcmp (slave_name,
1087 : tx_share_buf (slave_entry->slave_name_)) == 0) {
1088 5 : slave_id = slave_entry->slave_id_;
1089 5 : break;
1090 : }
1091 0 : slave_entry_item = dl_list_next (slave_entry_item);
1092 : }
1093 : /* scripter keeps tc_id as a combination of slave id and testcase
1094 : * number (slave number as last 4 digits), test case id needs to
1095 : * be stripped if given at all. Not used in current implementation,
1096 : * since all calls to this function give 0 in this argument so far,
1097 : * but it might prevent problems in in case someone wants to expand
1098 : * functionality.*/
1099 5 : if (tc_id != 0){
1100 0 : tc_id = tc_id&0xffff; /*to strip slave id*/
1101 : }
1102 5 : hex = writehex (slave_id, tc_id);
1103 5 : switch (command) {
1104 : case EAllocateSlave:
1105 2 : sleep (1);
1106 2 : in->send_rcp ("reserve", "deadbeef", hex, message,
1107 : slave_entry->fd_);
1108 2 : break;
1109 : case EFreeSlave:
1110 2 : in->send_rcp ("release", "deadbeef", hex, message,
1111 : slave_entry->fd_);
1112 2 : break;
1113 : case ERemoteSlave:
1114 1 : if (!strncmp (message, "run", 3)) {
1115 1 : slave_entry->run_cnt_++;
1116 : }
1117 1 : MIN_DEBUG ("slave_entry = %x, run count = %d",
1118 : slave_entry, slave_entry->run_cnt_);
1119 1 : in->send_rcp ("remote", "deadbeef", hex, message,
1120 : slave_entry->fd_);
1121 : break;
1122 : default:
1123 : break;
1124 : }
1125 5 : DELETE (hex);
1126 5 : }
1127 : /* ------------------------------------------------------------------------- */
1128 : /**Handler for sendreceive ipc message from slave
1129 : */
1130 : int ec_msg_sndrcv_handler (MsgBuffer * message)
1131 0 : {
1132 : char *hex;
1133 : Text *tx;
1134 0 : tx = tx_create ("sendreceive ");
1135 0 : tx_c_append (tx, message->message_);
1136 0 : tx_c_append (tx, "=");
1137 0 : tx_c_append (tx, message->desc_);
1138 0 : hex = writehex (own_id, 0);
1139 0 : in->send_rcp ("remote", hex, "deadbeef", tx_share_buf(tx), 0);
1140 :
1141 0 : tx_destroy (&tx);
1142 0 : DELETE (hex);
1143 0 : return 0;
1144 : }
1145 : /* ------------------------------------------------------------------------- */
1146 : /** Handler for ipc external controller message,
1147 : * used in master/slave scenarios (hence _ms_);
1148 : * since those in turn have several "subtypes",
1149 : * function reads type and calls apropriate handlers.
1150 : * @param message MsgBUffer containing received IPC message
1151 : * @return result of the operation
1152 : */
1153 : int ec_msg_ms_handler (MsgBuffer * message)
1154 6 : {
1155 6 : char *extifmessage = NULL;
1156 6 : char *param1 = NULL;
1157 6 : char *param2 = NULL;
1158 6 : char *param3 = NULL;
1159 6 : char *param4 = NULL;
1160 6 : char *param5 = NULL;
1161 : TScripterKeyword kw;
1162 6 : TParsingType parsing=ENormalParsing;
1163 :
1164 6 : MinItemParser *params = INITPTR;
1165 : #ifdef MIN_EXTIF
1166 2 : slave_info *slave_entry = INITPTR;
1167 : #endif
1168 :
1169 6 : extifmessage = NEW2 (char, strlen (message->message_) + 255);
1170 :
1171 6 : switch (message->extif_msg_type_) {
1172 : case EAllocateSlave:
1173 : /* since only master test case can send this message,
1174 : we will set own_id of this min instance to PID of this
1175 : TMC, so that we can forward IPC messages correctly */
1176 :
1177 2 : own_id = message->sender_;
1178 : #ifdef MIN_EXTIF
1179 1 : slave_entry = NEW (slave_info);
1180 1 : memset (slave_entry, 0x0, sizeof (slave_info));
1181 1 : slave_entry->slave_name_ = tx_create (message->message_);
1182 1 : slave_entry->slave_id_ = 0;
1183 1 : slave_entry->run_cnt_ = 0;
1184 1 : dl_list_add (ms_assoc, (void *)slave_entry);
1185 : #else
1186 1 : if (allocate_ip_slave (message->desc_, message->message_,
1187 : own_id)) {
1188 0 : MIN_FATAL ("slave allocation failed");
1189 0 : DELETE (extifmessage);
1190 0 : return -1;
1191 : }
1192 : #endif
1193 2 : send_to_slave (EAllocateSlave, message->message_, 0,
1194 : message->desc_);
1195 2 : break;
1196 :
1197 : case EFreeSlave:
1198 :
1199 2 : send_to_slave (EFreeSlave, message->message_, 0, "");
1200 2 : break;
1201 :
1202 : case ERemoteSlave:
1203 2 : MIN_DEBUG ("MESSAGE: %s\n", message->message_);
1204 2 : MIN_DEBUG ("DESC: %s\n", message->desc_);
1205 2 : params =
1206 : mip_create (message->desc_, 0,
1207 : strlen (message->desc_) + 1);
1208 2 : mip_get_string (params, "", ¶m1);
1209 :
1210 :
1211 2 : kw = get_keyword (param1);
1212 2 : switch (kw) {
1213 : case EKeywordRun:
1214 1 : mip_get_next_string (params, ¶m2);
1215 1 : mip_get_next_string (params, ¶m3);
1216 1 : mip_get_next_string (params, ¶m4);
1217 : /* parsing is set to QuoteStyle, because test case
1218 : * title may contain whitespaces */
1219 1 : parsing=mip_get_parsing_type (params);
1220 1 : mip_set_parsing_type (params, EQuoteStyleParsing);
1221 : /* if title is specified, it's passed in here... */
1222 1 : if(mip_get_next_string (params, ¶m5) == 0){
1223 0 : sprintf (extifmessage, "run module=%s "
1224 : "testcasefile=%s testcasenum=%s "
1225 : "testcasetitle=\"%s\"", param2,
1226 : param3, param4, param5);
1227 : /* if it's not, id is used for compatibility */
1228 : } else {
1229 1 : sprintf (extifmessage, "run module=%s "
1230 : "testcasefile=%s testcasenum=%s", param2,
1231 : param3, param4);
1232 : }
1233 1 : mip_set_parsing_type (params, parsing);
1234 :
1235 1 : break;
1236 : case EKeywordSet:
1237 0 : mip_get_next_string (params, ¶m2);
1238 0 : sprintf (extifmessage, "set %s", param2);
1239 0 : if (mip_get_next_string (params, ¶m3) == ENOERR)
1240 0 : sprintf (extifmessage + strlen (extifmessage),
1241 : " type=%s", param3);
1242 0 : break;
1243 : case EKeywordRequest:
1244 0 : mip_get_next_string (params, ¶m2);
1245 0 : sprintf (extifmessage, "request %s", param2);
1246 0 : if (mip_get_next_string (params, ¶m3) == ENOERR)
1247 0 : sprintf (extifmessage + strlen (extifmessage),
1248 : " type=%s", param3);
1249 0 : break;
1250 : case EKeywordExpect:
1251 1 : mip_get_next_string (params, ¶m2);
1252 1 : tec_ms_handle_data_request (get_id_from_slavename
1253 : (message->message_),
1254 : param2, message->sender_);
1255 1 : DELETE (extifmessage);
1256 1 : return 0;
1257 : break;
1258 : case EKeywordRelease:
1259 : case EKeywordWait:
1260 : case EKeywordUnset:
1261 :
1262 : default:
1263 0 : strcpy (extifmessage, message->desc_);
1264 : break;
1265 : }
1266 1 : send_to_slave (ERemoteSlave, message->message_, 0,
1267 : extifmessage);
1268 1 : break;
1269 : default:
1270 0 : MIN_DEBUG ("MESSAGE: %s\n", message->message_);
1271 0 : MIN_DEBUG ("DESC: %s\n", message->desc_);
1272 : break;
1273 : }
1274 :
1275 5 : DELETE (extifmessage);
1276 5 : DELETE (param1);
1277 5 : DELETE (param2);
1278 5 : DELETE (param3);
1279 5 : DELETE (param4);
1280 5 : DELETE (param5);
1281 5 : mip_destroy (¶ms);
1282 :
1283 5 : return 0;
1284 : }
1285 : /* ------------------------------------------------------------------------- */
1286 : /** Function reads message received from external controller and
1287 : * calls handling
1288 : */
1289 : int tec_extif_message_received (char *message, int length)
1290 12 : {
1291 12 : MinItemParser *extif_message = INITPTR;
1292 12 : int result = 666;
1293 :
1294 12 : MIN_DEBUG ("tec_extif_message_received: length %d", length);
1295 12 : MIN_DEBUG ("EXTIF SAYS: %s", message);
1296 12 : extif_message = mip_create (message, 0, length);
1297 12 : if (extif_message != INITPTR) {
1298 12 : result = min_if_dispatch_extif_msg (extif_message);
1299 11 : mip_destroy (&extif_message);
1300 : } else {
1301 0 : result = -1;
1302 0 : MIN_WARN ("Could not create item parser object");
1303 : }
1304 11 : MIN_DEBUG (" RETURNING: %d ", result);
1305 :
1306 11 : return result;
1307 : }
1308 : /* ------------------------------------------------------------------------- */
1309 : /** Function that replaces "test case complete" callback, if min instance
1310 : * is used as slave.
1311 : * @param run_id runtime id of test case (position in "selected cases" list)
1312 : * @param execution_result indicates if starting of test case was successful
1313 : * @param test_result result of test
1314 : * @param desc description (taken from ipc message);
1315 : */
1316 : void
1317 : master_report (int run_id, int execution_result, int test_result, char *desc)
1318 0 : {
1319 0 : DLListIterator finished_case_item = DLListNULLIterator;
1320 0 : DLListIterator work_module_item = DLListNULLIterator;
1321 : char *extifmessage;
1322 :
1323 0 : MIN_DEBUG ("MIN CALLBACK");
1324 : /*let's get module pid from finished case */
1325 0 : finished_case_item = dl_list_at (selected_cases, run_id);
1326 0 : work_module_item = tc_get_test_module_ptr (finished_case_item);
1327 0 : extifmessage = NEW2 (char, 30);
1328 0 : sprintf (extifmessage, "remote run ready result=%d", test_result);
1329 0 : send_to_master (run_id + 1, extifmessage);
1330 : #ifdef MIN_EXTIF
1331 0 : original_complete_callback (run_id, execution_result, test_result,
1332 : desc);
1333 : #endif
1334 :
1335 : /*Revert to "normal" external controller communincation if
1336 : * it is allowed, otherwise mark that it's allowed to revert. */
1337 0 : if (ok_to_break == ESTrue) {
1338 : #ifdef MIN_EXTIF
1339 0 : MIN_DEBUG ("Restoring Callback");
1340 0 : tfwif_callbacks.complete_callback_ = original_complete_callback;
1341 : #else
1342 : ;
1343 : #endif
1344 : } else
1345 0 : ok_to_break = ESTrue;
1346 0 : DELETE (extifmessage);
1347 0 : }
1348 : /* ------------------------------------------------------------------------- */
1349 : /** Adds a new entry to pool of ip slaves
1350 : * @param he host address information
1351 : * @param slavetype type of the slave e.g. "phone"
1352 : * @return 0 on success, 1 on error
1353 : */
1354 : int tec_add_ip_slave_to_pool (struct addrinfo **ai, char *slavetype)
1355 16 : {
1356 : slave_info *slave;
1357 : DLListIterator it;
1358 :
1359 16 : if (find_slave_by_addrinfo (*ai, &it) != INITPTR) {
1360 0 : MIN_WARN ("Slave already registered");
1361 0 : return 1;
1362 : }
1363 16 : slave = NEW(slave_info);
1364 16 : slave->status_ = SLAVE_STAT_FREE;
1365 16 : slave->slave_id_ = 0;
1366 16 : slave->run_cnt_ = 0;
1367 16 : slave->addrinfo_ = *ai;
1368 16 : slave->slave_type_ = tx_create (slavetype);
1369 16 : slave->slave_name_ = INITPTR;
1370 16 : slave->fd_ = -1;
1371 16 : slave->write_queue_ = dl_list_create ();
1372 :
1373 16 : dl_list_add (ms_assoc, slave);
1374 :
1375 16 : return 0;
1376 : }
1377 : /* ------------------------------------------------------------------------- */
1378 : /** Deletes entry from the pool of ip slaves
1379 : * @param he host address information
1380 : * @param slavetype type of the slave e.g. "phone"
1381 : * @return 0 on success, 1 on error
1382 : */
1383 : int tec_del_ip_slave_from_pool (struct addrinfo *ai, char *slavetype)
1384 0 : {
1385 : slave_info *slave;
1386 : DLListIterator it;
1387 :
1388 0 : if (ms_assoc == INITPTR)
1389 0 : return 1;
1390 :
1391 0 : slave = find_slave_by_addrinfo (ai, &it);
1392 0 : if (slave == INITPTR) {
1393 0 : MIN_WARN ("slave not found");
1394 0 : return 1;
1395 : }
1396 :
1397 0 : dl_list_remove_it (it);
1398 :
1399 0 : if (slave->status_ & SLAVE_STAT_RESERVED) {
1400 0 : MIN_WARN ("slave still reserved");
1401 : }
1402 :
1403 0 : tx_destroy (&slave->slave_name_);
1404 0 : tx_destroy (&slave->slave_type_);
1405 :
1406 : /* FIXME flush write queue */
1407 :
1408 0 : DELETE (slave);
1409 :
1410 0 : return 0;
1411 : }
1412 : /* ------------------------------------------------------------------------- */
1413 : /** Used in tcp/ip operation to report case result to master
1414 : * @param run_id runtime id of test case (position in "selected cases" list)
1415 : * @param execution_result indicates if starting of test case was successful
1416 : * @param test_result result of test
1417 : * @param desc description (taken from ipc message);
1418 : */
1419 : void
1420 : tcp_master_report (int run_id, int execution_result, int test_result,
1421 : char *desc)
1422 0 : {
1423 0 : DLListIterator finished_case_item = DLListNULLIterator;
1424 0 : DLListIterator work_module_item = DLListNULLIterator;
1425 : char *extifmessage;
1426 :
1427 : /*let's get module pid from finished case */
1428 0 : finished_case_item = dl_list_at (selected_cases, run_id);
1429 0 : work_module_item = tc_get_test_module_ptr (finished_case_item);
1430 0 : extifmessage = NEW2 (char, 30);
1431 0 : sprintf (extifmessage, "remote run ready result=%d", test_result);
1432 0 : send_to_master (run_id + 1, extifmessage);
1433 0 : DELETE (extifmessage);
1434 0 : }
1435 :
1436 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
1437 : #ifdef MIN_UNIT_TEST
1438 :
1439 :
1440 : #endif /* MIN_UNIT_TEST */
1441 :
1442 : /* End of file */
|