1 /*
2 * Trace Recorder for Tracealyzer v4.10.3
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<stdio.h>
15 #include<winsock2.h>
16
17 #include <trcRecorder.h>
18
19 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
20
21 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
22
23 #pragma comment(lib,"ws2_32.lib") //Winsock Library
24
25 typedef struct TraceStreamPortTCPIP
26 {
27 #if (TRC_USE_INTERNAL_BUFFER)
28 uint8_t buffer[(TRC_ALIGNED_STREAM_PORT_BUFFER_SIZE)];
29 #else
30 TraceUnsignedBaseType_t buffer[1];
31 #endif
32 } TraceStreamPortTCPIP_t;
33
34 static TraceStreamPortTCPIP_t* pxStreamPortTCPIP TRC_CFG_RECORDER_DATA_ATTRIBUTE;
35 static SOCKET server_socket = (UINT_PTR)0, trace_socket = (UINT_PTR)0;
36 struct sockaddr_in server, client;
37
38 static int prvInitServerSocketIfNeeded(void);
39 static int prvInitWinsockIfNeeded(void);
40 static int prvInitTraceSocketIfNeeded(void);
41 static void prvCloseAllSockets(void);
42
prvInitWinsockIfNeeded(void)43 static int prvInitWinsockIfNeeded(void)
44 {
45 WSADATA wsa;
46
47 if (server_socket)
48 return 0;
49
50 if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
51 {
52 return -1;
53 }
54
55 return 0;
56 }
57
prvInitServerSocketIfNeeded(void)58 static int prvInitServerSocketIfNeeded(void)
59 {
60 if (prvInitWinsockIfNeeded() < 0)
61 {
62 return -1;
63 }
64
65 if (server_socket)
66 return 0;
67
68 if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
69 {
70 return -1;
71 }
72
73 server.sin_family = AF_INET;
74 server.sin_addr.s_addr = INADDR_ANY;
75 server.sin_port = htons(TRC_CFG_STREAM_PORT_TCPIP_PORT);
76
77 if (bind(server_socket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
78 {
79 closesocket(server_socket);
80 WSACleanup();
81 server_socket = (UINT_PTR)0;
82 return -1;
83 }
84
85 if (listen(server_socket, 3) < 0)
86 {
87 closesocket(server_socket);
88 WSACleanup();
89 server_socket = (UINT_PTR)0;
90 return -1;
91 }
92
93 return 0;
94 }
95
prvInitTraceSocketIfNeeded(void)96 static int prvInitTraceSocketIfNeeded(void)
97 {
98 int c;
99
100 if (!server_socket)
101 return -1;
102
103 if (trace_socket)
104 return 0;
105
106 c = sizeof(struct sockaddr_in);
107 trace_socket = accept(server_socket, (struct sockaddr *)&client, &c);
108 if (trace_socket == INVALID_SOCKET)
109 {
110 trace_socket = (UINT_PTR)0;
111
112 closesocket(server_socket);
113 WSACleanup();
114 server_socket = (UINT_PTR)0;
115
116 return -1;
117 }
118
119 return 0;
120 }
121
prvTraceWriteToSocket(void * data,uint32_t size,int32_t * ptrBytesWritten)122 int32_t prvTraceWriteToSocket(void* data, uint32_t size, int32_t *ptrBytesWritten)
123 {
124 int ret;
125
126 if (prvInitServerSocketIfNeeded() < 0)
127 {
128 return -1;
129 }
130
131 if (prvInitTraceSocketIfNeeded() < 0)
132 {
133 return -1;
134 }
135
136 if (!trace_socket)
137 {
138 if (ptrBytesWritten != 0)
139 {
140 *ptrBytesWritten = 0;
141 }
142 return -1;
143 }
144 ret = send(trace_socket, data, size, 0);
145 if (ret <= 0)
146 {
147 if (ptrBytesWritten != 0)
148 {
149 *ptrBytesWritten = 0;
150 }
151
152 closesocket(trace_socket);
153 trace_socket = (UINT_PTR)0;
154 return ret;
155 }
156
157 if (ptrBytesWritten != 0)
158 {
159 *ptrBytesWritten = ret;
160 }
161
162 return 0;
163 }
164
prvTraceReadFromSocket(void * data,uint32_t bufsize,int32_t * ptrBytesRead)165 int32_t prvTraceReadFromSocket(void* data, uint32_t bufsize, int32_t *ptrBytesRead)
166 {
167 unsigned long bytesAvailable = 0;
168
169 if (prvInitServerSocketIfNeeded() < 0)
170 return -1;
171
172 if (prvInitTraceSocketIfNeeded() < 0)
173 return -1;
174
175 if (ioctlsocket(trace_socket, FIONREAD, &bytesAvailable) != NO_ERROR)
176 {
177 closesocket(trace_socket);
178 trace_socket = (UINT_PTR)0;
179 return -1;
180 }
181
182 if (bytesAvailable > 0)
183 {
184 *ptrBytesRead = recv(trace_socket, data, bufsize, 0);
185 if (*ptrBytesRead == SOCKET_ERROR)
186 {
187 closesocket(trace_socket);
188 trace_socket = (UINT_PTR)0;
189 return -1;
190 }
191 }
192
193 return 0;
194 }
195
prvCloseAllSockets(void)196 static void prvCloseAllSockets(void)
197 {
198 if (trace_socket != 0)
199 {
200 closesocket(trace_socket);
201 trace_socket = 0;
202 }
203
204 if (server_socket != 0)
205 {
206 closesocket(server_socket);
207 server_socket = 0;
208 }
209 }
210
xTraceStreamPortInitialize(TraceStreamPortBuffer_t * pxBuffer)211 traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer)
212 {
213 TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortTCPIP_t);
214
215 if (pxBuffer == 0)
216 {
217 return TRC_FAIL;
218 }
219
220 pxStreamPortTCPIP = (TraceStreamPortTCPIP_t*)pxBuffer;
221
222 #if (TRC_USE_INTERNAL_BUFFER == 1)
223 return xTraceInternalEventBufferInitialize(pxStreamPortTCPIP->buffer, sizeof(pxStreamPortTCPIP->buffer));
224 #else
225 return TRC_SUCCESS;
226 #endif
227 }
228
xTraceStreamPortOnTraceEnd(void)229 traceResult xTraceStreamPortOnTraceEnd(void)
230 {
231 prvCloseAllSockets();
232
233 return TRC_SUCCESS;
234 }
235
236 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
237
238 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
239