Remove unused directories and files in video_in_hal
[staging/basesystem.git] / otherservice / rpc_library / library / src / rpc_lib.c
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file rpc_lib.c
19  * @brief RPC Library-API Function Implementation
20  *
21  */
22 /** @mainpage
23  * This document describes the following API functions, structures, 
24  * type declarations, and macros.
25  * - RPC library external specification
26  * - External specifications for RPC tools
27  *
28  * For an overview of other RPC libraries and tools and anomaly processing,
29  * to reference the Word version of the documentation.
30  * (external specifications and programming guides) */
31 /** @defgroup RPClib RPC library external specification */
32 /** @defgroup RPCtool RPC tool (rpc_apidef) */
33 /** @defgroup RPC_ID_assign RPC_ID Assignment */
34 /** @defgroup RPClib_in RPC library internal specifications (incomplete) */
35 /** @addtogroup RPClib
36  * @{
37  */
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <sys/types.h>
45 #include <sys/time.h>
46 #include <sys/socket.h>
47 #include <sys/select.h>
48 #include <sys/poll.h>
49 #include <sys/stat.h>
50 #include <netinet/in.h>
51 #include <sys/un.h>
52 #include <sys/inotify.h>
53
54 #include <other_service/rpc.h>
55 #include "rpc_internal.h"
56
57 #include <native_service/cl_process.h> // for CL_INTFY_FILENAME_FORMAT
58 #include <native_service/cl_monitor.h>
59
60
61 /* Prototype declarations */
62 static RPC_Result ProcessAPIcallRequest(RpcIdInfo *idinfo, RPC_ID client,
63     UINT16 api_num, char *args_string,
64     unsigned int args_size);
65 static RPC_Result RpcAllDeleteSrvrPid(RpcIdInfo *idinfo);
66 static RPC_Result RpcClientWaitCertification(RpcIdInfo *idinfo, pid_t *srvr_pid);
67 static RPC_Result RpcRegistSrvrPid(RpcIdInfo *idinfo, RPC_ID srvr_rpc_id, pid_t srvr_pid, int wd);
68
69 #define THREAD_INFO_CHECK(th) \
70   if ((th) == NULL) { \
71     RPC_LOG_STATE("No thread info"); \
72     return RPC_ERR_Fatal; \
73   }
74
75 #define SUB_THREAD_CHECK() \
76   if (g_rpc_thread_alive == 0) { \
77     RPC_LOG_STATE("No sub thread -- shutdown"); \
78     RpcDestroyThreadInfo(); \
79     return RPC_ERR_Fatal; \
80   }
81
82 /**
83  * Waiting for response packet for API call and API result transmission
84  * Timeout time in msec.
85  * If the other program is abnormal (process termination), delay occurs in the meanwhile.
86  * Confirm the operation on the actual machine and set again.
87  */
88 #define RESPONSE_WAIT_MSEC_DEFAULT 2000
89 static unsigned int Response_wait_msec = RESPONSE_WAIT_MSEC_DEFAULT;
90
91 char *RPC_DEBUG = NULL;
92
93 #if defined(RPC_USE_UNIX_AUTOBIND)
94
95   static RPC_Result
96 CreateClientIdinfo(RpcThreadInfo *th, RPC_ID *pID) {
97   if (RpcCreateIdInfo(th, *pID, NULL, NO_SECURE_CHECK) < 0) {
98     RPC_LOG_ERR("Can't create id_info");
99     return RPC_ERR_Fatal;
100   }
101
102   *pID = RPC_my_id(RPC_clnt_idinfo(th));
103   RPC_LOG_DEBUG("RPC: assigned client ID %d", *pID);
104   if (RPC_DEBUG) {  // LCOV_EXCL_BR_LINE 7: debug
105     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
106     printf("RPC[%s]: client start finished.\n", RPC_DEBUG);  // LCOV_EXCL_LINE 7: debug
107   }
108   return RPC_OK;
109 }
110 #else /* !AUTOBIND */
111
112 #include <sys/file.h>
113
114   static int
115 FindUniqClientId(void) {
116 #define RPC_ID_FILE_NAME "/tmp/RPC/id"
117 #define RPC_MIN_CLIENT_ID 1024
118 #define RPC_MAX_CLIENT_ID (1024+32768-1)
119
120   int fd, found;
121   RPC_ID id, next;
122   struct stat statbuf;
123   char fname[32];
124
125   fd = open(RPC_ID_FILE_NAME, O_RDWR|O_CLOEXEC, 0777);
126   if (fd < 0) {
127     id = RPC_MIN_CLIENT_ID;
128     fd = open(RPC_ID_FILE_NAME, O_RDWR|O_CREAT|O_CLOEXEC, 0777);
129     if (fd < 0) {
130       return -1;
131     }
132     flock(fd, LOCK_EX); // Possible sleep here
133   } else {
134     flock(fd, LOCK_EX); // Possible sleep here
135     read(fd, &id, sizeof(id));
136   }
137
138   found = 0;
139   while(found == 0) {
140     rpc_set_socket_name(fname, id);
141     if (stat(fname, &statbuf) < 0) {
142       found = 1;
143       break;
144     }
145     id++;
146     if (id > RPC_MAX_CLIENT_ID) {
147       id = RPC_MIN_CLIENT_ID;
148     }
149   }
150
151   next = id + 1;
152   if (next > RPC_MAX_CLIENT_ID) {
153     next = RPC_MIN_CLIENT_ID;
154   }
155
156   lseek(fd, 0, SEEK_SET);
157   write(fd, &next, sizeof(next));
158   flock(fd, LOCK_UN);
159   close(fd);
160
161   return id;
162 }
163
164   static RPC_Result
165 CreateClientIdinfo(RpcThreadInfo *th, UINT16 port) {
166   if (RpcCreateIdInfo(th, port, NULL, NO_SECURE_CHECK) < 0) {
167     RPC_LOG_ERR("Can't create id_info");
168     return RPC_ERR_Fatal;
169   }
170   // LCOV_EXCL_BR_START 7: debug
171   if (RPC_DEBUG) {
172     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
173     printf("RPC[%s]: client start finished.\n", RPC_DEBUG);
174   }
175   // LCOV_EXCL_BR_STOP
176   return RPC_OK;
177 }
178 #endif /* AUTOBIND */
179
180 /** @fn RPC_START_SERVER(ID)
181  * @brief RPC_start() macro for the server
182  *
183  * Used by RPC-API server programs to activate the RPC library.
184  * ID specifies a symbol of the form XXX_RPC_ID defined in rpc_id.h.
185  * Only one server program per thread is allowed.
186  * When a server program calls an API as a client of another server, 
187  * it only needs to call RPC_START_SERVER, 
188  * not RPC_START_CLIENT.
189  *
190  * RPC_end() should be called when the RPC library is no longer needed.
191  * @param ID [IN]RPC_ID of the program
192  * @see RPC_start
193  * @see RPC_end
194  */
195 /** @fn RPC_START_CLIENT(pID)
196  * @brief RPC_start() macro for clients
197  *
198  * Use only the client functions of the RPC library
199  * (only calling APIs provided by other programs),
200  * This macro is used for the start process.
201  *
202  *
203  * RPC_end() should be called when the RPC library is no longer needed.
204  *
205  * @param pID [OUT]Pointer to the RPC_ID of the program
206  * @see RPC_start
207  * @see RPC_end
208  */
209 /** @brief Start processing of the RPC library
210  *
211  * - With an open socket, RPC_ID, and API call dispatching functions
212  *   Register in the global variable (managed separately for each thread and RPC_ID)
213  * - Starting use as a server
214  *   - func specifies a function pointer (defined in stub) that is not a NULL.
215  *   - Specifies a fixed ID defined in rpc_id.h as the ID.
216  *   - If the same thread has already started using the server, an error code is returned.
217  *   - When the server function is started for the first time in a process, 
218  *     one subthread is started to process received packets 
219  *     in the background.
220  * - Starting use as a client
221  *   - NULL is specified in the func.
222  *   - In principle, an invalid ID value (RPC_NO_PORT) is specified.
223  *     This function automatically assigns IDs and returns the assignment result to pID.
224  *     - However, if another program has already started using it as a client, 
225  *       it shares the socket/RPC_ID instead of creating a new socket.
226  *   - Exceptionally, it is allowed to specify a fixed ID defined in rpc_id.h as the ID.
227  *     This is the only way to use RPC_start() in programs 
228  *     where it is difficult to always call RPC_end() at the end of use by program structure/design.
229  *     - In this case, the pID argument is not referenced.
230  * - The maximum number of threads that use the RPC library in a process is 
231  *   specified by RPC_MAX_THREADS_IN_PROCESS.
232  *
233  * @param id [IN]RPC_ID of the program (in the case of RPC_NO_PORT, this means automatic assignment)
234  * @param dispatch_func Dispatching functions (defined in stub files for servers, 
235  * and NULL specified in programs that do not provide APIs)
236  * @param pID [OUT]RPC_ID of the automatically assigned program
237  *
238  * @retval RPC_OK: normal completion
239  * @retval Otherwise: Abnormal termination (FATAL)
240  *
241  * @note Normally, this function is not called directly, but the following macro is used.
242  * - RPC_START_SERVER(ID)
243  *   For programs that provide RPC server functions.
244  *   This macro is also used when both server and client functions are used.
245  * - RPC_START_CLIENT(pID)
246  *   For programs that use only the RPC client function.
247  */
248   RPC_Result
249 RPC_start(RPC_ID id, RPC_dispatch_func_t func, RPC_ID *pID, INT32 secure_check)
250 {
251 #if defined(RPC_USE_SYSLOG)
252   static int init_syslog = 0;
253
254   if (init_syslog == 0) {
255     openlog("librpc", LOG_PID, LOG_USER);
256     setlogmask(LOG_UPTO(LOG_INFO));
257     /* setlogmask(LOG_MASK(LOG_DEBUG)); */
258     init_syslog = 1;
259     if (func != NULL)
260       RPC_LOG_STATE("RPC_START_SERVER(%#x)\n", id);
261   }
262 #endif /* RPC_USE_SYSLOG */
263
264   if (func != NULL && id == RPC_NO_ID) { /* No ID is specified despite as a server */
265     RPC_LOG_ERR("Invalid RPC_start server arg");
266     return RPC_ERR_Fatal;
267   }
268   if (func != NULL && pID != NULL) { /* Requested obtaining pID despite as a server */  // LCOV_EXCL_BR_LINE 200: macro guarantee impossible both not NULL, RPC_START_***
269     RPC_LOG_ERR("Invalid RPC_start server arg");  // LCOV_EXCL_START 200: macro guarantee impossible both not NULL, RPC_START_***
270     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
271     return RPC_ERR_Fatal;
272   }  // LCOV_EXCL_STOP
273   if (func == NULL && id != RPC_NO_ID) { /* Specified ID despite as a client */
274     RPC_LOG_ERR("Invalid RPC_start server arg");
275     return RPC_ERR_Fatal;
276   }
277 #if defined(RPC_USE_UNIX_AUTOBIND)
278   if (func == NULL && pID == NULL) {
279     /* pID is NULL despite as a client (not supported for ID-specified clients) */
280     RPC_LOG_ERR_W_NAME("RPC_Start(ID, NULL, NULL) is no longer supported, ID is auto-assigned");
281     return RPC_ERR_Fatal;
282   }
283 #else /* !AUTOBIND */
284   if (func == NULL && id == RPC_NO_ID && pID == NULL) {
285     /* pID is NULL despite as an auto-assigned client */
286     RPC_LOG_ERR("Invalid RPC_start arg");
287     return RPC_ERR_Fatal;
288   }
289 #endif /* !AUTOBIND */
290   if ((secure_check != NO_SECURE_CHECK) && (secure_check != NEED_SECURE_CHECK)) {  // LCOV_EXCL_BR_LINE 200: macro guarantee only two value, RPC_START_***
291   /* Check Arguments for Client Authentication */
292     RPC_LOG_ERR("Invalid RPC_start arg");  // LCOV_EXCL_START 200: macro guarantee only two value, RPC_START_***
293     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
294     return RPC_ERR_Fatal;
295   }  // LCOV_EXCL_STOP
296
297   RpcThreadInfo *th = RpcMyThreadInfo();
298   if (th == NULL) {
299     th = RpcCreateThreadInfo();
300     if (th == NULL) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc
301       return RPC_ERR_Fatal;
302     }
303   }
304
305   /* RPC_start is already done in the same thread */
306   if (func != NULL) {/* Server start */
307     if (RPC_srvr_idinfo(th) != NULL) {/* Server already started */
308       RPC_LOG_ERR("duplicated RPC_START_SERVER");
309       return RPC_ERR_Fatal;
310     }
311   } else { /* Client start */
312     if (RPC_clnt_idinfo(th) != NULL) {/* Client already started */
313       if (pID != NULL) {  // LCOV_EXCL_BR_LINE 6: double check
314         *pID = (RPC_clnt_idinfo(th))->port;
315         RPC_LOG_DEBUG("use existing client ID=%d", *pID);
316         RPC_inc_clnt_count(RPC_clnt_idinfo(th));
317       }
318       /*
319        * When pID == NULL (RPC_ID fixed), there is no guarantee 
320        * that RPC_end() will be called as many times as needed, so it does not count up.
321        */
322       return RPC_OK;
323     }
324   }
325
326   if (func == NULL) {/* Client start */
327 #if defined(RPC_USE_UNIX_AUTOBIND)
328     /* Automatically assign everything without supporting ID specification */
329     RPC_ID id_local = RPC_NO_ID;
330     RPC_Result ret = CreateClientIdinfo(th, &id_local);
331     if(RPC_OK != ret) return ret;
332
333     if (pID) {  // LCOV_EXCL_BR_LINE 6: double check
334       *pID = id_local;
335     }
336     RPC_clnt_inotify_fd(RPC_clnt_idinfo(th)) = inotify_init1(IN_CLOEXEC);
337     return ret;
338 #else /* !AUTOBIND */
339     if (id == RPC_NO_ID) {
340       /* No port number specified -> Automatically assign an ID and port number here */
341       /*
342        * FindUniqClientId() returns ID within the range of RPC_MIN_CLIENT_ID(1024) to RPC_MAX_CLIENT_ID(1024+32768-1)
343        */
344       int ret;
345       ret = FindUniqClientId();
346       if (ret < 0) {
347         return RPC_ERR_Fatal;
348       }
349       /* pID != NULL is already checked */
350       *pID = (UINT16)ret;
351       return CreateClientIdinfo(th, *pID);
352     } else {
353       /*
354        * Client start with specified port number
355        * Programs that cannot guarantee an RPC_end() call 
356        * at termination specify a fixed RPC_ID from the upper level and use it.
357        * (To avoid memory shortage caused by building up socket-files in /tmp/RPC)
358        */
359       return CreateClientIdinfo(th, id);
360     }
361 #endif /* !AUTOBIND */
362   }
363
364   /* Dispatch func specified (servers) -> bind */
365   CL_MonitorInit(CL_MONITOR_INIT_USER);    /* Using the API for Error Monitoring */
366
367   if (RpcCreateIdInfo(th, id, func, secure_check) < 0) {
368     RPC_LOG_ERR("Can't create id_info");
369     return RPC_ERR_Fatal;
370   }
371
372   if (RPC_DEBUG) {  // LCOV_EXCL_BR_LINE 7: debug
373     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
374     printf("RPC[%s]: server thread invoked\n", RPC_DEBUG);  // LCOV_EXCL_LINE 7: debug
375   }
376   char *env;
377   if ((env = getenv("RPC_RESPONSE_WAIT")) != NULL) {
378     Response_wait_msec =  (unsigned int)strtol(env, NULL, 10);
379   }
380
381   return RPC_OK;
382 }
383
384   static void
385 RpcEndSub(RpcThreadInfo *th, RpcIdInfo *idinfo) {
386   int sockfd;
387 #if !defined(RPC_USE_UNIX_AUTOBIND)
388   char path[120];
389
390   rpc_set_socket_name(path, RPC_my_id(idinfo));
391 #endif /* !AUTOBIND */
392   sockfd = idinfo->sock;
393   RpcDestroyIdInfo(th, idinfo);
394   close(sockfd);
395 #if !defined(RPC_USE_UNIX_AUTOBIND)
396   unlink(path);
397 #endif /* !AUTOBIND */
398 }
399
400 /** @brief RPC Library End-of-Use Processing
401  *
402  * - Perform termination processing such as closing the opened socket, releasing the memory.
403  *   (Server/Client Common)
404  * - If there are no programs in the thread that use RPC_ID, 
405  *   the subthread started by RPC_start is terminated.
406  * - Each RPC_ID must be called before the program exits.
407  * - RPC_end must be called by the thread that performed the RPC_start.
408  * - Ignored unused or no longer used RPC_ID if specified.
409  *
410  * @param ID [IN]RPC_ID of the program
411  */
412   void
413 RPC_end(RPC_ID id) {
414   RpcThreadInfo *th = RpcMyThreadInfo();
415   if (th == NULL) {
416     return;
417   }
418   RpcIdInfo *idinfo;
419   idinfo = RPC_srvr_idinfo(th);
420   if (idinfo != NULL && RPC_my_id(idinfo) == id) {/* srvr */
421     RpcEndSub(th, idinfo);
422   }
423
424   idinfo = RPC_clnt_idinfo(th);
425   if (idinfo != NULL && RPC_my_id(idinfo) == id) {/* client */
426
427     RPC_dec_clnt_count(idinfo);
428     if (RPC_clnt_count(idinfo) == 0) {
429     /* Deleting management table of the communication destination server PID */
430     RpcAllDeleteSrvrPid(idinfo);
431     close(RPC_clnt_inotify_fd(idinfo));
432
433       RpcEndSub(th, idinfo);
434     }
435   }
436   if (RPC_srvr_idinfo(th) == NULL && RPC_clnt_idinfo(th) == NULL) {
437     RPC_LOG_DEBUG("destroy thread info %p", th);
438     RpcDestroyThreadInfo();
439   }
440 }
441
442 /** @brief RPC library use termination processing (forced cleanup at process termination)
443  *
444  * Deletes the socket file created for RPC communication in the process.
445  * For  to release the resources of programs that use the RPC library with RPC_end() in principle, 
446  * but this API is an insurance process to eliminate socket file leaks.
447  *
448  * - Since it is assumed that the socket is called immediately before the process terminates, 
449  *   closing sockets and releasing memory is not performed automatically when the process terminates.
450  * - All RPC processing (both server and client) after this API call cannot be used.
451  *   Operation is not guaranteed even if RPC_START is performed again after that.
452  *
453  * No action for versions of the RPC library that use Unix autobind.
454  */
455   void
456 RPC_end_all(void) {
457 #if !defined(RPC_USE_UNIX_AUTOBIND)
458   RpcUnlinkSocketFiles();
459 #endif
460 }
461
462 /**
463  * @fn RPC_Result RPC_set_API_timeout(RPC_ID id, UINT32 sec)
464  * @brief Setting the timeout period during server API processing
465  *
466  * @param sec [IN] Timeout (sec) Set within the range of 1 to 60 sec.
467  *
468  * @retval RPC_OK: normal completion
469  * @retval RPC_ERR_Configuration: Argument out of range
470  * @retval RPC_ERR_Fatal: Fatal error
471  */
472   RPC_Result
473 RPC_set_API_timeout(INT32 sec) {
474   /* param check */
475   if ((sec > 60) || (sec < 1)) {
476     RPC_LOG_ERR( "RPC_set_API_timeout() : Invalid Param." );
477     return RPC_ERR_Configuration;
478   }
479
480   /* thread_info check */
481   RpcThreadInfo *th = RpcMyThreadInfo();
482   THREAD_INFO_CHECK(th);
483
484   /* thread_info->id_info check */
485   if (RPC_srvr_idinfo(th) != NULL ) {  // LCOV_EXCL_BR_LINE 200: server start abnormal can't test
486     RpcIdInfo *idinfo = RPC_srvr_idinfo(th);
487
488     /* thread_info->id_info->apicall_info check */
489     if( RPC_apicall_info(idinfo) != NULL ) {  // LCOV_EXCL_BR_LINE 200: server start abnormal can't test
490       RPC_apicall_api_timeout_sec(idinfo) = sec;
491     } else {  // LCOV_EXCL_START 200: server start abnormal can't test
492       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
493       RPC_LOG_ERR( "No apicall_info" );
494       return RPC_ERR_Fatal;
495     }
496
497   } else {
498     RPC_LOG_STATE("No srvr_id info");
499     return RPC_ERR_Fatal;
500   }  // LCOV_EXCL_STOP
501   return RPC_OK;
502 }
503
504
505 /** @brief API call execution function (client side)
506  *
507  * (These functions are called from within a client-facing STUB. Users never use these directly.)
508  */
509   RPC_Result
510 RPC_API_call(RPC_ID server, UINT16 api_num,
511     const char *args_string, unsigned int args_size,
512     char **ret_string, unsigned int *ret_size) {
513   *ret_string = NULL;
514
515   RpcThreadInfo *th = RpcMyThreadInfo();
516
517   THREAD_INFO_CHECK(th);
518
519   RpcIdInfo *idinfo;
520   idinfo = RPC_clnt_idinfo(th);
521
522   pid_t srvr_pid;
523
524   if (idinfo == NULL) {  // LCOV_EXCL_BR_LINE 8: dead code, idinfo always isn't NULL
525     /*
526      * In the past, the remedy of uninitialized clients has been done here.
527      * However, because it becomes to accumulate garbage in the /tmp/RPC by changing UNIX sockets,
528      * as an error without remedies.
529      */
530     // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL
531     RPC_LOG_ERR_W_NAME("warning!!! RPC call without RPC_start(): server=%d, api_num=%d", server, api_num);
532     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
533 #if defined(RPC_USE_UNIX_AUTOBIND)
534     RPC_ID id = RPC_NO_ID;
535     RPC_Result ret = CreateClientIdinfo(th, &id);
536 #else /* !AUTOBIND */
537     int id;
538     id = FindUniqClientId();
539     if (id < 0) {
540       return RPC_ERR_Fatal;
541     }
542     RPC_Result ret = CreateClientIdinfo(th, (UINT16)id);
543 #endif /* !AUTOBIND */
544     if (ret != RPC_OK) {
545       return ret;
546     }
547     idinfo = RPC_clnt_idinfo(th);
548     if (idinfo == NULL) {
549       return RPC_ERR_Fatal;
550     }
551   }  // LCOV_EXCL_STOP
552
553   char api_head[RPC_APICALL_FORMAT_ARGS_START + 1];
554   sprintf(api_head, RPC_APICALL_FORMAT, api_num);
555
556   rpc_send_buf sendbuf[2];
557   sendbuf[0].buf = api_head;
558   sendbuf[0].bytes = RPC_APICALL_FORMAT_ARGS_START;
559   if (args_size > 0) {
560     sendbuf[1].buf = args_string;
561     sendbuf[1].bytes = args_size;
562   }
563
564   int seq_num;
565
566 send_api_call:
567   seq_num = RpcSendUdp2(idinfo, server,
568       (api_num == RPC_API_NUM_RPC_ALIVE
569        ? RPC_SEND_TO_SERVER_NO_RETRY
570        : RPC_SEND_TO_SERVER),
571       RPC_PACKET_APICALL,
572       (args_size > 0) ? 2 : 1, sendbuf);
573   if (seq_num < 0) {
574     return RPC_ERR_No_Response;
575   }
576
577   // wait for response
578   UINT16 response;
579   RPC_Result result = RpcClientWaitResponse(idinfo, (UINT32)seq_num, Response_wait_msec,
580       &response);
581   if (result != RPC_OK) {
582     return result;
583   }
584
585   if (response == RPC_RESPONSE_API_BUSY) {        /* Server is busy */
586     return RPC_ERR_Busy;
587   } else if (response == RPC_RESPONSE_API_ERR) {    /*  API call error */
588     RPC_LOG_STATE("APIcall error (can't queue)");
589     return RPC_ERR_Fatal;
590   } else if (response == RPC_RESPONSE_API_DEADLOCK) {  /* Server is in deadlock */
591     RPC_LOG_STATE("server DeadLock.");
592     return RPC_ERR_Server_DeadLock;
593   } else if (response == RPC_RESPONSE_API_CERTIFY) {  /* Authentication request */
594     struct sockaddr_un srvr_sa_un, secure_sa_un;
595     socklen_t srvr_sa_len, secure_sa_len;
596     int secure_sock_un;
597
598     /* Create client socket for authentication */
599     memset(&secure_sa_un, 0, sizeof(secure_sa_un));
600     secure_sa_un.sun_family = AF_UNIX;
601     secure_sock_un = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
602     RpcSetClientSecureName(secure_sa_un.sun_path, RPC_port(idinfo));
603     secure_sa_len = (socklen_t)(sizeof(secure_sa_un.sun_family) + SECURE_SOCK_NAME_LEN);
604     if (bind(secure_sock_un, (struct sockaddr *)&secure_sa_un, secure_sa_len) < 0) {
605       RPC_LOG_PERROR("STREAM : bind(unix), ID:%#x", RPC_port(idinfo));
606     }
607     idinfo->secure_sock = secure_sock_un;
608
609     /* Destination Server Socket Setting */
610     memset(&srvr_sa_un, 0, sizeof(srvr_sa_un));
611     srvr_sa_un.sun_family = AF_UNIX;
612     RpcSetServerSecureName(srvr_sa_un.sun_path, server);
613     srvr_sa_len = (socklen_t)(sizeof(srvr_sa_un.sun_family) + SECURE_SOCK_NAME_LEN);
614
615     /* Connection */
616     int cr = connect(RPC_my_secure_sock(idinfo), (struct sockaddr *)&srvr_sa_un, srvr_sa_len);
617     if (0 > cr) {
618       RPC_LOG_STATE("client connect() is failed.");
619       return RPC_ERR_Fatal;
620     }
621
622     /* Waiting for server authentication */
623     RPC_Result ret_certify = RpcClientWaitCertification(idinfo, &srvr_pid);
624     close(RPC_my_secure_sock(idinfo));
625     if (RPC_OK != ret_certify) {/* Authentication NG */
626       RPC_LOG_STATE("denied the connection.");
627       return ret_certify;
628     }
629
630     /* inotify monitoring of server processes */
631     char intfy_fname[32];
632     snprintf(intfy_fname, sizeof(intfy_fname), CL_INTFY_FILENAME_FORMAT, srvr_pid);
633     int wd = inotify_add_watch(RPC_clnt_inotify_fd(idinfo), intfy_fname, IN_DELETE_SELF);
634     if (0 > wd) {
635       RPC_LOG_STATE("intfy_fname is Not Found [%s].", intfy_fname);
636     }
637
638     /* Register the communication destination server PID in the management table. */
639     if (RPC_OK != RpcRegistSrvrPid(idinfo, server, srvr_pid, wd)) {
640       return RPC_ERR_Fatal;
641     }
642     goto send_api_call;  /* Sending the API request again */
643
644   } else if (response == RPC_RESPONSE_NONE) {  // LCOV_EXCL_BR_LINE 8: dead code, not implement
645     // Not implemented to cancel processing
646     // LCOV_EXCL_START 8: dead code, not implement
647     RPC_LOG_STATE("No response for API call");
648     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
649     return RPC_ERR_No_Response;
650   }  // LCOV_EXCL_STOP
651
652   // When the server ALIVE is queried, no result is returned, so return here
653   if (api_num == RPC_API_NUM_RPC_ALIVE) {
654     return RPC_OK;
655   }
656
657   // API call is accepted at server
658   // now wait for the return packet
659   result = RpcClientWaitResult(idinfo, server);
660   if (result != RPC_OK) {
661     RpcDiscardAPIcallReturn(idinfo);
662     return result;
663   }
664
665   /****** Function error and return value must be handled separately *******/
666   UINT8 *return_str = RPC_apicall_return_str(idinfo); /* pgr0689 */
667 #ifdef APICALL_RETURN_TIMEOUT
668   if (return_str  == NULL) {
669     RPC_LOG_STATE("APIcall return timeout");
670     return RPC_ERR_No_Response;
671   }
672 #else
673   rpc_assert(return_str != NULL);  // LCOV_EXCL_BR_LINE 6: double check
674 #endif
675
676   RPC_THREAD_MUTEX_LOCK(idinfo->thread_info);
677
678   *ret_string = rpc_malloc(RPC_apicall_return_str_len(idinfo));
679   if (*ret_string != NULL) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc
680     if (ret_size) {
681       *ret_size = RPC_apicall_return_str_len(idinfo);
682     }
683     memcpy(*ret_string, RPC_apicall_return_str(idinfo),
684         RPC_apicall_return_str_len(idinfo));
685   } else {
686     RPC_LOG_STATE("APIcall: No Memory");  // LCOV_EXCL_START 5: fail safe for libc malloc
687     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
688     result = RPC_ERR_Fatal;
689   }  // LCOV_EXCL_STOP
690   RPC_THREAD_MUTEX_UNLOCK(idinfo->thread_info);
691   RpcDiscardAPIcallReturn(idinfo);
692
693   return result;
694 }
695
696 /** @brief Releasing allocated memory while API call is processing
697  *
698  * (These functions are called from within a client-facing STUB. Users never use it directly.)
699  */
700   void
701 RPC_free_return_string(void *ptr) {
702   if (ptr != NULL) {
703     rpc_free(ptr);
704   }
705 }
706
707 /** @brief Retrieving file descriptors for determining whether RPC-API calls are requested
708  *
709  * - This function returns a file descriptor used to determine whether or not there is a request to the server.
710  * - For the FD returned by this function, Don't use the other way than the FD specified 
711  *   in the poll or select parameter.
712  * - Intended use
713  *   - Obtain FD using this function.
714  *   - Wait for data to arrive by poll or select.
715  *   - Call RPC_process_API_request() when data arrived.
716  *   - This procedure performs handling request of the API call from the client.
717  *     (Server-side API function is executed.)
718  *
719  * @param id [IN]RPC_ID of the server program.
720  * @param fd [OUT]Storage of file descriptor
721  *
722  * @retval RPC_OK: normal completion
723  * @retval Otherwise: Abnormal termination (FATAL)
724  * @see RPC_process_API_request
725  */
726   RPC_Result
727 RPC_get_fd(RPC_ID id, int *fd) {
728   if ((id == RPC_NO_ID) || (fd == NULL)) {
729     return RPC_ERR_Fatal;
730   }
731   rpc_assert(fd != NULL);  // LCOV_EXCL_BR_LINE 6: double check
732
733   RpcThreadInfo *th = RpcMyThreadInfo();
734
735   THREAD_INFO_CHECK(th);
736
737   SUB_THREAD_CHECK();  // LCOV_EXCL_BR_LINE 15: macro define in rpc_lib.c
738
739   RpcIdInfo *idinfo = RPC_srvr_idinfo(th);
740
741   rpc_assert(idinfo != NULL && RPC_my_id(idinfo) == id);  // LCOV_EXCL_BR_LINE 6: double check
742
743   *fd = RPC_pipe_sub_main(th)[PIPE_READ];
744
745   return RPC_OK;
746 }
747
748 /** API Call Request Handling
749 */
750   static RPC_Result
751 ProcessAPIcallRequest(RpcIdInfo *idinfo, RPC_ID client, UINT16 api_num,
752     char *args_string, unsigned int args_size) {
753   /* ----------------------------
754    * call API dispatch function
755    * ----------------------------
756    */
757
758   /* API Running Client RPC_ID Setting */
759   RPC_apicall_in_process_client(idinfo) = client;
760
761   char *ret_string = NULL;
762   unsigned int ret_size = 0;
763   RPC_dispatch_func_t dispatch = RPC_apicall_dispatch_func(idinfo);
764   rpc_assert(dispatch != NULL);  // LCOV_EXCL_BR_LINE 6: double check
765   RPC_Result api_ret;
766   api_ret = dispatch(api_num, args_string, args_size, &ret_string, &ret_size); /* pgr0060 */
767
768   unsigned char retcode[RPC_RETCODE_LEN+1];
769   sprintf((char *)retcode, "%08x ", api_ret);
770
771   rpc_send_buf sendbuf[2];
772   sendbuf[0].buf = retcode;
773   sendbuf[0].bytes = sizeof(retcode) - 1;
774
775   int seq_num;
776
777   if (ret_string != NULL) {
778     sendbuf[1].buf = ret_string;
779     sendbuf[1].bytes = ret_size;
780     seq_num = RpcSendUdp2(idinfo, client, RPC_SEND_TO_CLIENT,
781         RPC_PACKET_APIRETURN, 2, sendbuf);
782   } else {
783     seq_num = RpcSendUdp2(idinfo, client, RPC_SEND_TO_CLIENT,
784         RPC_PACKET_APIRETURN, 1, sendbuf);
785   }
786   RPC_marshall_free(1, ret_string);
787
788   if (seq_num < 0) {
789     RPC_LOG_ERR("send result failed!");
790     return RPC_ERR_Fatal;
791   }
792
793   /* Set API Running Client RPC_ID to None */
794   RPC_apicall_in_process_client(idinfo) = RPC_NO_PORT;
795
796   /* Sleep API-processing entries */
797   RPC_THREAD_MUTEX_LOCK(idinfo->thread_info);
798   CL_MonitorSetEntry(CL_MONITOR_TYPE_RPC, RPC_port(idinfo),
799       CL_MONITOR_STATE_SLEEP, 0, 0);
800   RPC_THREAD_MUTEX_UNLOCK(idinfo->thread_info);
801
802   return api_ret;
803 }
804
805 /** @brief Executing RPC-API calls
806  *
807  * Process all queued API execution requests from clients.
808  * The API function of the server program is called from here.
809  * If there is no API execution request, the system returns normally immediately without waiting.
810  *
811  * @param id [IN]RPC_ID of the server program
812  * @retval RPC_OK: normal completion
813  * @retval Otherwise: Fatal errors
814  */
815   RPC_Result
816 RPC_process_API_request(RPC_ID id) {
817   if (id == RPC_NO_ID) {
818     return RPC_ERR_Fatal;
819   }
820   RpcThreadInfo *th = RpcMyThreadInfo();
821
822   THREAD_INFO_CHECK(th);
823
824   SUB_THREAD_CHECK();
825
826   RpcIdInfo *idinfo = RPC_srvr_idinfo(th);
827
828   rpc_assert(idinfo != NULL && id == RPC_my_id(idinfo));  // LCOV_EXCL_BR_LINE 6: double check
829
830   rpc_assert(RPC_apicall_info(idinfo) != NULL /* pgr0689 */   // LCOV_EXCL_BR_LINE 6: double check
831       && RPC_apicall_dispatch_func(idinfo) != NULL);  // LCOV_EXCL_BR_LINE 6: double check
832
833   char c;
834   read(RPC_pipe_sub_main(th)[PIPE_READ], &c, sizeof(c));
835
836   /* Process all API calls here */
837   UINT16 api_num;
838   RPC_ID client = RPC_NO_PORT;
839   RPC_Result result = RPC_OK;
840   char *args_string;
841   unsigned int args_size;
842   do {
843     api_num = RpcGetAPIRequest(idinfo, &client,
844         &args_string, &args_size);
845
846     if (api_num > 0) {/* API calls were queued */
847       result = ProcessAPIcallRequest(idinfo, client, api_num,
848           args_string, args_size);
849
850       RpcFreeAPIArgsString(args_string);
851
852       if (result == RPC_ERR_API_Fatal || result == RPC_ERR_Fatal) {
853         break;
854       } else {
855         result = RPC_OK;
856       }
857     }
858   } while(api_num > 0);
859
860   return result;
861 }
862
863 /** @brief Returns the operational state of the RPC server
864  *
865  * Returns whether or not the server with the specified RPC_ID is running.
866  *
867  * @param id [IN]RPC_ID of the server program
868  * @retval RPC_OK: Running
869  * @retval RPC_ERR_No_Response: Server is not running
870  */
871   RPC_Result
872 RPC_is_server_ready(RPC_ID id) {
873 #if defined(RPC_USE_UNIX_AUTOBIND)
874   char *ret_string = NULL;
875   unsigned int ret_size;
876   RPC_Result ret;
877
878   // Invoke Internal-API Calls for Server ALIVE Queries
879   ret = RPC_API_call(id, RPC_API_NUM_RPC_ALIVE, NULL, 0,
880       &ret_string, &ret_size);
881   RPC_free_return_string(ret_string);
882
883   return ret;
884 #else /* !AUTOBIND */
885   struct stat statbuf;
886   int err;
887   char sockname[128];
888
889   /* Check if server socket is created */
890   rpc_set_socket_name(sockname, id);
891   err = stat(sockname, &statbuf);
892   if (err == 0) {
893     return RPC_OK;
894   } else {
895     return RPC_ERR_No_Response;
896   }
897 #endif /* !AUTOBIND */
898 }
899
900 /** @brief Registering UIDs and GID Lists
901  *
902  * Register a list of UIDs and GIDs that can be accepted by the RPC server.
903  * A function used by the RPC server after RPC_START_SECURE_SERVER().
904  * Return error if called from an RPC client or an RPC server that has not called RPC_START_SECURE_SERVER().
905  *
906  * @param uid_num          [IN] Number of registered UIDs (number of elements in UID list array)
907  * @param *uid_list          [IN] Start pointer of registered UID list
908  * @param gid_num          [IN] Number of registered GIDs (number of elements in the array of GID lists)
909  * @param *gid_list          [IN] Start pointer of registered GID list
910  * @retval RPC_OK:              List registration completed
911  * @retval RPC_ERR_Fatal:       Failed to save to list
912  */
913 RPC_Result
914 RPC_regist_credential(int uid_num, uid_t *uid_list, int gid_num, gid_t *gid_list) {
915   RpcThreadInfo *th = RpcMyThreadInfo();
916   THREAD_INFO_CHECK(th);
917
918   if (NULL == RPC_srvr_idinfo(th)) {
919     RPC_LOG_ERR("No server thread info");
920     return RPC_ERR_Fatal;
921   }
922
923   RpcIdInfo *idinfo = RPC_srvr_idinfo(th);
924   if ((NULL == idinfo) || (NULL == RPC_apicall_info(idinfo))) {  // LCOV_EXCL_BR_LINE 8: dead code, idinfo always isn't NULL
925     // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL
926     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
927     RPC_LOG_ERR("No RPC_ID info");
928     return RPC_ERR_Fatal;
929   }  // LCOV_EXCL_STOP
930
931   /* Neither UID nor GID list is specified. */
932   if ((NULL == uid_list) && (NULL == gid_list)) {
933     RPC_LOG_ERR("RPC_regist_credential() : UID and GID list is NULL.");
934     return RPC_ERR_Fatal;
935   }
936
937   /* UID list argument check */
938   if ((NULL == uid_list) && ((0 < uid_num ) && (uid_num <= CREDENTIAL_LIST_NUM_MAX))) {/* UID list is invalid */
939     RPC_LOG_ERR("RPC_regist_credential() : UID list is illegal.");
940     return RPC_ERR_Fatal;
941   } else if ((NULL != uid_list) && ((1 > uid_num) || (uid_num > CREDENTIAL_LIST_NUM_MAX))) {/* Number of UID list elements is invalid */
942     RPC_LOG_ERR("RPC_regist_credential() : UID list num is illegal.");
943     return RPC_ERR_Configuration;
944   }
945
946   /* GID list argument check */
947   if ((NULL == gid_list) && ((0 < gid_num ) && (gid_num <= CREDENTIAL_LIST_NUM_MAX))) {/* GID list is invalid */
948     RPC_LOG_ERR("RPC_regist_credential() : GID list is illegal.");
949     return RPC_ERR_Fatal;
950   } else if ((NULL != gid_list) && ((1 > gid_num) || (gid_num > CREDENTIAL_LIST_NUM_MAX))) {/* Number of GID list elements is invalid */
951     RPC_LOG_ERR("RPC_regist_credential() : GID list num is illegal.");
952     return RPC_ERR_Configuration;
953   }
954
955   if (NO_SECURE_CHECK == RPC_secure_check(idinfo)) {/* Return error if registration is not necessary */
956     RPC_LOG_ERR("Needless secure check.");
957     return RPC_ERR_Fatal;
958   }
959
960   if (REGISTERED == RPC_regist_credential_info(idinfo)) {/* Return error if a list has already been registered */
961     RPC_LOG_ERR("credential info has been registered already.");
962     return RPC_ERR_Fatal;
963   }
964
965   /* Allocate as many memory areas as there are UID and GID lists */
966   RPC_apicall_info(idinfo)->uid_list = rpc_malloc(sizeof(uid_t) * (unsigned int)uid_num);
967   if (NULL == RPC_apicall_info(idinfo)->uid_list) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc
968     RPC_LOG_ERR("Can't malloc uid_list.");  // LCOV_EXCL_START 5: fail safe for libc malloc
969     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
970     return RPC_ERR_Fatal;
971   }  // LCOV_EXCL_STOP
972   RPC_apicall_info(idinfo)->gid_list = rpc_malloc(sizeof(gid_t) * (unsigned int)gid_num);
973   if (NULL == RPC_apicall_info(idinfo)->gid_list) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc
974     RPC_LOG_ERR("Can't malloc gid_list.");  // LCOV_EXCL_START 5: fail safe for libc malloc
975     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
976     return RPC_ERR_Fatal;
977   }  // LCOV_EXCL_STOP
978
979   /* Copy UID and GID registration list and number of elements */
980   memcpy(RPC_apicall_info(idinfo)->uid_list, uid_list, sizeof(uid_t) * (unsigned int)uid_num);    /* UID list */
981   memcpy(RPC_apicall_info(idinfo)->gid_list, gid_list, sizeof(gid_t) * (unsigned int)gid_num);    /* GID list */
982   RPC_uid_num(idinfo) = uid_num;    /* Number of elements in the UID list */
983   RPC_gid_num(idinfo) = gid_num;    /* Number of elements in the GID list */
984
985   /* Set whether to register authentication information to Yes/No */
986   RPC_regist_credential_info(idinfo) = REGISTERED;
987
988   return RPC_OK;
989 }
990
991 /** @brief Obtain authentication info (UID, GID) of API requesting client
992  *
993  * Obtain the UID and GID of the client that requested the API processing being executed.
994  * Return error if called from an RPC client or to an RPC server that has not called RPC_START_SECURE_SERVER().
995  * This function should be called within an API function (in other words, API is being executed) provided to the client.
996  * if called the other function, error is returned because there is no API being executed.
997  *
998  * @param *client_uid          [OUT] Requesting client UID of running API
999  * @param *client_gid          [OUT] Requesting client GID of running API
1000  * @retval RPC_OK:              Succeeded to obtain of authentication info
1001  * @retval RPC_ERR_Fatal:       Failed to obtain of authentication Info
1002  */
1003 RPC_Result
1004 RPC_get_client_credential(uid_t *client_uid, gid_t *client_gid) {
1005   RpcThreadInfo *th = RpcMyThreadInfo();
1006   THREAD_INFO_CHECK(th);
1007
1008   if (NULL == RPC_srvr_idinfo(th)) {
1009     RPC_LOG_ERR("No server thread info");
1010     return RPC_ERR_Fatal;
1011   }
1012
1013   RpcIdInfo *idinfo = RPC_srvr_idinfo(th);
1014   if ((NULL == idinfo) || (NULL == RPC_apicall_info(idinfo))) {  // LCOV_EXCL_BR_LINE 8: dead code, idinfo always isn't NULL
1015     // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL
1016     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1017     RPC_LOG_ERR("No RPC_ID info");
1018     return RPC_ERR_Fatal;
1019   }  // LCOV_EXCL_STOP
1020
1021   if ((NULL == client_uid) || (NULL == client_gid)) {/* Argument check */
1022     RPC_LOG_ERR("RPC_regist_credential() : Invalid Param.");
1023     return RPC_ERR_Fatal;
1024   }
1025
1026   if (NO_SECURE_CHECK == RPC_secure_check(idinfo)) {/* Return error if no security */
1027     RPC_LOG_ERR("Needless secure check.");
1028     return RPC_ERR_Fatal;
1029   }
1030
1031   if (RPC_NO_PORT == RPC_apicall_in_process_client(idinfo)) {/* Return error if the API is not being executed */
1032     RPC_LOG_ERR("NOT in process APIcall.");
1033     return RPC_ERR_Fatal;
1034   }
1035
1036   char buf[7], client_path_name[SOCK_NAME_LEN];  /* Client socket name */
1037
1038   /* Converting client_id to the socket name associated with RPC_ID */
1039   RpcSetClientName(buf, RPC_apicall_in_process_client(idinfo));
1040   memcpy(client_path_name, buf + 1, 5);
1041   client_path_name[5] = '\0';
1042   RpcClientSockNameInfo *current = RPC_sock_info_head(idinfo);
1043
1044   /* Search info of running client from the management table */
1045   while (NULL != current) {
1046     if (0 == strcmp(current->client_sock_name, client_path_name)) {/* Match Running Client Info */
1047       *client_uid = current->uid;
1048       *client_gid = current->gid;
1049       return RPC_OK;
1050     }
1051     current = current->next;
1052   }
1053   RPC_LOG_ERR("Nothing client credential info.");
1054   return RPC_ERR_Fatal;  /* Not found Client info */
1055 }
1056
1057 /** @brief Waiting for server authentication
1058  *
1059  * When a client requests an API to the server,
1060  * wait for the server to check whether it is allowed to communicate.
1061  *
1062  * @param *idinfo         [IN] Information associated with the client's RPC_ID
1063  *
1064  * @retval RPC_OK:                      Authentication OK (communication with the server is permitted)
1065  * @retval RPC_ERR_Reject_connect:      Authentication NG (Communication denied)
1066  */
1067 static  RPC_Result
1068 RpcClientWaitCertification(RpcIdInfo *idinfo, pid_t *srvr_pid) {
1069   fd_set fds;
1070   RpcCertifyResult recv_ret;  /* Authentication result from the server */
1071   RPC_Result ret = RPC_ERR_Fatal;
1072
1073   for(;;) {
1074     FD_ZERO(&fds);
1075     FD_SET(RPC_my_secure_sock(idinfo), &fds);
1076
1077     int sret = select(RPC_my_secure_sock(idinfo) + 1, &fds, NULL, NULL, NULL);
1078     if (sret < 0 && errno == EINTR) {/* signal interrupt */  // LCOV_EXCL_BR_LINE 5: fail safe for libc select
1079       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1080       continue;  // LCOV_EXCL_LINE 5: fail safe for libc select
1081     } else if (sret > 0 && FD_ISSET(RPC_my_secure_sock(idinfo), &fds)) {
1082       /* Check the response from the server */
1083       ssize_t rret = recv(RPC_my_secure_sock(idinfo), (char*)&recv_ret, sizeof(RpcCertifyResult), 0);
1084       if (0 < rret) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc recv
1085         switch(recv_ret.certify_res) {
1086           case CERTIFY_OK:  /* OK */
1087             ret = RPC_OK;
1088             *srvr_pid = recv_ret.srvr_pid;
1089           break;
1090
1091           case CERTIFY_NG:  /* NG */
1092             ret = RPC_ERR_Reject_connect;
1093             break;
1094
1095           default:
1096             ret = RPC_ERR_Fatal;
1097             break;
1098         }
1099         goto exit_loop_ok;
1100       } else if(0 == rret) {  // LCOV_EXCL_START 5: fail safe for libc recv
1101         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1102         RPC_LOG_ERR("server process terminate.");
1103         return RPC_ERR_Fatal;
1104       } else {
1105         RPC_LOG_PERROR("certification_wait recv()");
1106         return RPC_ERR_Fatal;
1107       }  // LCOV_EXCL_STOP
1108     }
1109   }
1110 exit_loop_ok:
1111   return ret;
1112 }
1113
1114 /** @brief Register the PID of the communication destination server in the management table.
1115  *
1116  * Register a pair of the PID and ID of the server in the management table.
1117  *
1118  * @param *idinfo  [IN] Information associated with the client's RPC_ID
1119  * @param srvr_rpc_id  [IN] RPC_ID of the communication destination server
1120  * @param srvr_pid  [IN] PID of the communication destination server
1121  *
1122  * @retval RPC_OK      : Registration completed
1123  * @retval RPC_ERR_Fatal          : Registration failed
1124  */
1125 static  RPC_Result
1126 RpcRegistSrvrPid(RpcIdInfo *idinfo, RPC_ID srvr_rpc_id, pid_t srvr_pid, int wd) {
1127   if ((NULL == idinfo) || (srvr_rpc_id == RPC_NO_ID) || (0 > srvr_pid)) {  // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL
1128     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1129     RPC_LOG_ERR("RpcRegistSrvrPid() : Invalid Param.");
1130     return RPC_ERR_Fatal;
1131   }  // LCOV_EXCL_STOP
1132
1133   RpcSrvrPidInfo *srvr_pid_buf, *current;
1134
1135   srvr_pid_buf = rpc_malloc(sizeof(RpcSrvrPidInfo));
1136   if( srvr_pid_buf == NULL ){  // LCOV_EXCL_START 5: fail safe for libc malloc
1137     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1138     return RPC_ERR_Fatal;
1139   }  // LCOV_EXCL_STOP
1140
1141   srvr_pid_buf->srvr_rpc_id = srvr_rpc_id;  /* Server RPC_ID */
1142   srvr_pid_buf->srvr_pid = srvr_pid;          /* Server PID  */
1143   srvr_pid_buf->wd = wd;            /* wd    */
1144   srvr_pid_buf->next = NULL;      /* Next node in the communication destination server PID management table */
1145
1146   if (0 == RPC_srvr_pid_head(idinfo)) {
1147     RPC_srvr_pid_head(idinfo) = srvr_pid_buf;
1148   } else {
1149     for (current = RPC_srvr_pid_head(idinfo); current->next != NULL; current = current->next)
1150       ;
1151     current->next = srvr_pid_buf;
1152   }
1153   return RPC_OK;
1154 }
1155
1156 /** @brief Delete Termination Process PID from Management Table
1157  *
1158  * Check whether the terminated process matches the communicating server process, and delete it from the management table.
1159  *
1160  * @param *idinfo    [IN] Information associated with the client's RPC_ID
1161  * @param srvr_rpc_id    [IN] Currently communicating server RPC_ID
1162  * @param wd      [IN] Wd of the termination process
1163  *
1164  * @retval RPC_OK    : Deletion completed
1165  * @retval RPC_ERR_Server_Finish: Deletion completed (server process in communication terminated)
1166  * @retval RPC_ERR_Fatal        : Argument error
1167  */
1168   RPC_Result
1169 RpcDeleteSrvrPid(RpcIdInfo *idinfo, RPC_ID srvr_rpc_id, int wd) {
1170   if ((NULL == idinfo) || (RPC_NO_ID == srvr_rpc_id)) {  // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL
1171     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1172     RPC_LOG_ERR("rpc_check_srvr_pid() : Invalid Param.");
1173     return RPC_ERR_Fatal;
1174   }  // LCOV_EXCL_STOP
1175
1176   RPC_Result ret = RPC_OK;
1177   int cnt = 0;
1178   RpcSrvrPidInfo *current, *previous;
1179   current = RPC_srvr_pid_head(idinfo);
1180
1181   while (NULL != current) {
1182     if (wd == current->wd) {
1183
1184       /* Check whether the termination process matches the communicating server process */
1185       if (srvr_rpc_id == current->srvr_rpc_id) {
1186         ret = RPC_ERR_Server_Finish;
1187       }
1188
1189       /* Delete info from the Server info table */
1190       if (0 == cnt) {/* Delete the start of the management table */
1191         RPC_srvr_pid_head(idinfo) = RPC_srvr_pid_head(idinfo)->next;
1192         rpc_free(current);
1193         current = RPC_srvr_pid_head(idinfo);
1194         cnt = -1;
1195       } else {/* Delete all but the first element */
1196         // LCOV_EXCL_START 8: dead code
1197         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1198         previous->next = current->next;
1199         rpc_free(current);
1200         current = previous->next;
1201         // LCOV_EXCL_STOP
1202       }
1203     } else {
1204       previous = current;
1205       current = current->next;
1206     }
1207     cnt ++;
1208   }
1209   return ret;
1210 }
1211
1212 /** @brief Delete all PID management tables of the communication destination server
1213  *
1214  * Releases the PID management table and deletes all data when the client terminates with RPC_end().
1215  *
1216  * @param *idinfo      [IN] Information associated with the client's RPC_ID
1217  *
1218  * @retval RPC_OK      : Deletion completed
1219  * @retval RPC_ERR_Fatal          : Argument error
1220  */
1221 static  RPC_Result
1222 RpcAllDeleteSrvrPid(RpcIdInfo *idinfo) {
1223   if (NULL == idinfo) {  // LCOV_EXCL_BR_LINE 6: double check in rpc_lib.c --> RPC_end()
1224     RPC_LOG_ERR("RpcAllDeleteSrvrPid() : Invalid Param.");  // LCOV_EXCL_START 6:  double check in rpc_lib.c --> RPC_end()
1225     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
1226     return RPC_ERR_Fatal;
1227   }  // LCOV_EXCL_STOP
1228
1229   RpcSrvrPidInfo *current = RPC_srvr_pid_head(idinfo);
1230   while (NULL != current) {
1231
1232     if (0 <= current->wd) {
1233       inotify_rm_watch(RPC_clnt_inotify_fd(idinfo), current->wd);
1234     }
1235
1236     RpcSrvrPidInfo *previous = current;
1237     current = current->next;
1238
1239     rpc_free(previous);
1240   }
1241   RPC_srvr_pid_head(idinfo) = NULL;
1242   return RPC_OK;
1243 }
1244
1245 /** @brief Logging RPC-API calling process
1246  *
1247  * Receive File name, function name and line-number of the client calling API and API-function-name, and logging them.
1248  *
1249  * @param filename [IN]Pointer to caller filename string
1250  * @param funcname [IN]Pointer to caller function-name string
1251  * @param line [IN]Line-number in the source file of the client
1252  * @param apiname [IN]Pointer to call-API-function-name string
1253  * @retval 0: normal completion
1254  * @retval Otherwise: Fatal error
1255  */
1256   int
1257 RPC_record_dbg_log( const char *filename, const char *funcname, int line,
1258     const char *apiname ) {
1259   printf( "[RPC debug log]%s() called from %s() [%s, line %d]\n",
1260       apiname, funcname, filename, line );
1261   return 0;
1262 }
1263
1264 /** @}*/