1*366f6083SPeter Grehan /*- 2*366f6083SPeter Grehan * Copyright (c) 2011 NetApp, Inc. 3*366f6083SPeter Grehan * All rights reserved. 4*366f6083SPeter Grehan * 5*366f6083SPeter Grehan * Redistribution and use in source and binary forms, with or without 6*366f6083SPeter Grehan * modification, are permitted provided that the following conditions 7*366f6083SPeter Grehan * are met: 8*366f6083SPeter Grehan * 1. Redistributions of source code must retain the above copyright 9*366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer. 10*366f6083SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 11*366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer in the 12*366f6083SPeter Grehan * documentation and/or other materials provided with the distribution. 13*366f6083SPeter Grehan * 14*366f6083SPeter Grehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15*366f6083SPeter Grehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*366f6083SPeter Grehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*366f6083SPeter Grehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18*366f6083SPeter Grehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*366f6083SPeter Grehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*366f6083SPeter Grehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*366f6083SPeter Grehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*366f6083SPeter Grehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*366f6083SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*366f6083SPeter Grehan * SUCH DAMAGE. 25*366f6083SPeter Grehan * 26*366f6083SPeter Grehan * $FreeBSD$ 27*366f6083SPeter Grehan */ 28*366f6083SPeter Grehan 29*366f6083SPeter Grehan /* 30*366f6083SPeter Grehan * Test program for the micro event library. Set up a simple TCP echo 31*366f6083SPeter Grehan * service. 32*366f6083SPeter Grehan * 33*366f6083SPeter Grehan * cc mevent_test.c mevent.c -lpthread 34*366f6083SPeter Grehan */ 35*366f6083SPeter Grehan 36*366f6083SPeter Grehan #include <sys/types.h> 37*366f6083SPeter Grehan #include <sys/socket.h> 38*366f6083SPeter Grehan #include <netinet/in.h> 39*366f6083SPeter Grehan 40*366f6083SPeter Grehan #include <stdio.h> 41*366f6083SPeter Grehan #include <stdlib.h> 42*366f6083SPeter Grehan #include <pthread.h> 43*366f6083SPeter Grehan 44*366f6083SPeter Grehan #include "mevent.h" 45*366f6083SPeter Grehan 46*366f6083SPeter Grehan #define TEST_PORT 4321 47*366f6083SPeter Grehan 48*366f6083SPeter Grehan static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; 49*366f6083SPeter Grehan static pthread_cond_t accept_condvar = PTHREAD_COND_INITIALIZER; 50*366f6083SPeter Grehan 51*366f6083SPeter Grehan #define MEVENT_ECHO 52*366f6083SPeter Grehan 53*366f6083SPeter Grehan #ifdef MEVENT_ECHO 54*366f6083SPeter Grehan struct esync { 55*366f6083SPeter Grehan pthread_mutex_t e_mt; 56*366f6083SPeter Grehan pthread_cond_t e_cond; 57*366f6083SPeter Grehan }; 58*366f6083SPeter Grehan 59*366f6083SPeter Grehan static void 60*366f6083SPeter Grehan echoer_callback(int fd, enum ev_type type, void *param) 61*366f6083SPeter Grehan { 62*366f6083SPeter Grehan struct esync *sync = param; 63*366f6083SPeter Grehan 64*366f6083SPeter Grehan pthread_mutex_lock(&sync->e_mt); 65*366f6083SPeter Grehan pthread_cond_signal(&sync->e_cond); 66*366f6083SPeter Grehan pthread_mutex_unlock(&sync->e_mt); 67*366f6083SPeter Grehan } 68*366f6083SPeter Grehan 69*366f6083SPeter Grehan static void * 70*366f6083SPeter Grehan echoer(void *param) 71*366f6083SPeter Grehan { 72*366f6083SPeter Grehan struct esync sync; 73*366f6083SPeter Grehan struct mevent *mev; 74*366f6083SPeter Grehan char buf[128]; 75*366f6083SPeter Grehan int fd = (int)(uintptr_t) param; 76*366f6083SPeter Grehan int len; 77*366f6083SPeter Grehan 78*366f6083SPeter Grehan pthread_mutex_init(&sync.e_mt, NULL); 79*366f6083SPeter Grehan pthread_cond_init(&sync.e_cond, NULL); 80*366f6083SPeter Grehan 81*366f6083SPeter Grehan pthread_mutex_lock(&sync.e_mt); 82*366f6083SPeter Grehan 83*366f6083SPeter Grehan mev = mevent_add(fd, EVF_READ, echoer_callback, &sync); 84*366f6083SPeter Grehan if (mev == NULL) { 85*366f6083SPeter Grehan printf("Could not allocate echoer event\n"); 86*366f6083SPeter Grehan exit(1); 87*366f6083SPeter Grehan } 88*366f6083SPeter Grehan 89*366f6083SPeter Grehan while (!pthread_cond_wait(&sync.e_cond, &sync.e_mt)) { 90*366f6083SPeter Grehan len = read(fd, buf, sizeof(buf)); 91*366f6083SPeter Grehan if (len > 0) { 92*366f6083SPeter Grehan write(fd, buf, len); 93*366f6083SPeter Grehan write(0, buf, len); 94*366f6083SPeter Grehan } else { 95*366f6083SPeter Grehan break; 96*366f6083SPeter Grehan } 97*366f6083SPeter Grehan } 98*366f6083SPeter Grehan 99*366f6083SPeter Grehan mevent_delete_close(mev); 100*366f6083SPeter Grehan 101*366f6083SPeter Grehan pthread_mutex_unlock(&sync.e_mt); 102*366f6083SPeter Grehan pthread_mutex_destroy(&sync.e_mt); 103*366f6083SPeter Grehan pthread_cond_destroy(&sync.e_cond); 104*366f6083SPeter Grehan } 105*366f6083SPeter Grehan 106*366f6083SPeter Grehan #else 107*366f6083SPeter Grehan 108*366f6083SPeter Grehan static void * 109*366f6083SPeter Grehan echoer(void *param) 110*366f6083SPeter Grehan { 111*366f6083SPeter Grehan char buf[128]; 112*366f6083SPeter Grehan int fd = (int)(uintptr_t) param; 113*366f6083SPeter Grehan int len; 114*366f6083SPeter Grehan 115*366f6083SPeter Grehan while ((len = read(fd, buf, sizeof(buf))) > 0) { 116*366f6083SPeter Grehan write(1, buf, len); 117*366f6083SPeter Grehan } 118*366f6083SPeter Grehan } 119*366f6083SPeter Grehan #endif /* MEVENT_ECHO */ 120*366f6083SPeter Grehan 121*366f6083SPeter Grehan static void 122*366f6083SPeter Grehan acceptor_callback(int fd, enum ev_type type, void *param) 123*366f6083SPeter Grehan { 124*366f6083SPeter Grehan pthread_mutex_lock(&accept_mutex); 125*366f6083SPeter Grehan pthread_cond_signal(&accept_condvar); 126*366f6083SPeter Grehan pthread_mutex_unlock(&accept_mutex); 127*366f6083SPeter Grehan } 128*366f6083SPeter Grehan 129*366f6083SPeter Grehan static void * 130*366f6083SPeter Grehan acceptor(void *param) 131*366f6083SPeter Grehan { 132*366f6083SPeter Grehan struct sockaddr_in sin; 133*366f6083SPeter Grehan pthread_t tid; 134*366f6083SPeter Grehan int news; 135*366f6083SPeter Grehan int s; 136*366f6083SPeter Grehan 137*366f6083SPeter Grehan if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 138*366f6083SPeter Grehan perror("socket"); 139*366f6083SPeter Grehan exit(1); 140*366f6083SPeter Grehan } 141*366f6083SPeter Grehan 142*366f6083SPeter Grehan sin.sin_len = sizeof(sin); 143*366f6083SPeter Grehan sin.sin_family = AF_INET; 144*366f6083SPeter Grehan sin.sin_addr.s_addr = htonl(INADDR_ANY); 145*366f6083SPeter Grehan sin.sin_port = htons(TEST_PORT); 146*366f6083SPeter Grehan 147*366f6083SPeter Grehan if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 148*366f6083SPeter Grehan perror("bind"); 149*366f6083SPeter Grehan exit(1); 150*366f6083SPeter Grehan } 151*366f6083SPeter Grehan 152*366f6083SPeter Grehan if (listen(s, 1) < 0) { 153*366f6083SPeter Grehan perror("listen"); 154*366f6083SPeter Grehan exit(1); 155*366f6083SPeter Grehan } 156*366f6083SPeter Grehan 157*366f6083SPeter Grehan (void) mevent_add(s, EVF_READ, acceptor_callback, NULL); 158*366f6083SPeter Grehan 159*366f6083SPeter Grehan pthread_mutex_lock(&accept_mutex); 160*366f6083SPeter Grehan 161*366f6083SPeter Grehan while (!pthread_cond_wait(&accept_condvar, &accept_mutex)) { 162*366f6083SPeter Grehan news = accept(s, NULL, NULL); 163*366f6083SPeter Grehan if (news < 0) { 164*366f6083SPeter Grehan perror("accept error"); 165*366f6083SPeter Grehan } else { 166*366f6083SPeter Grehan printf("incoming connection, spawning thread\n"); 167*366f6083SPeter Grehan pthread_create(&tid, NULL, echoer, 168*366f6083SPeter Grehan (void *)(uintptr_t)news); 169*366f6083SPeter Grehan } 170*366f6083SPeter Grehan } 171*366f6083SPeter Grehan } 172*366f6083SPeter Grehan 173*366f6083SPeter Grehan main() 174*366f6083SPeter Grehan { 175*366f6083SPeter Grehan pthread_t tid; 176*366f6083SPeter Grehan 177*366f6083SPeter Grehan pthread_create(&tid, NULL, acceptor, NULL); 178*366f6083SPeter Grehan 179*366f6083SPeter Grehan mevent_dispatch(); 180*366f6083SPeter Grehan } 181