/* Copyright (C) 2007-2008 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
*/
#include "proxy_int.h"
#include "proxy_http_int.h"
#include "qemu-common.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define  HTTP_VERSION  "1.1"

static void
http_service_free( HttpService*  service )
{
    PROXY_LOG("%s", __FUNCTION__);
    if (service->footer != service->footer0)
        g_free(service->footer);
    g_free(service);
}


static ProxyConnection*
http_service_connect( HttpService*  service,
                      SocketType    sock_type,
                      SockAddress*  address )
{
    /* the HTTP proxy can only handle TCP connections */
    if (sock_type != SOCKET_STREAM)
        return NULL;

    /* if the client tries to directly connect to the proxy, let it do so */
    if (sock_address_equal( address, &service->server_addr ))
        return NULL;

    PROXY_LOG("%s: trying to connect to %s",
              __FUNCTION__, sock_address_to_string(address));

    if (sock_address_get_port(address) == 80) {
        /* use the rewriter for HTTP */
        PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__);
        return http_rewriter_connect(service, address);
    } else {
        PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__);
        return http_connector_connect(service, address);
    }
}


int
proxy_http_setup( const char*         servername,
                  int                 servernamelen,
                  int                 serverport,
                  int                 num_options,
                  const ProxyOption*  options )
{
    HttpService*        service;
    SockAddress         server_addr;
    const ProxyOption*  opt_nocache   = NULL;
    const ProxyOption*  opt_keepalive = NULL;
    const ProxyOption*  opt_auth_user = NULL;
    const ProxyOption*  opt_auth_pass = NULL;
    const ProxyOption*  opt_user_agent = NULL;

    if (servernamelen < 0)
        servernamelen = strlen(servername);

    PROXY_LOG( "%s: creating http proxy service connecting to: %.*s:%d",
               __FUNCTION__, servernamelen, servername, serverport );

    /* resolve server address */
    if (proxy_resolve_server(&server_addr, servername,
                             servernamelen, serverport) < 0)
    {
        return -1;
    }

    /* create service object */
    service = g_malloc0(sizeof(*service));
    if (service == NULL) {
        PROXY_LOG("%s: not enough memory to allocate new proxy service", __FUNCTION__);
        return -1;
    }

    service->server_addr = server_addr;

    /* parse options */
    {
        const ProxyOption*  opt = options;
        const ProxyOption*  end = opt + num_options;

        for ( ; opt < end; opt++ ) {
            switch (opt->type) {
                case PROXY_OPTION_HTTP_NOCACHE:     opt_nocache    = opt; break;
                case PROXY_OPTION_HTTP_KEEPALIVE:   opt_keepalive  = opt; break;
                case PROXY_OPTION_AUTH_USERNAME:    opt_auth_user  = opt; break;
                case PROXY_OPTION_AUTH_PASSWORD:    opt_auth_pass  = opt; break;
                case PROXY_OPTION_HTTP_USER_AGENT:  opt_user_agent = opt; break;
                default: ;
            }
        }
    }

    /* prepare footer */
    {
        int    wlen;
        char*  p    = service->footer0;
        char*  end  = p + sizeof(service->footer0);

        /* no-cache */
        if (opt_nocache) {
            p += snprintf(p, end-p, "Pragma: no-cache\r\nCache-Control: no-cache\r\n");
            if (p >= end) goto FooterOverflow;
        }
        /* keep-alive */
        if (opt_keepalive) {
            p += snprintf(p, end-p, "Connection: Keep-Alive\r\nProxy-Connection: Keep-Alive\r\n");
            if (p >= end) goto FooterOverflow;
        }
        /* authentication */
        if (opt_auth_user && opt_auth_pass) {
            char  user_pass[256];
            char  encoded[512];
            int   uplen;

            uplen = snprintf( user_pass, sizeof(user_pass), "%.*s:%.*s",
                              opt_auth_user->string_len, opt_auth_user->string,
                              opt_auth_pass->string_len, opt_auth_pass->string );

            if (uplen >= (int)sizeof(user_pass)) goto FooterOverflow;

            wlen = proxy_base64_encode(user_pass, uplen, encoded, (int)sizeof(encoded));
            if (wlen < 0) {
                PROXY_LOG( "could not base64 encode '%.*s'", uplen, user_pass);
                goto FooterOverflow;
            }

            p += snprintf(p, end-p, "Proxy-authorization: Basic %.*s\r\n", wlen, encoded);
            if (p >= end) goto FooterOverflow;
        }
        /* user agent */
        if (opt_user_agent) {
            p += snprintf(p, end-p, "User-Agent: %.*s\r\n",
                          opt_user_agent->string_len,
                          opt_user_agent->string);
            if (p >= end) goto FooterOverflow;
        }

        p += snprintf(p, end-p, "\r\n");

        if (p >= end) {
        FooterOverflow:
            PROXY_LOG( "%s: buffer overflow when creating connection footer",
                       __FUNCTION__);
            http_service_free(service);
            return -1;
        }

        service->footer     = service->footer0;
        service->footer_len = (p - service->footer);
    }

    PROXY_LOG( "%s: creating HTTP Proxy Service Footer is (len=%d):\n'%.*s'",
               __FUNCTION__, service->footer_len,
               service->footer_len, service->footer );

    service->root->opaque       = service;
    service->root->serv_free    = (ProxyServiceFreeFunc)    http_service_free;
    service->root->serv_connect = (ProxyServiceConnectFunc) http_service_connect;

    if (proxy_manager_add_service( service->root ) < 0) {
        PROXY_LOG("%s: could not register service ?", __FUNCTION__);
        http_service_free(service);
        return -1;
    }
    return 0;
}

