-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
217 lines (178 loc) · 6.66 KB
/
main.cpp
File metadata and controls
217 lines (178 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#include <vector>
#include <cstdlib> // For rand()
#include "peer_decoder.h"
#include "torrent_file.h"
#include "request.h"
#include "custom_bencoder.h"
#include <openssl/sha.h> // Include OpenSSL SHA header
using namespace std;
// Define global variables
uint64_t connection_id;
uint32_t transaction_id;
uint64_t downloaded = 0, uploaded = 0, left_length = 0;
uint32_t ip_address = 0, event = 0, key = rand(); // Random key generation
uint16_t port = htons(6881); // Set port to 6881 and convert to network byte order
uint16_t num_want = 0;
uint8_t peer_id[20]; // Buffer for 20-byte peer ID
uint8_t info_hash[20]; // Buffer for the info hash
std::string peer_id_str = "0MjRoxR3KuzXecjOVAF2"; // Example peer ID
uint64_t CONNECTION_ID = 0x41727101980LL; // Example connection ID
uint32_t TRANSACTION_ID = rand(); // Generate a random transaction ID
uint32_t ACTION_ANNOUNCE = 1;
const char *ip_addr;
void decode_torrent_file()
{
ifstream file("puppy.torrent", ios::binary);
if (!file)
{
cerr << "Error opening .torrent file!" << endl;
return;
}
// Read the entire torrent file
string bencode((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
bencoding::string_subs sa(bencode);
bencoding::bencode_dict torrent_dict;
torrent_dict.decode(sa.str, sa.citer);
// Extract info dictionary
bencoding::bencode_dict file_info_dict;
bencoding::string_subs snew(torrent_dict["info"]->encode());
file_info_dict.decode(snew.str, snew.citer);
// Generate SHA-1 hash of the "info" dictionary for the info_hash
SHA1(reinterpret_cast<const unsigned char *>(snew.str.data()), snew.str.size(), info_hash);
// Prepare announce request parameters
downloaded = htonll(0);
//************************ */
// Please fix @nayan
// add a function for sending seeders & leechers differently
//************************ */
left_length = htonll(stoull(file_info_dict["length"]->get_as_str()));
// left_length = htonll(5); // Set to 5 for seeder
uploaded = htonll(0);
struct in_addr addr;
// std::string url_string = torrent_dict["announce"]->get_as_str();
// ip_addr = url_string.c_str();
// ip_addr = "170.178.183.18";
// std::string url_string = torrent_dict["announce"]->get_as_str();
std::string url_string = "http://torrent.ubuntu.com";
// Remove the protocol (e.g., "udp://")
// std::string hostname = url_string.substr(url_string.find("://") + 3);
std::string hostname = url_string;
// Optionally, find the first slash '/' and cut off the path
// size_t path_pos = hostname.find(':');
// if (path_pos != std::string::npos)
// {
// hostname = hostname.substr(0, path_pos);
// }
ip_addr = hostname.c_str(); // Now ip_addr contains only the hostname
std::cout<<ip_addr<<endl;
inet_aton(ip_addr, &addr); // Default (0) to let the tracker detect
ip_address = htonl(addr.s_addr);
event = htonl(0);
key = htonl(rand());
num_want = htons(0);
port = htons(6881); // Listening port (convert to network byte order)
peer_id_str = "0MjRoxR3KuzXecjOVAF2"; // 20-byte peer ID
// Truncate the peer_id_str to fit into the 16-byte peer_id array
memcpy(peer_id, peer_id_str.data(), 16);
}
int main()
{
decode_torrent_file();
// Initialize socket and address info
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
// Set up the hints for the tracker address
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // Use IPv4
hints.ai_socktype = SOCK_DGRAM; // UDP
if ((rv = getaddrinfo(ip_addr, TRACKER_PORT, &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// Loop through all results and create socket
for (p = servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
perror("socket");
continue;
}
break;
}
if (p == NULL)
{
fprintf(stderr, "failed to create socket\n");
return 2;
}
// Send connect request to the tracker
int connect_transaction_id = send_connect_request(sockfd, p);
if (connect_transaction_id == -1)
{
fprintf(stderr, "failed to send connect request\n");
return 3;
}
addr_len = sizeof their_addr;
// Receive response from the tracker
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN - 1, 0, (struct sockaddr *)&their_addr, &addr_len)) == -1)
{
perror("recvfrom");
exit(1);
}
printf("Got packet from %s\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s));
printf("Packet is %d bytes long\n", numbytes);
uint32_t response_action, response_transaction_id;
memcpy(&response_action, buf, 4);
memcpy(&response_transaction_id, buf + 4, 4);
// Validate the transaction ID matches
if (response_transaction_id != transaction_id)
{
fprintf(stderr, "Transaction ID mismatch\n");
return 5;
}
if (response_action == 0)
{ // Connect response
memcpy(&connection_id, buf + 8, 8);
connection_id = ntohll(connection_id); // Receive in host order
printf("Received valid connection ID: %llu\n", (unsigned long long)connection_id);
}
else
{
fprintf(stderr, "Received unexpected action: %u\n", response_action);
return 6;
}
// Announce request
int announce_transaction_id = send_announce_request(sockfd, p);
if (announce_transaction_id == -1)
{
fprintf(stderr, "failed to send announce request\n");
return 7;
}
addr_len = sizeof their_addr;
// Receive announce response from the tracker
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN - 1, 0, (struct sockaddr *)&their_addr, &addr_len)) == -1)
{
perror("recvfrom");
exit(1);
}
printf("Got packet from %s\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s));
printf("Packet is %d bytes long\n", numbytes);
// Decode the response to extract peer information
std::vector<uint8_t> response(buf, buf + numbytes);
std::vector<Peer> peers = decodeResponse(response);
// Print the decoded peer information
printPeers(peers);
// Clean up
freeaddrinfo(servinfo);
if (close(sockfd) == -1)
{
perror("close");
}
return 0;
}