Skip to content

Commit

Permalink
feat(daisi): Add TCP network interface
Browse files Browse the repository at this point in the history
  • Loading branch information
ltoenning committed Sep 28, 2023
1 parent ef8206b commit 8213b68
Show file tree
Hide file tree
Showing 14 changed files with 845 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-sola.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ jobs:
build/tests/unittests/DaisiDatastructureSimpleTemporalNetworkTest
build/tests/unittests/DaisiCppsOrderManagementStnOrderManagement
build/tests/unittests/DaisiCppsLogicalAuctionParticipantState
build/tests/unittests/network_tcp/daisi_network_tcp_framing_manager_test
- name: Run MINHTON integrationtest
run: |
export LD_LIBRARY_PATH=~/ns-3_install/lib
Expand Down
1 change: 1 addition & 0 deletions cppcheck.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ unusedVariable:daisi/src/cpps/negotiation/initiator/iterated_auction_initiator_p
unusedVariable:daisi/src/cpps/negotiation/utils/kmeans.h
unusedVariable:daisi/src/cpps/negotiation/participant/iterated_auction_participant.cpp
unusedVariable:daisi/src/cpps/negotiation/utils/simple_temporal_network.cpp
unusedVariable:daisi/src/network_tcp/server.cpp

# From SERIALIZE macro
constParameter:daisi/src/path_planning/message/misc/reached_goal.h
Expand Down
1 change: 1 addition & 0 deletions daisi/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_subdirectory(main)
add_subdirectory(cpps)
add_subdirectory(minhton-ns3)
add_subdirectory(natter-ns3)
add_subdirectory(network_tcp)
add_subdirectory(manager)
#add_subdirectory(path_planning)
add_subdirectory(sola-ns3)
Expand Down
53 changes: 53 additions & 0 deletions daisi/src/network_tcp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
add_library(daisi_network_tcp_definitions INTERFACE definitions.h)

add_library(daisi_network_tcp_framing_manager STATIC)
target_sources(daisi_network_tcp_framing_manager
PRIVATE
framing_manager.cpp
framing_manager.h
)
target_link_libraries(daisi_network_tcp_framing_manager
PRIVATE
daisi_utils
)
target_include_directories(daisi_network_tcp_framing_manager
PUBLIC
${DAISI_SOURCE_DIR}/src
)

add_library(daisi_network_tcp_client STATIC)
target_sources(daisi_network_tcp_client
PRIVATE
client.h
client.cpp
)
target_link_libraries(daisi_network_tcp_client
PUBLIC
daisi_network_tcp_framing_manager
ns3::libcore
daisi_network_tcp_definitions
PRIVATE
daisi_utils
)
target_include_directories(daisi_network_tcp_client
PUBLIC
${DAISI_SOURCE_DIR}/src
)

add_library(daisi_network_tcp_server STATIC)
target_sources(daisi_network_tcp_server
PRIVATE
server.h
server.cpp
)
target_link_libraries(daisi_network_tcp_server
PUBLIC
ns3::libcore
daisi_network_tcp_framing_manager
PRIVATE
daisi_utils
)
target_include_directories(daisi_network_tcp_server
PUBLIC
${DAISI_SOURCE_DIR}/src
)
131 changes: 131 additions & 0 deletions daisi/src/network_tcp/client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright 2023 The SOLA authors
//
// This file is part of DAISI.
//
// DAISI is free software: you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; version 2.
//
// DAISI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along with DAISI. If not, see
// <https://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-2.0-only

#include "client.h"

#include "utils/daisi_check.h"
#include "utils/socket_manager.h"
#include "utils/sola_utils.h"

namespace daisi::network_tcp {

Client::Client(ClientCallbacks callbacks, const Endpoint &endpoint)
: Client("", callbacks, endpoint) {}

Client::Client(const Ipv4 &ip, ClientCallbacks callbacks, const Endpoint &endpoint)
: socket_(daisi::SocketManager::get().createSocket(daisi::SocketType::kTCP)),
callbacks_(std::move(callbacks)) {
socket_->SetConnectCallback(MakeCallback(&Client::connectedSuccessful, this),
MakeCallback(&Client::connectionFailed, this));
socket_->SetCloseCallbacks(MakeCallback(&Client::closedSocket, this),
MakeCallback(&Client::closedSocket, this));
socket_->SetRecvCallback(MakeCallback(&Client::readFromSocket, this));

// https://groups.google.com/g/ns-3-users/c/tZmjq_KoCfo/m/x1xBvn-H31gJ
ns3::Address addr;
socket_->GetSockName(addr);
auto iaddr = ns3::InetSocketAddress::ConvertFrom(addr);

ip_ = daisi::getIpv4AddressString(iaddr.GetIpv4());
port_ = iaddr.GetPort();

if (!ip.empty() && ip != ip_) {
throw std::runtime_error("IP requested from application does not match socket IP");
}

// Connect to remote
ns3::InetSocketAddress remote_addr(endpoint.ip.c_str(), endpoint.port);
socket_->Connect(remote_addr);
}

Client::~Client() {
if (socket_) {
socket_->SetRecvCallback(ns3::MakeNullCallback<void, ns3::Ptr<ns3::Socket>>());
socket_->SetCloseCallbacks(ns3::MakeNullCallback<void, ns3::Ptr<ns3::Socket>>(),
ns3::MakeNullCallback<void, ns3::Ptr<ns3::Socket>>());
socket_->Close();

if (callbacks_.disconnected_cb) {
callbacks_.disconnected_cb();
}
}
}

void Client::send(const std::string &msg) {
DAISI_CHECK(connected_, "Not connected");
DAISI_CHECK(socket_, "Socket not available");

std::string framed_msg = FramingManager::frameMsg(msg);

DAISI_CHECK(connected_, "Not connected");
const auto res =
socket_->Send(reinterpret_cast<const uint8_t *>(framed_msg.data()), framed_msg.size(), 0);

if (res != framed_msg.size()) {
throw std::runtime_error("sending failed");
}
}

uint16_t Client::getPort() const { return port_; }

Ipv4 Client::getIP() const { return ip_; }

void Client::readFromSocket(ns3::Ptr<ns3::Socket> socket) {
DAISI_CHECK(socket == socket_, "Reading from invalid socket");
ns3::Ptr<ns3::Packet> packet = socket_->Recv();
processPacket(packet);
}

void Client::processPacket(ns3::Ptr<ns3::Packet> packet) {
DAISI_CHECK(packet != nullptr, "Invalid packet");

std::string data;
data.resize(packet->GetSize());
packet->CopyData(reinterpret_cast<uint8_t *>(data.data()), packet->GetSize());

manager_.processNewData(data);

if (!callbacks_.new_msg_cb) return;

while (manager_.hasPackets()) {
callbacks_.new_msg_cb(manager_.nextPacket());
}
}

void Client::closedSocket(ns3::Ptr<ns3::Socket>) {
connected_ = false;
socket_->SetRecvCallback(ns3::MakeNullCallback<void, ns3::Ptr<ns3::Socket>>());
socket_->Close();
socket_ = nullptr;

if (callbacks_.disconnected_cb) {
callbacks_.disconnected_cb();
}
}

void Client::connectedSuccessful(ns3::Ptr<ns3::Socket>) {
connected_ = true;

if (callbacks_.connected_cb) {
callbacks_.connected_cb();
}
}

void Client::connectionFailed(ns3::Ptr<ns3::Socket>) {
throw std::runtime_error("failed to connect");
}

} // namespace daisi::network_tcp
87 changes: 87 additions & 0 deletions daisi/src/network_tcp/client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2023 The SOLA authors
//
// This file is part of DAISI.
//
// DAISI is free software: you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; version 2.
//
// DAISI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along with DAISI. If not, see
// <https://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-2.0-only

#ifndef DAISI_NETWORK_TCP_CLIENT_H_
#define DAISI_NETWORK_TCP_CLIENT_H_

#include <cstdint>
#include <functional>
#include <memory>
#include <string>

#include "network_tcp/definitions.h"
#include "network_tcp/framing_manager.h"
#include "ns3/socket.h"

namespace daisi::network_tcp {

struct ClientCallbacks {
std::function<void(const std::string &msg)> new_msg_cb;
std::function<void()> connected_cb;
std::function<void()> disconnected_cb;
};

/**
* ns-3 client to connect to a single listening ns-3 TCP sockets and send/recv data
*/
class Client {
public:
Client(ClientCallbacks callbacks, const Endpoint &endpoint);

Client(const Ipv4 &own_ip, ClientCallbacks callbacks, const Endpoint &endpoint);

~Client();

// Forbid copy/move operations
Client(const Client &) = delete;
Client &operator=(const Client &) = delete;
Client(const Client &&) = delete;
Client &operator=(Client &&) = delete;

/**
* Send message
* @param msg message to send
*/
void send(const std::string &msg);

uint16_t getPort() const;

Ipv4 getIP() const;

bool isConnected() const;

private:
void readFromSocket(ns3::Ptr<ns3::Socket> socket);
void processPacket(ns3::Ptr<ns3::Packet> packet);

void closedSocket(ns3::Ptr<ns3::Socket>);
void connectedSuccessful(ns3::Ptr<ns3::Socket>);
void connectionFailed(ns3::Ptr<ns3::Socket>);

ns3::Ptr<ns3::Socket> socket_;

bool connected_ = false;

FramingManager manager_;

Ipv4 ip_;
uint16_t port_;

const ClientCallbacks callbacks_;
};
} // namespace daisi::network_tcp

#endif // DAISI_NETWORK_TCP_CLIENT_H_
35 changes: 35 additions & 0 deletions daisi/src/network_tcp/definitions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2023 The SOLA authors
//
// This file is part of DAISI.
//
// DAISI is free software: you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; version 2.
//
// DAISI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along with DAISI. If not, see
// <https://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-2.0-only

#ifndef DAISI_NETWORK_TCP_DEFINITIONS_H_
#define DAISI_NETWORK_TCP_DEFINITIONS_H_

#include <cstdint>
#include <string>

namespace daisi::network_tcp {

using Ipv4 = std::string;
using TcpSocketHandle = uint64_t;

struct Endpoint {
Ipv4 ip;
uint16_t port;
};

} // namespace daisi::network_tcp

#endif // DAISI_NETWORK_TCP_DEFINITIONS_H_
Loading

0 comments on commit 8213b68

Please sign in to comment.