---
title: llarp/layers/platform/driver_base.hpp

---

# llarp/layers/platform/driver_base.hpp



## Namespaces

| Name           |
| -------------- |
| **[llarp](Namespaces/namespacellarp.md)** <br>[crypto.hpp] |
| **[llarp::layers](Namespaces/namespacellarp_1_1layers.md)**  |
| **[llarp::layers::platform](Namespaces/namespacellarp_1_1layers_1_1platform.md)**  |

## Classes

|                | Name           |
| -------------- | -------------- |
| struct | **[llarp::layers::platform::PlatformAddr](Classes/structllarp_1_1layers_1_1platform_1_1PlatformAddr.md)** <br>a (ipv6 address, flowlabel) tuple that we use for platform layer side addressing  |
| struct | **[llarp::layers::platform::AddressMapping](Classes/structllarp_1_1layers_1_1platform_1_1AddressMapping.md)** <br>an entry for mapping an os address to a flow address  |
| struct | **[llarp::layers::platform::Traffic](Classes/structllarp_1_1layers_1_1platform_1_1Traffic.md)** <br>datum the os gives us that we forward to the flow layer as needed.  |
| struct | **[llarp::layers::platform::MapAddressEvent](Classes/structllarp_1_1layers_1_1platform_1_1MapAddressEvent.md)** <br>this contains all info needed for mapping a platform address to our platform driver  |
| class | **[llarp::layers::platform::PlatformDriver_Base](Classes/classllarp_1_1layers_1_1platform_1_1PlatformDriver__Base.md)** <br>base type that is responsible for bridging the os and the flow layer.  |




## Source code

```cpp
#pragma once

#include "name_resolver.hpp"

#include <llarp/layers/flow/flow_identity.hpp>
#include <llarp/layers/flow/flow_info.hpp>
#include <llarp/layers/flow/flow_addr.hpp>
#include <llarp/layers/flow/traffic.hpp>

#include <llarp/net/net_int.hpp>
#include <llarp/util/formattable.hpp>
#include <llarp/util/types.hpp>

#include <memory>
#include <optional>
#include <queue>
#include <string_view>
#include <unordered_map>
#include <set>
#include <variant>
#include <vector>

namespace llarp::layers::platform
{

  struct PlatformAddr
  {
    net::ipv6addr_t ip;

    net::flowlabel_t flow{};

    PlatformAddr(net::ipaddr_t ip_, std::optional<net::flowlabel_t> flow_ = std::nullopt);

    std::string
    ToString() const;
  };

  enum class EtherType_t
  {
    ipv4_unicast,
    ip_hybrid_unicast,
    plainquic,
    proto_auth
  };

  struct AddressMapping
  {
    flow::FlowInfo flow;
    PlatformAddr platform_addr;
  };

  struct Traffic
  {
    EtherType_t kind;
    PlatformAddr src, dst;
    std::vector<byte_t> data;
  };

  struct MapAddressEvent
  {
    std::string name;

    std::optional<PlatformAddr> pin_to;
  };

  class PlatformDriver_Base
  {
   protected:
    std::unordered_multimap<flow::FlowAddr, flow::FlowIdentity> m_active_flows;

    // TODO: how do we want to propagate congestion at this layer?
    void
    send_data_to_flow_layer(EtherType_t kind, flow::FlowInfo to, std::vector<byte_t> data);

    virtual std::vector<Traffic>
    read_platform_traffic() const;

    virtual std::vector<flow::Traffic>
    read_flow_traffic() const;

    virtual void
    wakeup_os() const;

    virtual void
    wakeup_flow_layer() const;

    virtual std::optional<std::tuple<EtherType_t, flow::FlowInfo, std::vector<byte_t>>>
    process_os_traffic(Traffic&&);

   public:
    virtual ~PlatformDriver_Base() = default;

    // TODO: define distance function for "best" and "worst"
    virtual std::set<AddressMapping>
    get_address_mappings_for(
        flow::FlowAddr remote, std::optional<net::flowlabel_t> flow_label = std::nullopt);

    virtual std::unique_ptr<NameResolverJob_Base>
    make_resolver_job_for(UnresolvedName_t name) const;

    inline void
    process_layer()
    {
      // TODO: review me

      // read flow traffic first, return early if we got stuff after waking up the os side of
      // things.
      if (auto pkts = read_flow_traffic(); not pkts.empty())
      {
        // got traffic from the void
        for (auto& pkt : pkts)
        {}
        wakeup_os();
        return;
      }

      // read os traffic if we have no more flow traffic to process.
      if (auto pkts = read_platform_traffic(); not pkts.empty())
      {
        using SendToFlowLayerEvent_t = std::tuple<EtherType_t, flow::FlowInfo, std::vector<byte_t>>;
        std::vector<SendToFlowLayerEvent_t> send_queue;
        // got os traffic
        for (auto& pkt : pkts)
        {
          // process our os packet and convert it to a flow layer event if needed
          if (auto maybe_flow_pkt = process_os_traffic(std::move(pkt)))
          {
            auto&& [kind, flow_pkt, data] = std::move(*maybe_flow_pkt);
            send_data_to_flow_layer(kind, flow_pkt, data);
          }
          wakeup_flow_layer();
          return;
        }
      }
    }
  };
}  // namespace llarp::layers::platform

namespace llarp
{
  template <>
  inline constexpr bool IsToStringFormattable<layers::platform::PlatformAddr> = true;
}
```


-------------------------------

Updated on 2023-01-23 at 14:22:33 +0000
