09c2a771f64474875a5fc0bd3e1421169b3b6f08
[platform/upstream/connectedhomeip.git] / examples / common / chip-app-server / Server.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 #include "Server.h"
19
20 #include "DataModelHandler.h"
21 #include "RendezvousServer.h"
22 #include "SessionManager.h"
23
24 #include <ble/BLEEndPoint.h>
25 #include <inet/IPAddress.h>
26 #include <inet/InetError.h>
27 #include <inet/InetLayer.h>
28 #include <lib/mdns/DiscoveryManager.h>
29 #include <platform/CHIPDeviceLayer.h>
30 #include <setup_payload/SetupPayload.h>
31 #include <support/CodeUtils.h>
32 #include <support/ErrorStr.h>
33 #include <support/logging/CHIPLogging.h>
34 #include <sys/param.h>
35 #include <system/SystemPacketBuffer.h>
36 #include <transport/SecureSessionMgr.h>
37
38 using namespace ::chip;
39 using namespace ::chip::Inet;
40 using namespace ::chip::Transport;
41 using namespace ::chip::DeviceLayer;
42
43 namespace {
44
45 bool isRendezvousBypassed()
46 {
47     RendezvousInformationFlags rendezvousMode = RendezvousInformationFlags::kBLE;
48
49 #ifdef CONFIG_RENDEZVOUS_MODE
50     rendezvousMode = static_cast<RendezvousInformationFlags>(CONFIG_RENDEZVOUS_MODE);
51 #endif
52
53 #ifdef CHIP_BYPASS_RENDEZVOUS
54     rendezvousMode = RendezvousInformationFlags::kNone;
55 #endif
56
57     return rendezvousMode == RendezvousInformationFlags::kNone;
58 }
59
60 class ServerCallback : public SecureSessionMgrDelegate
61 {
62 public:
63     void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader,
64                            const Transport::PeerConnectionState * state, System::PacketBufferHandle buffer,
65                            SecureSessionMgr * mgr) override
66     {
67         const size_t data_len = buffer->DataLength();
68         char src_addr[PeerAddress::kMaxToStringSize];
69
70         // as soon as a client connects, assume it is connected
71         VerifyOrExit(!buffer.IsNull(), ChipLogProgress(AppServer, "Received data but couldn't process it..."));
72         VerifyOrExit(header.GetSourceNodeId().HasValue(), ChipLogProgress(AppServer, "Unknown source for received message"));
73
74         VerifyOrExit(state->GetPeerNodeId() != kUndefinedNodeId, ChipLogProgress(AppServer, "Unknown source for received message"));
75
76         state->GetPeerAddress().ToString(src_addr, sizeof(src_addr));
77
78         ChipLogProgress(AppServer, "Packet received from %s: %zu bytes", src_addr, static_cast<size_t>(data_len));
79
80         HandleDataModelMessage(header, std::move(buffer), mgr);
81
82     exit:;
83     }
84
85     void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * mgr) override
86     {
87         ChipLogProgress(AppServer, "Packet received error: %s", ErrorStr(error));
88         if (mDelegate != nullptr)
89         {
90             mDelegate->OnReceiveError();
91         }
92     }
93
94     void OnNewConnection(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) override
95     {
96         ChipLogProgress(AppServer, "Received a new connection.");
97     }
98
99     void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; }
100
101 private:
102     AppDelegate * mDelegate = nullptr;
103 };
104
105 DemoTransportMgr gTransports;
106 SecureSessionMgr gSessions;
107 ServerCallback gCallbacks;
108 SecurePairingUsingTestSecret gTestPairing;
109 RendezvousServer gRendezvousServer;
110
111 } // namespace
112
113 SecureSessionMgr & chip::SessionManager()
114 {
115     return gSessions;
116 }
117
118 // The function will initialize datamodel handler and then start the server
119 // The server assumes the platform's networking has been setup already
120 void InitServer(AppDelegate * delegate)
121 {
122     CHIP_ERROR err = CHIP_NO_ERROR;
123     Optional<Transport::PeerAddress> peer(Transport::Type::kUndefined);
124
125     InitDataModelHandler();
126     gCallbacks.SetDelegate(delegate);
127     gRendezvousServer.SetDelegate(delegate);
128
129     // Init transport before operations with secure session mgr.
130 #if INET_CONFIG_ENABLE_IPV4
131     err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6),
132                            UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv4));
133 #else
134     err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6));
135 #endif
136     SuccessOrExit(err);
137
138     err = gSessions.Init(chip::kTestDeviceNodeId, &DeviceLayer::SystemLayer, &gTransports);
139     SuccessOrExit(err);
140
141     // This flag is used to bypass BLE in the cirque test
142     // Only in the cirque test this is enabled with --args='bypass_rendezvous=true'
143     if (isRendezvousBypassed())
144     {
145         ChipLogProgress(AppServer, "Rendezvous and Secure Pairing skipped. Using test secret.");
146         err = gSessions.NewPairing(peer, chip::kTestControllerNodeId, &gTestPairing);
147         SuccessOrExit(err);
148     }
149     else
150     {
151         RendezvousParameters params;
152         uint32_t pinCode;
153
154         SuccessOrExit(err = DeviceLayer::ConfigurationMgr().GetSetupPinCode(pinCode));
155         params.SetSetupPINCode(pinCode)
156             .SetLocalNodeId(chip::kTestDeviceNodeId)
157             .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer())
158             .SetPeerAddress(Transport::PeerAddress::BLE());
159         SuccessOrExit(err = gRendezvousServer.Init(params, &gTransports));
160     }
161
162     err = gSessions.NewPairing(peer, chip::kTestControllerNodeId, &gTestPairing);
163     SuccessOrExit(err);
164
165     gSessions.SetDelegate(&gCallbacks);
166     chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(kIPAddressType_IPv6);
167
168 exit:
169     if (err != CHIP_NO_ERROR)
170     {
171         ChipLogError(AppServer, "ERROR setting up transport: %s", ErrorStr(err));
172     }
173     else
174     {
175         ChipLogProgress(AppServer, "Server Listening...");
176     }
177 }