1 /*
2 * Trace Recorder for Tracealyzer v4.6.6
3 * Copyright 2021 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_STREAM_PORT_BUFFER_SIZE)];
34 #else
35 TraceUnsignedBaseType_t buffer[1];
36 #endif
37 } TraceStreamPortTCPIP_t;
38
39 static TraceStreamPortTCPIP_t* pxStreamPortFile;
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* bytesRead);
43 static int32_t prvSocketInitializeListener();
44 static int32_t prvSocketAccept();
45 static void prvCloseAllSockets();
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 == 0)
53 return -1;
54
55 *piBytesWritten = send( new_sd, pvData, uiSize, 0 );
56 if (*piBytesWritten < 0)
57 {
58 /* EWOULDBLOCK may be expected when buffers are full */
59 if ((errno != 0) && (errno != EWOULDBLOCK))
60 {
61 closesocket(new_sd);
62 new_sd = -1;
63 return -1;
64 }
65 else
66 *piBytesWritten = 0;
67 }
68
69 return 0;
70 }
71
prvSocketReceive(void * pvData,uint32_t uiSize,int32_t * bytesRead)72 static int32_t prvSocketReceive( void* pvData, uint32_t uiSize, int32_t* bytesRead )
73 {
74 if (new_sd < 0)
75 return -1;
76
77 *bytesRead = recv( new_sd, pvData, uiSize, 0 );
78 /* EWOULDBLOCK may be expected when there is no pvData to receive */
79 if (errno != 0 && errno != EWOULDBLOCK)
80 {
81 closesocket(new_sd);
82 new_sd = -1;
83 return -1;
84 }
85
86 return 0;
87 }
88
prvSocketInitializeListener()89 static int32_t prvSocketInitializeListener()
90 {
91 if (sock >= 0)
92 return 0;
93
94 sock = lwip_socket(AF_INET, SOCK_STREAM, 0);
95
96 if (sock < 0)
97 return -1;
98
99 address.sin_family = AF_INET;
100 address.sin_port = htons(TRC_CFG_STREAM_PORT_TCPIP_PORT);
101 address.sin_addr.s_addr = INADDR_ANY;
102
103 if (bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)
104 {
105 closesocket(sock);
106 sock = -1;
107 return -1;
108 }
109
110 if (lwip_listen(sock, 5) < 0)
111 {
112 closesocket(sock);
113 sock = -1;
114 return -1;
115 }
116
117 return 0;
118 }
119
prvSocketAccept()120 static int32_t prvSocketAccept()
121 {
122 if (sock < 0)
123 return -1;
124
125 if (new_sd >= 0)
126 return 0;
127
128 remoteSize = sizeof( remote );
129 new_sd = accept( sock, (struct sockaddr *)&remote, (socklen_t*)&remoteSize );
130
131 if( new_sd < 0 )
132 {
133 closesocket(new_sd);
134 new_sd = -1;
135 closesocket(sock);
136 sock = -1;
137 return -1;
138 }
139
140 flags = fcntl( new_sd, F_GETFL, 0 );
141 fcntl( new_sd, F_SETFL, flags | O_NONBLOCK );
142
143 return 0;
144 }
145
prvCloseAllSockets()146 static void prvCloseAllSockets()
147 {
148 if (new_sd > 0)
149 {
150 closesocket(new_sd);
151 }
152
153 if (sock > 0)
154 {
155 closesocket(sock);
156 }
157 }
158 /************** MODIFY THE ABOVE PART TO USE YOUR TPC/IP STACK ****************/
159
prvTraceTcpWrite(void * pvData,uint32_t uiSize,int32_t * piBytesWritten)160 int32_t prvTraceTcpWrite(void* pvData, uint32_t uiSize, int32_t *piBytesWritten)
161 {
162 prvSocketInitializeListener();
163
164 prvSocketAccept();
165
166 return prvSocketSend(pvData, uiSize, piBytesWritten);
167 }
168
prvTraceTcpRead(void * pvData,uint32_t uiSize,int32_t * piBytesRead)169 int32_t prvTraceTcpRead(void* pvData, uint32_t uiSize, int32_t *piBytesRead)
170 {
171 prvSocketInitializeListener();
172
173 prvSocketAccept();
174
175 return prvSocketReceive(pvData, uiSize, piBytesRead);
176 }
177
xTraceStreamPortInitialize(TraceStreamPortBuffer_t * pxBuffer)178 traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer)
179 {
180 TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortTCPIP_t);
181
182 if (pxBuffer == 0)
183 {
184 return TRC_FAIL;
185 }
186
187 pxStreamPortFile = (TraceStreamPortTCPIP_t*)pxBuffer;
188
189 #if (TRC_USE_INTERNAL_BUFFER == 1)
190 return xTraceInternalEventBufferInitialize(pxStreamPortFile->buffer, sizeof(pxStreamPortFile->buffer));
191 #else
192 return TRC_SUCCESS;
193 #endif
194 }
195
xTraceStreamPortOnTraceEnd(void)196 traceResult xTraceStreamPortOnTraceEnd(void)
197 {
198 prvCloseAllSockets();
199
200 return TRC_SUCCESS;
201 }
202
203 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
204
205 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
206