2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup tag_NSMessageQueue
19 /// \brief API Header for Zone Player Service APIs to be used by senders and
22 /// APIs to register/unregister notifications and add/remove recievers to the notifications.
24 ///////////////////////////////////////////////////////////////////////////////
29 #include "ns_msg_queue.h"
32 #include <ns_mq_internal.h>
34 #include "ns_mq_anomaly.h"
36 #include <other_service/strlcpy.h>
37 #include <other_service/strlcat.h>
39 const UI_32 DEFAULT_MSG_PRIORITY = 10;
40 const UI_32 MAX_MESSAGES_STORED_IN_QUEUE = 256;
41 const UI_32 MAX_SYNC_RESPONSE_STORED_IN_QUEUE = 2;
43 ////////////////////////////////////////////////////////////////////////////////////////////////////
44 // Function : TranslateError
45 // Translates global error variables into FW EFrameworkunifiedStatus
46 ////////////////////////////////////////////////////////////////////////////////////////////////////
47 EFrameworkunifiedStatus TranslateError(int error) {
48 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusFail;
52 eStatus = eFrameworkunifiedStatusOK;
55 eStatus = eFrameworkunifiedStatusThreadBusy;
58 eStatus = eFrameworkunifiedStatusThreadSelfJoin;
61 eStatus = eFrameworkunifiedStatusFault;
64 eStatus = eFrameworkunifiedStatusInvldParam;
67 eStatus = eFrameworkunifiedStatusThreadNotExist;
70 eStatus = eFrameworkunifiedStatusErrNoEBADF;
73 eStatus = eFrameworkunifiedStatusErrNoEAGAIN;
76 eStatus = eFrameworkunifiedStatusErrNoEINTR;
79 eStatus = eFrameworkunifiedStatusInvldBufSize;
82 eStatus = eFrameworkunifiedStatusNotImplemented;
85 eStatus = eFrameworkunifiedStatusAccessError;
88 eStatus = eFrameworkunifiedStatusFail;
95 static UI_8 GetNormalizedMqName(PSTR normalized_mqname , PCSTR name, size_t size) {
96 if ((NULL != name) && (NULL != normalized_mqname)) {
98 strlcpy(normalized_mqname, "/", size);
99 strlcat(normalized_mqname, name, size);
101 strlcpy(normalized_mqname, name, size);
110 HANDLE OpenReceiverNotBlocked(PCSTR name) {
111 HANDLE rtnHandle = INVALID_HANDLE; // invalid until made valid.
112 PSTR normalized_qname = NULL;
113 SI_32 q_fd = -1; // fd to mqueue
114 SQhandle *rcvHndl = NULL;
115 struct mq_attr mqattr;
116 size_t norm_qname_size = 0;
118 // Check for invalid name
120 return INVALID_HANDLE;
123 if (strlen(name) >= MAX_QUEUE_NAME_SIZE) {
124 return INVALID_HANDLE;
127 norm_qname_size = strlen(name) + 2;
128 normalized_qname = (PSTR)malloc(norm_qname_size);
130 if (0 != GetNormalizedMqName(normalized_qname, name, norm_qname_size)) {
131 if (strlen(normalized_qname) > LIMIT_QUEUE_NAME_SIZE) {
132 free(normalized_qname);
133 return INVALID_HANDLE;
137 mqattr.mq_maxmsg = (__syscall_slong_t)MAX_MESSAGES_STORED_IN_QUEUE;
138 mqattr.mq_msgsize = MAX_QUEUE_MSG_SIZE;
140 q_fd = mq_open(normalized_qname, O_RDONLY | O_CREAT | O_NONBLOCK | O_CLOEXEC , 0666, &mqattr);
143 rcvHndl = (SQhandle *)malloc(sizeof(SQhandle));
144 if (rcvHndl != NULL) {
145 rcvHndl->check_code = MQ_CHECK_CODE;
147 rcvHndl->q_name = normalized_qname;
148 rcvHndl->q_type = eQTypeReveiver;
150 /////////////////////////////////////////
151 rcvHndl->threadid = 0;
152 /////////////////////////////////////////
154 // Set the return handle to rcvHndl
160 if (INVALID_HANDLE == rtnHandle) {
161 // couldn't connect the queue,
162 // release the memory to normalized queue name
163 if (normalized_qname != NULL) {
164 free(normalized_qname);
165 normalized_qname = NULL; // mb20110108 item 11
172 static HANDLE openReceiverInternal(PCSTR name, UI_32 mq_maxmsg, UI_32 mq_msgsize, BOOL is_internal) {
173 HANDLE rtnHandle = INVALID_HANDLE; // invalid until made valid.
174 PSTR normalized_qname = NULL;
175 SI_32 q_fd = -1; // fd to mqueue
176 SQhandle *rcvHndl = NULL;
177 struct mq_attr mqattr;
178 size_t norm_qname_size = 0;
180 // Check for invalid name
182 return INVALID_HANDLE;
185 if (strlen(name) >= MAX_QUEUE_NAME_SIZE) {
186 return INVALID_HANDLE;
189 norm_qname_size = strlen(name) + 2;
190 normalized_qname = (PSTR)malloc(norm_qname_size);
192 if (0 != GetNormalizedMqName(normalized_qname, name, norm_qname_size)) {
195 if (!is_internal && strlen(normalized_qname) > LIMIT_QUEUE_NAME_SIZE) {
196 free(normalized_qname);
197 return INVALID_HANDLE;
201 mqattr.mq_maxmsg = (__syscall_slong_t)mq_maxmsg;
202 mqattr.mq_msgsize = (__syscall_slong_t)mq_msgsize;
204 for (i = 0; i < (sizeof(mq_anomaly_list) / sizeof(mq_anomaly_list[0])); i++) {
205 if (strcmp(normalized_qname, mq_anomaly_list[i].name) == 0) {
206 mqattr.mq_maxmsg = (__syscall_slong_t)mq_anomaly_list[i].maxMsg;
212 q_fd = mq_open(normalized_qname, O_RDONLY | O_CREAT | O_CLOEXEC, 0666, &mqattr);
215 rcvHndl = (SQhandle *)malloc(sizeof(SQhandle));
216 if (rcvHndl != NULL) {
217 rcvHndl->check_code = MQ_CHECK_CODE;
219 rcvHndl->q_name = normalized_qname;
220 rcvHndl->q_type = eQTypeReveiver;
222 /////////////////////////////////////////
223 rcvHndl->threadid = 0;
224 /////////////////////////////////////////
226 // Set the return handle to rcvHndl
233 if (INVALID_HANDLE == rtnHandle) {
234 // couldn't connect the queue,
235 // release the memory to normalized queue name
236 if (normalized_qname != NULL) {
237 free(normalized_qname);
238 normalized_qname = NULL; // mb20110108 item 11
245 HANDLE OpenReceiver(PCSTR name) {
246 return openReceiverInternal(name, MAX_MESSAGES_STORED_IN_QUEUE, MAX_QUEUE_MSG_SIZE, FALSE);
249 HANDLE openSyncReceiver(PCSTR name) {
250 return openReceiverInternal(name, MAX_SYNC_RESPONSE_STORED_IN_QUEUE , MAX_QUEUE_MSG_SIZE, TRUE);
253 static HANDLE openSenderInternal(PCSTR name, UI_32 mq_maxmsg, UI_32 mq_msgsize, BOOL is_internal, BOOL zero_copy) {
254 HANDLE rtnHandle = INVALID_HANDLE; // invalid until made valid.
255 SI_32 q_fd = -1; // fd to queue
256 SQhandle *sndHndl = NULL;
257 PSTR normalized_qname = NULL;
258 size_t norm_qname_size = 0;
260 struct mq_attr mqattr;
262 // Check for invalid name
267 if (strlen(name) >= MAX_QUEUE_NAME_SIZE) {
271 norm_qname_size = strlen(name) + 2;
272 normalized_qname = (PSTR)malloc(norm_qname_size);
274 if (NULL == normalized_qname) {
278 if (0 != GetNormalizedMqName(normalized_qname, name, norm_qname_size)) {
282 if (!is_internal && strlen(normalized_qname) > LIMIT_QUEUE_NAME_SIZE) {
283 free(normalized_qname);
284 return INVALID_HANDLE;
288 mqattr.mq_maxmsg = (__syscall_slong_t)mq_maxmsg;
289 mqattr.mq_msgsize = (__syscall_slong_t)mq_msgsize;
291 for (i = 0; i < (sizeof(mq_anomaly_list) / sizeof(mq_anomaly_list[0])); i++) {
292 if (strcmp(normalized_qname, mq_anomaly_list[i].name) == 0) {
293 mqattr.mq_maxmsg = (__syscall_slong_t)mq_anomaly_list[i].maxMsg;
298 q_fd = mq_open(normalized_qname, O_WRONLY | O_CREAT | O_NONBLOCK | O_CLOEXEC, 0666, &mqattr);
301 sndHndl = (SQhandle *)malloc(sizeof(SQhandle));
302 if (NULL != sndHndl) {
303 sndHndl->check_code = MQ_CHECK_CODE;
305 sndHndl->q_name = normalized_qname;
306 sndHndl->q_type = eQTypeSender;
308 sndHndl->threadid = 0;
311 // Set the return handle to sndHndl
315 sndHndl->sendbuf = malloc(MAX_QUEUE_MSG_SIZE);
316 if (sndHndl->sendbuf == NULL) {
317 // LCOV_EXCL_START 5: malloc's error case
318 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
320 rtnHandle = INVALID_HANDLE;
324 sndHndl->sendbuf = NULL;
330 if (INVALID_HANDLE == rtnHandle) {
331 // couldn't connect the queue,
332 // release the memory to normalized queue name
333 if (normalized_qname != NULL) {
334 free(normalized_qname);
335 normalized_qname = NULL; // mb20110108 item 11
342 return rtnHandle; // invalid until made valid.
345 HANDLE OpenSender(PCSTR name) {
346 return openSenderInternal(name, MAX_MESSAGES_STORED_IN_QUEUE, MAX_QUEUE_MSG_SIZE, FALSE, FALSE);
350 HANDLE OpenSenderChild(PCSTR name, pthread_t threadid) {
351 HANDLE h = OpenSender(name);
352 if (INVALID_HANDLE != h) {
353 SQhandle *sq = (SQhandle *)h;
354 sq->threadid = threadid;
360 HANDLE openSyncSender(PCSTR name) {
361 return openSenderInternal(name, MAX_SYNC_RESPONSE_STORED_IN_QUEUE, MAX_QUEUE_MSG_SIZE, TRUE, FALSE);
364 HANDLE openSenderZc(PCSTR name) {
365 return openSenderInternal(name, MAX_MESSAGES_STORED_IN_QUEUE, MAX_QUEUE_MSG_SIZE, FALSE, TRUE);
369 EFrameworkunifiedStatus JoinChild(HANDLE hChildApp) {
370 // mb20110108 Code re-structured per comments 24 & 25
371 if (mqCheckValidHandle(hChildApp)) {
372 SQhandle *sq = (SQhandle *)hChildApp;
373 return TranslateError(pthread_join(sq->threadid, NULL));
375 return eFrameworkunifiedStatusFail;
379 EFrameworkunifiedStatus GetChildThreadPriority(HANDLE hChildApp, PSI_32 threadPrio) {
380 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusFail;
381 // LCOV_EXCL_BR_START 6:GetChildThreadPriority is called by McGetChildThreadPriority, and hChildApp will check there.
382 if (mqCheckValidHandle(hChildApp)) {
384 SQhandle *sq = (SQhandle *)hChildApp;
385 SI_32 schedPolicy; // this is needed according to syntax of pthread_getschedparam. api not available to get prio directly.
386 struct sched_param schedParam;
387 eStatus = TranslateError(pthread_getschedparam(sq->threadid, &schedPolicy, &schedParam));
389 *threadPrio = schedParam.sched_priority;
391 // LCOV_EXCL_START 6:GetChildThreadPriority is called by McGetChildThreadPriority, and hChildApp will check there.
392 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
393 eStatus = eFrameworkunifiedStatusInvldHandle;
400 /////////////////////////////////////////
402 EFrameworkunifiedStatus SendMessage(HANDLE hMessage, UI_32 length, PVOID data) {
403 return SendMessageWithPriority(hMessage, length, data, eFrameworkunifiedMsgPrioNormal);
406 EFrameworkunifiedStatus SendMessageWithPriority(HANDLE hMessage, UI_32 length, PVOID data, EFrameworkunifiedMessagePriorties priority) {
407 // define a Q handle structure
408 SQhandle *sndHndl = NULL;
410 // mb20110108 Added per comments 27 & 28
411 if (length > 0 && NULL == data) {
412 return eFrameworkunifiedStatusInvldBuf;
415 // check handle for null case...
416 if (mqCheckValidHandle(hMessage) == FALSE) {
417 return eFrameworkunifiedStatusInvldHandle;
420 sndHndl = (SQhandle *)hMessage;
422 // check to see if this is a sender handle
423 if (sndHndl->q_type != eQTypeSender) {
424 return eFrameworkunifiedStatusInvldHndlType;
427 if (-1 == mq_send((mqd_t)sndHndl->fd, (PCSTR)data, (size_t)length, (unsigned int)priority)) {
428 if (errno == EAGAIN) {
429 return eFrameworkunifiedStatusMsgQFull;
431 return TranslateError(errno);
434 return eFrameworkunifiedStatusOK;
437 SI_32 ReceiveMessage(HANDLE hMessage, UI_32 length, PVOID data) {
438 // define a Q handle structure
439 SQhandle *rcvHndl = NULL;
441 // check handle for null case...
442 if (mqCheckValidHandle(hMessage) == FALSE) {
447 rcvHndl = (SQhandle *)hMessage;
449 // check to see if this is a receiver handle
450 if (rcvHndl->q_type != eQTypeReveiver) {
456 return (SI_32)mq_receive((mqd_t)rcvHndl->fd, (char *)data, (size_t)length, NULL);
459 EFrameworkunifiedStatus CloseReceiver(HANDLE handle) {
460 SQhandle *rcvHndl = NULL;
463 // check handle for null case...
464 if (mqCheckValidHandle(handle) == FALSE) {
465 return eFrameworkunifiedStatusInvldHandle;
468 rcvHndl = (SQhandle *)handle;
470 // check to see if this is a receiver handle
471 if (rcvHndl->q_type != eQTypeReveiver) {
472 return eFrameworkunifiedStatusInvldHndlType;
475 rcvHndl->check_code = 0;
478 if (NULL != rcvHndl->q_name) {
479 free(rcvHndl->q_name); // remove the memory to the name
480 rcvHndl->q_name = NULL;
482 free((void *)handle); // remove handle.. now..
483 handle = INVALID_HANDLE;
485 return ((-1 == mq_close((mqd_t)q_fd)) ? eFrameworkunifiedStatusInvldHandle : eFrameworkunifiedStatusOK);
488 EFrameworkunifiedStatus CloseSender(HANDLE handle) {
489 SQhandle *sndHndl = NULL;
492 // check handle for null case...
493 if (mqCheckValidHandle(handle) == FALSE) {
494 return eFrameworkunifiedStatusInvldHandle;
497 sndHndl = (SQhandle *)handle;
499 // check to see if this is a sender handle
500 if (sndHndl->q_type != eQTypeSender) {
501 return eFrameworkunifiedStatusInvldHndlType;
504 sndHndl->check_code = 0;
505 q_fd = sndHndl->fd; // copy the fd, need it to close the queues....
507 if (NULL != sndHndl->q_name) {
508 free(sndHndl->q_name); // remove the memory to the name
509 sndHndl->q_name = NULL;
511 if (NULL != sndHndl->sendbuf) {
512 free(sndHndl->sendbuf);
513 sndHndl->sendbuf = NULL;
515 free((void *)handle); // remove handle.. now..
516 handle = INVALID_HANDLE; // invalidate handle so user doesn't reuse...
518 return (-1 == mq_close((mqd_t)q_fd)) ? eFrameworkunifiedStatusInvldHandle : eFrameworkunifiedStatusOK;
521 static UI_8 IsMessageAvailable(SI_32 fd) {
522 struct mq_attr sMqStatus;
523 if (-1 == mq_getattr(fd, &sMqStatus)) {
527 if (0 < sMqStatus.mq_curmsgs) {
535 void Flush(HANDLE hMessage) {
536 SQhandle *rcvHndl = NULL;
538 if (mqCheckValidHandle(hMessage)) {
539 rcvHndl = (SQhandle *)hMessage;
541 if (rcvHndl->q_type != eQTypeReveiver) {
545 // check there is anything on the queue before going into the loop....
546 if (IsMessageAvailable(rcvHndl->fd)) {
547 CHAR l_pReceiveBuffer_o[MAX_QUEUE_MSG_SIZE];
549 // read till there isn't anything on the queue.
550 while (IsMessageAvailable(rcvHndl->fd)) {
551 mq_receive((mqd_t)rcvHndl->fd, l_pReceiveBuffer_o, (size_t)MAX_QUEUE_MSG_SIZE, NULL);
557 EQType GetQueueType(HANDLE hMessage) {
558 EQType qType = eQTypeInvld;
560 if (mqCheckValidHandle(hMessage)) {
561 SQhandle *handle = (SQhandle *)hMessage;
562 qType = handle->q_type;
568 PCSTR GetQueueName(HANDLE hMessage) {
571 if (mqCheckValidHandle(hMessage)) {
572 SQhandle *hMsgQ = (SQhandle *)hMessage;
574 if (hMsgQ->q_type == eQTypeSender ||
575 hMsgQ->q_type == eQTypeReveiver) {
576 name = hMsgQ->q_name;
583 int GetQueueFD(HANDLE hMessage) {
586 if (mqCheckValidHandle(hMessage)) {
587 SQhandle *hMsgQ = (SQhandle *)hMessage;
589 if (hMsgQ->q_type == eQTypeSender ||
590 hMsgQ->q_type == eQTypeReveiver) {