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

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>

#define LOG_TAG "DhcpClient"
#include <cutils/log.h>
#include <cutils/properties.h>

#include <sysutils/ServiceManager.h>

#include <netutils/ifc.h>
#include <netutils/dhcp.h>

#include "DhcpClient.h"
#include "DhcpState.h"
#include "DhcpListener.h"
#include "IDhcpEventHandlers.h"
#include "Controller.h"

DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) :
            mState(DhcpState::INIT), mHandlers(handlers) {
    mServiceManager = new ServiceManager();
    mListener = NULL;
    mListenerSocket = NULL;
    mController = NULL;
    mDoArpProbe = false;
    pthread_mutex_init(&mLock, NULL);
}

DhcpClient::~DhcpClient() {
    delete mServiceManager;
    if (mListener)
        delete mListener;
}

int DhcpClient::start(Controller *c) {
    ALOGD("Starting DHCP service (arp probe = %d)", mDoArpProbe);
    char svc[PROPERTY_VALUE_MAX];
    snprintf(svc,
             sizeof(svc),
             "dhcpcd:%s%s",
             (!mDoArpProbe ? "-A " : ""),
             c->getBoundInterface());

    pthread_mutex_lock(&mLock);

    if (mController) {
        pthread_mutex_unlock(&mLock);
        errno = EBUSY;
        return -1;
    }
    mController = c;

    sockaddr_in addr;
    if ((mListenerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
        ALOGE("Failed to create DHCP listener socket");
        pthread_mutex_unlock(&mLock);
        return -1;
    }
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(DhcpClient::STATUS_MONITOR_PORT);

    if (bind(mListenerSocket, (struct sockaddr *) &addr, sizeof(addr))) {
        ALOGE("Failed to bind DHCP listener socket");
        close(mListenerSocket);
        mListenerSocket = -1;
        pthread_mutex_unlock(&mLock);
        return -1;
    }

    if (mServiceManager->start(svc)) {
        ALOGE("Failed to start dhcp service");
        pthread_mutex_unlock(&mLock);
        return -1;
    }

    mListener = new DhcpListener(mController, mListenerSocket, mHandlers);
    if (mListener->startListener()) {
        ALOGE("Failed to start listener");
#if 0
        mServiceManager->stop("dhcpcd");
        return -1;
#endif
        delete mListener;
        mListener = NULL;
        pthread_mutex_unlock(&mLock);
    }

    pthread_mutex_unlock(&mLock);
    return 0;
}

int DhcpClient::stop() {
    pthread_mutex_lock(&mLock);
    if (!mController) {
        pthread_mutex_unlock(&mLock);
        return 0;
    }

    if (mListener) {
        mListener->stopListener();
        delete mListener;
        mListener = NULL;
    }
    close(mListenerSocket);

    if (mServiceManager->stop("dhcpcd")) {
        ALOGW("Failed to stop DHCP service (%s)", strerror(errno));
        // XXX: Kill it the hard way.. but its gotta go!
    }

    mController = NULL;
    pthread_mutex_unlock(&mLock);
    return 0;
}

void DhcpClient::setDoArpProbe(bool probe) {
    mDoArpProbe = probe;
}
