Question

I am making a Winamp plugin with the single function of sending the details of the song being played over HTTP to a webpage/webserver. I couldn't find anything like this that actually works, so decided to dive in for the first time into C++ and just do it myself.

The plugin is a C++ DLL file. I have got to the point where I can output the song title to a windows message box every time a new song is played (not bad for a C++ first-timer! ;) )

Where am I stuck:

I couldn't find anything to get me in the push notification on C++ direction AT ALL.

I tried, without any success, embedding/including HTTP libraries into my DLL to try post requests instead. libcurl, this library here, and this library too - but couldn't get any of them to work! I just kept getting linking errors and then some. After a few hours I just gave up.

I am a very skilled JavaScript programmer so I thought perhaps using JS to connect into a push notification service can work out but running JS inside C++ looks too complicated to me. Perhaps I'm wrong?

Bottom line, I don't know which solution is better (read: easier) to implement - push notifications or post requests?

I appreciate any solutions/input/directions/information or whatever you got. I can post code but the only code I have is the part getting the song information from Winamp and that part works.

Thanks in advance.

EDIT: I guess it's worth noting I'm using the new VS2012?

Was it helpful?

Solution

That's OK to use these kind of libraries, but when speaking of C++, I mainly think of "pure code", so I like the native style to do something, and do it without the help of libraries.

Thinking of that, I can provide you an example on how to send a HTTP's POST request, using Microsoft's winsock2 library.

First, I'd like to point out that I used this link to have a base on how to use winsock2.h.

Ok, now going on to the code, you need these includes:

#include <string>
#include <sstream>
#include <winsock2.h>

You'll also need to link winsock2 library (or specify it in your project settings, as you use VS2012):

#pragma comment(lib, "ws2_32.lib")

Now, the function I edited from the link (I've just edited it to make it look simpler, and also to do some error check and proper cleanup):

int http_post(char *hostname, char *api, char *parameters, std::string& message)
{
    int result;

    WSADATA wsaData;
    result = WSAStartup(MAKEWORD(1, 1), &wsaData);

    if(result != NO_ERROR)
    {
        //printf("WSAStartup failed: %d\n", result);
        return 0;
    }

    sockaddr_in sin;

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock == INVALID_SOCKET)
    {
        //printf("Error at socket(): %ld\n", WSAGetLastError());
        WSACleanup();
        return 0;
    }

    sin.sin_family = AF_INET;
    sin.sin_port = htons(80);

    struct hostent *host_addr = gethostbyname(hostname);
    if(host_addr == NULL)
    {
        //printf("Unable to locate host\n");
        closesocket(sock);
        WSACleanup();
        return 0;
    }

    sin.sin_addr.s_addr = *((int *)*host_addr->h_addr_list);

    if(connect(sock, (const struct sockaddr *)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR)
    {
        //printf("Unable to connect to server: %ld\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return 0;
    }

    std::stringstream stream;
    stream << "POST " << api << " HTTP/1.0\r\n"
           << "User-Agent: Mozilla/5.0\r\n"
           << "Host: " << hostname << "\r\n"
           << "Content-Type: application/x-www-form-urlencoded;charset=utf-8\r\n"
           << "Content-Length: " << strlen(parameters) << "\r\n"
           << "Accept-Language: en-US;q=0.5\r\n"
           << "Accept-Encoding: gzip, deflate\r\n"
           << "Accept: */*\r\n"
           << "\r\n" << parameters
    ;

    if(send(sock, stream.str().c_str(), stream.str().length(), 0) == SOCKET_ERROR)
    {
        //printf("send failed: %d\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return 0;
    }

    if(shutdown(sock, SD_SEND) == SOCKET_ERROR)
    {
        //printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return 0;
    }

    char buffer[1];

    do
    {
        result = recv(sock, buffer, 1, 0);
        if(result > 0)
        {
            //printf("Bytes received: %d\n", result);
            message += buffer[0];
        }
        else if(result == 0)
        {
            //printf("Connection closed\n");
        }
        else
        {
            //printf("recv failed: %d\n", WSAGetLastError());
        }
    }
    while(result > 0);

    closesocket(sock);
    WSACleanup();

    return 1;
}

As you are using a DLL, I commented out the printfs, so you can use your proper output function according to the Winamp plugin API.

Now, to use the function, it's self-explanatory:

std::string post;
http_post("www.htmlcodetutorial.com", "/cgi-bin/mycgi.pl", "user=example123&artist=The Beatles&music=Eleanor Rigby", post);

By doing this, and checking the function return number (either 1 for success or 0 for failure), you can parse the result string returned from the site, and check if everything went OK.

About your last question, using POST request is OK, but you, as a webmaster, know that it's possible to "abuse" this option, such as request flooding, etc. But it really is the simplest way.

If you, by the server side part, parse the data correctly, and check for any improper use of the request, then you can use this method without any problems.

And last, as you are a C++ beginner, you'll need to know how to manipulate std::strings for parsing the song name and artist to the post POST message string safely, if you don't know yet, I recommend this link.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top