/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef NFLOG_LISTENER_H
#define NFLOG_LISTENER_H

#include <netdutils/Netfilter.h>

#include "NetlinkListener.h"

namespace android {
namespace net {

class NFLogListenerInterface {
  public:
    using DispatchFn =
        std::function<void(const nlmsghdr& nlmsg, const nfgenmsg& nfmsg,
                           const netdutils::Slice msg)>;

    virtual ~NFLogListenerInterface() = default;

    // Similar to NetlinkListener::subscribe() but performs an additional
    // level of deserialization and dispatch.
    //
    // Threadsafe.
    // All dispatch functions invoked on a single service thread.
    // subscribe() and join() must not be called from the stack of fn().
    virtual netdutils::Status subscribe(uint16_t nfLogGroup, const DispatchFn& fn) = 0;

    // Overloaded version of subscribe which allows to specify a copyRange for obtaining packet
    // payloads.
    virtual netdutils::Status subscribe(
            uint16_t nfLogGroup, uint32_t copyRange, const DispatchFn& fn) = 0;

    // Halt delivery of messages from a nfLogGroup previously subscribed to above.
    //
    // Threadsafe.
    virtual netdutils::Status unsubscribe(uint16_t nfLogGroup) = 0;
};

// NFLogListener manages a single netlink socket with specialized
// settings required for processing of NFLOG messages.
//
// NFLogListener currently assumes that it is ok to drop messages
// generated by the kernel when under heavy load. This makes the
// class most suitable for advisory tasks and statistics.
class NFLogListener : public NFLogListenerInterface {
  public:
    using DispatchFn = NFLogListenerInterface::DispatchFn;

    // Do not invoke this constructor directly outside of tests. Use
    // makeNFLogListener() instead.
    NFLogListener(std::shared_ptr<NetlinkListenerInterface> listener);

    ~NFLogListener() override;

    netdutils::Status subscribe(uint16_t nfLogGroup, const DispatchFn& fn) override;

    netdutils::Status subscribe(
            uint16_t nfLogGroup, uint32_t copyRange, const DispatchFn& fn) override;

    netdutils::Status unsubscribe(uint16_t nfLogGroup) override;

  private:
    std::shared_ptr<NetlinkListenerInterface> mListener;
    std::mutex mMutex;
    std::map<uint16_t, DispatchFn> mDispatchMap;  // guarded by mMutex
};

// Allocate and return a new NFLogListener. On success, the returned
// listener is ready to use with a running service thread.
netdutils::StatusOr<std::unique_ptr<NFLogListener>> makeNFLogListener();

}  // namespace net
}  // namespace android

#endif /* NFLOG_LISTENER_H */
