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