• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * @brief
32  *   This file includes the platform-specific initializers.
33  */
34 
35 #include "platform-simulation.h"
36 
37 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME
38 
39 #include <assert.h>
40 #include <errno.h>
41 #include <inttypes.h>
42 #include <libgen.h>
43 #include <stddef.h>
44 #include <stdint.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <syslog.h>
48 
49 #include <openthread/tasklet.h>
50 #include <openthread/platform/alarm-milli.h>
51 
52 #include "utils/uart.h"
53 
54 uint32_t gNodeId = 1;
55 
56 extern bool          gPlatformPseudoResetWasRequested;
57 static volatile bool gTerminate = false;
58 
59 int    gArgumentsCount = 0;
60 char **gArguments      = NULL;
61 
62 uint64_t sNow = 0; // microseconds
63 int      sSockFd;
64 uint16_t sPortOffset;
65 
handleSignal(int aSignal)66 static void handleSignal(int aSignal)
67 {
68     OT_UNUSED_VARIABLE(aSignal);
69 
70     gTerminate = true;
71 }
72 
otSimSendEvent(const struct Event * aEvent)73 void otSimSendEvent(const struct Event *aEvent)
74 {
75     ssize_t            rval;
76     struct sockaddr_in sockaddr;
77 
78     memset(&sockaddr, 0, sizeof(sockaddr));
79     sockaddr.sin_family = AF_INET;
80     inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
81     sockaddr.sin_port = htons(9000 + sPortOffset);
82 
83     rval = sendto(sSockFd, aEvent, offsetof(struct Event, mData) + aEvent->mDataLength, 0, (struct sockaddr *)&sockaddr,
84                   sizeof(sockaddr));
85 
86     if (rval < 0)
87     {
88         perror("sendto");
89         exit(EXIT_FAILURE);
90     }
91 }
92 
receiveEvent(otInstance * aInstance)93 static void receiveEvent(otInstance *aInstance)
94 {
95     struct Event event;
96     ssize_t      rval = recvfrom(sSockFd, (char *)&event, sizeof(event), 0, NULL, NULL);
97 
98     if (rval < 0 || (uint16_t)rval < offsetof(struct Event, mData))
99     {
100         perror("recvfrom");
101         exit(EXIT_FAILURE);
102     }
103 
104     platformAlarmAdvanceNow(event.mDelay);
105 
106     switch (event.mEvent)
107     {
108     case OT_SIM_EVENT_ALARM_FIRED:
109         break;
110 
111     case OT_SIM_EVENT_RADIO_RECEIVED:
112         platformRadioReceive(aInstance, event.mData, event.mDataLength);
113         break;
114 
115     case OT_SIM_EVENT_UART_WRITE:
116         otPlatUartReceived(event.mData, event.mDataLength);
117         break;
118 
119     default:
120         assert(false);
121     }
122 }
123 
platformSendSleepEvent(void)124 static void platformSendSleepEvent(void)
125 {
126     struct Event event;
127 
128     assert(platformAlarmGetNext() > 0);
129 
130     event.mDelay      = platformAlarmGetNext();
131     event.mEvent      = OT_SIM_EVENT_ALARM_FIRED;
132     event.mDataLength = 0;
133 
134     otSimSendEvent(&event);
135 }
136 
137 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
platformUartRestore(void)138 void platformUartRestore(void)
139 {
140 }
141 
otPlatUartEnable(void)142 otError otPlatUartEnable(void)
143 {
144     return OT_ERROR_NONE;
145 }
146 
otPlatUartDisable(void)147 otError otPlatUartDisable(void)
148 {
149     return OT_ERROR_NONE;
150 }
151 
otPlatUartSend(const uint8_t * aData,uint16_t aLength)152 otError otPlatUartSend(const uint8_t *aData, uint16_t aLength)
153 {
154     otError      error = OT_ERROR_NONE;
155     struct Event event;
156 
157     event.mDelay      = 0;
158     event.mEvent      = OT_SIM_EVENT_UART_WRITE;
159     event.mDataLength = aLength;
160 
161     memcpy(event.mData, aData, aLength);
162 
163     otSimSendEvent(&event);
164 
165     otPlatUartSendDone();
166 
167     return error;
168 }
169 
otPlatUartFlush(void)170 otError otPlatUartFlush(void)
171 {
172     return OT_ERROR_NONE;
173 }
174 #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
175 
socket_init(void)176 static void socket_init(void)
177 {
178     struct sockaddr_in sockaddr;
179     char *             offset;
180     memset(&sockaddr, 0, sizeof(sockaddr));
181     sockaddr.sin_family = AF_INET;
182 
183     offset = getenv("PORT_OFFSET");
184 
185     if (offset)
186     {
187         char *endptr;
188 
189         sPortOffset = (uint16_t)strtol(offset, &endptr, 0);
190 
191         if (*endptr != '\0')
192         {
193             fprintf(stderr, "Invalid PORT_OFFSET: %s\n", offset);
194             exit(EXIT_FAILURE);
195         }
196 
197         sPortOffset *= (MAX_NETWORK_SIZE + 1);
198     }
199 
200     sockaddr.sin_port        = htons((uint16_t)(9000 + sPortOffset + gNodeId));
201     sockaddr.sin_addr.s_addr = INADDR_ANY;
202 
203     sSockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
204 
205     if (sSockFd == -1)
206     {
207         perror("socket");
208         exit(EXIT_FAILURE);
209     }
210 
211     if (bind(sSockFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
212     {
213         perror("bind");
214         exit(EXIT_FAILURE);
215     }
216 }
217 
otSysInit(int argc,char * argv[])218 void otSysInit(int argc, char *argv[])
219 {
220     char *endptr;
221 
222     if (gPlatformPseudoResetWasRequested)
223     {
224         gPlatformPseudoResetWasRequested = false;
225         return;
226     }
227 
228     if (argc != 2)
229     {
230         exit(EXIT_FAILURE);
231     }
232 
233     openlog(basename(argv[0]), LOG_PID, LOG_USER);
234     setlogmask(setlogmask(0) & LOG_UPTO(LOG_NOTICE));
235 
236     gArgumentsCount = argc;
237     gArguments      = argv;
238 
239     gNodeId = (uint32_t)strtol(argv[1], &endptr, 0);
240 
241     if (*endptr != '\0' || gNodeId < 1 || gNodeId > MAX_NETWORK_SIZE)
242     {
243         fprintf(stderr, "Invalid NodeId: %s\n", argv[1]);
244         exit(EXIT_FAILURE);
245     }
246 
247     socket_init();
248 
249     platformAlarmInit(1);
250     platformRadioInit();
251     platformRandomInit();
252 
253     signal(SIGTERM, &handleSignal);
254     signal(SIGHUP, &handleSignal);
255 }
256 
otSysPseudoResetWasRequested(void)257 bool otSysPseudoResetWasRequested(void)
258 {
259     return gPlatformPseudoResetWasRequested;
260 }
261 
otSysDeinit(void)262 void otSysDeinit(void)
263 {
264     close(sSockFd);
265 }
266 
otSysProcessDrivers(otInstance * aInstance)267 void otSysProcessDrivers(otInstance *aInstance)
268 {
269     fd_set read_fds;
270     fd_set write_fds;
271     fd_set error_fds;
272     int    max_fd = -1;
273     int    rval;
274 
275     if (gTerminate)
276     {
277         exit(0);
278     }
279 
280     FD_ZERO(&read_fds);
281     FD_ZERO(&write_fds);
282     FD_ZERO(&error_fds);
283 
284     FD_SET(sSockFd, &read_fds);
285     max_fd = sSockFd;
286 
287 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
288     platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
289 #endif
290 
291     if (!otTaskletsArePending(aInstance) && platformAlarmGetNext() > 0 && !platformRadioIsTransmitPending())
292     {
293         platformSendSleepEvent();
294 
295         rval = select(max_fd + 1, &read_fds, &write_fds, &error_fds, NULL);
296 
297         if ((rval < 0) && (errno != EINTR))
298         {
299             perror("select");
300             exit(EXIT_FAILURE);
301         }
302 
303         if (rval > 0 && FD_ISSET(sSockFd, &read_fds))
304         {
305             receiveEvent(aInstance);
306         }
307     }
308 
309     platformAlarmProcess(aInstance);
310     platformRadioProcess(aInstance, &read_fds, &write_fds);
311 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
312     platformUartProcess();
313 #endif
314 }
315 
316 #if OPENTHREAD_CONFIG_OTNS_ENABLE
317 
otPlatOtnsStatus(const char * aStatus)318 void otPlatOtnsStatus(const char *aStatus)
319 {
320     struct Event event;
321     uint16_t     statusLength = (uint16_t)strlen(aStatus);
322 
323     assert(statusLength < sizeof(event.mData));
324 
325     memcpy(event.mData, aStatus, statusLength);
326     event.mDataLength = statusLength;
327     event.mDelay      = 0;
328     event.mEvent      = OT_SIM_EVENT_OTNS_STATUS_PUSH;
329 
330     otSimSendEvent(&event);
331 }
332 
333 #endif // OPENTHREAD_CONFIG_OTNS_ENABLE
334 
335 #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
336