rendered paste body#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <sys/epoll.h>#include <popt.h>#include <pthread.h>int syncSocket, commandSocket, epoll_fd;pthread_mutex_t socketListLock;struct socketListNode { int fd; struct sockaddr sa; int (*rcallback)(int, struct sockaddr *, void *, int r); int (*wcallback)(int); struct socketListNode *next, *prev;};#define HASHBUCKETS 1093static inline const unsigned int socketHashVal(const int val) { return (val % HASHBUCKETS);}struct socketListNode *socketHash[HASHBUCKETS];unsigned long int nodes;static inline struct socketListNode *findNode(int fd) { register struct socketListNode *tmp; pthread_mutex_lock(&socketListLock); tmp = socketHash[socketHashVal(fd)]; while(tmp) { if(tmp->fd == fd) break; tmp = tmp->next; } pthread_mutex_unlock(&socketListLock); return tmp;}static inline struct socketListNode *appendNode(int fd, struct sockaddr *sa, int (*rcallback)(int,struct sockaddr *,void *,int), int (*wcallback)(int)) { struct socketListNode *ptr; struct socketListNode **hashNode; if( (ptr = findNode(fd)) ) { if(sa) memcpy(&ptr->sa, sa, sizeof(ptr->sa)); ptr->rcallback = rcallback; ptr->wcallback = wcallback; return ptr; } ptr = (struct socketListNode *)malloc(sizeof(struct socketListNode)); ptr->fd = fd; ptr->rcallback = rcallback; ptr->wcallback = wcallback; ptr->next = NULL; ptr->prev = NULL; if(sa) memcpy(&ptr->sa, sa, sizeof(ptr->sa)); pthread_mutex_lock(&socketListLock); hashNode = &socketHash[socketHashVal(fd)]; if(*hashNode == NULL) { *hashNode = ptr; } else { register struct socketListNode *tmp = *hashNode; while(tmp->next) { tmp = tmp->next; } tmp->next = ptr; ptr->prev = tmp; } pthread_mutex_unlock(&socketListLock); ++nodes; return ptr;}static inline void deleteNodePtr(struct socketListNode *ptr) { if(ptr) { pthread_mutex_lock(&socketListLock); if(ptr->prev) ptr->prev->next = ptr->next; if(ptr->next) ptr->next->prev = ptr->prev; if(socketHash[socketHashVal(ptr->fd)] == ptr) { socketHash[socketHashVal(ptr->fd)] = ptr->next; } pthread_mutex_lock(&socketListLock); free(ptr); }}static inline void deleteNode(int fd) { register struct socketListNode *tmp; struct socketListNode **hashNode; pthread_mutex_lock(&socketListLock); hashNode = &socketHash[socketHashVal(fd)]; tmp = *hashNode; while(tmp) { if(tmp->fd == fd) { if(tmp->prev) tmp->prev->next = tmp->next; if(tmp->next) tmp->next->prev = tmp->prev; if(*hashNode == tmp) *hashNode = tmp; pthread_mutex_unlock(&socketListLock); free(tmp); --nodes; return; } tmp = tmp->next; } pthread_mutex_unlock(&socketListLock);}void *threadManager(void *arg) { int id = (int)arg; int nfds, i, l=0; char buf[1500]; struct sockaddr sa; socklen_t sa_len; struct epoll_event *events; int c = 0; events = (struct epoll_event *)calloc(32, sizeof(struct epoll_event)); while(1) { ++l; nfds = epoll_wait(epoll_fd, events, 32, -1); for(i = 0; i < nfds; ++i) { struct socketListNode *node = findNode(events[i].data.fd);// printf("activity on %d found %x\n", events[i].data.fd, node); if(node) { if(events[i].events & EPOLLIN && node->rcallback) { int r; r = recvfrom(events[i].data.fd, buf, 1500, MSG_OOB|MSG_TRUNC, &sa, &sa_len); node->rcallback(events[i].data.fd, &sa, buf, r); } if(events[i].events & EPOLLOUT && node->wcallback) { node->wcallback(events[i].data.fd); } } } } close(epoll_fd); pthread_exit(NULL);}int syncReadCallback(int fd, struct sockaddr *sa, void *data, int len) { printf("Packet: %d: %s\n", len, data); return sendto(fd, data, len, 0, sa, sizeof(struct sockaddr));}int syncWriteCallback(int fd) { // Oi? return 0;}int main(int argc, const char *argv[]) { char *ip = NULL; char c; poptContext optCon; int i, j; int threadCount = 4; pthread_t *threads; struct ip_mreq mreq; struct sockaddr_in sa; struct epoll_event ev; struct poptOption options[] = { { "listen", 'l', POPT_ARG_STRING, &ip, 0, "Set a specific listening IP", "address" }, { "threads", 't', POPT_ARG_INT, &threadCount, 0, "Set the number of threads to use", "count" }, POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; optCon = poptGetContext(NULL, argc, argv, options, 0); while( (c = poptGetNextOpt(optCon)) >= 0) { printf("Oi: %c\n", c); } if(ip != NULL) { printf("Binding to: %s\n", ip); } for(i = 0; i < 31; i++) { socketHash[i] = NULL; } nodes = 0; syncSocket = socket(PF_INET, SOCK_DGRAM, 0); mreq.imr_interface.s_addr = htonl(INADDR_ANY); mreq.imr_multiaddr.s_addr = inet_addr("239.4.0.1"); sa.sin_family = AF_INET; sa.sin_addr.s_addr = INADDR_ANY; //inet_addr("159.18.161.34"); sa.sin_port = htons(7364); if(bind(syncSocket, &sa, sizeof(sa)) == -1) { perror("bind"); } if(setsockopt(syncSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) { perror("setsockopt"); exit(-1); } epoll_fd = epoll_create(5); ev.events = EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP; ev.data.fd = syncSocket; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, syncSocket, &ev); appendNode(syncSocket, NULL, syncReadCallback, syncWriteCallback); threads = (pthread_t *)calloc(threadCount, sizeof(pthread_t)); for(i = 0; i < threadCount; ++i) { pthread_create(&threads[i], NULL, threadManager, (void *)i); } for(i = 0; i < threadCount; ++i) { pthread_join(threads[i], NULL); } exit(0);}