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

Commit 44480ef

Browse files
committed
refactor: Pass server model via dependency injection instead of template parameter
fix: Move header code to impl file
1 parent ebf631e commit 44480ef

3 files changed

Lines changed: 47 additions & 52 deletions

File tree

examples/exampleDoIPServer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void listenTcp() {
3030
LOG_UDP_INFO("TCP listener thread started");
3131

3232
while (true) {
33-
tcpConnection = server->waitForTcpConnection<ExampleDoIPServerModel>();
33+
tcpConnection = server->waitForTcpConnection(std::make_unique<ExampleDoIPServerModel>());
3434

3535
while (tcpConnection->isSocketActive()) {
3636
tcpConnection->receiveTcpMessage();

inc/DoIPServer.h

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,12 @@ class DoIPServer {
9393
*/
9494
bool setupTcpSocket();
9595

96-
template <typename Model = DefaultDoIPServerModel>
9796
/**
9897
* @brief Block until a TCP client connects and create a DoIP connection.
99-
* @tparam Model Server model type used by the connection (default `DefaultDoIPServerModel`).
98+
* @param model Server model instance used by the connection.
10099
* @return Unique pointer to established `DoIPConnection`, or nullptr on failure.
101100
*/
102-
std::unique_ptr<DoIPConnection> waitForTcpConnection();
101+
std::unique_ptr<DoIPConnection> waitForTcpConnection(UniqueServerModelPtr model);
103102

104103
[[nodiscard]]
105104
/**
@@ -238,8 +237,11 @@ class DoIPServer {
238237

239238
ssize_t sendNegativeUdpAck(DoIPNegativeAck ackCode);
240239

241-
template <typename Model>
242-
void tcpListenerThread();
240+
/**
241+
* @brief Background TCP listener that accepts connections and spawns handlers.
242+
* @param modelFactory Factory callable that returns a `UniqueServerModelPtr` per connection.
243+
*/
244+
void tcpListenerThread(std::function<UniqueServerModelPtr()> modelFactory);
243245

244246
void connectionHandlerThread(std::unique_ptr<DoIPConnection> connection);
245247

@@ -250,50 +252,6 @@ class DoIPServer {
250252
ssize_t sendUdpResponse(DoIPMessage msg);
251253
};
252254

253-
// Template implementation must be in header for external linkage
254-
template <typename Model>
255-
std::unique_ptr<DoIPConnection> DoIPServer::waitForTcpConnection() {
256-
static_assert(std::is_default_constructible<Model>::value,
257-
"Model must be default-constructible");
258-
259-
// waits till client approach to make connection
260-
if (listen(m_tcp_sock, 5) < 0) {
261-
return nullptr;
262-
}
263-
264-
int tcpSocket = accept(m_tcp_sock, nullptr, nullptr);
265-
if (tcpSocket < 0) {
266-
return nullptr;
267-
}
268-
269-
return std::unique_ptr<DoIPConnection>(new DoIPConnection(tcpSocket, std::make_unique<Model>()));
270-
}
271-
272-
/*
273-
* Background thread: TCP connection acceptor
274-
*/
275-
template <typename Model>
276-
void DoIPServer::tcpListenerThread() {
277-
LOG_DOIP_INFO("TCP listener thread started");
278-
279-
while (m_running.load()) {
280-
auto connection = waitForTcpConnection<Model>();
281-
282-
if (!connection) {
283-
if (m_running.load()) {
284-
LOG_TCP_DEBUG("Failed to accept connection, retrying...");
285-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
286-
}
287-
continue;
288-
}
289-
290-
// Spawn a dedicated thread for this connection
291-
// Note: We detach because the connection thread manages its own lifecycle
292-
std::thread(&DoIPServer::connectionHandlerThread, this, std::move(connection)).detach();
293-
}
294-
295-
LOG_DOIP_INFO("TCP listener thread stopped");
296-
}
297255

298256
} // namespace doip
299257

src/DoIPServer.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ bool DoIPServer::setupUdpSocket() {
220220
m_workerThreads.emplace_back([this]() { udpListenerThread(); });
221221
m_workerThreads.emplace_back([this]() { udpAnnouncementThread(); });
222222
// Also start TCP acceptor thread so TCP 13400 enters LISTEN state and accepts connections
223-
m_workerThreads.emplace_back([this]() { tcpListenerThread<DefaultDoIPServerModel>(); });
223+
m_workerThreads.emplace_back([this]() { tcpListenerThread([](){ return std::make_unique<DefaultDoIPServerModel>(); }); });
224224

225225
return true;
226226
}
@@ -447,4 +447,41 @@ ssize_t DoIPServer::sendUdpResponse(DoIPMessage msg) {
447447
LOG_DOIP_ERROR("Failed to send message: {}", strerror(errno));
448448
}
449449
return sentBytes;
450-
}
450+
}
451+
452+
std::unique_ptr<DoIPConnection> DoIPServer::waitForTcpConnection(UniqueServerModelPtr model) {
453+
// waits till client approach to make connection
454+
if (listen(m_tcp_sock, 5) < 0) {
455+
return nullptr;
456+
}
457+
458+
int tcpSocket = accept(m_tcp_sock, nullptr, nullptr);
459+
if (tcpSocket < 0) {
460+
return nullptr;
461+
}
462+
463+
return std::unique_ptr<DoIPConnection>(new DoIPConnection(tcpSocket, std::move(model)));
464+
}
465+
466+
void DoIPServer::tcpListenerThread(std::function<UniqueServerModelPtr()> modelFactory) {
467+
LOG_DOIP_INFO("TCP listener thread started");
468+
469+
while (m_running.load()) {
470+
auto model = modelFactory ? modelFactory() : std::make_unique<DefaultDoIPServerModel>();
471+
auto connection = waitForTcpConnection(std::move(model));
472+
473+
if (!connection) {
474+
if (m_running.load()) {
475+
LOG_TCP_DEBUG("Failed to accept connection, retrying...");
476+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
477+
}
478+
continue;
479+
}
480+
481+
// Spawn a dedicated thread for this connection
482+
// Note: We detach because the connection thread manages its own lifecycle
483+
std::thread(&DoIPServer::connectionHandlerThread, this, std::move(connection)).detach();
484+
}
485+
486+
LOG_DOIP_INFO("TCP listener thread stopped");
487+
}

0 commit comments

Comments
 (0)