コード例 #1
0
ファイル: session.c プロジェクト: happydayday/libevlite
int32_t session_start_reconnect( struct session * self )
{
    evsets_t sets = self->evsets;

    if ( self->status&SESSION_EXITING )
    {
        // 会话等待退出,
        return -1;
    }

    if ( self->status&SESSION_WRITING )
    {
        // 正在等待写事件的情况下
        return -2;
    }

    // 停止会话
    _stop( self );

    // 2秒后尝试重连, 避免忙等
    event_set( self->evwrite, -1, 0 );
    event_set_callback( self->evwrite, channel_on_reconnect, self );
    evsets_add( sets, self->evwrite, TRY_RECONNECT_INTERVAL );
    self->status |= SESSION_WRITING;            // 让session忙起来

    return 0;
}
コード例 #2
0
void trylock_accept_mutex( struct iothread * thr )
{
    struct acceptor * a = thr->core_acceptor;

    if ( pthread_mutex_trylock(&(a->lock)) == 0 )
    {
        if ( a->holding == 0 )
        {
#if USE_LIBEVENT
            event_set( a->ev_accept, a->socketfd, EV_READ, accept_new_session, thr );
            event_base_set( thr->core_sets, a->ev_accept );
            event_add( a->ev_accept, 0 );
#else
            event_set( a->ev_accept, a->socketfd, EV_READ );
            event_set_callback( a->ev_accept, accept_new_session, thr );
            evsets_add(thr->core_sets, a->ev_accept, 0 );
#endif
            a->holding = 1;
        }

        //pthread_mutex_unlock( &(a->lock) );
    }

    return;
}
コード例 #3
0
void accept_new_session( int32_t fd, int16_t ev, void * arg )
{
    evsets_t coreset = ( evsets_t )arg;

    if ( ev & EV_READ )
    {
        char dsthost[20];
        uint16_t dstport = 0;

        int32_t newfd = tcp_accept( fd, dsthost, &dstport );
        if ( newfd > 0 )
        {
            set_non_block( newfd );

            event_t event = event_create();
            if ( event == NULL )
            {
                printf( "accept new fd failed .\n" );
                return;
            }

            event_set( event, newfd, EV_READ|EV_PERSIST );
            event_set_callback( event, process_message, event );
            evsets_add( coreset, event, 0 );
        }
    }
}
コード例 #4
0
ファイル: test_addtimer.c プロジェクト: JoyZou/libevlite
void ev_timer_callback( int32_t fd, int16_t ev, void * arg )
{
    event_t e = (event_t)arg;
    evsets_t sets = event_get_sets( e );

    printf("ev_timer_callback(handler=%p, fd=%d, ev=%d) : %d \n", e, fd, ev, time(NULL) );

    evsets_add( sets, e, 2*1000 );
}
コード例 #5
0
ファイル: iolayer.c プロジェクト: snivel/libevlite
int32_t _listen_direct( evsets_t sets, struct acceptor * acceptor )
{
    // 开始关注accept事件

    event_set( acceptor->event, acceptor->fd, EV_READ|EV_PERSIST );
    event_set_callback( acceptor->event, channel_on_accept, acceptor );
    evsets_add( sets, acceptor->event, 0 );

    return 0;
}
コード例 #6
0
ファイル: iolayer.c プロジェクト: snivel/libevlite
int32_t _connect_direct( evsets_t sets, struct connector * connector )
{
    // 开始关注连接事件
    connector->evsets = sets;

    event_set( connector->event, connector->fd, EV_WRITE );
    event_set_callback( connector->event, channel_on_connected, connector );
    evsets_add( sets, connector->event, connector->mseconds );

    return 0;
}
コード例 #7
0
void echoserver_process_message( int32_t fd, int16_t ev, void * arg )
{
    struct session * s = (struct session *)arg;

    if ( ev & EV_READ )
    {
        char buf[16384];
        int32_t readn = -1;

        readn = read( fd, buf, 16384 );
        if ( readn <= 0 )
        {
#if __DEBUG
            printf( "Client[%ld, %d] is closed, BYTES:%d, TIME:%lld .\n",
                s->sid, s->fd, s->iobytes, mtime() );
#endif
            //evsets_del( event_get_sets(s->evread), s->evread );
            event_destroy( s->evread );
            close( s->fd );
            free( s );

            goto PROCESS_END;
        }
        else
        {
#if __DEBUG
            printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, mtime() );
#endif
            readn = write( fd, buf, readn );
            s->iobytes += readn;
        }

#if USE_LIBEVENT
        {
            struct timeval tv = {TIMEOUT_MSECS/1000, 0};
            event_add( s->evread, &tv );
        }
#else
        evsets_add( event_get_sets(s->evread), s->evread, TIMEOUT_MSECS );
#endif
    }
    else
    {
#if __DEBUG
        printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, mtime() );
#endif
    }

PROCESS_END :

    return;

}
コード例 #8
0
ファイル: session.c プロジェクト: happydayday/libevlite
// 注册网络事件
void session_add_event( struct session * self, int16_t ev )
{
    int8_t status = self->status;
    evsets_t sets = self->evsets;

    // 注册读事件
    // 不在等待读事件的正常会话
    if ( !(status&SESSION_EXITING)
            && (ev&EV_READ) && !(status&SESSION_READING) )
    {
        event_set( self->evread, self->fd, ev );
        event_set_callback( self->evread, channel_on_read, self );
        evsets_add( sets, self->evread, self->setting.timeout_msecs );

        self->status |= SESSION_READING;
    }

    // 注册写事件
    if ( (ev&EV_WRITE) && !(status&SESSION_WRITING) )
    {
        int32_t wait_for_shutdown = 0;

        // 在等待退出的会话上总是会添加10s的定时器
        if ( status&SESSION_EXITING )
        {
            // 对端主机崩溃 + Socket缓冲区满的情况下
            // 会一直等不到EV_WRITE发生, 这时libevlite就出现了会话泄漏
            wait_for_shutdown = MAX_SECONDS_WAIT_FOR_SHUTDOWN;
        }

        event_set( self->evwrite, self->fd, ev );
        event_set_callback( self->evwrite, channel_on_write, self );
        evsets_add( sets, self->evwrite, wait_for_shutdown );

        self->status |= SESSION_WRITING;
    }
}
コード例 #9
0
ファイル: session.c プロジェクト: happydayday/libevlite
int32_t session_start_keepalive( struct session * self )
{
    int8_t status = self->status;
    evsets_t sets = self->evsets;

    if ( self->setting.keepalive_msecs > 0 && !(status&SESSION_KEEPALIVING) )
    {
        event_set( self->evkeepalive, -1, 0 );
        event_set_callback( self->evkeepalive, channel_on_keepalive, self );
        evsets_add( sets, self->evkeepalive, self->setting.keepalive_msecs );

        self->status |= SESSION_KEEPALIVING;
    }

    return 0;
}
コード例 #10
0
ファイル: iolayer.c プロジェクト: snivel/libevlite
int32_t iolayer_reconnect( struct iolayer * self, struct connector * connector )
{
    // 首先必须先关闭以前的描述符
    if ( connector->fd > 0 )
    {
        close( connector->fd );
        connector->fd = -1;
    }

    // 2秒后尝试重连, 避免忙等
    event_set( connector->event, -1, 0 );
    event_set_callback( connector->event, _reconnect_direct, connector );
    evsets_add( connector->evsets, connector->event, TRY_RECONNECT_INTERVAL );

    return 0;
}
コード例 #11
0
ファイル: test_addtimer.c プロジェクト: JoyZou/libevlite
int32_t test_addtimer( evsets_t sets, event_t * events )
{
    int32_t i = 0;
    struct timeval tv_start, tv_end;

    gettimeofday( &tv_start, NULL );

    for ( i = 0; i < NTEST; ++i )
    {
        evsets_add( sets, events[i], 10000 );
    }

    gettimeofday( &tv_end, NULL );

    printf("evsets_add(%d) : %ld secs, %ld usecs .\n", NTEST,
        tv_end.tv_sec - tv_start.tv_sec, tv_end.tv_usec - tv_start.tv_usec );

    return 0;
}
コード例 #12
0
ファイル: threads.c プロジェクト: spriteray/libevlite
int32_t iothread_start( struct iothread * self, uint8_t index, iothreads_t parent )
{
    self->index = index;
    self->parent = parent;

    self->sets = evsets_create();
    if ( self->sets == NULL )
    {
        iothread_stop(self);
        return -1;
    }

    self->cmdevent = event_create();
    self->queue = msgqueue_create( MSGQUEUE_DEFAULT_SIZE );
    if ( self->queue == NULL || self->cmdevent == NULL )
    {
        iothread_stop(self);
        return -2;
    }

    // 初始化命令事件
    event_set( self->cmdevent, msgqueue_popfd(self->queue), EV_READ|EV_PERSIST );
    event_set_callback( self->cmdevent, iothread_on_command, self );
    evsets_add( self->sets, self->cmdevent, 0 );

    // 启动线程
    pthread_attr_t attr;
    pthread_attr_init( &attr );
    //    assert( pthread_attr_setstacksize( &attr, THREAD_DEFAULT_STACK_SIZE ) );
    pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );

    int32_t rc = pthread_create(&(self->id), &attr, iothread_main, self);
    pthread_attr_destroy( &attr );

    if ( rc != 0 )
    {
        iothread_stop(self);
        return -3;
    }

    return 0;
}
コード例 #13
0
ファイル: test_addtimer.c プロジェクト: JoyZou/libevlite
int32_t test_evtimer()
{
    evsets_t sets = NULL;
    event_t ev_timer = NULL;

    sets = evsets_create();

    ev_timer = event_create();
    event_set( ev_timer, -1, 0 );
    event_set_callback( ev_timer, ev_timer_callback, ev_timer );

    evsets_add( sets, ev_timer, 2*1000 );

    while( 1 )
    {
        evsets_dispatch( sets );
    }

    event_destroy( ev_timer );
    evsets_destroy( sets );

    return 0;
}
コード例 #14
0
void accept_new_session( int32_t fd, int16_t ev, void * arg )
{
    struct iothread * thr = (struct iothread *)arg;
    struct acceptor * a = thr->core_acceptor;

    if ( ev & EV_READ )
    {
        //
        // 接收新连接完毕后
        //
        char srchost[20];
        char dsthost[20];
        uint16_t dstport = 0;

        int32_t newfd = tcp_accept( fd, srchost, dsthost, &dstport );
        if ( newfd > 0 )
        {
            uint64_t sid = 0;
            struct session * newsession = NULL;

            set_fd_nonblock( newfd );

            newsession = (struct session *)malloc( sizeof(struct session) );
            if ( newsession == NULL )
            {
                printf("Out of memory, allocate for 'newsession' failed .\n");
                goto ACCEPT_END;
            }

            newsession->evread = event_create();
            if ( newsession->evread == NULL )
            {
                printf("Out of memory, allocate for 'newsession->evread' failed .\n");
                goto ACCEPT_END;
            }

            newsession->iobytes = 0;
            newsession->fd = newfd;

            sid = thr->key;
            sid <<= 32;
            sid += thr->index++;
            newsession->sid = sid;

#if USE_LIBEVENT
            {
                struct timeval tv = {TIMEOUT_MSECS/1000, 0};
                event_set( newsession->evread, newsession->fd, EV_READ, echoserver_process_message, newsession );
                event_base_set( thr->core_sets, newsession->evread );
                event_add( newsession->evread, &tv );
            }
#else
            event_set( newsession->evread, newsession->fd, EV_READ );
            event_set_callback( newsession->evread, echoserver_process_message, newsession );
            evsets_add( thr->core_sets, newsession->evread, TIMEOUT_MSECS );
#endif

#if __DEBUG
            printf( "Thread[%d] accept a new Client[%lld, fd:%d, '%s':%d] .\n",
                thr->key, newsession->sid, newsession->fd, dsthost, dstport );
#endif
        }

        a->holding = 0;
        pthread_mutex_unlock( &(a->lock) );
    }

ACCEPT_END :

    return;
}
コード例 #15
0
int main( int argc, char ** argv )
{
    if ( argc != 2 )
    {
        printf("echoserver [port] .\n");
        return 0;
    }

    evsets_t coreset = evsets_create();
    if ( coreset == NULL )
    {
        printf( "create core event sets failed .\n" );
        goto FINAL;
    }

    signal( SIGPIPE, SIG_IGN );
    signal( SIGINT, echoserver_signal_handler );
    signal( SIGTERM, echoserver_signal_handler );

    // listen port
    uint16_t port = (uint16_t)atoi( argv[1] );
    int32_t fd = tcp_listen( "127.0.0.1", port, listenfd_options );
    if ( fd < 0 )
    {
        printf( "listen failed %d .\n", port );
        goto FINAL;
    }
    set_non_block( fd );
    event_t evaccept = event_create();
    if ( evaccept == NULL )
    {
        printf( "create accept event failed .\n" );
        goto FINAL;
    }
    event_set( evaccept, fd, EV_READ|EV_PERSIST );
    event_set_callback( evaccept, accept_new_session, coreset );
    evsets_add( coreset, evaccept, 0 );

    // running ...
    isrunning = 1;
    while ( isrunning == 1 )
    {
        evsets_dispatch( coreset );
    }

FINAL :
    if ( evaccept != NULL )
    {
        event_destroy( evaccept );
    }

    if ( fd > 0 )
    {
        close( fd );
    }

    if ( coreset != NULL )
    {
        evsets_destroy( coreset );
    }

    return 0;
}
コード例 #16
0
void echoserver_process_message( int32_t fd, int16_t ev, void * arg )
{
    struct session * s = (struct session *)arg;

    if ( ev & EV_READ )
    {
        char buf[16384];
        int32_t readn = -1;

        readn = read( fd, buf, 16384 );
        if ( readn <= 0 )
        {
#if __DEBUG
            printf( "Client[%ld, %d] is closed, BYTES:%d, TIME:%lld .\n",
                s->sid, s->fd, s->iobytes, milliseconds() );
#endif
            //evsets_del( event_get_sets(s->evread), s->evread );
            event_destroy( s->evread );
            close( s->fd );
            free( s );

            goto PROCESS_END;
        }
        else
        {
#if __DEBUG
            printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() );
#endif
            readn = write( fd, buf, readn );
            s->iobytes += readn;
        }

#if USE_LIBEVENT
        {
            struct timeval tv = {TIMEOUT_MSECS/1000, 0};
            event_add( s->evread, &tv );
        }
#else
        evsets_add( event_get_sets(s->evread), s->evread, TIMEOUT_MSECS );
#endif
    }
    else
    {
#if __DEBUG
        printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() );
#endif
    }

PROCESS_END :
}

void accept_new_session( int32_t fd, int16_t ev, void * arg )
{
    struct iothread * thr = (struct iothread *)arg;
    struct acceptor * a = thr->core_acceptor;

    if ( ev & EV_READ )
    {
        //
        // 接收新连接完毕后
        //
        char srchost[20];
        char dsthost[20];
        uint16_t dstport = 0;

        int32_t newfd = tcp_accept( fd, srchost, dsthost, &dstport );
        if ( newfd > 0 )
        {
            uint64_t sid = 0;
            struct session * newsession = NULL;

            set_fd_nonblock( newfd );

            newsession = (struct session *)malloc( sizeof(struct session) );
            if ( newsession == NULL )
            {
                printf("Out of memory, allocate for 'newsession' failed .\n");
                goto ACCEPT_END;
            }

            newsession->evread = event_create();
            if ( newsession->evread == NULL )
            {
                printf("Out of memory, allocate for 'newsession->evread' failed .\n");
                goto ACCEPT_END;
            }

            newsession->iobytes = 0;
            newsession->fd = newfd;

            sid = thr->key;
            sid <<= 32;
            sid += thr->index++;
            newsession->sid = sid;

#if USE_LIBEVENT
            {
                struct timeval tv = {TIMEOUT_MSECS/1000, 0};
                event_set( newsession->evread, newsession->fd, EV_READ, echoserver_process_message, newsession );
                event_base_set( thr->core_sets, newsession->evread );
                event_add( newsession->evread, &tv );
            }
#else
            event_set( newsession->evread, newsession->fd, EV_READ );
            event_set_callback( newsession->evread, echoserver_process_message, newsession );
            evsets_add( thr->core_sets, newsession->evread, TIMEOUT_MSECS );
#endif

#if __DEBUG
            printf( "Thread[%d] accept a new Client[%lld, fd:%d, '%s':%d] .\n",
                thr->key, newsession->sid, newsession->fd, dsthost, dstport );
#endif
        }

        a->holding = 0;
        pthread_mutex_unlock( &(a->lock) );
    }

ACCEPT_END :
}

void trylock_accept_mutex( struct iothread * thr )
{
    struct acceptor * a = thr->core_acceptor;

    if ( pthread_mutex_trylock(&(a->lock)) == 0 )
    {
        if ( a->holding == 0 )
        {
#if USE_LIBEVENT
            event_set( a->ev_accept, a->socketfd, EV_READ, accept_new_session, thr );
            event_base_set( thr->core_sets, a->ev_accept );
            event_add( a->ev_accept, 0 );
#else
            event_set( a->ev_accept, a->socketfd, EV_READ );
            event_set_callback( a->ev_accept, accept_new_session, thr );
            evsets_add(thr->core_sets, a->ev_accept, 0 );
#endif
            a->holding = 1;
        }

        //pthread_mutex_unlock( &(a->lock) );
    }
}

void acceptor_destroy( struct acceptor * self )
{
    pthread_mutex_destroy( &(self->lock) );

    if ( self->socketfd > 0 )
    {
        close( self->socketfd );
    }

    if ( self->ev_accept != NULL )
    {
        event_destroy( self->ev_accept );
    }

    free( self );
}

struct acceptor * acceptor_create( const char * host, uint16_t port )
{
    struct acceptor * a = NULL;

    a = (struct acceptor *)malloc( sizeof(struct acceptor) );
    if ( a )
    {
        a->holding = 0;
        a->socketfd = 0;
        a->ev_accept = NULL;
        pthread_mutex_init( &(a->lock), NULL );

        a->socketfd = tcp_listen( host, port );
        if ( a->socketfd < 0 )
        {
            acceptor_destroy( a );
            return NULL;
        }

        set_fd_nonblock( a->socketfd );

        a->ev_accept = event_create();
        if ( a->ev_accept == NULL )
        {
            acceptor_destroy( a );
            return NULL;
        }
    }

    return a;
}

void * iothread_main( void * arg )
{
    struct iothread * thr = (struct iothread *)arg;

    thr->running = 1;
    while ( thr->running )
    {
        //
        // 尝试加锁
        //
        trylock_accept_mutex( thr );

        //
        // 分发IO事件
        //
        evsets_dispatch( thr->core_sets );
    }

    return (void *)0;
}

struct iothread * iothread_create( uint8_t key, struct acceptor * a )
{
    pthread_t tid;
    struct iothread * thr = NULL;

    thr = (struct iothread *)malloc( sizeof(struct iothread) );
    if ( thr )
    {
        thr->key = key;
        thr->index = 0;
        thr->core_acceptor = a;

        thr->core_sets = evsets_create();
        if ( thr->core_sets == NULL )
        {
#if __DEBUG
            printf( "out of memory, allocate for 'thr->core_sets' failed, Thread[%d] .\n", key );
#endif
            return NULL;
        }

        pthread_create( &tid, NULL, iothread_main, thr );
    }

    return thr;
}