1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Konrad Marek Zapalowicz
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_tcp_handling.c
22 : * @version 0.1
23 : * @brief RCP handling routines for tcp based master slave
24 : */
25 :
26 : /* ------------------------------------------------------------------------- */
27 : /* INCLUDE FILES */
28 : #include <sys/types.h>
29 : #include <sys/socket.h>
30 : #include <sys/select.h>
31 : #include <netdb.h>
32 : #include <netinet/in.h>
33 : #include <arpa/inet.h>
34 : #include <pthread.h>
35 :
36 : #include <tec.h>
37 : #include <tec_events.h>
38 : #include <min_common.h>
39 : #include <dllist.h>
40 : #include <min_parser.h>
41 : #include <min_logger.h>
42 : #include <tec_rcp_handling.h>
43 :
44 : /* ------------------------------------------------------------------------- */
45 : /* EXTERNAL DATA STRUCTURES */
46 : /* None */
47 :
48 : /* ------------------------------------------------------------------------- */
49 : /* EXTERNAL GLOBAL VARIABLES */
50 : extern DLList *ms_assoc;
51 : extern int slave_exit;
52 : /* ------------------------------------------------------------------------- */
53 : /* EXTERNAL FUNCTION PROTOTYPES */
54 :
55 : /* ------------------------------------------------------------------------- */
56 : /* GLOBAL VARIABLES */
57 : int rcp_listen_socket = -1;
58 : pthread_mutex_t socket_write_mutex_ = PTHREAD_MUTEX_INITIALIZER;
59 : int current_slave_fd;
60 : /* ------------------------------------------------------------------------- */
61 : /* CONSTANTS */
62 : /* None */
63 :
64 : /* ------------------------------------------------------------------------- */
65 : /* MACROS */
66 : /* None */
67 :
68 : /* ------------------------------------------------------------------------- */
69 : /* LOCAL CONSTANTS AND MACROS */
70 :
71 : /* ------------------------------------------------------------------------- */
72 : /* MODULE DATA STRUCTURES */
73 : /* None */
74 :
75 : /* ------------------------------------------------------------------------- */
76 : /* LOCAL FUNCTION PROTOTYPES */
77 : /* ------------------------------------------------------------------------- */
78 : /** Goes through the list of slaves and sets sockets that are available
79 : * for reading or writing to the fd sets
80 : * @param rd set of read sockets
81 : * @param wr set of write sockets
82 : * @param nfds highest fd in sets before calling this func
83 : * @return the value of highest fd in set
84 : */
85 : LOCAL int set_active_rcp_sockets (fd_set *rd, fd_set *wr, int nfds);
86 : /* ------------------------------------------------------------------------- */
87 : /** Read/write sockets
88 : * @param rd set of read sockets
89 : * @param wr set of write sockets
90 : */
91 : LOCAL void rw_rcp_sockets (fd_set *rd, fd_set *rw);
92 : /* ------------------------------------------------------------------------- */
93 : /** Reads the socket bound to the slave_info
94 : * @param slave_info the slave with a socket available for reading
95 : */
96 : LOCAL void socket_read_rcp (slave_info *slave);
97 : /* ------------------------------------------------------------------------- */
98 : /** Writes to socket bound to slave_info
99 : * @param slave_info the slave with a socket available for writing
100 : */
101 : LOCAL void socket_write_rcp (slave_info *slave);
102 : /* ------------------------------------------------------------------------- */
103 : /** Finds a slave with fd
104 : * @param fd search key
105 : * @param itp out used to pass also the DLListIterator to caller
106 : * @return slave_info if found, INITPTR if not
107 : */
108 : LOCAL slave_info *find_slave_by_fd (int fd, DLListIterator *itp);
109 : /* ------------------------------------------------------------------------- */
110 : /** Searches for master (a "special" slave)
111 : * @return slave_info if found, INITPTR if not
112 : */
113 : LOCAL slave_info *find_master ();
114 : /* ------------------------------------------------------------------------- */
115 : /** Frees the tcp type slave - closes slave socket, marks the slave free
116 : * @param slave slave to be freed
117 : */
118 : LOCAL void free_tcp_slave (slave_info *slave);
119 : /* ------------------------------------------------------------------------- */
120 : /** Splits RCP's adress string fields into two ints.
121 : * @param hex [in] string to be split, has to be 8 characters, otherwise
122 : * function fails
123 : * @param dev_id [out] pointer to int that will hold device id
124 : * @param case_id [out] pointer to int that will hold case id
125 : * @return result of operation, 0 if ok
126 : */
127 : LOCAL int splithex (char *hex, int *dev_id, int *case_id);
128 :
129 : /* ------------------------------------------------------------------------- */
130 : /* FORWARD DECLARATIONS */
131 : /* None */
132 :
133 : /* ==================== LOCAL FUNCTIONS ==================================== */
134 : /* ------------------------------------------------------------------------- */
135 : LOCAL int set_active_rcp_sockets (fd_set *rd, fd_set *wr, int nfds)
136 2191005 : {
137 : DLListIterator it;
138 : slave_info *slave;
139 :
140 6573026 : for (it = dl_list_head (ms_assoc); it != INITPTR;
141 2191016 : it = dl_list_next (it)) {
142 2191016 : slave = dl_list_data (it);
143 2191016 : if (slave->fd_ != 0 && slave->fd_ != -1) {
144 2189815 : FD_SET (slave->fd_, rd);
145 2189815 : FD_SET (slave->fd_, wr);
146 2189815 : nfds = MAX (nfds, slave->fd_);
147 : }
148 : }
149 :
150 2191005 : return nfds;
151 : }
152 : /* ------------------------------------------------------------------------- */
153 : LOCAL void rw_rcp_sockets (fd_set *rd, fd_set *wr)
154 2190990 : {
155 : DLListIterator it;
156 : slave_info *slave;
157 :
158 6572993 : for (it = dl_list_head (ms_assoc); it != INITPTR;
159 2191013 : it = dl_list_next (it)) {
160 2191013 : slave = dl_list_data (it);
161 2191013 : if (slave->fd_ > 0) {
162 2189816 : if (FD_ISSET (slave->fd_, rd))
163 5 : socket_read_rcp (slave);
164 2189816 : if (slave->fd_ > 0 && FD_ISSET (slave->fd_, wr))
165 2189814 : socket_write_rcp (slave);
166 : }
167 : }
168 :
169 :
170 : return;
171 : }
172 : /* ------------------------------------------------------------------------- */
173 : LOCAL void free_tcp_slave (slave_info *slave)
174 0 : {
175 : slave_info *master;
176 : DLListIterator it;
177 0 : if (!strcmp (tx_share_buf(slave->slave_type_), "master")) {
178 0 : master = find_slave_by_fd (slave->fd_, &it);
179 0 : close (master->fd_);
180 0 : tx_destroy (&master->slave_type_);
181 0 : tx_destroy (&master->slave_name_);
182 0 : dl_list_free (&master->write_queue_);
183 0 : dl_list_remove_it (it);
184 0 : DELETE (master);
185 0 : slave_exit = 1;
186 0 : return;
187 : }
188 :
189 0 : close (slave->fd_);
190 0 : slave->fd_ = -1;
191 0 : slave->status_ = SLAVE_STAT_FREE;
192 0 : slave->slave_id_ = 0;
193 0 : tx_destroy (&slave->slave_name_);
194 0 : return;
195 : }
196 : /* ------------------------------------------------------------------------- */
197 : LOCAL void socket_read_rcp (slave_info *slave)
198 5 : {
199 : int bytes_read;
200 : char *buff, len_buff[2];
201 : unsigned int len;
202 :
203 5 : bytes_read = read (slave->fd_, &len_buff, 2);
204 5 : if (bytes_read != 2) {
205 0 : MIN_WARN ("can't read even 2 bytes from socket");
206 0 : free_tcp_slave (slave);
207 0 : return;
208 : }
209 5 : len = len_buff [1] << 8 | len_buff [0];
210 5 : MIN_INFO ("Message from RCP socket of len %d", len);
211 5 : buff = NEW2 (char, len + 1);
212 5 : bytes_read = read (slave->fd_, buff, len);
213 5 : if (bytes_read != len) {
214 0 : MIN_WARN ("failed to read the whole message");
215 0 : free_tcp_slave (slave);
216 0 : return;
217 : }
218 :
219 5 : buff [len] = '\0';
220 5 : current_slave_fd = slave->fd_;
221 5 : tec_extif_message_received (buff, len);
222 :
223 5 : DELETE (buff);
224 :
225 5 : return;
226 :
227 : }
228 : /* ------------------------------------------------------------------------- */
229 : LOCAL void socket_write_rcp (slave_info *slave)
230 2189814 : {
231 : Text *tx;
232 : DLListIterator it;
233 : int ret;
234 : char len_buff[5];
235 :
236 2189814 : if (slave->write_queue_ == NULL || slave->write_queue_ == INITPTR) {
237 0 : MIN_WARN ("write queue does not exist");
238 0 : return;
239 : }
240 :
241 2189814 : pthread_mutex_lock (&socket_write_mutex_);
242 :
243 2189814 : it = dl_list_head (slave->write_queue_);
244 2189814 : if (it == DLListNULLIterator) {
245 2189811 : pthread_mutex_unlock (&socket_write_mutex_);
246 :
247 2189811 : return;
248 : }
249 :
250 3 : tx = dl_list_data (it);
251 :
252 3 : len_buff[0] = strlen (tx_share_buf(tx));
253 3 : len_buff[1] = strlen (tx_share_buf(tx)) >> 8;
254 :
255 3 : ret = write (slave->fd_, &len_buff, 2);
256 :
257 3 : MIN_DEBUG ("SENDING TO EXTIF :%s", tx_share_buf (tx));
258 3 : ret = write (slave->fd_, tx_share_buf (tx), strlen (tx_share_buf (tx)));
259 :
260 3 : dl_list_remove_it (it);
261 3 : tx_destroy (&tx);
262 3 : pthread_mutex_unlock (&socket_write_mutex_);
263 :
264 3 : return;
265 :
266 : }
267 : /* ------------------------------------------------------------------------- */
268 : LOCAL slave_info *find_slave_by_fd (int fd, DLListIterator *itp)
269 7 : {
270 : DLListIterator it;
271 : slave_info *ips;
272 :
273 7 : *itp = INITPTR;
274 :
275 14 : for (it = dl_list_head (ms_assoc); it != INITPTR;
276 0 : it = dl_list_next (it)) {
277 7 : ips = dl_list_data (it);
278 7 : if (ips->fd_ == fd) {
279 7 : *itp = it;
280 7 : return ips;
281 : }
282 : }
283 :
284 0 : return INITPTR;
285 : }
286 : /* ------------------------------------------------------------------------- */
287 : LOCAL slave_info *find_master ()
288 0 : {
289 : DLListIterator it;
290 : slave_info *ips;
291 :
292 :
293 0 : for (it = dl_list_head (ms_assoc); it != INITPTR;
294 0 : it = dl_list_next (it)) {
295 0 : ips = dl_list_data (it);
296 0 : if (!strcmp (tx_share_buf (ips->slave_type_), "master")) {
297 0 : return ips;
298 : }
299 : }
300 :
301 0 : return INITPTR;
302 : }
303 : /* ------------------------------------------------------------------------- */
304 : LOCAL int splithex (char *hex, int *dev_id, int *case_id)
305 4 : {
306 : char dev_id_c[5];
307 : char case_id_c[5];
308 : char *endptr;
309 :
310 4 : if (strlen (hex) != 8) {
311 0 : return -1;
312 : }
313 :
314 4 : snprintf (dev_id_c, 5, "%s", hex);
315 4 : snprintf (case_id_c, 5, "%s", hex + 4);
316 4 : *dev_id = strtol (dev_id_c, &endptr, 16);
317 4 : *case_id = strtol (case_id_c, &endptr, 16);
318 :
319 4 : return 0;
320 : }
321 : /* ------------------------------------------------------------------------- */
322 :
323 : /* ------------------------------------------------------------------------- */
324 : /* ======================== FUNCTIONS ====================================== */
325 : /* ------------------------------------------------------------------------- */
326 : /** Handles socket polling thread
327 : * @return NULL
328 : */
329 : void *ec_poll_sockets (void *arg)
330 15 : {
331 : fd_set rd, wr, er;
332 15 : int nfds = 0;
333 : struct timeval tv;
334 : int ret;
335 :
336 :
337 : while (1) {
338 2191005 : FD_ZERO (&rd);
339 2191005 : FD_ZERO (&wr);
340 2191005 : FD_ZERO (&er);
341 2191005 : nfds = set_active_rcp_sockets (&rd, &wr, nfds);
342 :
343 2191005 : tv.tv_sec = 0;
344 2191005 : tv.tv_usec = 100000;
345 2191005 : ret = select (nfds + 1, &rd, &wr, &er, &tv);
346 :
347 2190990 : rw_rcp_sockets (&rd, &wr);
348 2190990 : }
349 :
350 : return NULL;
351 : }
352 :
353 : /* ------------------------------------------------------------------------- */
354 : /** Build rcp message and adds it to the write queue of slave
355 : * @param cmd command e.g. "reserve"
356 : * @param sender RCP sender identifier
357 : * @param rcvr RCP receiver identifier
358 : * @param msg the rest of message
359 : * @param fd the socket of the destination
360 : */
361 : void socket_send_rcp (char *cmd, char *sender, char *rcvr, char* msg, int fd)
362 3 : {
363 : Text *tx;
364 : slave_info *entry;
365 : DLListIterator it;
366 :
367 3 : MIN_DEBUG ("cmd:%s sender:%s rcvr:%s msg:%s fd:%d",
368 : cmd, sender, rcvr, msg, fd);
369 :
370 3 : tx = tx_create (cmd);
371 3 : tx_c_append (tx, " ");
372 3 : tx_c_append (tx, sender);
373 3 : tx_c_append (tx, " ");
374 3 : tx_c_append (tx, rcvr);
375 3 : tx_c_append (tx, " ");
376 3 : tx_c_append (tx, msg);
377 :
378 3 : if (fd == 0 && !strcmp (rcvr, "deadbeef"))
379 0 : entry = find_master ();
380 : else
381 3 : entry = find_slave_by_fd (fd, &it);
382 :
383 3 : if (entry == INITPTR) {
384 0 : MIN_WARN ("No entry found for socket %d", fd);
385 0 : return;
386 : }
387 3 : pthread_mutex_lock (&socket_write_mutex_);
388 :
389 3 : dl_list_add (entry->write_queue_, tx);
390 :
391 3 : pthread_mutex_unlock (&socket_write_mutex_);
392 :
393 : }
394 :
395 : /* ------------------------------------------------------------------------- */
396 : /** Tries to allocate slave entry for IP communication
397 : * @param he host address information
398 : * @param slavetype type of the slave e.g. "phone"
399 : * @return 0 on success, 1 on error
400 : */
401 : int allocate_ip_slave (char *slavetype, char *slavename, pid_t pid)
402 1 : {
403 : slave_info *slave;
404 : static int slave_id = 0;
405 : DLListIterator it;
406 1 : int found = 0, sfd;
407 : struct addrinfo *rp;
408 :
409 1 : if (ms_assoc == INITPTR)
410 0 : return -1;
411 :
412 2 : for (it = dl_list_head (ms_assoc); it != INITPTR;
413 0 : it = dl_list_next (it)) {
414 1 : slave = dl_list_data (it);
415 1 : if (!strcmp (tx_share_buf (slave->slave_type_), slavetype) &&
416 : slave->status_ == SLAVE_STAT_FREE) {
417 1 : found = 1;
418 1 : slave->slave_name_ = tx_create (slavename);
419 1 : break;
420 : }
421 : }
422 :
423 1 : if (found == 0) {
424 0 : MIN_WARN ("no slave of type %s found from ip slave pool");
425 0 : return -1;
426 : }
427 :
428 1 : for (rp = slave->addrinfo_; rp != NULL; rp = rp->ai_next) {
429 1 : sfd = socket(rp->ai_family, rp->ai_socktype,
430 : rp->ai_protocol);
431 1 : if (sfd == -1)
432 0 : continue;
433 :
434 1 : if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
435 1 : break;
436 :
437 0 : close(sfd);
438 : }
439 :
440 1 : if (rp == NULL) {
441 0 : MIN_WARN ("Could not connect %s", strerror(errno));
442 0 : return -1;
443 : }
444 :
445 1 : if (slave_id >= 0xffff) {
446 0 : MIN_WARN ("Slave id wraparound");
447 0 : slave_id = 1;
448 : } else
449 1 : slave_id ++;
450 :
451 1 : slave->fd_ = sfd;
452 1 : slave->slave_id_ = slave_id;
453 1 : slave->status_ = SLAVE_STAT_RESERVED;
454 1 : slave->pid_ = pid;
455 :
456 1 : return 0;
457 : }
458 :
459 : /* ------------------------------------------------------------------------- */
460 : /** Creates a new master entry
461 : * param socket the socket of the master
462 : */
463 : void new_tcp_master (int socket)
464 0 : {
465 : slave_info *master;
466 :
467 0 : master = NEW (slave_info);
468 0 : master->slave_name_ = tx_create ("deadbeef");
469 0 : master->slave_type_ = tx_create ("master");
470 0 : master->fd_ = socket;
471 0 : master->write_queue_ = dl_list_create ();
472 0 : master->status_ = SLAVE_STAT_RESERVED;
473 :
474 0 : dl_list_add (ms_assoc, master);
475 :
476 : return;
477 : }
478 :
479 : /* ------------------------------------------------------------------------- */
480 : /** Function to close slave
481 : * @param slave the slave_info struck
482 : */
483 1 : void tcp_slave_close (slave_info *slave) {
484 1 : close (slave->fd_);
485 1 : slave->fd_ = -1;
486 1 : slave->status_ = SLAVE_STAT_FREE ;
487 1 : tx_destroy (&slave->slave_name_);
488 1 : }
489 :
490 : /* ------------------------------------------------------------------------- */
491 : /**Function handles "response" message coming from external controller over tcp
492 : * @param extif_message pointer to item parser. It is assumed that
493 : * mip_get_string was executed once for this parser to get first "word"
494 : * @return result of operation, 0 if ok.
495 : */
496 : int tcp_msg_handle_response (MinItemParser * extif_message)
497 4 : {
498 4 : char *command = INITPTR;
499 4 : char *param1 = NULL;
500 4 : char *srcid = INITPTR;
501 4 : char *destid = INITPTR;
502 4 : int result = 666;
503 4 : int retval = 666;
504 4 : int slave_id = 0;
505 4 : int case_id = 0;
506 : MsgBuffer ipc_message;
507 4 : slave_info *slave_entry = INITPTR;
508 : DLListIterator slave_entry_item;
509 :
510 4 : mip_get_next_string (extif_message, &srcid);
511 :
512 4 : mip_get_next_string (extif_message, &destid);
513 :
514 4 : mip_get_next_string (extif_message, &command);
515 :
516 4 : slave_entry = find_slave_by_fd (current_slave_fd, &slave_entry_item);
517 4 : if (slave_entry == INITPTR) {
518 0 : MIN_FATAL ("no slave found bound to fd %d!",
519 : current_slave_fd);
520 : }
521 :
522 4 : current_slave_fd = -1;
523 :
524 4 : if (strcasecmp (command, "reserve") == 0) {
525 1 : mip_get_next_int (extif_message, &result);
526 :
527 : /*it seems that result was not send, assume success */
528 1 : splithex (srcid, &slave_id, &case_id);
529 1 : slave_entry->slave_id_ = slave_id;
530 1 : if (retval == -1)
531 0 : result = 0;
532 1 : slave_entry->status_ = SLAVE_STAT_RESERVED;
533 :
534 1 : ipc_message.sender_ = ec_settings.engine_pid_;
535 1 : ipc_message.receiver_ = slave_entry->pid_;
536 1 : ipc_message.type_ = MSG_EXTIF;
537 1 : ipc_message.special_ = 0;
538 1 : ipc_message.extif_msg_type_ = EResponseSlave;
539 1 : ipc_message.param_ = result;
540 1 : MIN_DEBUG ("ipc sending with result %d", result);
541 1 : mq_send_message (mq_id, &ipc_message);
542 1 : retval = 0;
543 3 : } else if (strcasecmp (command, "release") == 0) {
544 1 : retval =
545 : mip_get_next_tagged_int (extif_message, "result=", &result);
546 1 : if (retval == -1)
547 1 : mip_get_next_int (extif_message, &result);
548 : /*result was not tagged int */
549 1 : if (retval == -1)
550 1 : result = 0;
551 : /*it seems that result was not send, assume success */
552 1 : ipc_message.sender_ = ec_settings.engine_pid_;
553 1 : ipc_message.receiver_ = slave_entry->pid_;
554 1 : ipc_message.type_ = MSG_EXTIF;
555 1 : ipc_message.param_ = result;
556 1 : ipc_message.special_ = 0;
557 1 : ipc_message.extif_msg_type_ = EResponseSlave;
558 1 : MIN_DEBUG ("ipc sending with result %d", result);
559 1 : mq_send_message (mq_id, &ipc_message);
560 : /*slave released, remove it from ms_assoc */
561 1 : splithex (srcid, &slave_id, &case_id);
562 1 : MIN_DEBUG ("slave_entry = %x, run count = %d",
563 : slave_entry, slave_entry->run_cnt_);
564 1 : if (slave_entry->run_cnt_ == 0) {
565 : /* we have a result - can close */
566 1 : tcp_slave_close (slave_entry);
567 : } else
568 0 : slave_entry->status_ &= 0xe;
569 :
570 1 : retval = 0;
571 2 : } else if (strcasecmp (command, "remote") == 0) {
572 2 : mip_get_next_string (extif_message, &command);
573 2 : if (strcasecmp (command, "run") == 0) {
574 2 : splithex (srcid, &slave_id, &case_id);
575 : /*translate received caseid into proper
576 : number that can be stored in scripter*/
577 2 : case_id = (slave_id<<16) + case_id;
578 2 : mip_get_next_string (extif_message, ¶m1);
579 2 : if (strcasecmp (param1, "started") == 0) {
580 1 : ipc_message.sender_ = ec_settings.engine_pid_;
581 1 : ipc_message.receiver_ = slave_entry->pid_;
582 1 : ipc_message.type_ = MSG_EXTIF;
583 1 : ipc_message.special_ = case_id;
584 1 : ipc_message.param_ = 0;
585 1 : ipc_message.extif_msg_type_ = EResponseSlave;
586 1 : MIN_DEBUG ("ipc sending with result 0");
587 1 : mq_send_message (mq_id, &ipc_message);
588 1 : retval = 0;
589 1 : } else if (strcasecmp (param1, "ready") == 0) {
590 1 : mip_get_int (extif_message, "result=", &result);
591 1 : ipc_message.sender_ = ec_settings.engine_pid_;
592 1 : ipc_message.receiver_ = slave_entry->pid_;
593 1 : ipc_message.type_ = MSG_EXTIF;
594 1 : ipc_message.special_ = case_id;
595 1 : ipc_message.param_ = result;
596 1 : ipc_message.extif_msg_type_ =
597 : ERemoteSlaveResponse;
598 1 : MIN_DEBUG ("ipc sending with result %d",
599 : result);
600 1 : mq_send_message (mq_id, &ipc_message);
601 1 : retval = 0;
602 2 : if (slave_entry != INITPTR &&
603 : slave_entry->status_
604 : & SLAVE_STAT_RESERVED) {
605 1 : slave_entry->run_cnt_ -= 1;
606 :
607 : } else {
608 : /* we have are free - can close */
609 0 : tcp_slave_close (slave_entry);
610 : }
611 0 : } else if (strcasecmp (param1, "error") == 0) {
612 0 : mip_get_int (extif_message, "result=", &result);
613 0 : ipc_message.sender_ = ec_settings.engine_pid_;
614 0 : ipc_message.receiver_ = slave_entry->pid_;
615 0 : ipc_message.type_ = MSG_EXTIF;
616 0 : ipc_message.special_ = case_id;
617 0 : ipc_message.param_ = result;
618 0 : ipc_message.extif_msg_type_ = EResponseSlave;
619 0 : MIN_DEBUG ("ipc sending with result %d",
620 : result);
621 0 : mq_send_message (mq_id, &ipc_message);
622 0 : retval = 0;
623 0 : if (slave_entry != INITPTR &&
624 : slave_entry->status_ &
625 : SLAVE_STAT_RESERVED) {
626 0 : slave_entry->run_cnt_ -= 1;
627 :
628 : } else {
629 : /* we have are free - can close */
630 0 : tcp_slave_close (slave_entry);
631 : }
632 :
633 : }
634 0 : } else if (strcasecmp (command, "request") == 0) {
635 0 : retval =
636 : handle_remote_event_request_resp (extif_message);
637 0 : } else if (strcasecmp (command, "release") == 0)
638 0 : retval = 0;
639 : }
640 4 : DELETE (command);
641 4 : DELETE (param1);
642 4 : DELETE (srcid);
643 4 : DELETE (destid);
644 :
645 4 : return retval;
646 : }
647 :
648 : /* ------------------------------------------------------------------------- */
649 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
650 : /* None */
651 :
652 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
653 : /* None */
654 :
655 : /* ------------------------------------------------------------------------- */
656 : /* End of file */
|