All pastes #84586 Raw Edit

multicast test

public c v1 · immutable
·published 2006-07-11 02:46 UTC
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);}