1 /*
2 * Trace Recorder for Tracealyzer v4.9.2
3 * Copyright 2023 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Supporting functions for trace streaming, used by the "stream ports"
9 * for reading and writing data to the interface.
10 * Existing ports can easily be modified to fit another setup, e.g., a
11 * different TCP/IP stack, or to define your own stream port.
12 */
13
14 #include <trcRecorder.h>
15
16 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
17
18 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
19
20 /* TCP/IP includes - for lwIP in this case */
21 #include <lwip/tcpip.h>
22 #include <lwip/sockets.h>
23 #include <lwip/errno.h>
24
25 int sock = -1, new_sd = -1;
26 int flags = 0;
27 int remoteSize;
28 struct sockaddr_in address, remote;
29
30 typedef struct TraceStreamPortTCPIP
31 {
32 #if (TRC_USE_INTERNAL_BUFFER)
33 uint8_t buffer[(TRC_ALIGNED_STREAM_PORT_BUFFER_SIZE)];
34 #else
35 TraceUnsignedBaseType_t buffer[1];
36 #endif
37 } TraceStreamPortTCPIP_t;
38
39 static TraceStreamPortTCPIP_t* pxStreamPortTCPIP TRC_CFG_RECORDER_DATA_ATTRIBUTE;
40
41 static int32_t prvSocketSend(void* pvData, uint32_t uiSize, int32_t* piBytesWritten);
42 static int32_t prvSocketReceive(void* pvData, uint32_t uiSize, int32_t* piBytesRead);
43 static int32_t prvSocketInitializeListener(void);
44 static int32_t prvSocketAccept(void);
45 static void prvCloseAllSockets(void);
46
prvSocketSend(void * pvData,uint32_t uiSize,int32_t * piBytesWritten)47 static int32_t prvSocketSend( void* pvData, uint32_t uiSize, int32_t* piBytesWritten )
48 {
49 if (new_sd < 0)
50 return -1;
51
52 if (piBytesWritten == (void*)0)
53 return -1;
54
55 *piBytesWritten = send( new_sd, pvData, uiSize, 0 );
56
57 if (*piBytesWritten < 0)
58 {
59 *piBytesWritten = 0;
60
61 /* EWOULDBLOCK may be expected when buffers are full */
62 if (errno != EWOULDBLOCK)
63 {
64 close(new_sd);
65 new_sd = -1;
66 return -1;
67 }
68 }
69
70 return 0;
71 }
72
prvSocketReceive(void * pvData,uint32_t uiSize,int32_t * piBytesRead)73 static int32_t prvSocketReceive( void* pvData, uint32_t uiSize, int32_t* piBytesRead )
74 {
75 if (new_sd < 0)
76 return -1;
77
78 if (piBytesRead == (void*)0)
79 return -1;
80
81 *piBytesRead = recv( new_sd, pvData, uiSize, 0 );
82
83 if (*piBytesRead < 0)
84 {
85 *piBytesRead = 0;
86
87 /* EWOULDBLOCK may be expected when there is no pvData to receive */
88 if (errno != EWOULDBLOCK)
89 {
90 close(new_sd);
91 new_sd = -1;
92 return -1;
93 }
94 }
95
96 return 0;
97 }
98
prvSocketInitializeListener(void)99 static int32_t prvSocketInitializeListener(void)
100 {
101 if (sock >= 0)
102 {
103 return 0;
104 }
105
106 sock = socket(AF_INET, SOCK_STREAM, 0);
107
108 if (sock < 0)
109 {
110 return -1;
111 }
112
113 address.sin_family = AF_INET;
114 address.sin_port = htons(TRC_CFG_STREAM_PORT_TCPIP_PORT);
115 address.sin_addr.s_addr = INADDR_ANY;
116
117 if (bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)
118 {
119 close(sock);
120 sock = -1;
121 return -1;
122 }
123
124 if (listen(sock, 5) < 0)
125 {
126 close(sock);
127 sock = -1;
128 return -1;
129 }
130
131 return 0;
132 }
133
prvSocketAccept(void)134 static int32_t prvSocketAccept(void)
135 {
136 if (sock < 0)
137 return -1;
138
139 if (new_sd >= 0)
140 return 0;
141
142 remoteSize = sizeof( remote );
143 new_sd = accept( sock, (struct sockaddr *)&remote, (socklen_t*)&remoteSize );
144
145 if( new_sd < 0 )
146 {
147 close(new_sd);
148 new_sd = -1;
149 close(sock);
150 sock = -1;
151 return -1;
152 }
153
154 flags = fcntl( new_sd, F_GETFL, 0 );
155 fcntl( new_sd, F_SETFL, flags | O_NONBLOCK );
156
157 return 0;
158 }
159
prvCloseAllSockets(void)160 static void prvCloseAllSockets(void)
161 {
162 if (new_sd > 0)
163 {
164 close(new_sd);
165 }
166
167 if (sock > 0)
168 {
169 close(sock);
170 }
171 }
172 /************** MODIFY THE ABOVE PART TO USE YOUR TPC/IP STACK ****************/
173
prvTraceTcpWrite(void * pvData,uint32_t uiSize,int32_t * piBytesWritten)174 int32_t prvTraceTcpWrite(void* pvData, uint32_t uiSize, int32_t *piBytesWritten)
175 {
176 prvSocketInitializeListener();
177
178 prvSocketAccept();
179
180 return prvSocketSend(pvData, uiSize, piBytesWritten);
181 }
182
prvTraceTcpRead(void * pvData,uint32_t uiSize,int32_t * piBytesRead)183 int32_t prvTraceTcpRead(void* pvData, uint32_t uiSize, int32_t *piBytesRead)
184 {
185 prvSocketInitializeListener();
186
187 prvSocketAccept();
188
189 return prvSocketReceive(pvData, uiSize, piBytesRead);
190 }
191
xTraceStreamPortInitialize(TraceStreamPortBuffer_t * pxBuffer)192 traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer)
193 {
194 TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortTCPIP_t);
195
196 if (pxBuffer == 0)
197 {
198 return TRC_FAIL;
199 }
200
201 pxStreamPortTCPIP = (TraceStreamPortTCPIP_t*)pxBuffer;
202
203 #if (TRC_USE_INTERNAL_BUFFER == 1)
204 return xTraceInternalEventBufferInitialize(pxStreamPortTCPIP->buffer, sizeof(pxStreamPortTCPIP->buffer));
205 #else
206 return TRC_SUCCESS;
207 #endif
208 }
209
xTraceStreamPortOnTraceEnd(void)210 traceResult xTraceStreamPortOnTraceEnd(void)
211 {
212 prvCloseAllSockets();
213
214 return TRC_SUCCESS;
215 }
216
217 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
218
219 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
220