/*
 * Copyright (C) 2010 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.
 */

#pragma once

#include <string>

#include <netd_resolv/resolv.h>  // android_net_context
#include <sysutils/FrameworkCommand.h>
#include <sysutils/FrameworkListener.h>

struct addrinfo;
struct hostent;

namespace android {
namespace net {

class NetworkDnsEventReported;

class DnsProxyListener : public FrameworkListener {
  public:
    DnsProxyListener();
    virtual ~DnsProxyListener() {}

    static constexpr const char* SOCKET_NAME = "dnsproxyd";

  private:
    class GetAddrInfoCmd : public FrameworkCommand {
      public:
        GetAddrInfoCmd();
        virtual ~GetAddrInfoCmd() {}
        int runCommand(SocketClient* c, int argc, char** argv) override;
    };

    /* ------ getaddrinfo ------*/
    class GetAddrInfoHandler {
      public:
        // Note: All of host, service, and hints may be NULL
        GetAddrInfoHandler(SocketClient* c, char* host, char* service, addrinfo* hints,
                           const android_net_context& netcontext);
        ~GetAddrInfoHandler();

        void run();
        std::string threadName();

      private:
        void doDns64Synthesis(int32_t* rv, addrinfo** res, NetworkDnsEventReported* event);

        SocketClient* mClient;  // ref counted
        char* mHost;            // owned. TODO: convert to std::string.
        char* mService;         // owned. TODO: convert to std::string.
        addrinfo* mHints;       // owned
        android_net_context mNetContext;
    };

    /* ------ gethostbyname ------*/
    class GetHostByNameCmd : public FrameworkCommand {
      public:
        GetHostByNameCmd();
        virtual ~GetHostByNameCmd() {}
        int runCommand(SocketClient* c, int argc, char** argv) override;
    };

    class GetHostByNameHandler {
      public:
        GetHostByNameHandler(SocketClient* c, char* name, int af,
                             const android_net_context& netcontext);
        ~GetHostByNameHandler();

        void run();
        std::string threadName();

      private:
        void doDns64Synthesis(int32_t* rv, hostent* hbuf, char* buf, size_t buflen, hostent** hpp,
                              NetworkDnsEventReported* event);

        SocketClient* mClient;  // ref counted
        char* mName;            // owned. TODO: convert to std::string.
        int mAf;
        android_net_context mNetContext;
    };

    /* ------ gethostbyaddr ------*/
    class GetHostByAddrCmd : public FrameworkCommand {
      public:
        GetHostByAddrCmd();
        virtual ~GetHostByAddrCmd() {}
        int runCommand(SocketClient* c, int argc, char** argv) override;
    };

    class GetHostByAddrHandler {
      public:
        GetHostByAddrHandler(SocketClient* c, void* address, int addressLen, int addressFamily,
                             const android_net_context& netcontext);
        ~GetHostByAddrHandler();

        void run();
        std::string threadName();

      private:
        void doDns64ReverseLookup(hostent* hbuf, char* buf, size_t buflen, hostent** hpp,
                                  NetworkDnsEventReported* event);

        SocketClient* mClient;  // ref counted
        void* mAddress;         // address to lookup; owned
        int mAddressLen;        // length of address to look up
        int mAddressFamily;     // address family
        android_net_context mNetContext;
    };

    /* ------ resnsend ------*/
    class ResNSendCommand : public FrameworkCommand {
      public:
        ResNSendCommand();
        virtual ~ResNSendCommand() {}
        int runCommand(SocketClient* c, int argc, char** argv) override;
    };

    class ResNSendHandler {
      public:
        ResNSendHandler(SocketClient* c, std::string msg, uint32_t flags,
                        const android_net_context& netcontext);
        ~ResNSendHandler();

        void run();
        std::string threadName();

      private:
        SocketClient* mClient;  // ref counted
        std::string mMsg;
        uint32_t mFlags;
        android_net_context mNetContext;
    };

    /* ------ getdnsnetid ------*/
    class GetDnsNetIdCommand : public FrameworkCommand {
      public:
        GetDnsNetIdCommand();
        virtual ~GetDnsNetIdCommand() {}
        int runCommand(SocketClient* c, int argc, char** argv) override;
    };
};

}  // namespace net
}  // namespace android
