Skip to content
This repository was archived by the owner on Dec 17, 2025. It is now read-only.

Commit 9eebe87

Browse files
authored
Merge pull request #11 from Magolves/dev
Dev
2 parents d8ce4ad + 816a914 commit 9eebe87

28 files changed

Lines changed: 1242 additions & 1054 deletions

.clang-tidy

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
---
2-
Checks: '*,-llvmlibc-*,-fuchsia-*,-google-readability-todo,-readability-else-after-return,-llvm-header-guard,-llvm-namespace-comment,-modernize-use-trailing-return-type,-altera-struct-pack-align,-google-explicit-constructor,-hicpp-explicit-conversions,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-hicpp-signed-bitwise,-readability-identifier-length,-bugprone-reserved-identifier,-cert-dcl37-c,-cert-dcl51-cpp,-google-runtime-int,-misc-include-cleaner,-misc-non-private-member-variables-in-classes,-google-build-using-namespace,-readability-convert-member-functions-to-static,-llvm-include-order,-misc-const-correctness,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-modernize-use-nodiscard'
2+
Checks: |
3+
-bugprone-*
4+
-performance-*
5+
-readability-braces-around-statements
6+
-readability-inconsistent-declaration-parameter-name
7+
-readability-implicit-bool-conversion
8+
-readability-redundant-declaration
9+
-readability-redundant-member-init
10+
-readability-static-definition-in-anonymous-namespace
11+
-readability-uppercase-literal-suffix
12+
-cppcoreguidelines-avoid-goto
13+
-cppcoreguidelines-avoid-magic-numbers
14+
-cppcoreguidelines-no-malloc
15+
-cppcoreguidelines-owning-memory
16+
-cppcoreguidelines-slicing
17+
-modernize-use-override
18+
-modernize-avoid-c-arrays
19+
-modernize-loop-convert
20+
-modernize-redundant-void-arg
21+
-modernize-use-auto
22+
-modernize-use-equals-default
23+
-modernize-use-equals-delete
24+
-modernize-use-nullptr
25+
-misc-definitions-in-headers
26+
-misc-misplaced-const
27+
-misc-no-recursion
28+
-misc-static-assert
329
WarningsAsErrors: ''
430
HeaderFilterRegex: '.*'
531
FormatStyle: none

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ endif()
5858

5959
# Configuration options
6060
set(DOIP_ALIVE_CHECK_RETRIES "1" CACHE STRING "Number of retries for DoIP alive check messages")
61+
set(DOIP_MAXIMUM_MTU "4095" CACHE STRING "Maximum Transmission Unit (MTU) size for DoIP messages")
6162

6263
# Validate numeric options
63-
foreach(VAR DOIP_ALIVE_CHECK_RETRIES)
64+
foreach(VAR DOIP_ALIVE_CHECK_RETRIES DOIP_MAXIMUM_MTU)
6465
if(NOT ${VAR} MATCHES "^[0-9]+$")
6566
message(FATAL_ERROR "${VAR} must be a positive integer")
6667
endif()

Doxyfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ INLINE_GROUPED_CLASSES = NO
4949
INLINE_SIMPLE_STRUCTS = NO
5050
TYPEDEF_HIDES_STRUCT = NO
5151
LOOKUP_CACHE_SIZE = 0
52-
NUM_PROC_THREADS = 1
52+
NUM_PROC_THREADS = 4
5353

5454
#---------------------------------------------------------------------------
5555
# Build related configuration options
@@ -60,7 +60,7 @@ EXTRACT_PRIV_VIRTUAL = NO
6060
EXTRACT_PACKAGE = NO
6161
EXTRACT_STATIC = YES
6262
EXTRACT_LOCAL_CLASSES = YES
63-
EXTRACT_LOCAL_METHODS = NO
63+
EXTRACT_LOCAL_METHODS = YES
6464
EXTRACT_ANON_NSPACES = NO
6565
RESOLVE_UNNAMED_PARAMS = YES
6666
HIDE_UNDOC_MEMBERS = NO
@@ -103,7 +103,7 @@ WARNINGS = YES
103103
WARN_IF_UNDOCUMENTED = YES
104104
WARN_IF_DOC_ERROR = YES
105105
WARN_IF_INCOMPLETE_DOC = YES
106-
WARN_NO_PARAMDOC = NO
106+
WARN_NO_PARAMDOC = YES
107107
WARN_AS_ERROR = NO
108108
WARN_FORMAT = "$file:$line: $text"
109109
WARN_LINE_FORMAT = "at line $line of file $file"
@@ -153,7 +153,7 @@ USE_MDFILE_AS_MAINPAGE = README.md
153153
#---------------------------------------------------------------------------
154154
SOURCE_BROWSER = YES
155155
INLINE_SOURCES = NO
156-
STRIP_CODE_COMMENTS = YES
156+
STRIP_CODE_COMMENTS = NO
157157
REFERENCED_BY_RELATION = YES
158158
REFERENCES_RELATION = YES
159159
REFERENCES_LINK_SOURCE = YES

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![CMake](https://img.shields.io/badge/CMake-3.15+-blue.svg)](https://cmake.org/)
88
[![doctest](https://img.shields.io/badge/Tests-doctest-green.svg)](https://github.com/doctest/doctest)
99

10-
C/C++ library for Diagnostics over IP (DoIP) (fork from https://github.com/AVL-DiTEST-DiagDev/libdoip)
10+
C/C++ library for Diagnostics over IP (DoIP) (fork from [https://github.com/AVL-DiTEST-DiagDev/libdoip](https://github.com/AVL-DiTEST-DiagDev/libdoip))
1111

1212
**CAUTION** The current API is under construction any may change at any time.
1313

@@ -26,9 +26,9 @@ See [Logging](./doc/LOGGING.md) for details.
2626

2727
Quick start — read the generated tutorial for the example server:
2828

29-
- Online (published): https://magolves.github.io/libdoip/index.html
29+
- Online (published): [https://magolves.github.io/libdoip/index.html](https://magolves.github.io/libdoip/index.html)
3030
- Local example page: see `doc/ExampleDoIPServer.md` (included in the Doxygen HTML under "Example DoIP Server Tutorial").
31-
- Example tutorial (direct): https://magolves.github.io/libdoip/ExampleDoIPServer.html
31+
- Example tutorial (direct): [https://magolves.github.io/libdoip/md_doc_ExampleDoIPServer.html](https://magolves.github.io/libdoip/md_doc_ExampleDoIPServer.html)
3232

3333
If you want to generate the docs locally, install Doxygen and Graphviz and
3434
run:
@@ -47,7 +47,7 @@ xdg-open docs/html/index.html
4747
git clone https://github.com/Magolves/libdoip.git
4848
```
4949

50-
2. Enter the directory 'libdoip' and build the library with:
50+
1. Enter the directory 'libdoip' and build the library with:
5151

5252
```bash
5353
cmake . -Bbuild
@@ -83,14 +83,13 @@ handlers.
8383

8484
- Example source files: `examples/exampleDoIPServer.cpp`,
8585
`examples/ExampleDoIPServerModel.h`
86-
- Example tutorial (published): https://magolves.github.io/libdoip/ExampleDoIPServer.html
86+
- Example tutorial: [https://magolves.github.io/libdoip/ExampleDoIPServer.html](https://magolves.github.io/libdoip/ExampleDoIPServer.html)
8787

8888
See the "Examples" section in the generated Doxygen main page for
8989
additional annotated links to these files.
9090

91-
9291
## References
9392

9493
- [ISO 13400-2:2019(en) Road vehicles — Diagnostic communication over Internet Protocol (DoIP) — Part 2: Transport protocol and network layer services](<https://www.iso.org/obp/ui/#iso:std:iso:13400:-2:ed-2:v1:en>)
9594
- [Specification of Diagnostic over IP](<https://www.autosar.org/fileadmin/standards/R20-11/CP/AUTOSAR_SWS_DiagnosticOverIP.pdf>)
96-
- [Diagnostics over Internet Protocol (DoIP)](<https://cdn.vector.com/cms/content/know-how/_application-notes/AN-IND-1-026_DoIP_in_CANoe.pdf>)
95+
- [Diagnostics over Internet Protocol (DoIP)](<https://cdn.vector.com/cms/content/know-how/_application-notes/AN-IND-1-026_DoIP_in_CANoe.pdf>)

doc/ExampleDoIPServer.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,6 @@ m_model.onDownstreamRequest = [this](IConnectionContext &ctx, const DoIPMessage
174174
Below is a PlantUML diagram illustrating `DoIPServer`, `DoIPConnection`,
175175
`DoIPServerModel` and a downstream UDS/CAN backend interaction.
176176

177-
[\image html ]ServerModel.svg
178-
179-
For GitHub or other markdown viewers that don't process the Doxygen
180-
directive, the SVG is also referenced directly:
181-
182177
![ServerModel](diagrams/ServerModel.svg)
183178

184179
## Logging and debugging tips

doc/Fix-UDP-reception.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
From your **tcpdump output**, the **8-byte UDP packet** from the client (port 50290) to the server (port 13400) **is arriving** at the loopback interface:
2+
3+
```
4+
17:31:49.091339 lo In IP localhost.50290 > localhost.13400: UDP, length 8
5+
0x0020: 04fb 0001 0000 0000
6+
```
7+
This is a **DoIP Vehicle Identification Request** (type `0x0001`), and it is **reaching the kernel**.
8+
9+
---
10+
11+
### **Root Cause Analysis**
12+
Since the packet is visible in `tcpdump` but **not logged by your server**, the issue is **almost certainly in your server code**. Here’s what’s happening:
13+
14+
#### **1. The Server Socket is Not Receiving the Packet**
15+
- The server socket is bound to port 13400, but **something is preventing `recvfrom` from returning the packet**.
16+
- Possible reasons:
17+
- The socket is **not in the expected state** (e.g., closed, re-bound, or filtered).
18+
- The socket is **not the same as the one bound to port 13400** (e.g., `m_udp_sock` was overwritten or closed).
19+
- The socket is **blocked by a firewall or SELinux** (unlikely for loopback, but possible).
20+
- The socket is **not actually bound to port 13400** (e.g., `bind` failed silently).
21+
22+
#### **2. The Server is Stuck in a Timeout Loop**
23+
- Your logs show `recvfrom returned: -1 (errno: 11)` repeatedly.
24+
- This means `recvfrom` is **timing out** (`EAGAIN`), but the packet is **not being delivered to userspace**.
25+
- This suggests the socket is **not properly bound** or is **not the same socket** as the one receiving the packet.
26+
27+
---
28+
29+
### **Debugging Steps**
30+
#### **1. Verify the Socket is Bound Correctly**
31+
Add this **right after `bind()`** in `setupUdpSocket()`:
32+
```cpp
33+
// After bind()
34+
sockaddr_in bound_addr;
35+
socklen_t bound_addr_len = sizeof(bound_addr);
36+
getsockname(m_udp_sock, (sockaddr*)&bound_addr, &bound_addr_len);
37+
LOG_UDP_DEBUG(
38+
"Socket {} bound to {}:{}",
39+
m_udp_sock,
40+
inet_ntoa(bound_addr.sin_addr),
41+
ntohs(bound_addr.sin_port)
42+
);
43+
```
44+
- If this logs `0.0.0.0:13400` or `127.0.0.1:13400`, the socket is bound correctly.
45+
- If not, `bind()` failed or was not called.
46+
47+
#### **2. Check for Socket Descriptor Leaks or Overwrites**
48+
- Log `m_udp_sock` in `receiveUdpMessage()`:
49+
```cpp
50+
LOG_UDP_DEBUG("Using socket fd: {}", m_udp_sock);
51+
```
52+
- If the value changes between `setupUdpSocket()` and `receiveUdpMessage()`, something is overwriting it.
53+
54+
#### **3. Test with a Minimal UDP Server**
55+
Replace your `receiveUdpMessage()` with this **minimal test**:
56+
```cpp
57+
ssize_t DoIPServer::receiveUdpMessage() {
58+
char buf[1024];
59+
sockaddr_in client_addr;
60+
socklen_t client_len = sizeof(client_addr);
61+
ssize_t read_bytes = recvfrom(
62+
m_udp_sock, buf, sizeof(buf), 0,
63+
(sockaddr*)&client_addr, &client_len
64+
);
65+
LOG_UDP_DEBUG(
66+
"recvfrom returned: {} (errno: {})",
67+
read_bytes, errno
68+
);
69+
if (read_bytes > 0) {
70+
LOG_UDP_INFO(
71+
"RX {} bytes from {}:{}",
72+
read_bytes,
73+
inet_ntoa(client_addr.sin_addr),
74+
ntohs(client_addr.sin_port)
75+
);
76+
}
77+
return read_bytes;
78+
}
79+
```
80+
- If this works, the issue is in your buffer or processing logic.
81+
- If it still times out, the socket is **not receiving packets**.
82+
83+
#### **4. Check for Firewall/SELinux**
84+
Even for loopback, run:
85+
```bash
86+
sudo iptables -L -n -v # Check firewall rules
87+
sudo setenforce 0 # Disable SELinux temporarily
88+
```
89+
Retest. If it works, adjust your firewall/SELinux rules.
90+
91+
#### **5. Use `strace` to Confirm `recvfrom` Behavior**
92+
Run the server with:
93+
```bash
94+
strace -e trace=recvfrom ./your_server
95+
```
96+
- If `recvfrom` is **never called**, your loop is broken.
97+
- If it returns `-1 EAGAIN` repeatedly, the socket is **not receiving packets**.
98+
99+
#### **6. Check for Multiple Sockets**
100+
- If your code creates **multiple UDP sockets**, ensure the correct one is used for `recvfrom`.
101+
- Log all socket creation and `bind()` calls.
102+
103+
---
104+
105+
### **Most Likely Fixes**
106+
1. **The socket is not bound to port 13400.**
107+
- Confirm `bind()` succeeds and logs the correct port.
108+
2. **`m_udp_sock` is overwritten or closed.**
109+
- Log its value in `setupUdpSocket()` and `receiveUdpMessage()`.
110+
3. **The socket is non-blocking and the timeout is too short.**
111+
- Try removing `SO_RCVTIMEO` temporarily to see if packets arrive.
112+
113+
---
114+
115+
### **Summary**
116+
- The packet **is arriving at the kernel** (confirmed by `tcpdump`).
117+
- The server **is not receiving it**, likely due to:
118+
- Socket not bound correctly.
119+
- Wrong socket file descriptor used in `recvfrom`.
120+
- Firewall/SELinux blocking delivery to userspace.
121+
122+
**Next step:**
123+
Add the debug logs for `m_udp_sock` and `getsockname()` as shown above. If the socket is correct, test with the minimal `recvfrom` code. If it still fails, the issue is **outside your code** (firewall, SELinux, or kernel networking stack).

examples/CMakeLists.txt

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,54 @@
11
# Examples CMakeLists.txt
22

3-
# DoIP Server Example
4-
add_executable(exampleDoIPServer exampleDoIPServer.cpp)
5-
target_link_libraries(exampleDoIPServer
6-
PRIVATE
7-
${DOIP_NAME}
8-
Threads::Threads
3+
set (EXAMPLE_SOURCES
4+
exampleDoIPServer.cpp
5+
exampleDoIPClient.cpp
6+
exampleDoIPDiscover.cpp
97
)
108

11-
# Set properties for the example
12-
set_target_properties(exampleDoIPServer PROPERTIES
13-
CXX_STANDARD 17
14-
CXX_STANDARD_REQUIRED ON
15-
CXX_EXTENSIONS OFF
16-
)
17-
18-
# DoIP Client Example
19-
add_executable(exampleDoIPClient exampleDoIPClient.cpp)
20-
target_link_libraries(exampleDoIPClient
21-
PRIVATE
22-
${DOIP_NAME}
23-
)
24-
25-
# Set properties for the client example
26-
set_target_properties(exampleDoIPClient PROPERTIES
27-
CXX_STANDARD 17
28-
CXX_STANDARD_REQUIRED ON
29-
CXX_EXTENSIONS OFF
30-
)
31-
32-
# Simple DoIP Server Example (using high-level API)
33-
add_executable(exampleDoIPServerSimple exampleDoIPServerSimple.cpp)
34-
target_link_libraries(exampleDoIPServerSimple
35-
PRIVATE
36-
${DOIP_NAME}
37-
Threads::Threads
38-
)
39-
40-
# Set properties for the simple server example
41-
set_target_properties(exampleDoIPServerSimple PROPERTIES
42-
CXX_STANDARD 17
43-
CXX_STANDARD_REQUIRED ON
44-
CXX_EXTENSIONS OFF
45-
)
46-
47-
# Disable switch-default warning for examples using spdlog
48-
target_compile_options(exampleDoIPServer PRIVATE -Wno-switch-default)
49-
target_compile_options(exampleDoIPClient PRIVATE -Wno-switch-default)
50-
target_compile_options(exampleDoIPServerSimple PRIVATE -Wno-switch-default)
51-
52-
# Install examples (optional)
53-
install(TARGETS exampleDoIPServer exampleDoIPClient exampleDoIPServerSimple
54-
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/examples
55-
)
9+
foreach(example_source ${EXAMPLE_SOURCES})
10+
get_filename_component(example_name ${example_source} NAME_WE)
11+
add_executable(${example_name} ${example_source})
12+
target_link_libraries(${example_name}
13+
PRIVATE
14+
${DOIP_NAME}
15+
Threads::Threads
16+
)
17+
18+
# Set properties for the example
19+
set_target_properties(${example_name} PROPERTIES
20+
CXX_STANDARD 17
21+
CXX_STANDARD_REQUIRED ON
22+
CXX_EXTENSIONS OFF
23+
)
24+
25+
# Disable switch-default warning for examples using spdlog
26+
target_compile_options(${example_name} PRIVATE -Wno-switch-default)
27+
28+
# Install examples (optional)
29+
install(TARGETS ${example_name}
30+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/examples
31+
)
32+
33+
endforeach()
34+
35+
if (WITH_UNIT_TEST)
36+
enable_testing()
37+
# Integration fixture: start exampleDoIPServer as a daemon
38+
add_test(NAME Integration_StartExampleServer
39+
COMMAND $<TARGET_FILE:exampleDoIPServer> --daemonize --loopback
40+
)
41+
set_tests_properties(Integration_StartExampleServer PROPERTIES FIXTURES_SETUP example_server TIMEOUT 20)
42+
43+
# Integration test: run discover against the running server
44+
add_test(NAME Integration_DiscoverRuns
45+
COMMAND $<TARGET_FILE:exampleDoIPDiscover> --loopback
46+
)
47+
set_tests_properties(Integration_DiscoverRuns PROPERTIES FIXTURES_REQUIRED example_server TIMEOUT 20)
48+
49+
# Teardown fixture: stop exampleDoIPServer
50+
add_test(NAME Integration_StopExampleServer
51+
COMMAND pkill -f exampleDoIPServer
52+
)
53+
set_tests_properties(Integration_StopExampleServer PROPERTIES FIXTURES_CLEANUP example_server TIMEOUT 10)
54+
endif()

0 commit comments

Comments
 (0)