Adrian
Adrian

Reputation: 188

"The requested URL /announce was not found on this server" error for bittorrent HTTP request

I am trying to make a HTTP request to bittorrent tracker server to get the peer list.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>  // for gethostbyname()
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
using namespace std;

struct in_addr *atoaddr( const char* address)
{
static struct hostent *host;
static struct in_addr saddr;

// First try nnn.nnn.nnn.nnn form
saddr.s_addr = inet_addr(address);
if (saddr.s_addr != -1)
    return &saddr;

host = gethostbyname(address);
if( host )
    return (struct in_addr *) *host->h_addr_list;

return 0;
}

int main(){
int numbytes=0;
int m_Port=80;
string m_Host="torrent.ubuntu.com";
int m_Sock;
struct hostent *host;
static struct in_addr saddr;
string buffer;
char* buf;

//HTTP request string
buffer.append("GET http://torrent.ubuntu.com:6969/announce HTTP/1.1\r\n");
buffer.append("Host: torrent.ubuntu.com\r\n");
buffer.append("Accept-Encoding: identity\r\n");
buffer.append("info_hash: %36%be%21%35%ab%cc%f4%03%2f%bb%28%bb%1b%0d%4f%da%f7%49%f8%58\r\n");
buffer.append("peer_id: ABCDEFGHIJKLMNOPQRST\r\n");
buffer.append("port: 6881\r\n");
buffer.append("compact: 1\r\n");
buffer.append("uploaded: 0\r\n");
buffer.append("downloaded: 0\r\n");
buffer.append("left: 987758592\r\n");
buffer.append("event: started\r\n");
buffer.append("\r\n");

in_addr* addr = atoaddr( m_Host.c_str() );
if( !addr )
{
    cout<<"Error address\n";
    return 1;
}

sockaddr_in address;
memset( (char*)&address, 0, sizeof(address) );
address.sin_family = AF_INET;
address.sin_port = htons( m_Port );
address.sin_addr.s_addr = addr->s_addr;

m_Sock = socket( AF_INET, SOCK_STREAM, 0 );
if(m_Sock<0){
    cout<<"Socket error\n";
    return 1;
}

if( ::connect( m_Sock, (sockaddr const*)&address, sizeof(address) ) < 0 )
{
    cout<<"connect error";
    return 1;
}

buf = (char*)buffer.c_str();
numbytes = buffer.length();
while( numbytes > 0 )
{
    int n = ::send( m_Sock, buf, buffer.size(), 0 );
    std::cout<<"\n\n--HTTP request:\n"<<buf<<std::endl;
    if( n<0 )
    {
        cout<<"number of bytes sent <0\n";
        return 1;
    }
    numbytes -= n;
    buf += n;
}

cout<<"\ngetting response: \n";
unsigned char recvBuf[ 2048 ];
int a;
do{
    a = recv( m_Sock, (char*)recvBuf, sizeof(recvBuf), 0 );
    fwrite(recvBuf, 1, a, stdout);
}while(a!=0);

if(m_Sock>0)
    close(m_Sock);

return 0;
}

I always get a response like:

HTTP/1.1 404 Not Found
Date: Sun, 16 Mar 2014 13:40:10 GMT
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 294
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /announce was not found on this server.</p>
<hr>
<address>Apache/2.2.22 (Ubuntu) Server at bttracker.debian.org Port 6969</address>
</body></html>

I tried with POSTMAN extension from Google Chrome to make the same request and i get a response like:

d8:completei12e10:incompletei1e8:intervali1800e5:peers18:[�_�����4&N=;8��e

which is what i'm expecting to see when making the request from my C code. What am i doing wrong?

Upvotes: 1

Views: 646

Answers (2)

Adrian
Adrian

Reputation: 188

I used Wireshark (thanks to an old friend advise) for getting the request sent by POSTMAN. Here is the code that worked for me:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>  // for gethostbyname()
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
using namespace std;

// Try to work out address from string
// returns 0 if bad
struct in_addr *atoaddr( const char* address) 
{
static struct hostent *host;
static struct in_addr saddr;

// First try nnn.nnn.nnn.nnn form
saddr.s_addr = inet_addr(address);
if (saddr.s_addr != -1)
    return &saddr;

host = gethostbyname(address);
if( host )
    return (struct in_addr *) *host->h_addr_list;

return 0;
}

int main(){
int numbytes=0;
int m_Port=6969;
string m_Host="torrent.ubuntu.com";
int m_Sock;
struct hostent *host;
static struct in_addr saddr;
string buffer;
char* buf;

//  HTTP request string

//  buffer.append("GET /announce HTTP/1.1\r\n");
//  buffer.append("Host: torrent.ubuntu.com:6969\r\n");
//  buffer.append("Accept-Encoding: identity\r\n");
//  buffer.append("info_hash:     %36%be%21%35%ab%cc%f4%03%2f%bb%28%bb%1b%0d%4f%da%f7%49%f8%58\r\n");
//  buffer.append("peer_id: ABCDEFGHIJKLMNOPQRST\r\n");
//  buffer.append("port: 6881\r\n");
//  buffer.append("uploaded: 0\r\n");
//  buffer.append("downloaded: 0\r\n");
//  buffer.append("left: 987758592\r\n");
//  buffer.append("compact: 1\r\n");
//  buffer.append("event: started\r\n");
buffer.append("GET /announce?info_hash=%36%be%21%35%ab%cc%f4%03%2f%bb%28%bb%1b%0d%4f%da%f7%49%f8%58&"
        "peer_id=ABCDEFGHIJKLMNOPQRST&"
        "port=6881&"
        "compact=1&"
        "uploaded=0&"
        "downloaded=0&"
        "left=987758592&"
        "event=started HTTP/1.1\r\n");
buffer.append("\r\n");

in_addr* addr = atoaddr( m_Host.c_str() );
if( !addr )
{
    cout<<"Error address\n";
    return 1;
}

sockaddr_in address;
memset( (char*)&address, 0, sizeof(address) );
address.sin_family = AF_INET;
address.sin_port = htons( m_Port );
address.sin_addr.s_addr = addr->s_addr;

m_Sock = socket( AF_INET, SOCK_STREAM, 0 );
if(m_Sock<0){
    cout<<"Socket error\n";
    return 1;
}

if( ::connect( m_Sock, (sockaddr const*)&address, sizeof(address) ) < 0 )
{
    cout<<"connect error";
    return 1;
}

buf = (char*)buffer.c_str();
numbytes = buffer.length();
while( numbytes > 0 )
{
    int n = ::send( m_Sock, buf, buffer.size(), 0 );
    std::cout<<"\n\n--HTTP request:\n"<<buf<<std::endl;
    if( n<0 )
    {
        cout<<"number of bytes sent <0\n";
        return 1;
    }
    numbytes -= n;
    buf += n;
}

cout<<"\ngetting response: \n";
unsigned char recvBuf[ 2048 ];
int a;
do{
    a = recv( m_Sock, (char*)recvBuf, sizeof(recvBuf), 0 );
    fwrite(recvBuf, 1, a, stdout);
}while(a!=0);
cout<<"\n";

if(m_Sock>0)
    close(m_Sock);

return 0;
}

Upvotes: 0

Mauren
Mauren

Reputation: 1975

I believe your code fails because you made a small mistake: instead of connecting your socket to port 80, you should be connecting to port 6969 and then send a GET /announce query, instead of sending full URL in the GET method.

Upvotes: 1

Related Questions