void net_handler(int,int,struct peer*);
int net_listen_sock();
void net_loop();
+int net_queue(int,struct peer*,void*,size_t);
int net_setup(struct net_info*);
int net_start();
int net_tcp();
int net_udp();
+int net_wait(int,struct peer*,size_t);
#endif
#ifndef __PEER_H_
#define __PEER_H_
+#define PEER_INFOHASH_SIZE 20
+#define PEER_PEER_ID_SIZE 20
+
struct peer {
unsigned int choked : 1;
unsigned int interested: 1;
- uint8_t infohash[20];
- unsigned char peer_id[20];
+ uint8_t infohash[PEER_INFOHASH_SIZE];
+ unsigned char peer_id[PEER_PEER_ID_SIZE];
+
+ void *data;
+ size_t data_size;
};
enum peer_message {
--- /dev/null
+#include<net.h>
+
+int net_queue(int sock, struct peer *info, void *p, size_t size) {
+ struct epoll_event ev;
+
+ info->data = malloc(size);
+ if(NULL==info->data) { return -1; }
+
+ memcpy(info->data,p,size);
+
+ ev.events = EPOLLOUT;
+ ev.data.ptr = info;
+ ev.data.fd = sock;
+
+ if(-1==epoll_ctl(epoll_fd,EPOLL_CTL_ADD,sock,&ev)) {
+ perror("epoll_ctl");
+ return -1;
+ }
+
+ return 1;
+}
#include<peer.h>
#define HANDSHAKE_STRING "\x13" "BitTorrent protocol\0\0\0\0\0\0\0\0";
-#define HANDSHAKE_INFOHASH_SIZE 20
+#define HANDSHAKE_STRING_LENGTH 28
-int peer_handshake(int sock, struct peer **info) {
- ssize_t i;
- const char header[64] = HANDSHAKE_STRING;
+#define HEADER_LENGTH HANDSHAKE_STRING_LENGTH+PEER_INFOHASH_SIZE+PEER_PEER_ID_SIZE
-
+static int peer_handshake_receive(int);
- assert(HANDSHAKE_INFOHASH_SIZE==infohash_size);
- assert(PEER_ID_SIZE==peer_id_size);
+int peer_handshake(int sock) {
+ struct peer *info;
+ char header[HEADER_LENGTH] = HANDSHAKE_STRING;
+ ssize_t i;
if(sock<0) { return -1; }
- memcpy(&(header[24]),infohash,HANDSHAKE_INFOHASH_SIZE);
- memcpy(&(header[44]),peer_id,PEER_ID_SIZE);
+ if(peer_init(&info)<0) { return -1; }
+
+ if(peer_handshake_receive(sock)<0) { return -1; }
+
+ // copy infohash to buffer
+ memcpy(
+ &(header[HANDSHAKE_STRING_LENGTH]),
+ info->infohash,
+ PEER_INFOHASH_SIZE);
+
+ // copy peer id to buffer
+ memcpy(
+ &(header[HANDSHAKE_STRING_LENGTH+PEER_INFOHASH_SIZE]),
+ info->peer_id,
+ PEER_PEER_ID_SIZE);
// send header
+ i = send(sock,header,HEADER_LENGTH,0);
+ if(i<HEADER_LENGTH) {
+ if(i<0) {
+ perror("send");
+ return -1;
+ }
+ goto epoll;
+ }
+
+ return 1;
+epoll:
+ if(net_queue(sock,info,&(header[i]),HEADER_LENGTH-i)<0) { return -1; }
+ return 0;
+}
+
+static int peer_handshake_receive(int sock, struct peer *info) {
+ char header[HEADER_LENGTH];
+ ssize_t i;
+
+ i = recv(sock,header,HEADER_LENGTH);
+ if(-1==i) {
+ if(!((errno==EAGAIN)||(errno==EWOULDBLOCK))) {
+ perror("recv");
+ return;
+ }
+ goto wait;
+ }
return -1;
+wait:
+ if(net_wait(sock,info,
}