Re-organized sub-directory by category
[staging/basesystem.git] / service / native / framework_unified / client / NS_SharedMemIf / src / ns_shared_mem_if.cpp
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 /// \ingroup tag_NSSharedMemory
19 /// \brief SharedMemIf implementation
20 ///
21 /// Implements interface functions to SharedMem service
22 //////////////////////////////////////////////////////////////////////////////////////////////////
23 #include <native_service/ns_shared_mem_if.h>         ///< Shared mem source interface file
24 #include <native_service/ns_logger_if.h>
25
26 #include <sys/mman.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <time.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <unistd.h>
33
34 #define NS_SHM_HEADER_SIZE (48)
35
36 /////////////////////////////////////////////////////////////////////////////
37 /// Utility functions and classes
38
39 static TMemID getclock(void) {
40   struct timespec tp;
41   if (clock_gettime(CLOCK_MONOTONIC_RAW, &tp) < 0) {   // LCOV_EXCL_BR_LINE 5: clock_gettime's error case.
42     return 0;
43   }
44   return (TMemID)(((uint64_t)tp.tv_sec * 1000 * 1000 * 1000 + tp.tv_nsec) >> 8);
45 }
46
47 static size_t uitoa(unsigned int value, char *buf) {
48   static const char c[] = "0123456789abcdef";
49   int i;
50
51   if (buf == NULL) {
52       FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "buf is NULL");
53       return 0;
54   }
55   for (i = 0; i < 8; i++) {
56     buf[i] = c[(value >> ((7 - i) * 4)) & 0xf];
57   }
58   buf[i] = '\0';
59
60   return i;
61 }
62
63 static inline void create_shmname(char *buf, TMemID id) {
64   if (buf == NULL) {
65     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "buf is NULL");
66     return;
67   }
68   strcpy(buf, "nsshm_");  // NOLINT  (readability/nolint)
69   buf += sizeof("nsshm_") - 1;
70   uitoa(id, buf);
71 }
72
73 //////////////////////////////////////////////////////////////////////////////////////////////////
74 // Public interface function definitions
75
76 TMemID SetDataToShared(const void *data, UI_32 dataBytes, const char *from, const char *to) {
77   TMemID id;
78   char shmname[16];
79   int fd;
80   void *addr = MAP_FAILED;
81
82   if (data == NULL) {
83     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "data is NULL");
84     return BAD_MEM_ID;
85   }
86   if (from == NULL) {
87     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "from is NULL");
88     return BAD_MEM_ID;
89   }
90   if (to == NULL) {
91     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "to is NULL");
92     return BAD_MEM_ID;
93   }
94
95   if (dataBytes == 0) {
96     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "DataSize is invalied(%d)", dataBytes);
97     return BAD_MEM_ID;
98   }
99
100   while (1) {
101     id = getclock();
102     create_shmname(shmname, id);
103
104     if ((fd = shm_open(shmname, O_CREAT | O_EXCL | O_RDWR, 0666)) < 0) {
105       if (errno == EEXIST) {
106         continue;
107       }
108       FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "shm_open: %s", strerror(errno));
109       return BAD_MEM_ID;
110     }
111     break;
112   }
113
114   if (ftruncate(fd, dataBytes + NS_SHM_HEADER_SIZE) < 0) {  // LCOV_EXCL_BR_LINE 5: ftruncate's error case.
115     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "ftruncate: %s", strerror(errno));
116     id = BAD_MEM_ID;
117     goto exit;
118   }
119
120   if ((addr = mmap(NULL, dataBytes + NS_SHM_HEADER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
121     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "mmap: %s", strerror(errno));
122     id = BAD_MEM_ID;
123     goto exit;
124   }
125
126   strcpy(reinterpret_cast<char *>(addr), from);  // NOLINT  (readability/nolint)
127   strcpy(reinterpret_cast<char *>(addr) + (NS_SHM_HEADER_SIZE / 2), to);  // NOLINT  (readability/nolint)
128   /**
129    * @todo
130    * Specifying a large number (4097 or higher) for the Session Data Size for transmission results in a segmentation fault.
131    */
132   memcpy(reinterpret_cast<char *>(addr) + NS_SHM_HEADER_SIZE, data, dataBytes);
133
134 exit:
135   close(fd);
136   if (addr != MAP_FAILED) {
137     munmap(addr, dataBytes + NS_SHM_HEADER_SIZE);
138   }
139   if (id == BAD_MEM_ID) {
140     shm_unlink(shmname);
141   }
142   return id;
143 }
144
145 EFrameworkunifiedStatus GetDataFromShared(TMemID id, void *data, UI_32 dataMaxBytes) {
146   EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusFail;
147   char shmname[16];
148   int fd;
149   void *addr = MAP_FAILED;
150   struct stat sb;
151
152   if (id == BAD_MEM_ID) {
153     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "ShMemID is invalied(%u)", id);
154     return eFrameworkunifiedStatusInvldParam;
155   }
156   if (data == NULL) {
157     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "data is NULL");
158     return eFrameworkunifiedStatusInvldParam;
159   }
160   if (dataMaxBytes == 0) {
161     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "DataSize is invalied(%d)", dataMaxBytes);
162     return eFrameworkunifiedStatusInvldParam;
163   }
164
165   create_shmname(shmname, id);
166
167   if ((fd = shm_open(shmname, O_RDONLY, 0)) < 0) {
168     if (errno == ENOENT) {
169       eStatus = eFrameworkunifiedStatusInvldID;
170     }
171     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "shm_open: %s", strerror(errno));
172     return eStatus;
173   }
174
175   if (fstat(fd, &sb) < 0) {  // LCOV_EXCL_BR_LINE 5: fstat's error case
176     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "fstat: %s", strerror(errno));
177     goto exit;
178   }
179   if (sb.st_size - NS_SHM_HEADER_SIZE > static_cast<SI_64>(dataMaxBytes)) {
180     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "DataSize is invalied(%d-%d)", dataMaxBytes, (int)sb.st_size);
181     eStatus = eFrameworkunifiedStatusInvldParam;
182     goto exit;
183   }
184
185   if ((addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {  // LCOV_EXCL_BR_LINE 5: mmap's error case.
186     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
187     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "mmap: %s", strerror(errno));  // LCOV_EXCL_LINE 5: mmap's error case.
188     goto exit;
189   }
190
191   memcpy(data, reinterpret_cast<char *>(addr) + NS_SHM_HEADER_SIZE, sb.st_size - NS_SHM_HEADER_SIZE);
192   eStatus = eFrameworkunifiedStatusOK;
193
194 exit:
195   close(fd);
196   if (addr != MAP_FAILED) {
197     munmap(addr, sb.st_size);
198   }
199   return eStatus;
200 }
201
202 UI_32 GetLengthOfDataFromShared(TMemID id) {
203   UI_32 size = 0;
204   char shmname[16];
205   int fd;
206   struct stat sb;
207
208   if (id == BAD_MEM_ID) {
209     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "ShMemID is invalied(%u)", id);  // LCOV_EXCL_BR_LINE 15:marco defined in "native_service/ns_logger_if.h"
210     return 0;
211   }
212
213   create_shmname(shmname, id);
214
215   if ((fd = shm_open(shmname, O_RDWR, 0)) < 0) {
216     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "shm_open: %s", strerror(errno));
217     return 0;
218   }
219
220   if (fstat(fd, &sb) < 0) {  // LCOV_EXCL_BR_LINE 5: fstat's error case.
221     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
222     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "fstat: %s", strerror(errno));  // LCOV_EXCL_LINE 5: mmap's error case.
223     goto exit;
224   }
225
226   size = static_cast<UI_32>(sb.st_size - NS_SHM_HEADER_SIZE);
227
228 exit:
229   close(fd);
230   return size;
231 }
232
233 EFrameworkunifiedStatus DiscardDataFromShared(TMemID id) {
234   EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
235   char shmname[16];
236
237   if (id == BAD_MEM_ID) {
238     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "ShMemID is invalied(%u)", id);
239     return eFrameworkunifiedStatusInvldParam;
240   }
241
242   create_shmname(shmname, id);
243
244   if (shm_unlink(shmname) < 0) {
245     if (errno == ENOENT) {
246       eStatus = eFrameworkunifiedStatusInvldID;
247     } else {
248       eStatus = eFrameworkunifiedStatusFail;
249     }
250     FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "shm_unlink: %s", strerror(errno));
251   }
252
253   return eStatus;
254 }