Simple coroutine library integrated with IO event loop (libevent) / objects in plain C Snapshot
Classes | Typedefs | Enumerations | Functions
EVSOCKET

a socket attached to user mode thread. More...

Classes

struct  tagEVSOCKET

Typedefs

typedef struct tagEVSOCKET EVSOCKET

Enumerations

enum  EVSOCKET_STATE {
  EVSOCKET_STATE_INIT, EVSOCKET_STATE_CONNECTING, EVSOCKET_STATE_CONNECTED, EVSOCKET_STATE_READING,
  EVSOCKET_STATE_WRITING, EVSOCKET_STATE_CLOSED, EVSOCKET_STATE_ERROR
}

Functions

EVSOCKETEVSOCKET_init (EVTHREAD *thread, int fd, int is_connected)
int EVSOCKET_close (EVSOCKET *socket)
int EVSOCKET_connect (EVSOCKET *socket, struct sockaddr *address, socklen_t socklen, struct timeval timeout)
void EVSOCKET_set_idle_timeout (EVSOCKET *socket, struct timeval timeout)
int EVSOCKET_recv (EVSOCKET *socket, void *buf, size_t buf_size, int flags, struct timeval timeout)
int EVSOCKET_recv_all (EVSOCKET *socket, void *buf, size_t buf_size, int flags, struct timeval timeout)
int EVSOCKET_send (EVSOCKET *socket, void *buf, size_t buf_size, int flags, struct timeval timeout)

Detailed Description

a socket attached to user mode thread.


Typedef Documentation

typedef struct tagEVSOCKET EVSOCKET

Enumeration Type Documentation

Enumerator:
EVSOCKET_STATE_INIT 
EVSOCKET_STATE_CONNECTING 
EVSOCKET_STATE_CONNECTED 
EVSOCKET_STATE_READING 
EVSOCKET_STATE_WRITING 
EVSOCKET_STATE_CLOSED 
EVSOCKET_STATE_ERROR 

Definition at line 178 of file evthread.h.


Function Documentation

int EVSOCKET_close ( EVSOCKET socket)

Definition at line 279 of file evthread.c.

{
  int rt;

  if ( socket->fd == -1) {
    return -1;
  }

  if (socket->timer_idle_timeout) {
    EVTIMER_free( socket->timer_idle_timeout );
  }
  if (socket->timer_io_timeout) {
    EVTIMER_free( socket->timer_io_timeout);  
  }

  event_del( &socket->read_event );   
  event_del( &socket->write_event );   
  
  do {
    rt = close(socket->fd);
  } while(rt == -1 && errno == EINTR);
  socket->fd = -1;

  EVTHREAD_OBJECT_free( &socket->object_base );
  return rt;
}
int EVSOCKET_connect ( EVSOCKET socket,
struct sockaddr *  address,
socklen_t  socklen,
struct timeval  timeout 
)

Definition at line 353 of file evthread.c.

{
  int rt;
  VALUES *rvalues;
  int event_id;

  if (socket->state != EVSOCKET_STATE_INIT) {
    return -1;
  }

  do {
    rt = connect( socket->fd, address, socklen );
  } while (rt == -1 && errno == EINTR);
 
  if (rt == 0) {
     MLOG_DEBUG( "socket %d connected", socket->fd ); 
     socket->state = EVSOCKET_STATE_CONNECTED;
     return 0;
  }
  if (rt == -1)  {
    if (errno == EINPROGRESS) {
     socket->state = EVSOCKET_STATE_CONNECTING;

     socket->timer_io_timeout = EVTIMER_init( socket->thread, TIMER_ID_COMM_TIMEOUT, timeout );
     if (socket->timer_io_timeout) { 
       EVTIMER_start(socket->timer_io_timeout);         
     }

     event_add( &socket->write_event, 0 );
     
     CTHREAD_yield( &rvalues, 0 );
     VALUES_scan( rvalues, "%d", &event_id );

     event_del( &socket->write_event );
     
     if (socket->timer_io_timeout) {
       EVTIMER_free( socket->timer_io_timeout ); 
       socket->timer_io_timeout = 0; 
     }

     switch(event_id) {
       case EVENT_ID_HAS_IO_EVENT:
         MLOG_DEBUG( "socket %d connected", socket->fd ); 
         socket->state = EVSOCKET_STATE_CONNECTED;
         rt = 0;
         break;
       default: 
         MLOG_DEBUG( "socket %d connect timeout", socket->fd ); 
         socket->state = EVSOCKET_STATE_ERROR;
         close( socket->fd );
         socket->fd = -1;
         rt = -1;
         break;
      }
    } else {
      MLOG_DEBUG("socket %d connect error, errno %d", socket->fd, errno );
    }
  }
  return rt;
}
EVSOCKET* EVSOCKET_init ( EVTHREAD thread,
int  fd,
int  is_connected 
)

Definition at line 242 of file evthread.c.

{
  EVSOCKET *socket;

  socket = (EVSOCKET *) malloc( sizeof( EVSOCKET ) );
  if (!socket) {
    return 0;
  }


  socket->fd = fd;
  socket->timer_idle_timeout = 0;
  socket->timer_io_timeout = 0;
  socket->state = is_connected ? EVSOCKET_STATE_CONNECTED : EVSOCKET_STATE_INIT; 
  
  socket->thread = thread;
  socket->loop = thread->loop;
  memset( &socket->idle_timeout, 0 , sizeof(struct timeval));

  
  if (fd_set_blocking( fd, 0 )) {
    free(socket);
    return  0;
  }
  
  EVTHREAD_OBJECT_init( &socket->object_base, EVTHREAD_OBJECT_SOCKET , thread );
 
  event_set( &socket->read_event, fd, EV_READ , socket_cb, (void *) socket );
  event_base_set( socket->loop->ev_base, &socket->read_event );

  event_set( &socket->write_event, fd, EV_WRITE , socket_cb, (void *) socket );
  event_base_set( socket->loop->ev_base, &socket->write_event );

  return socket;
}   
int EVSOCKET_recv ( EVSOCKET socket,
void *  buf,
size_t  buf_size,
int  flags,
struct timeval  timeout 
)

Definition at line 558 of file evthread.c.

{
  int rt;

  rt = EVSOCKET_recv_internal( socket, buf, buf_size, flags, timeout );
  if (rt >= 0) {
     if (socket->timer_idle_timeout) { 
       EVTIMER_start(socket->timer_idle_timeout);
     }
  }
  return rt;
}
int EVSOCKET_recv_all ( EVSOCKET socket,
void *  buf,
size_t  buf_size,
int  flags,
struct timeval  timeout 
)

Definition at line 571 of file evthread.c.

{
  uint8_t *cur = (uint8_t *) buf;
  int pos, rt;

  for(pos = 0 ; buf_size != 0 ; pos += rt ) {
    rt = EVSOCKET_recv_internal( socket, cur, buf_size, flags, timeout );
    if (rt <= 0) {
      return rt;
    }
    cur += rt;
    buf_size -= rt;
  }

  if (rt >= 0) {
     if (socket->timer_idle_timeout) { 
       EVTIMER_start(socket->timer_idle_timeout);
     }
  }
  
  return pos;
}
int EVSOCKET_send ( EVSOCKET socket,
void *  buf,
size_t  buf_size,
int  flags,
struct timeval  timeout 
)

Definition at line 594 of file evthread.c.

{
  uint8_t *cur = (uint8_t *) buf;
  int pos, rt;

  for(pos = 0 ; buf_size != 0 ; pos += rt ) {

    rt = EVSOCKET_send_internal( socket, cur, buf_size, flags, timeout );
    if (rt < 0) {
      return -1;
    }
    cur += rt;
    buf_size -= rt;
  } 
  return pos;
}
void EVSOCKET_set_idle_timeout ( EVSOCKET socket,
struct timeval  timeout 
)

Definition at line 339 of file evthread.c.

{ 
  M_UNUSED( socket );
  M_UNUSED( timeout );

  socket->idle_timeout = timeout;
  if (socket->state == EVSOCKET_STATE_CONNECTED) {
     socket->timer_idle_timeout = EVTIMER_init( socket->thread, TIMER_ID_IDLE_TIMEOUT, timeout );
     if (socket->timer_idle_timeout) { 
       EVTIMER_start(socket->timer_idle_timeout);       
     }
  }
}