1 /*
2 * Trace Recorder for Tracealyzer v4.5.1
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_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
17 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
18
19 /* TCP/IP includes - for lwIP in this case */
20 #include "lwip/tcpip.h"
21 #include "lwip/sockets.h"
22 #include "lwip/errno.h"
23
24 #define TRC_TCPIP_PORT 12000
25
26 int sock = -1, new_sd = -1;
27 int flags = 0;
28 int remoteSize;
29 struct sockaddr_in address, remote;
30
trcSocketSend(void * data,int32_t size,int32_t * bytesWritten)31 int32_t trcSocketSend( void* data, int32_t size, int32_t* bytesWritten )
32 {
33 if (new_sd < 0)
34 return -1;
35
36 if (bytesWritten == NULL)
37 return -1;
38
39 *bytesWritten = send( new_sd, data, size, 0 );
40 if (*bytesWritten < 0)
41 {
42 /* EWOULDBLOCK may be expected when buffers are full */
43 if ((errno != 0) && (errno != EWOULDBLOCK))
44 {
45 closesocket(new_sd);
46 new_sd = -1;
47 return -1;
48 }
49 else
50 *bytesWritten = 0;
51 }
52
53 return 0;
54 }
55
trcSocketReceive(void * data,int32_t size,int32_t * bytesRead)56 int32_t trcSocketReceive( void* data, int32_t size, int32_t* bytesRead )
57 {
58 if (new_sd < 0)
59 return -1;
60
61 *bytesRead = recv( new_sd, data, size, 0 );
62 /* EWOULDBLOCK may be expected when there is no data to receive */
63 if (errno != 0 && errno != EWOULDBLOCK)
64 {
65 closesocket(new_sd);
66 new_sd = -1;
67 return -1;
68 }
69
70 return 0;
71 }
72
trcSocketInitializeListener()73 int32_t trcSocketInitializeListener()
74 {
75 if (sock >= 0)
76 return 0;
77
78 sock = lwip_socket(AF_INET, SOCK_STREAM, 0);
79
80 if (sock < 0)
81 return -1;
82
83 address.sin_family = AF_INET;
84 address.sin_port = htons( TRC_TCPIP_PORT );
85 address.sin_addr.s_addr = INADDR_ANY;
86
87 if (bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)
88 {
89 closesocket(sock);
90 sock = -1;
91 return -1;
92 }
93
94 if (lwip_listen(sock, 5) < 0)
95 {
96 closesocket(sock);
97 sock = -1;
98 return -1;
99 }
100
101 return 0;
102 }
103
trcSocketAccept()104 int32_t trcSocketAccept()
105 {
106 if (sock < 0)
107 return -1;
108
109 if (new_sd >= 0)
110 return 0;
111
112 remoteSize = sizeof( remote );
113 new_sd = accept( sock, (struct sockaddr *)&remote, (socklen_t*)&remoteSize );
114
115 if( new_sd < 0 )
116 {
117 closesocket(new_sd);
118 new_sd = -1;
119 closesocket(sock);
120 sock = -1;
121 return -1;
122 }
123
124 flags = fcntl( new_sd, F_GETFL, 0 );
125 fcntl( new_sd, F_SETFL, flags | O_NONBLOCK );
126
127 return 0;
128 }
129 /************** MODIFY THE ABOVE PART TO USE YOUR TPC/IP STACK ****************/
130
trcTcpWrite(void * data,uint32_t size,int32_t * ptrBytesWritten)131 int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten)
132 {
133 return trcSocketSend(data, size, ptrBytesWritten);
134 }
135
trcTcpRead(void * data,uint32_t size,int32_t * ptrBytesRead)136 int32_t trcTcpRead(void* data, uint32_t size, int32_t *ptrBytesRead)
137 {
138 trcSocketInitializeListener();
139
140 trcSocketAccept();
141
142 return trcSocketReceive(data, size, ptrBytesRead);
143 }
144
145 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
146 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
147