src/log.c \
src/main.c \
src/meta.c \
+ src/net/handler.c \
src/net/listen.c \
src/net/loop.c \
+ src/net/setup.c \
src/net/start.c \
src/net/tcp.c \
src/net/udp.c \
#include<opt.h>
+#include<fcntl.h>
#include<netdb.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
+#include<sys/epoll.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
struct net_info {
- int tcp;
- int udp;
+ int tcp_socket;
+ int udp_socket;
+
+ int epoll_fd;
};
#define NET_MESSAGE_SHUTDOWN_FAILED "net thread shutdown failed\n"
hints.ai_next = NULL; \
}
+void net_handler();
int net_listen_sock();
void net_loop();
+int net_setup(struct net_info*);
int net_start();
int net_tcp();
int net_udp();
--- /dev/null
+#include<net.h>
+
+void net_handler(int sock) {
+ char buf[5];
+ ssize_t i;
+ unsigned int len;
+
+ i = recv(sock,buf,5,MSG_PEEK);
+ if(-1==i) {
+ if(!((errno==EAGAIN)||(errno==EWOULDBLOCK))) {
+ perror("recv");
+ return;
+ }
+ }
+
+ len = 0;
+ for(size_t i=0;i<4;i++) {
+ len <<= 1;
+ len += buf[i];
+ }
+
+ if(0==len) { return; } // message of length 0 == keep-alive
+
+ switch(buf[4]) {
+ case PEER_MESSAGE_CHOKE:
+ break;
+ case PEER_MESSAGE_UNCHOKE:
+ break;
+ case PEER_MESSAGE_INTERESTED:
+ break;
+ case PEER_MESSAGE_NOT_INTERESTED:
+ break;
+ case PEER_MESSAGE_HAVE:
+ break;
+ case PEER_MESSAGE_BITFIELD:
+ break;
+ case PEER_MESSAGE_REQUEST:
+ break;
+ case PEER_MESSAGE_PIECE:
+ break;
+ case PEER_MESSAGE_CANCEL:
+ break;
+ case PEER_MESSAGE_REJECT:
+ break;
+ case PEER_MESSAGE_HASH_REQUEST:
+ break;
+ case PEER_MESSAGE_HASHES:
+ break;
+ case PEER_MESSAGE_HASH_REJECT:
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
#include<net.h>
-void net_loop() {
+static void net_await_epoll_event(struct net_info*);
+static void net_await_udp_event(int);
+static void setnonblocking(int);
+
+void net_loop(struct net_info *info) {
+ net_await_epoll_event(info);
+ net_await_udp_event(info->udp_socket);
+}
+
+#define MAX_EVENTS 10
+
+static void net_await_epoll_event(struct net_info *info) {
+ struct epoll_event ev, events[MAX_EVENTS];
+ int nfds, conn_sock;
+
+ nfds = epoll_wait(info->epoll_fd,events,MAX_EVENTS,-1);
+ if(nfds==-1) {
+ perror("epoll_wait");
+ return;
+ }
+
+ for(int n=0;n<nfds;n++) {
+ if(events[n].data.fd==info->tcp_socket) {
+ conn_sock = accept(info->tcp_socket,NULL,NULL);
+ if(-1==conn_sock) {
+ perror("accept");
+ return;
+ }
+
+ setnonblocking(conn_sock);
+
+ ev.events = EPOLLIN | EPOLLET;
+ ev.data.fd = conn_sock;
+
+ if(-1==epoll_ctl(info->epoll_fd,EPOLL_CTL_ADD,conn_sock,&ev)) {
+ perror("epoll_ctl");
+ return;
+ }
+ } else {
+ net_handler(events[n].data.fd);
+ }
+ }
+}
+
+static void net_await_udp_event(int sock) {
+ return;
+}
+
+static void setnonblocking(int sock) {
+ if(-1==fcntl(sock,F_SETFL,O_NONBLOCK)) {
+ perror("fcntl");
+ }
+
return;
}
--- /dev/null
+#include<net.h>
+
+static int net_setup_epoll(struct net_info*);
+
+int net_setup(struct net_info *info) {
+ if((info->tcp_socket = net_tcp())<0) { return -1; }
+ if((info->udp_socket = net_udp())<0) { return -1; }
+
+ if(net_setup_epoll(info)<0) { return -1; }
+
+ return 1;
+}
+
+static int net_setup_epoll(struct net_info *info) {
+ struct epoll_event ev;
+
+ info->epoll_fd = epoll_create1(0);
+ if(info->epoll_fd==-1) {
+ perror("epoll_create1");
+ return -1;
+ }
+
+ ev.events = EPOLLIN;
+ ev.data.fd = info->tcp_socket;
+ if(epoll_ctl(info->epoll_fd, EPOLL_CTL_ADD, info->tcp_socket, &ev)==-1) {
+ perror("epoll_ctl");
+ return -1;
+ }
+
+ return 1;
+}
static void net_shutdown(void *p) {
struct net_info *info = (struct net_info*)p;
- close(info->tcp);
- close(info->udp);
+ close(info->tcp_socket);
+ close(info->udp_socket);
return;
}
static void *net_spawn(void *p) {
struct net_info info;
- if((info.tcp = net_tcp())<0) { return NULL; }
- if((info.udp = net_udp())<0) { return NULL; }
+ if(net_setup(&info)<0) { return NULL; }
pthread_cleanup_push(&net_shutdown,&info);
while(1) {
pthread_testcancel();
- net_loop();
+ net_loop(&info);
}
pthread_cleanup_pop(1);