• 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 "lib/platform/exit_code.h"
53 #include "utils/uart.h"
54 
55 uint32_t gNodeId = 1;
56 
57 extern bool          gPlatformPseudoResetWasRequested;
58 static volatile bool gTerminate = false;
59 
60 int    gArgumentsCount = 0;
61 char **gArguments      = NULL;
62 
63 uint64_t sNow = 0; // microseconds
64 int      sSockFd;
65 uint16_t sPortBase = 9000;
66 uint16_t sPortOffset;
67 
handleSignal(int aSignal)68 static void handleSignal(int aSignal)
69 {
70     OT_UNUSED_VARIABLE(aSignal);
71 
72     gTerminate = true;
73 }
74 
otSimSendEvent(const struct Event * aEvent)75 void otSimSendEvent(const struct Event *aEvent)
76 {
77     ssize_t            rval;
78     struct sockaddr_in sockaddr;
79 
80     memset(&sockaddr, 0, sizeof(sockaddr));
81     sockaddr.sin_family = AF_INET;
82     inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
83     sockaddr.sin_port = htons(sPortBase + sPortOffset);
84 
85     rval = sendto(sSockFd, aEvent, offsetof(struct Event, mData) + aEvent->mDataLength, 0, (struct sockaddr *)&sockaddr,
86                   sizeof(sockaddr));
87 
88     if (rval < 0)
89     {
90         perror("sendto");
91         DieNow(OT_EXIT_ERROR_ERRNO);
92     }
93 }
94 
receiveEvent(otInstance * aInstance)95 static void receiveEvent(otInstance *aInstance)
96 {
97     struct Event event;
98     ssize_t      rval = recvfrom(sSockFd, (char *)&event, sizeof(event), 0, NULL, NULL);
99 
100     if (rval < 0 || (uint16_t)rval < offsetof(struct Event, mData))
101     {
102         perror("recvfrom");
103         DieNow(OT_EXIT_ERROR_ERRNO);
104     }
105 
106     platformAlarmAdvanceNow(event.mDelay);
107 
108     switch (event.mEvent)
109     {
110     case OT_SIM_EVENT_ALARM_FIRED:
111         break;
112 
113     case OT_SIM_EVENT_RADIO_RECEIVED:
114         platformRadioReceive(aInstance, event.mData, event.mDataLength);
115         break;
116 
117     case OT_SIM_EVENT_UART_WRITE:
118         otPlatUartReceived(event.mData, event.mDataLength);
119         break;
120 
121     default:
122         assert(false);
123     }
124 }
125 
platformSendSleepEvent(void)126 static void platformSendSleepEvent(void)
127 {
128     struct Event event;
129 
130     assert(platformAlarmGetNext() > 0);
131 
132     event.mDelay      = platformAlarmGetNext();
133     event.mEvent      = OT_SIM_EVENT_ALARM_FIRED;
134     event.mDataLength = 0;
135 
136     otSimSendEvent(&event);
137 }
138 
139 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
platformUartRestore(void)140 void platformUartRestore(void) {}
141 
otPlatUartEnable(void)142 otError otPlatUartEnable(void) { return OT_ERROR_NONE; }
143 
otPlatUartDisable(void)144 otError otPlatUartDisable(void) { return OT_ERROR_NONE; }
145 
otPlatUartSend(const uint8_t * aData,uint16_t aLength)146 otError otPlatUartSend(const uint8_t *aData, uint16_t aLength)
147 {
148     otError      error = OT_ERROR_NONE;
149     struct Event event;
150 
151     event.mDelay      = 0;
152     event.mEvent      = OT_SIM_EVENT_UART_WRITE;
153     event.mDataLength = aLength;
154 
155     memcpy(event.mData, aData, aLength);
156 
157     otSimSendEvent(&event);
158 
159     otPlatUartSendDone();
160 
161     return error;
162 }
163 
otPlatUartFlush(void)164 otError otPlatUartFlush(void) { return OT_ERROR_NONE; }
165 #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
166 
socket_init(void)167 static void socket_init(void)
168 {
169     struct sockaddr_in sockaddr;
170     memset(&sockaddr, 0, sizeof(sockaddr));
171     sockaddr.sin_family = AF_INET;
172 
173     parseFromEnvAsUint16("PORT_BASE", &sPortBase);
174 
175     parseFromEnvAsUint16("PORT_OFFSET", &sPortOffset);
176     sPortOffset *= (MAX_NETWORK_SIZE + 1);
177 
178     sockaddr.sin_port        = htons((uint16_t)(sPortBase + sPortOffset + gNodeId));
179     sockaddr.sin_addr.s_addr = INADDR_ANY;
180 
181     sSockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
182 
183     if (sSockFd == -1)
184     {
185         perror("socket");
186         DieNow(OT_EXIT_ERROR_ERRNO);
187     }
188 
189     if (bind(sSockFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
190     {
191         perror("bind");
192         DieNow(OT_EXIT_ERROR_ERRNO);
193     }
194 }
195 
otSysInit(int argc,char * argv[])196 void otSysInit(int argc, char *argv[])
197 {
198     char *endptr;
199 
200     if (gPlatformPseudoResetWasRequested)
201     {
202         gPlatformPseudoResetWasRequested = false;
203         return;
204     }
205 
206     if (argc != 2)
207     {
208         DieNow(OT_EXIT_FAILURE);
209     }
210 
211     openlog(basename(argv[0]), LOG_PID, LOG_USER);
212     setlogmask(setlogmask(0) & LOG_UPTO(LOG_NOTICE));
213 
214     gArgumentsCount = argc;
215     gArguments      = argv;
216 
217     gNodeId = (uint32_t)strtol(argv[1], &endptr, 0);
218 
219     if (*endptr != '\0' || gNodeId < 1 || gNodeId > MAX_NETWORK_SIZE)
220     {
221         fprintf(stderr, "Invalid NodeId: %s\n", argv[1]);
222         DieNow(OT_EXIT_FAILURE);
223     }
224 
225     socket_init();
226 
227     platformAlarmInit(1);
228     platformRadioInit();
229     platformRandomInit();
230 
231     signal(SIGTERM, &handleSignal);
232     signal(SIGHUP, &handleSignal);
233 }
234 
otSysPseudoResetWasRequested(void)235 bool otSysPseudoResetWasRequested(void) { return gPlatformPseudoResetWasRequested; }
236 
otSysDeinit(void)237 void otSysDeinit(void) { close(sSockFd); }
238 
otSysProcessDrivers(otInstance * aInstance)239 void otSysProcessDrivers(otInstance *aInstance)
240 {
241     fd_set read_fds;
242     fd_set write_fds;
243     fd_set error_fds;
244     int    max_fd = -1;
245     int    rval;
246 
247     if (gTerminate)
248     {
249         exit(0);
250     }
251 
252     FD_ZERO(&read_fds);
253     FD_ZERO(&write_fds);
254     FD_ZERO(&error_fds);
255 
256     FD_SET(sSockFd, &read_fds);
257     max_fd = sSockFd;
258 
259 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
260     platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
261 #endif
262 
263     if (!otTaskletsArePending(aInstance) && platformAlarmGetNext() > 0 && !platformRadioIsTransmitPending())
264     {
265         platformSendSleepEvent();
266 
267         rval = select(max_fd + 1, &read_fds, &write_fds, &error_fds, NULL);
268 
269         if ((rval < 0) && (errno != EINTR))
270         {
271             perror("select");
272             DieNow(OT_EXIT_ERROR_ERRNO);
273         }
274 
275         if (rval > 0 && FD_ISSET(sSockFd, &read_fds))
276         {
277             receiveEvent(aInstance);
278         }
279     }
280 
281     platformAlarmProcess(aInstance);
282     platformRadioProcess(aInstance, &read_fds, &write_fds);
283 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
284     platformUartProcess();
285 #endif
286 }
287 
288 #if OPENTHREAD_CONFIG_OTNS_ENABLE
289 
otPlatOtnsStatus(const char * aStatus)290 void otPlatOtnsStatus(const char *aStatus)
291 {
292     struct Event event;
293     uint16_t     statusLength = (uint16_t)strlen(aStatus);
294 
295     assert(statusLength < sizeof(event.mData));
296 
297     memcpy(event.mData, aStatus, statusLength);
298     event.mDataLength = statusLength;
299     event.mDelay      = 0;
300     event.mEvent      = OT_SIM_EVENT_OTNS_STATUS_PUSH;
301 
302     otSimSendEvent(&event);
303 }
304 
305 #endif // OPENTHREAD_CONFIG_OTNS_ENABLE
306 
307 #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
308