LCOV - code coverage report
Current view: top level - src - lora_comms.cc (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 163 163 100.0 %
Date: 2021-11-05 21:57:31 Functions: 36 36 100.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : #include <mutex>
       2                 :            : #include <condition_variable>
       3                 :            : #include <queue>
       4                 :            : #include <chrono>
       5                 :            : #include <napi.h>
       6                 :            : #include <lora_comms_int.h>
       7                 :            : 
       8                 :            : using namespace std::chrono_literals;
       9                 :            : 
      10                 :            : class LoRaComms : public Napi::ObjectWrap<LoRaComms>
      11                 :            : {
      12                 :            : public:
      13                 :            :     LoRaComms(const Napi::CallbackInfo& info);
      14                 :            : 
      15                 :            :     static Napi::Object Initialize(Napi::Env env, Napi::Object exports);
      16                 :            : 
      17                 :            : private:
      18                 :            :     static void Start(const Napi::CallbackInfo& info);
      19                 :            :     static void Stop(const Napi::CallbackInfo& info);
      20                 :            :     static void Reset(const Napi::CallbackInfo& info);
      21                 :            : 
      22                 :            :     static void RecvFrom(const Napi::CallbackInfo& info);
      23                 :            :     static void SendTo(const Napi::CallbackInfo& info);
      24                 :            : 
      25                 :            :     static void SetGWSendHWM(const Napi::CallbackInfo& info);
      26                 :            :     static void SetGWSendTimeout(const Napi::CallbackInfo& info);
      27                 :            :     static void SetGWRecvTimeout(const Napi::CallbackInfo& info);
      28                 :            : 
      29                 :            :     static void StartLogging(const Napi::CallbackInfo& info);
      30                 :            :     static void StopLogging(const Napi::CallbackInfo& info);
      31                 :            :     static void ResetLogging(const Napi::CallbackInfo& info);
      32                 :            :     static void GetLogInfoMessage(const Napi::CallbackInfo& info);
      33                 :            :     static void GetLogErrorMessage(const Napi::CallbackInfo& info);
      34                 :            :     static void SetLogWriteHWM(const Napi::CallbackInfo& info);
      35                 :            :     static void SetLogWriteTimeout(const Napi::CallbackInfo& info);
      36                 :            :     static void SetLogMaxMessageSize(const Napi::CallbackInfo& info);
      37                 :            :     static Napi::Value GetLogMaxMessageSize(const Napi::CallbackInfo& info);
      38                 :            : 
      39                 :            :     static struct timeval TimeVal(const Napi::CallbackInfo& info,
      40                 :            :                                   const uint32_t arg);
      41                 :            :     static enum comm_link CommLink(const Napi::CallbackInfo& info,
      42                 :            :                                    const uint32_t arg);
      43                 :            : };
      44                 :            : 
      45                 :            : // LoRaComms has no instance methods so we never create an instance
      46                 :            : //LCOV_EXCL_START
      47                 :            : LoRaComms::LoRaComms(const Napi::CallbackInfo& info) :
      48                 :            :     Napi::ObjectWrap<LoRaComms>(info)
      49                 :            : {
      50                 :            : }
      51                 :            : //LCOV_EXCL_STOP
      52                 :            : 
      53                 :         57 : Napi::Error ErrnoError(const Napi::Env& env, const int errnum)
      54                 :            : {
      55                 :         57 :     char buf[1024] = {0};
      56                 :         57 :     auto errmsg = strerror_r(errnum, buf, sizeof(buf));
      57                 :            :     static_assert(std::is_same<decltype(errmsg), char*>::value,
      58                 :            :                   "strerror_r must return char*");
      59                 :        114 :     Napi::Error err = Napi::Error::New(env, errmsg ? errmsg : std::to_string(errnum));
      60                 :         57 :     err.Set("errno", Napi::Number::New(env, errnum));
      61                 :        114 :     return err;
      62                 :            : // Bug in lcov/gcc: For some reason the closing brace below is uncovered
      63                 :            : // even though the return above is covered.
      64                 :            : //LCOV_EXCL_START
      65                 :            : }
      66                 :            : //LCOV_EXCL_STOP
      67                 :            : 
      68                 :            : class StartAsyncWorker : public Napi::AsyncWorker
      69                 :            : {
      70                 :            : public:
      71                 :         16 :     StartAsyncWorker(const Napi::Function& callback,
      72                 :         16 :                      const Napi::String& cfg_dir) :
      73                 :            :         Napi::AsyncWorker(callback),
      74                 :         16 :         cfg_dir(cfg_dir.Utf8Value())
      75                 :            :     {
      76                 :         16 :     }
      77                 :            : 
      78                 :            : protected:
      79                 :         16 :     void Execute() override
      80                 :            :     {
      81                 :         16 :         if (start(cfg_dir.empty() ? nullptr : cfg_dir.c_str()) != EXIT_SUCCESS)
      82                 :            :         {
      83                 :          1 :             SetError("failed");
      84                 :            :         }
      85                 :            : 
      86                 :         16 :         close_log_queues(false);
      87                 :         16 :     }
      88                 :            : 
      89                 :            : private:
      90                 :            :     std::string cfg_dir;
      91                 :            : };
      92                 :            : 
      93                 :         16 : void LoRaComms::Start(const Napi::CallbackInfo& info)
      94                 :            : {
      95                 :         16 :     (new StartAsyncWorker(info[1].As<Napi::Function>(),
      96                 :         16 :                           info[0].As<Napi::String>()))
      97                 :         16 :         ->Queue();
      98                 :         16 : }
      99                 :            : 
     100                 :         15 : void LoRaComms::Stop(const Napi::CallbackInfo& info)
     101                 :            : {
     102                 :         15 :     stop();
     103                 :         15 : }
     104                 :            : 
     105                 :         15 : void LoRaComms::Reset(const Napi::CallbackInfo& info)
     106                 :            : {
     107                 :         15 :     reset();
     108                 :         15 : }
     109                 :            : 
     110                 :            : class CommsAsyncWorker : public Napi::AsyncWorker
     111                 :            : {
     112                 :            : public:
     113                 :        111 :     CommsAsyncWorker(const Napi::Function& callback,
     114                 :            :                      const Napi::Buffer<uint8_t>& buffer,
     115                 :        111 :                      const struct timeval& timeout) :
     116                 :            :         Napi::AsyncWorker(callback),
     117                 :        222 :         buf(buffer.Data()),
     118                 :        111 :         len(buffer.Length()),
     119                 :        111 :         timeout(timeout),
     120                 :        222 :         buffer_ref(Napi::Persistent(buffer))
     121                 :            :     {
     122                 :        111 :     }
     123                 :            : 
     124                 :            : // Two versions of this are present in coverage, ~CommsAsyncWorker and
     125                 :            : // ~CommsAsyncWorker.2. Only the latter gets called which leaves the former
     126                 :            : // uncovered. The child classes' destructors are called (both versions).
     127                 :            : //LCOV_EXCL_START
     128                 :            :     ~CommsAsyncWorker()
     129                 :            :     {
     130                 :            :     }
     131                 :            : //LCOV_EXCL_STOP
     132                 :            : 
     133                 :            : protected:
     134                 :            :     virtual ssize_t Communicate() = 0;
     135                 :            : 
     136                 :        111 :     void Execute() override
     137                 :            :     {
     138                 :        111 :         result = Communicate();
     139                 :        111 :         if (result < 0)
     140                 :            :         {
     141                 :         57 :             errnum = errno;
     142                 :            :         }
     143                 :        111 :     }
     144                 :            : 
     145                 :        111 :     void OnOK() override
     146                 :            :     {
     147                 :        111 :         Napi::Env env = Env();
     148                 :        444 :         Callback().MakeCallback(
     149                 :        111 :             Receiver().Value(),
     150                 :            :             {
     151                 :        168 :                 result < 0 ? ErrnoError(env, errnum).Value() : env.Null(),
     152                 :        222 :                 Napi::Number::New(env, result)
     153                 :            :             });
     154                 :        111 :     }
     155                 :            : 
     156                 :            :     void *buf;
     157                 :            :     size_t len;
     158                 :            :     struct timeval timeout;
     159                 :            : 
     160                 :            : private:
     161                 :            :     Napi::Reference<Napi::Buffer<uint8_t>> buffer_ref;
     162                 :            :     ssize_t result;
     163                 :            :     int errnum;
     164                 :            : };
     165                 :            : 
     166                 :            : class LinkAsyncWorker : public CommsAsyncWorker
     167                 :            : {
     168                 :            : public:
     169                 :         65 :     LinkAsyncWorker(const Napi::Function& callback,
     170                 :            :                     const int link,
     171                 :            :                     const Napi::Buffer<uint8_t>& buffer,
     172                 :         65 :                     const struct timeval& timeout) :
     173                 :            :         CommsAsyncWorker(callback, buffer, timeout),
     174                 :         65 :         link(static_cast<enum comm_link>(link))
     175                 :            :     {
     176                 :         65 :     }
     177                 :            : 
     178                 :            : // Two versions of this are present in coverage, ~LinkAsyncWorker and
     179                 :            : // ~LinkAsyncWorker.2. Only the latter gets called which leaves the former
     180                 :            : // uncovered. The child classes' destructors are called (both versions).
     181                 :            : //LCOV_EXCL_START
     182                 :            :     ~LinkAsyncWorker()
     183                 :            :     {
     184                 :            :     }
     185                 :            : //LCOV_EXCL_STOP
     186                 :            : 
     187                 :            : protected:
     188                 :            :     enum comm_link link;
     189                 :            : };
     190                 :            : 
     191                 :            : class RecvFromAsyncWorker : public LinkAsyncWorker
     192                 :            : {
     193                 :            : public:
     194                 :         37 :     RecvFromAsyncWorker(const Napi::Function& callback,
     195                 :            :                         const int link,
     196                 :            :                         const Napi::Buffer<uint8_t>& buffer,
     197                 :         37 :                         const struct timeval& timeout) :
     198                 :         37 :         LinkAsyncWorker(callback, link, buffer, timeout)
     199                 :            :     {
     200                 :         37 :     }
     201                 :            : 
     202                 :            : protected:
     203                 :         37 :     ssize_t Communicate() override
     204                 :            :     {
     205                 :         37 :         return recv_from(link, buf, len, &timeout);
     206                 :            :     }
     207                 :            : };
     208                 :            : 
     209                 :         37 : void LoRaComms::RecvFrom(const Napi::CallbackInfo& info)
     210                 :            : {
     211                 :         37 :     (new RecvFromAsyncWorker(info[4].As<Napi::Function>(),
     212                 :         37 :                              info[0].As<Napi::Number>(),
     213                 :         37 :                              info[1].As<Napi::Buffer<uint8_t>>(),
     214                 :         74 :                              TimeVal(info, 2)))
     215                 :         37 :         ->Queue();
     216                 :         37 : }
     217                 :            : 
     218                 :            : class SendToAsyncWorker : public LinkAsyncWorker
     219                 :            : {
     220                 :            : public:
     221                 :         28 :     SendToAsyncWorker(const Napi::Function& callback,
     222                 :            :                       const int link,
     223                 :            :                       const Napi::Buffer<uint8_t>& buffer,
     224                 :            :                       ssize_t hwm,
     225                 :         28 :                       const struct timeval& timeout) :
     226                 :            :         LinkAsyncWorker(callback, link, buffer, timeout),
     227                 :         28 :         hwm(hwm)
     228                 :            :     {
     229                 :         28 :     }
     230                 :            : 
     231                 :            : protected:
     232                 :         28 :     ssize_t Communicate() override
     233                 :            :     {
     234                 :         28 :         return send_to(link, buf, len, hwm, &timeout);
     235                 :            :     }
     236                 :            : 
     237                 :            : private:
     238                 :            :     ssize_t hwm;
     239                 :            : };
     240                 :            : 
     241                 :         28 : void LoRaComms::SendTo(const Napi::CallbackInfo& info)
     242                 :            : {
     243                 :         28 :     (new SendToAsyncWorker(info[5].As<Napi::Function>(),
     244                 :         28 :                            info[0].As<Napi::Number>(),
     245                 :         28 :                            info[1].As<Napi::Buffer<uint8_t>>(),
     246                 :         28 :                            info[2].As<Napi::Number>(),
     247                 :         56 :                            TimeVal(info, 3)))
     248                 :         28 :         ->Queue();
     249                 :         28 : }
     250                 :            : 
     251                 :          2 : void LoRaComms::SetGWSendHWM(const Napi::CallbackInfo& info)
     252                 :            : {
     253                 :          2 :     set_gw_send_hwm(CommLink(info, 0), info[1].As<Napi::Number>());
     254                 :          2 : }
     255                 :            : 
     256                 :          2 : void LoRaComms::SetGWSendTimeout(const Napi::CallbackInfo& info)
     257                 :            : {
     258                 :          2 :     struct timeval tv = TimeVal(info, 1);
     259                 :          2 :     set_gw_send_timeout(CommLink(info, 0), &tv);
     260                 :          2 : }
     261                 :            : 
     262                 :          2 : void LoRaComms::SetGWRecvTimeout(const Napi::CallbackInfo& info)
     263                 :            : {
     264                 :          2 :     struct timeval tv = TimeVal(info, 1);
     265                 :          2 :     set_gw_recv_timeout(CommLink(info, 0), &tv);
     266                 :          2 : }
     267                 :            : 
     268                 :         16 : void LoRaComms::StartLogging(const Napi::CallbackInfo& info)
     269                 :            : {
     270                 :         16 :     set_logger(log_to_queues);
     271                 :         16 : }
     272                 :            : 
     273                 :          1 : void LoRaComms::StopLogging(const Napi::CallbackInfo& info)
     274                 :            : {
     275                 :          1 :     set_logger(nullptr);
     276                 :          1 :     close_log_queues(true);
     277                 :          1 : }
     278                 :            : 
     279                 :         15 : void LoRaComms::ResetLogging(const Napi::CallbackInfo& info)
     280                 :            : {
     281                 :         15 :     reset_log_queues();
     282                 :         15 : }
     283                 :            : 
     284                 :            : class LogAsyncWorker : public CommsAsyncWorker
     285                 :            : {
     286                 :            : public:
     287                 :         46 :     LogAsyncWorker(const Napi::Function& callback,
     288                 :            :                    get_log_message_fn get_log_message, 
     289                 :            :                    const Napi::Buffer<uint8_t>& buffer,
     290                 :         46 :                    const struct timeval& timeout) :
     291                 :            :         CommsAsyncWorker(callback, buffer, timeout),
     292                 :         46 :         get_log_message(get_log_message)
     293                 :            :     {
     294                 :         46 :     }
     295                 :            : 
     296                 :            : protected:
     297                 :         46 :     ssize_t Communicate() override
     298                 :            :     {
     299                 :         46 :         return get_log_message(static_cast<char*>(buf), len, &timeout);
     300                 :            :     }
     301                 :            : 
     302                 :            : private:
     303                 :            :     get_log_message_fn get_log_message;
     304                 :            : };
     305                 :            : 
     306                 :         29 : void LoRaComms::GetLogInfoMessage(const Napi::CallbackInfo& info)
     307                 :            : {
     308                 :         29 :     (new LogAsyncWorker(info[3].As<Napi::Function>(),
     309                 :            :                         get_log_info_message,
     310                 :         29 :                         info[0].As<Napi::Buffer<uint8_t>>(),
     311                 :         29 :                         TimeVal(info, 1)))
     312                 :         29 :         ->Queue();
     313                 :         29 : }
     314                 :            : 
     315                 :         17 : void LoRaComms::GetLogErrorMessage(const Napi::CallbackInfo& info)
     316                 :            : {
     317                 :         17 :     (new LogAsyncWorker(info[3].As<Napi::Function>(),
     318                 :            :                         get_log_error_message,
     319                 :         17 :                         info[0].As<Napi::Buffer<uint8_t>>(),
     320                 :         17 :                         TimeVal(info, 1)))
     321                 :         17 :         ->Queue();
     322                 :         17 : }
     323                 :            : 
     324                 :          1 : void LoRaComms::SetLogWriteHWM(const Napi::CallbackInfo& info)
     325                 :            : {
     326                 :          1 :     set_log_write_hwm(info[0].As<Napi::Number>());
     327                 :          1 : }
     328                 :            : 
     329                 :          1 : void LoRaComms::SetLogWriteTimeout(const Napi::CallbackInfo& info)
     330                 :            : {
     331                 :          1 :     struct timeval tv = TimeVal(info, 0);
     332                 :          1 :     set_log_write_timeout(&tv);
     333                 :          1 : }
     334                 :            : 
     335                 :          1 : void LoRaComms::SetLogMaxMessageSize(const Napi::CallbackInfo& info)
     336                 :            : {
     337                 :          1 :     set_log_max_msg_size(static_cast<uint32_t>(info[0].As<Napi::Number>()));
     338                 :          1 : }
     339                 :            : 
     340                 :         47 : Napi::Value LoRaComms::GetLogMaxMessageSize(const Napi::CallbackInfo& info)
     341                 :            : {
     342                 :         47 :     return Napi::Number::New(info.Env(), get_log_max_msg_size());
     343                 :            : }
     344                 :            : 
     345                 :            : typedef std::conditional<sizeof(time_t) == 8, int64_t, int32_t>::type tm_t;
     346                 :            : 
     347                 :        116 : struct timeval LoRaComms::TimeVal(const Napi::CallbackInfo& info,
     348                 :            :                                   const uint32_t arg)
     349                 :            : {
     350                 :            :     struct timeval tv;
     351                 :        116 :     tv.tv_sec = static_cast<tm_t>(info[arg].As<Napi::Number>());
     352                 :        116 :     tv.tv_usec = static_cast<tm_t>(info[arg+1].As<Napi::Number>());
     353                 :        116 :     return tv;
     354                 :            : }
     355                 :            : 
     356                 :          6 : enum comm_link LoRaComms::CommLink(const Napi::CallbackInfo& info,
     357                 :            :                                    const uint32_t arg)
     358                 :            : {
     359                 :          6 :     return static_cast<enum comm_link>(info[arg].As<Napi::Number>().Int32Value());
     360                 :            : }
     361                 :            : 
     362                 :          1 : Napi::Object LoRaComms::Initialize(Napi::Env env, Napi::Object exports)
     363                 :            : {
     364                 :          1 :     exports.Set("LoRaComms", DefineClass(env, "LoRaComms",
     365                 :            :     {
     366                 :          1 :         StaticMethod<&Start>("start"),
     367                 :          1 :         StaticMethod<&Stop>("stop"),
     368                 :          1 :         StaticMethod<&Reset>("reset"),
     369                 :            : 
     370                 :          1 :         StaticMethod<&RecvFrom>("recv_from"),
     371                 :          1 :         StaticMethod<&SendTo>("send_to"),
     372                 :            : 
     373                 :          1 :         StaticValue("uplink", Napi::Number::New(env, uplink)),
     374                 :          1 :         StaticValue("downlink", Napi::Number::New(env, downlink)),
     375                 :            : 
     376                 :          1 :         StaticMethod<&SetGWSendHWM>("set_gw_send_hwm"),
     377                 :          1 :         StaticMethod<&SetGWSendTimeout>("set_gw_send_timeout"),
     378                 :          1 :         StaticMethod<&SetGWRecvTimeout>("set_gw_recv_timeout"),
     379                 :            : 
     380                 :          1 :         StaticMethod<&StartLogging>("start_logging"),
     381                 :          1 :         StaticMethod<&StopLogging>("stop_logging"),
     382                 :          1 :         StaticMethod<&ResetLogging>("reset_logging"),
     383                 :          1 :         StaticMethod<&GetLogInfoMessage>("get_log_info_message"),
     384                 :          1 :         StaticMethod<&GetLogErrorMessage>("get_log_error_message"),
     385                 :          1 :         StaticMethod<&SetLogWriteHWM>("set_log_write_hwm"),
     386                 :          1 :         StaticMethod<&SetLogWriteTimeout>("set_log_write_timeout"),
     387                 :          1 :         StaticMethod<&SetLogMaxMessageSize>("set_log_max_msg_size"),
     388                 :          1 :         StaticMethod<&GetLogMaxMessageSize>("get_log_max_msg_size"),
     389                 :            : 
     390                 :          1 :         StaticValue("EBADF", Napi::Number::New(env, EBADF)),
     391                 :          1 :         StaticValue("EAGAIN", Napi::Number::New(env, EAGAIN)),
     392                 :          1 :         StaticValue("EINVAL", Napi::Number::New(env, EINVAL)),
     393                 :            : 
     394                 :          1 :         StaticValue("recv_from_buflen", Napi::Number::New(env, recv_from_buflen)),
     395                 :          1 :         StaticValue("send_to_buflen", Napi::Number::New(env, send_to_buflen))
     396                 :            :     }));
     397                 :            : 
     398                 :          1 :     return exports;
     399                 :            : }
     400                 :            : 
     401                 :          1 : Napi::Object Initialize(Napi::Env env, Napi::Object exports)
     402                 :            : {
     403                 :          1 :     return LoRaComms::Initialize(env, exports);
     404                 :            : }
     405                 :            : 
     406                 :          2 : NODE_API_MODULE(lora_comms, Initialize)

Generated by: LCOV version 1.14