~aleteoryx/muditaos

ref: d22405bb47b5472d1e781b285bacaffc9f67a477 muditaos/module-services/service-cellular/RequestFactory.cpp -rw-r--r-- 4.7 KiB
d22405bb — Alek Rudnik [EGD-7860] Fix building of application antenna 4 years ago
                                                                                
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
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-cellular/RequestFactory.hpp"

#include <re2/re2.h>

#include <at/Commands.hpp>
#include <log/log.hpp>

#include "service-cellular/requests/CallRequest.hpp"
#include "service-cellular/requests/SupplementaryServicesRequest.hpp"
#include "service-cellular/requests/PasswordRegistrationRequest.hpp"
#include "service-cellular/requests/PinChangeRequest.hpp"
#include "service-cellular/requests/ImeiRequest.hpp"
#include "service-cellular/requests/UssdRequest.hpp"
#include "service-cellular/requests/RejectRequest.hpp"

#include <EventStore.hpp>
#include <cmd/QECCNUM.hpp>

namespace cellular
{
    RequestFactory::RequestFactory(const std::string &data,
                                   at::BaseChannel &channel,
                                   cellular::api::CallMode callMode,
                                   bool simInserted)
        : request(data), channel(channel), callMode(callMode), simInserted(simInserted)
    {
        registerRequest(ImeiRegex, ImeiRequest::create);
        registerRequest(PasswordRegistrationRegex, PasswordRegistrationRequest::create);
        registerRequest(PinChangeRegex, PinChangeRequest::create);
        registerRequest(SupplementaryServicesRegex, SupplementaryServicesRequest::create);
        /*It have to be last check due to 3GPP TS 22.030*/
        registerRequest(UssdRegex, UssdRequest::create);
    }

    void RequestFactory::registerRequest(std::string regex, CreateCallback callback)
    {
        requestMap.emplace_back(std::make_pair(regex, callback));
    }

    std::unique_ptr<IRequest> RequestFactory::emergencyCheck()
    {
        at::cmd::QECCNUM cmd;
        auto qeccnumResult   = channel.cmd(cmd);
        auto qeccnumResponse = cmd.parseQECCNUM(qeccnumResult);

        auto isSimEmergency =
            std::find(qeccnumResponse.eccNumbersSim.begin(), qeccnumResponse.eccNumbersSim.end(), request) !=
            qeccnumResponse.eccNumbersSim.end();
        auto isNoSimEmergency =
            std::find(qeccnumResponse.eccNumbersNoSim.begin(), qeccnumResponse.eccNumbersNoSim.end(), request) !=
            qeccnumResponse.eccNumbersNoSim.end();

        if (isSimEmergency || isNoSimEmergency) {
            if (simInserted || isNoSimEmergency) {
                return std::make_unique<CallRequest>(request);
            }
            else {
                return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
            }
        }
        else if (callMode == cellular::api::CallMode::Emergency) {
            return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NotAnEmergencyNumber, request);
        }
        return nullptr;
    }

    std::unique_ptr<IRequest> RequestFactory::create()
    {
        if (auto req = emergencyCheck(); req) {
            return req;
        }

        std::string groupA, groupB, groupC, groupD, groupE, groupF;
        GroupMatch matchPack = {groupA, groupB, groupC, groupD, groupE, groupF};

        std::vector<std::string> results;

        for (const auto &element : requestMap) {
            auto const &requestCreateCallback = element.second;
            re2::StringPiece input(request);
            re2::RE2 reg(element.first);

            std::vector<RE2::Arg> reArguments;
            std::vector<RE2::Arg *> reArgumentPtrs;

            std::size_t numberOfGroups = reg.NumberOfCapturingGroups();

            if (numberOfGroups > matchPack.size()) {
                LOG_ERROR("Internal error, GroupMatch has to be redefined.");
                break;
            }

            reArguments.resize(numberOfGroups);
            reArgumentPtrs.resize(numberOfGroups);
            results.resize(numberOfGroups);

            for (std::size_t i = 0; i < numberOfGroups; ++i) {
                /// Bind RE arguments to strings from vector.
                reArguments[i] = &matchPack[i].get();
                /// Assign pointers to arguments.
                reArgumentPtrs[i] = &reArguments[i];
            }

            if (re2::RE2::FullMatchN(input, reg, reArgumentPtrs.data(), numberOfGroups)) {
                try {
                    if (auto req = requestCreateCallback(request, matchPack)) {
                        return req;
                    }
                }
                catch (const std::runtime_error &except) {
                    LOG_ERROR("Failed to create MMI request. Error message:\n%s", except.what());
                }
            }
        }

        if (!simInserted) {
            return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
        }
        return std::make_unique<CallRequest>(request);
    }

} // namespace cellular