#include <err.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <stdio.h>
#include <string.h>

/*
* If when a chunk is read into tmpbuf and the portion of the
* response we are looking for, the answer, is truncated, parseres()
* will either output the truncated answer or none at all.
*/
void
parseres(BIO *sbio)
{
       char tmpbuf[2048];
       int len;
       char *ans;

       while ((len = BIO_read(sbio, tmpbuf, 2048)) > 0) {
               if ((ans = strstr(tmpbuf, "Your IP address is ")) == NULL)
                       continue;
               printf("%s\n", strsep(&ans, "\""));
               break;
       }
}

/*
* Create connection to duckduckgo and make GET request query for
* "what is my ip" with a json formatted response.
* HTTP/1.0 in GET causes server to close connection automatically.
*/
BIO *
makereq(SSL_CTX *ctx)
{
       BIO *sbio;
       char *request = "GET /?q=what+is+my+ip&format=json&no_html=1"
                       " HTTP/1.0\r\nHost: duckduckgo.com\r\n\r\n";

       sbio = BIO_new_ssl_connect(ctx);
       if (sbio == NULL)
               err(1, "BIO_new_ssl_connect");
       BIO_set_conn_hostname(sbio, "duckduckgo.com:https");
       /*
        * BIO_do_connection and BIO_do_handshake are called
        * automatically from any I/O request (in this case BIO_puts)
        * and are here only for clarity
        */
       if (BIO_do_connect(sbio) <= 0)
               err(1, "BIO_do_connect");
       if (BIO_do_handshake(sbio) <= 0)
               err(1, "BIO_do_handshake");
       BIO_puts(sbio, request);
       return sbio;
}

/*
* make an https request to duckduckgo
* query "what is my ip"
* parse json response
* write to stdout
* TODO: verbose err strings
*/
int
main()
{
       SSL_CTX *ctx;
       BIO *sbio;

       SSL_library_init();
       if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
               err(1, "SSL_CTX_new");
       sbio = makereq(ctx);
       parseres(sbio);
       BIO_free_all(sbio);
       SSL_CTX_free(ctx);
       return 0;
}