summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/ldn/lan_discovery.h
blob: 3833cd764abfa541f5ae7f9e86cf89a4382a2807 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <array>
#include <cstring>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <random>
#include <span>
#include <thread>
#include <unordered_map>

#include "common/logging/log.h"
#include "common/socket_types.h"
#include "core/hle/result.h"
#include "core/hle/service/ldn/ldn_results.h"
#include "core/hle/service/ldn/ldn_types.h"
#include "network/network.h"

namespace Service::LDN {

class LANDiscovery;

class LanStation {
public:
    LanStation(s8 node_id_, LANDiscovery* discovery_);
    ~LanStation();

    void OnClose();
    NodeStatus GetStatus() const;
    void Reset();
    void OverrideInfo();

protected:
    friend class LANDiscovery;
    NodeInfo* node_info;
    NodeStatus status;
    s8 node_id;
    LANDiscovery* discovery;
};

class LANDiscovery {
public:
    using LanEventFunc = std::function<void()>;

    LANDiscovery(Network::RoomNetwork& room_network_);
    ~LANDiscovery();

    State GetState() const;
    void SetState(State new_state);

    Result GetNetworkInfo(NetworkInfo& out_network) const;
    Result GetNetworkInfo(NetworkInfo& out_network, std::vector<NodeLatestUpdate>& out_updates,
                          std::size_t buffer_count);

    DisconnectReason GetDisconnectReason() const;
    Result Scan(std::vector<NetworkInfo>& networks, u16& count, const ScanFilter& filter);
    Result SetAdvertiseData(std::span<const u8> data);

    Result OpenAccessPoint();
    Result CloseAccessPoint();

    Result OpenStation();
    Result CloseStation();

    Result CreateNetwork(const SecurityConfig& security_config, const UserConfig& user_config,
                         const NetworkConfig& network_config);
    Result DestroyNetwork();

    Result Connect(const NetworkInfo& network_info_, const UserConfig& user_config,
                   u16 local_communication_version);
    Result Disconnect();

    Result Initialize(LanEventFunc lan_event_ = empty_func, bool listening = true);
    Result Finalize();

    void ReceivePacket(const Network::LDNPacket& packet);

protected:
    friend class LanStation;

    void InitNetworkInfo();
    void InitNodeStateChange();

    void ResetStations();
    void UpdateNodes();

    void OnSyncNetwork(const NetworkInfo& info);
    void OnDisconnectFromHost();
    void OnNetworkInfoChanged();

    bool IsNodeStateChanged();
    bool IsFlagSet(ScanFilterFlag flag, ScanFilterFlag search_flag) const;
    int GetStationCount() const;
    MacAddress GetFakeMac() const;
    Result GetNodeInfo(NodeInfo& node, const UserConfig& user_config,
                       u16 local_communication_version);

    Network::IPv4Address GetLocalIp() const;
    template <typename Data>
    void SendPacket(Network::LDNPacketType type, const Data& data, Ipv4Address remote_ip);
    void SendPacket(Network::LDNPacketType type, Ipv4Address remote_ip);
    template <typename Data>
    void SendBroadcast(Network::LDNPacketType type, const Data& data);
    void SendBroadcast(Network::LDNPacketType type);
    void SendPacket(const Network::LDNPacket& packet);

    static const LanEventFunc empty_func;
    static constexpr Ssid fake_ssid{"YuzuFakeSsidForLdn"};

    bool inited{};
    std::mutex packet_mutex;
    std::array<LanStation, StationCountMax> stations;
    std::array<NodeLatestUpdate, NodeCountMax> node_changes{};
    std::array<u8, NodeCountMax> node_last_states{};
    std::unordered_map<MacAddress, NetworkInfo, MACAddressHash> scan_results{};
    NodeInfo node_info{};
    NetworkInfo network_info{};
    State state{State::None};
    DisconnectReason disconnect_reason{DisconnectReason::None};

    // TODO (flTobi): Should this be an std::set?
    std::vector<Ipv4Address> connected_clients;
    std::optional<Ipv4Address> host_ip;

    LanEventFunc lan_event;

    Network::RoomNetwork& room_network;
};
} // namespace Service::LDN