/*
 * Copyright (c) 2012 Netflix, Inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY NETFLIX, INC. AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL NETFLIX OR CONTRIBUTORS BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <map>
#include <curl/curl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <vector>
#include "DialDiscovery.h"
#include <assert.h>

#define SSDP_TIMEOUT 30
#define SSDP_RESPONSE_TIMEOUT 3

using namespace std;

DialDiscovery *DialDiscovery::sDiscovery = 0;

static char ip_addr[INET_ADDRSTRLEN] = "127.0.0.1";
static int my_port = 0;
static struct sockaddr_in saddr;
typedef struct
{
    struct sockaddr_in saddr;
    int sock;
    socklen_t addrlen;
}search_conn;

static pthread_mutex_t list_locker = PTHREAD_MUTEX_INITIALIZER;
class ScopeLocker
{
public:
    ScopeLocker(pthread_mutex_t &m) : mLock(m) 
        { pthread_mutex_lock(&mLock); }
    virtual ~ScopeLocker() 
        { pthread_mutex_unlock(&mLock); }
private:
    pthread_mutex_t mLock;
};

static const char ssdp_msearch[] = 
    "M-SEARCH * HTTP/1.1\r\n"
    "HOST: 239.255.255.250:1900\r\n"
    "MAN: \"ssdp:discover\"\r\n"
    "MX: 10\r\n"
    "ST: urn:dial-multiscreen-org:service:dial:1\r\n\r\n";

static string getLocation(char *pResponse) 
{
    string loc(pResponse);
    size_t prev = 0, index = loc.find("\r\n");
    string locUrl, retUrl;
    while( index != string::npos ) {
        locUrl = loc.substr(prev, index-prev);
        ATRACE("locUrl: ##%s## prev: %d index %d\n", locUrl.c_str(), (int)prev, (int)index );
        if( locUrl.find("LOCATION: ") != string::npos ) {
            index = locUrl.find("\r\n");
            retUrl = locUrl.substr( 10 );
            break;
        }

        prev = index+2; // move past the "\r\n" token
        index = loc.find("\r\n", prev);
    }
    return retUrl;
}

static size_t header_cb(void* ptr, size_t size, size_t nmemb, void* userdata)
{
    if ((size * nmemb) != 0) {
        string parse((char*)ptr);
        if( parse.find("Application-URL: ") != string::npos ) {
            size_t index_start = parse.find(":");
            index_start += 2;
            size_t index_end = parse.find("\r\n");
            string *header = static_cast<string*>(userdata);
            header->append(parse.substr(index_start, index_end-index_start));
            ATRACE("Apps URL set to %s\n", header->c_str());
#ifndef DEBUG
        }
#else
        } else {
            ATRACE("%s: Dropping %s\n", __FUNCTION__, (char*)ptr);
        }
#endif
    }
    return (size * nmemb);
}

static size_t receiveData(void *ptr, size_t size, size_t nmemb, void *userdata)
{
    if ((size * nmemb) != 0) {
        string *url = static_cast<string*>(userdata);
        url->append((char*)ptr);
    }
    return (size * nmemb);
}

static void getServerInfo( const string &server, string& appsUrl, string& ddxml ) 
{
    CURL *curl;
    CURLcode res = CURLE_OK;

    if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
        fprintf(stderr, "curl_global_init() failed\n");
        return; 
    }

    if ((curl = curl_easy_init()) == NULL) {
        fprintf(stderr, "curl_easy_init() failed\n");
        curl_global_cleanup();
        return;
    }

    ATRACE("Sending ##%s##\n", server.c_str());
    curl_easy_setopt(curl, CURLOPT_URL, server.c_str());
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb);
    curl_easy_setopt(curl, CURLOPT_HEADERDATA, &appsUrl);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receiveData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ddxml);
    res = curl_easy_perform(curl);

    curl_easy_cleanup(curl);
    //curl_global_cleanup();
}

void DialDiscovery::updateServerList(string& server)
{
    ServerMap::const_iterator it;
    it = mServerMap.find(server);
    if( it == mServerMap.end() ) {
        // not found, add it
        string appsUrl, ddxml;
        getServerInfo(server, appsUrl, ddxml);
        mServerMap[server] = new DialServer(server, appsUrl, ddxml);
    } else {
        // just mark that we found it
        (*it).second->setFound(true);
    }
}

void DialDiscovery::processServer(char *pResponse) 
{
    if (strstr(pResponse, "ST: urn:dial-multiscreen-org:service:dial:1")) {
        string server;
    
        ScopeLocker s(list_locker);
        // parse for LOCATION header
        server = getLocation(pResponse);
        ATRACE("FOUND server: %s\n", server.c_str());
    
        // save the appURL in the server
        updateServerList(server);
#ifndef DEBUG
    }
#else
    } else {
       ATRACE("Dropping Server\n");
    }
#endif
}

void *DialDiscovery::receiveResponses(void *p) 
{
    search_conn *pConn = (search_conn*)p;
    int bytes;
    char buf[4096] = {0,};
    while (1) {
        if (-1 == (bytes = recvfrom(pConn->sock, buf, sizeof(buf) - 1, 0,
                                  (struct sockaddr *)&pConn->saddr, &pConn->addrlen))) {
            perror("recvfrom");
            break;
        }
        buf[bytes] = 0;
        ATRACE("Received [%s:%d] %s\n", __FUNCTION__, __LINE__, buf);
        DialDiscovery::instance()->processServer(buf);
    }
    return 0;
}

void DialDiscovery::cleanServerList(void)
{
    ScopeLocker s(list_locker);

    ServerMap::const_iterator it;
    vector<string> removal;
    for( it = mServerMap.begin(); it != mServerMap.end(); it++ )
    {
        if( !(*it).second->isFound() ) {
            removal.push_back((*it).second->getLocation());
        }
    }

    // now remove and delete
    vector<string>::iterator iter;
    for( iter = removal.begin(); iter != removal.end(); iter ++)
    {
        ATRACE("Removing Server: %s\n", (*iter).c_str());
        DialServer *p = mServerMap[(*iter)];
        delete (p);
        mServerMap.erase((*iter));
    }
}

void DialDiscovery::resetDiscovery(void)
{
    ScopeLocker s(list_locker);
    ServerMap::const_iterator it;
    for( it = mServerMap.begin(); it != mServerMap.end(); it++ ) {
        (*it).second->setFound(false);
    }
}

void * DialDiscovery::send_mcast(void *p) 
{
    int one = 1, my_sock;
    socklen_t addrlen;
    //struct ip_mreq mreq;
    char send_buf[strlen((char*)ssdp_msearch) + INET_ADDRSTRLEN + 256] = {0,};
    int send_size;
    pthread_attr_t attr;
    search_conn connection;

    send_size = snprintf(send_buf, sizeof(send_buf), ssdp_msearch, ip_addr, my_port);
    ATRACE("[%s:%d] %s\n", __FUNCTION__, __LINE__, send_buf);

    if (-1 == (my_sock = socket(AF_INET, SOCK_DGRAM, 0))) {
        perror("socket");
        exit(1);
    }
    if (-1 == setsockopt(my_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
        perror("reuseaddr");
        exit(1);
    }
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr("239.255.255.250");
    saddr.sin_port = htons(1900);

    while (1) {
        addrlen = sizeof(saddr);
        ATRACE("Sending SSDP M-SEARCH to %s:%d\n",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
        if (-1 == sendto(my_sock, send_buf, send_size, 0, (struct sockaddr *)&saddr, addrlen)) {
          perror("sendto");
            continue;
        }

        // set all servers to not found
        DialDiscovery::instance()->resetDiscovery();

        // spawn a response thread
        connection.saddr = saddr;
        connection.sock = my_sock;
        connection.addrlen = addrlen;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
        pthread_create(&DialDiscovery::instance()->_responseThread, &attr, DialDiscovery::receiveResponses, &connection);

        // sleep SSDP_RESPONSE_TIMEOUT seconds to allow clients to response
        sleep(SSDP_RESPONSE_TIMEOUT);
        DialDiscovery::instance()->cleanServerList();

        sleep(SSDP_TIMEOUT-SSDP_RESPONSE_TIMEOUT);
        pthread_cancel(DialDiscovery::instance()->_responseThread);
    }
}

void DialDiscovery::init() 
{
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&_mcastThread, &attr, DialDiscovery::send_mcast, (void*)ssdp_msearch );
}

void DialDiscovery::getServerList( vector<DialServer*>& list )
{
    for( ServerMap::iterator it = mServerMap.begin(); it != mServerMap.end(); ++it ) {
        list.push_back( it->second );
    }
}

bool DialDiscovery::getServer( const string& friendlyName, DialServer &server )
{
    return true;
}

DialDiscovery::DialDiscovery() 
{
    assert( DialDiscovery::sDiscovery == 0 );
    DialDiscovery::sDiscovery = this;
}

DialDiscovery::~DialDiscovery()
{
    assert( sDiscovery == this );
    sDiscovery = 0;
}

DialDiscovery * DialDiscovery::create()
{
    assert( sDiscovery == 0 );
    return new DialDiscovery();
}

DialDiscovery * DialDiscovery::instance()
{
    return DialDiscovery::sDiscovery;
}

