123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- /*
- * 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 NETLINK_LISTENER_H
- #define NETLINK_LISTENER_H
- #include <functional>
- #include <map>
- #include <mutex>
- #include <thread>
- #include <android-base/thread_annotations.h>
- #include <netdutils/Netlink.h>
- #include <netdutils/Slice.h>
- #include <netdutils/Status.h>
- #include <netdutils/UniqueFd.h>
- namespace android {
- namespace net {
- class NetlinkListenerInterface {
- public:
- using DispatchFn = std::function<void(const nlmsghdr& nlmsg, const netdutils::Slice msg)>;
- using SkErrorHandler = std::function<void(const int fd, const int err)>;
- virtual ~NetlinkListenerInterface() = default;
- // Send message to the kernel using the underlying netlink socket
- virtual netdutils::Status send(const netdutils::Slice msg) = 0;
- // Deliver future messages with nlmsghdr.nlmsg_type == type to fn.
- //
- // 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 type, const DispatchFn& fn) = 0;
- // Halt delivery of future messages with nlmsghdr.nlmsg_type == type.
- // Threadsafe.
- virtual netdutils::Status unsubscribe(uint16_t type) = 0;
- virtual void registerSkErrorHandler(const SkErrorHandler& handler) = 0;
- };
- // NetlinkListener manages a netlink socket and associated blocking
- // service thread.
- //
- // This class is written in a generic way to allow multiple different
- // netlink subsystems to share this common infrastructure. If multiple
- // subsystems share the same message delivery requirements (drops ok,
- // no drops) they may share a single listener by calling subscribe()
- // with multiple types.
- //
- // This class is suitable for moderate performance message
- // processing. In particular it avoids extra copies of received
- // message data and allows client code to control which message
- // attributes are processed.
- //
- // Note that NetlinkListener is capable of processing multiple batched
- // netlink messages in a single system call. This is useful to
- // netfilter extensions that allow batching of events like NFLOG.
- class NetlinkListener : public NetlinkListenerInterface {
- public:
- NetlinkListener(netdutils::UniqueFd event, netdutils::UniqueFd sock, const std::string& name);
- ~NetlinkListener() override;
- netdutils::Status send(const netdutils::Slice msg) override;
- netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) override EXCLUDES(mMutex);
- netdutils::Status unsubscribe(uint16_t type) override EXCLUDES(mMutex);
- void registerSkErrorHandler(const SkErrorHandler& handler) override;
- private:
- netdutils::Status run();
- const netdutils::UniqueFd mEvent;
- const netdutils::UniqueFd mSock;
- const std::string mThreadName;
- std::mutex mMutex;
- std::map<uint16_t, DispatchFn> mDispatchMap GUARDED_BY(mMutex);
- std::thread mWorker;
- SkErrorHandler mErrorHandler;
- };
- } // namespace net
- } // namespace android
- #endif /* NETLINK_LISTENER_H */
|