XCP_SIM
common.c
1 /*
2  * BlueParrot XCP
3  *
4  * (C) 2021 by Christoph Schueler <github.com/Christoph2,
5  * cpu12.gems@googlemail.com>
6  *
7  * All Rights Reserved
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * s. FLOSS-EXCEPTION.txt
24  */
25 
26 /*
27 **
28 ** Socket routines independent of operating system and protocol.
29 **
30 */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 
36 #include "xcp.h"
37 #include "xcp_eth.h"
40 void XcpHw_ErrorMsg(char *const function, int errorCode);
41 
42 void XcpThrd_EnableAsyncCancellation(void);
43 bool XcpThrd_IsShuttingDown(void);
44 
45 void XcpTl_PrintBtDetails(void);
46 
47 static void XcpTl_Accept(void);
48 static int XcpTl_ReadHeader(uint16_t *len, uint16_t *counter);
49 static int XcpTl_ReadData(uint8_t *data, uint16_t len);
50 
51 #if XCP_TRANSPORT_LAYER == XCP_ON_ETHERNET
52 static char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size);
53 #endif
54 
55 XcpTl_ConnectionType XcpTl_Connection;
56 
57 static uint8_t XcpTl_RxBuffer[XCP_COMM_BUFLEN];
58 
59 void *XcpTl_Thread(void *param) {
60  XCP_UNREFERENCED_PARAMETER(param);
61  XcpThrd_EnableAsyncCancellation();
62  XCP_FOREVER { XcpTl_MainFunction(); }
63  return NULL;
64 }
65 
66 void XcpTl_MainFunction(void) {
67  XcpTl_Accept();
68  XcpTl_RxHandler();
69 }
70 
71 void *get_in_addr(struct sockaddr *sa) {
72  if (sa->sa_family == AF_INET) {
73  return &(((struct sockaddr_in *)sa)->sin_addr);
74  }
75  return &(((struct sockaddr_in6 *)sa)->sin6_addr);
76 }
77 
78 static int XcpTl_ReadHeader(uint16_t *len, uint16_t *counter) {
79  uint8_t header_buffer[8];
80  uint8_t bytes_remaining = XCP_ETH_HEADER_SIZE;
81  uint8_t offset = 0;
82  uint8_t nbytes = 0;
83 
84  XCP_FOREVER {
85  if (XcpTl_Connection.socketType == SOCK_DGRAM) {
86  nbytes =
87  recvfrom(XcpTl_Connection.boundSocket, (char *)header_buffer + offset,
88  bytes_remaining, 0,
89  (struct sockaddr *)&XcpTl_Connection.currentAddress, NULL);
90  if (XcpThrd_IsShuttingDown()) {
91  return 0;
92  }
93  } else if (XcpTl_Connection.socketType == SOCK_STREAM) {
94  nbytes = recv(XcpTl_Connection.connectedSocket,
95  (char *)header_buffer + offset, bytes_remaining, 0);
96  if (XcpThrd_IsShuttingDown()) {
97  return 0;
98  }
99  }
100  if (nbytes < 1) {
101  return nbytes;
102  }
103  bytes_remaining -= nbytes;
104  if (bytes_remaining == 0) {
105  break;
106  }
107  offset += nbytes;
108  }
109  *len = XCP_MAKEWORD(header_buffer[offset + 1], header_buffer[offset + 0]);
110  *counter = XCP_MAKEWORD(header_buffer[offset + 3], header_buffer[offset + 2]);
111  return 1;
112 }
113 
114 static int XcpTl_ReadData(uint8_t *data, uint16_t len) {
115  uint16_t bytes_remaining = len;
116  uint16_t offset = 0;
117  uint16_t nbytes = 0;
118 
119  XCP_FOREVER {
120  if (XcpTl_Connection.socketType == SOCK_DGRAM) {
121  nbytes = recvfrom(
122  XcpTl_Connection.boundSocket, (char *)data + offset, bytes_remaining,
123  0, (struct sockaddr *)&XcpTl_Connection.currentAddress, NULL);
124  } else if (XcpTl_Connection.socketType == SOCK_STREAM) {
125  nbytes = recv(XcpTl_Connection.connectedSocket, (char *)data + offset,
126  bytes_remaining, 0);
127  }
128  if (nbytes < 1) {
129  return nbytes;
130  }
131  bytes_remaining -= nbytes;
132  if (bytes_remaining == 0) {
133  break;
134  }
135  offset += nbytes;
136  }
137  return 1;
138 }
139 
140 void XcpTl_RxHandler(void) {
141  int res;
142  uint16_t dlc = 0U;
143  uint16_t counter = 0U;
144 
145  ZeroMemory(XcpTl_RxBuffer, XCP_COMM_BUFLEN);
146 
147  XCP_FOREVER {
148  res = XcpTl_ReadHeader(&dlc, &counter);
149  if (res == -1) {
150 #if defined(_WIN32)
151  XcpHw_ErrorMsg("XcpTl_RxHandler:XcpTl_ReadHeader()", WSAGetLastError());
152 #elif defined(__unix__)
153  XcpHw_ErrorMsg("XcpTl_RxHandler:XcpTl_ReadHeader()", errno);
154 #endif
155  exit(2);
156  } else if (res == 0) {
157  XcpTl_ReleaseConnection();
158  return;
159  }
160  if (!XcpThrd_IsShuttingDown()) {
161  Xcp_CtoIn.len = dlc;
162  res = XcpTl_ReadData(&XcpTl_RxBuffer[0], dlc);
163  if (res == -1) {
164 #if defined(_WIN32)
165  XcpHw_ErrorMsg("XcpTl_RxHandler:XcpTl_ReadData()", WSAGetLastError());
166 #elif defined(__unix__)
167  XcpHw_ErrorMsg("XcpTl_RxHandler:XcpTl_ReadData()", errno);
168 #endif
169  exit(2);
170  } else if (res == 0) {
171  printf("Empty data\n");
172  return;
173  }
174 #if 0
175  printf("\t[%02u] ", dlc);
176  XcpUtl_Hexdump(XcpTl_RxBuffer, dlc);
177 #endif
178  XCP_ASSERT_LE(dlc, XCP_TRANSPORT_LAYER_CTO_BUFFER_SIZE);
179  XcpUtl_MemCopy(Xcp_CtoIn.data, XcpTl_RxBuffer, dlc);
180  Xcp_DispatchCommand(&Xcp_CtoIn);
181  } else {
182  printf("shutting down\n");
183  }
184  }
185 }
186 
187 static void XcpTl_Accept(void) {
188  socklen_t FromLen = 0;
189  struct sockaddr_storage From;
190  uint32_t err;
191 
192  XcpUtl_ZeroMem(XcpTl_RxBuffer, XCP_COMM_BUFLEN);
193 
194  if (XcpTl_Connection.socketType == SOCK_STREAM) {
195  if (!XcpTl_Connection.connected) {
196  FromLen = sizeof(From);
197  XcpTl_Connection.connectedSocket =
198  accept(XcpTl_Connection.boundSocket,
199  (struct sockaddr *)&XcpTl_Connection.currentAddress, &FromLen);
200  if (XcpTl_Connection.connectedSocket == INVALID_SOCKET) {
201 #if defined(_WIN32)
202  err = WSAGetLastError();
203  if (err != WSAEINTR) {
204  XcpHw_ErrorMsg("XcpTl_Accept::accept()",
205  err); /* Not canceled by WSACancelBlockingCall(), i.e.
206  pthread_cancel() */
207  }
208 #elif defined(__unix__)
209  XcpHw_ErrorMsg("XcpTl_Accept::accept()", errno);
210 #endif
211  }
212  } else {
213  }
214  }
215 }
216 
217 void XcpTl_TxHandler(void) {}
218 
219 void XcpTl_SaveConnection(void) {
220  XcpUtl_MemCopy(&XcpTl_Connection.connectionAddress,
221  &XcpTl_Connection.currentAddress,
222  sizeof(struct sockaddr_storage));
223  XcpTl_Connection.connected = XCP_TRUE;
224 }
225 
226 void XcpTl_ReleaseConnection(void) { XcpTl_Connection.connected = XCP_FALSE; }
227 
228 bool XcpTl_VerifyConnection(void) {
229  return memcmp(&XcpTl_Connection.connectionAddress,
230  &XcpTl_Connection.currentAddress,
231  sizeof(struct sockaddr_storage)) == 0;
232 }
233 
234 #if XCP_TRANSPORT_LAYER == XCP_ON_ETHERNET
235 void XcpTl_PrintConnectionInformation(void) {
236  char buf[128];
237 
238  printf("XCPonEth -- Listening on port %u / %s [%s]\n\r", XCP_ETH_DEFAULT_PORT,
239  Xcp_Options.tcp ? "TCP" : "UDP", Xcp_Options.ipv6 ? "IPv6" : "IPv4");
240 }
241 #elif XCP_TRANSPORT_LAYER == XCP_ON_BTH
242 void XcpTl_PrintConnectionInformation(void) { XcpTl_PrintBtDetails(); }
243 #endif
244 
245 #if XCP_TRANSPORT_LAYER == XCP_ON_ETHERNET
246 
247 #endif