⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldp_state_machine.c

📁 Linux平台下
💻 C
字号:
/* *  Copyright (C) James R. Leu 2000 *  jleu@mindspring.com * *  This software is covered under the LGPL, for more *  info check out http://www.gnu.org/copyleft/lgpl.html */#include "ldp_struct.h"#include "ldp_global.h"#include "ldp_session.h"#include "ldp_entity.h"#include "ldp_peer.h"#include "ldp_if.h"#include "ldp_adj.h"#include "ldp_mesg.h"#include "ldp_buf.h"#include "ldp_state_machine.h"#include "mpls_assert.h"#include "mpls_socket_impl.h"#include "mpls_lock_impl.h"#include "mpls_trace_impl.h"/*                  HELLO CONNECT   INIT      KEEP   ADDR    LABEL   NOTIF   CLOSE  HTIMER KTIMER *//* SES_NONE         new   ignore    ignore    ignore ignore  ignore  ignore  close  ignore ignore *//* SES_NON_EXISTENT maint connect   close     close  close   close   close   close  close  ignore *//* SES_INITIALIZED  maint close     recv_init close  close   close   notif   close  close  ignore *//* SES_OPENSENT     maint close     recv_init close  close   close   notif   close  close  ignore *//* SES_OPENREC      maint close     close     finish close   close   notif   close  close  close  *//* SES_OPERATIONAL  maint close     kmaint    kmaint process process notif   close  close  close  */int ldp_state_table[LDP_STATE_NUM][LDP_EVENT_NUM] = {  {0, 6, 6, 6, 6, 6, 6, 7, 6, 6},  {1, 3, 7, 7, 7, 7, 7, 7, 7, 6},  {1, 7, 2, 7, 7, 7, 9, 7, 7, 6},  {1, 7, 2, 7, 7, 7, 9, 7, 7, 6},  {1, 7, 7, 4, 7, 7, 9, 7, 7, 7},  {1, 7, 8, 8, 5, 5, 9, 7, 7, 7}};mpls_return_enum ldp_buf_process(ldp_global * g, mpls_socket_handle socket,  ldp_buf * buf, void *extra, ldp_event_enum event, mpls_dest * from,  mpls_bool * more);mpls_return_enum(*ldp_state_func[LDP_FUNC_NUM]) (ldp_global *, ldp_session *,  ldp_adj *, ldp_entity *, uint32_t, ldp_mesg *, mpls_dest *) = {  ldp_state_new_adjacency,		/* 0 */  ldp_state_maintainance,		/* 1 */  ldp_state_recv_init,			/* 2 */  ldp_state_connect,			/* 3 */  ldp_state_finish_init,		/* 4 */  ldp_state_process,			/* 5 */  ldp_state_ignore,			/* 6 */  ldp_state_close,			/* 7 */  ldp_state_keepalive_maintainance,	/* 8 */  ldp_state_notif			/* 9 */};#define LDP_FUNC_CLOSE 7mpls_return_enum ldp_event(mpls_cfg_handle handle, mpls_socket_handle socket,  void *extra, ldp_event_enum event){  mpls_return_enum retval = MPLS_SUCCESS;  ldp_global *g = (ldp_global*)handle;  mpls_socket_handle socket_new = (mpls_socket_handle)0;  ldp_session *session = NULL;  ldp_entity *entity = NULL;  ldp_adj *adj = NULL;  uint8_t buffer[MPLS_PDUMAXLEN];  mpls_dest from;  ldp_mesg mesg;  ldp_buf buf;  LDP_ENTER(g->user_data, "ldp_event");  mpls_lock_get(g->global_lock);  switch (event) {    case LDP_EVENT_TCP_DATA:    case LDP_EVENT_UDP_DATA:    {      mpls_bool more;      buf.current = buffer;      buf.buffer = buffer;      buf.total = MPLS_PDUMAXLEN;      buf.size = 0;      buf.current_size = 0;      buf.want = 0;      /* do this so a failure will know which session caused it */      if (event == LDP_EVENT_TCP_DATA) {        session = extra;      }      do {        retval = ldp_buf_process(g, socket, &buf, extra, event, &from, &more);      } while (retval == MPLS_SUCCESS && more == MPLS_BOOL_TRUE);      break;    }    case LDP_EVENT_TCP_LISTEN:    {      socket_new = mpls_socket_tcp_accept(g->socket_handle, socket, &from);      if (mpls_socket_handle_verify(g->socket_handle, socket_new) ==        MPLS_BOOL_FALSE) {        LDP_PRINT(g->user_data, "Failed accepting socket\n");        retval = MPLS_FAILURE;      } else if (!(session = ldp_session_create_passive(g, socket_new,        &from))) {        mpls_socket_close(g->socket_handle, socket_new);        LDP_PRINT(g->user_data, "Failure creating passive session\n");        retval = MPLS_FATAL;      } else {        retval = ldp_state_machine(g, session, NULL, NULL,          LDP_EVENT_CONNECT, &mesg, &from);      }      break;    }    case LDP_EVENT_TCP_CONNECT:    {      retval = mpls_socket_connect_status(g->socket_handle, socket);      session = (ldp_session *)extra;      if (retval == MPLS_SUCCESS) {        /* only get this case if we did a non-block connect */        mpls_socket_writelist_del(g->socket_handle, socket);        retval = ldp_state_machine(g, session, NULL, NULL,          LDP_EVENT_CONNECT, &mesg, &from);      } else if (retval != MPLS_NON_BLOCKING) {        LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,          "ldp_event: LDP_EVENT_TCP_CONNECT errno = %d\n",          mpls_socket_get_errno(g->socket_handle, socket));      } else {	/* non-blocking connect is still blocking, we'll try again in a bit */	retval = MPLS_SUCCESS;      }      break;    }    case LDP_EVENT_CLOSE:    {      retval = ldp_state_machine(g, session, adj, entity,        LDP_EVENT_CLOSE, &mesg, &from);      break;    }    default:    {      MPLS_ASSERT(0);    }  }  /* ldp_state_machine return MPLS_SUCCESS when it has handled the event     to completion. If the handling off the event results in the session     needing to be shutdown MPLS_FAILURE is returned.  If the handling of     the event requires the LDP be shutdown LD_FATAL is returned, and     passed back to the user.  other values are invalid */  switch (retval) {    case MPLS_FAILURE:    {      /* if shutting down the session results in LDP_FATAL, then pass it       * back to the user */      LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,        "ldp_event: FAILURE executing a CLOSE\n");      retval = ldp_state_machine(g, session, adj, entity, LDP_EVENT_CLOSE,        NULL, &from);      if (retval == MPLS_FATAL) {        LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,          "ldp_event: CLOSE failed: FATAL propogated to the environemnt\n");      }      break;    }    case MPLS_FATAL:    {      LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,        "ldp_event: FATAL propogated to the environemnt\n");      break;    }    case MPLS_SUCCESS:    {      break;    }    default:    {      LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,        "ldp_event: invalid return value of %d\n", retval);      break;    }  }  mpls_lock_release(g->global_lock);  LDP_EXIT(g->user_data, "ldp_event");  return retval;}mpls_return_enum ldp_state_machine(ldp_global * g, ldp_session * session,  ldp_adj * adj, ldp_entity * entity, uint32_t event, ldp_mesg * msg,  mpls_dest * from){  int state = LDP_STATE_NONE;  int func = 0;  mpls_return_enum retval = MPLS_FAILURE;  LDP_ENTER(g->user_data, "ldp_state_machine");  if (session) {    state = session->state;  } else if (adj) {    state = LDP_STATE_NON_EXIST;  }  if (state >= LDP_STATE_NONE && state <= LDP_STATE_OPERATIONAL) {    if (event <= LDP_EVENT_KTIMER) {      LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_STATE,        "FSM: state %d, event %d\n", state, event);      func = ldp_state_table[state][event];      retval = ldp_state_func[func] (g, session, adj, entity, event, msg, from);    }  }  LDP_EXIT(g->user_data, "ldp_state_machine");  return retval;}mpls_return_enum ldp_buf_process(ldp_global * g, mpls_socket_handle socket,  ldp_buf * buf, void *extra, ldp_event_enum event, mpls_dest * from,  mpls_bool * more){  mpls_return_enum retval = MPLS_SUCCESS;  ldp_session *session = NULL;  ldp_entity *entity = NULL;  ldp_adj *adj = NULL;  ldp_mesg mesg;  int size = 0;  LDP_ENTER(g->user_data, "ldp_buf_process");  *more = MPLS_BOOL_TRUE;  memset(&mesg, 0, sizeof(mesg));  if (!buf->want) {    buf->want = MPLS_LDP_HDRSIZE;  }read_again:  switch (event) {    case LDP_EVENT_TCP_DATA:    {      session = (ldp_session *) extra;      MPLS_ASSERT(session);      session->mesg_rx++;      size = mpls_socket_tcp_read(g->socket_handle, socket,        buf->buffer + buf->size, buf->want - buf->size);      if (!size) {        LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,        LDP_TRACE_FLAG_ERROR, "ldp_event: LDP_EVENT_TCP_DATA errno = %d\n",          mpls_socket_get_errno(g->socket_handle, socket));        retval = MPLS_FAILURE;        session->shutdown_notif = LDP_NOTIF_SHUTDOWN;        session->shutdown_fatal = MPLS_BOOL_TRUE;        goto ldp_event_end;      }       if (size < 0) {        retval = MPLS_SUCCESS;        *more = MPLS_BOOL_FALSE;        goto ldp_event_end;      }      break;    }    case LDP_EVENT_UDP_DATA:    {      size = mpls_socket_udp_recvfrom(g->socket_handle, socket,        buf->buffer + buf->size, buf->total - buf->size, from);      if (!size) {        LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,          LDP_TRACE_FLAG_ERROR, "ldp_event: LDP_EVENT_UDP_DATA errno = %d\n",        mpls_socket_get_errno(g->socket_handle, socket));        retval = MPLS_FAILURE;        goto ldp_event_end;      }      if (size < 0) {        retval = MPLS_SUCCESS;        *more = MPLS_BOOL_FALSE;        goto ldp_event_end;      }      break;    }    default:    {      MPLS_ASSERT(0);      break;    }  }  buf->current_size += size;  buf->size += size;decode_again:  if (buf->size < buf->want) {    retval = MPLS_SUCCESS;    *more = MPLS_BOOL_FALSE;    goto ldp_event_end;  }  /* upon succesful decode the pduLength will be non 0 */  if (!mesg.header.pduLength) {    if (ldp_decode_header(g, buf, &mesg) != MPLS_SUCCESS) {      retval = MPLS_FAILURE;      if (session) {        session->shutdown_notif = LDP_NOTIF_BAD_MESG_LEN;      }      goto ldp_event_end;    }    /* -buf->size is already 10 (the size of the full header     * -pduLength include 6 bytes of the header     *     * therefore add 4 so we can compare buf->want to buf->size and     * not have to adjust     */    buf->want = mesg.header.pduLength + 4;    if (buf->size < buf->want) {      goto read_again;    }    if (buf->size > buf->want) {      buf->current_size = buf->want - MPLS_LDP_HDRSIZE;    }  }  do {    if (ldp_decode_one_mesg(g, buf, &mesg) != MPLS_SUCCESS) {      retval = MPLS_FAILURE;      if (session) {        session->shutdown_notif = LDP_NOTIF_BAD_MESG_LEN;      }      goto ldp_event_end_loop;    }    switch (ldp_mesg_get_type(&mesg)) {      case MPLS_HELLO_MSGTYPE:      {        mpls_oper_state_enum oper_state = MPLS_OPER_DOWN;        mpls_inet_addr addr;        int labelspace = 0;        int targeted;        event = LDP_EVENT_HELLO;        targeted = 0;        ldp_mesg_hello_get_targeted(&mesg, &targeted);        ldp_mesg_hdr_get_lsraddr(&mesg, &addr);        ldp_mesg_hdr_get_labelspace(&mesg, &labelspace);        if (targeted) {          ldp_peer *peer = NULL;          if ((peer = ldp_global_find_peer_addr(g, &addr))) {            entity = ldp_peer_get_entity(peer);            oper_state = peer->oper_state;          }        } else {          ldp_if *iff = NULL;          if ((iff = ldp_global_find_if_handle(g, from->if_handle))) {            entity = ldp_if_get_entity(iff);            oper_state = iff->oper_state;          }        }        if (!entity) {          /* No entity! No choice but to ignore this packet */          LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,            LDP_TRACE_FLAG_NORMAL, "ldp_event: unknown entity\n");          goto ldp_event_end_loop;        } else if (entity->admin_state == MPLS_ADMIN_DISABLE) {          LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,            LDP_TRACE_FLAG_NORMAL, "ldp_event: entity is disabled\n");          goto ldp_event_end_loop;        } else if (oper_state == MPLS_OPER_DOWN) {          LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,            LDP_TRACE_FLAG_NORMAL, "ldp_event: entity is down\n");          goto ldp_event_end_loop;        }        	if ((adj = ldp_entity_find_adj(entity, &mesg))) {	  session = adj->session;	} else {	  session = NULL;	}        /* if we don't have an adj one will be create by state machine */        break;      }      case MPLS_INIT_MSGTYPE:      {        event = LDP_EVENT_INIT;        break;      }      case MPLS_NOT_MSGTYPE:      {        event = LDP_EVENT_NOTIF;        break;      }      case MPLS_KEEPAL_MSGTYPE:      {        event = LDP_EVENT_KEEP;        break;      }      case MPLS_LBLWITH_MSGTYPE:      case MPLS_LBLREL_MSGTYPE:      case MPLS_LBLREQ_MSGTYPE:      case MPLS_LBLMAP_MSGTYPE:      case MPLS_LBLABORT_MSGTYPE:      {        event = LDP_EVENT_LABEL;        break;      }      case MPLS_ADDR_MSGTYPE:      case MPLS_ADDRWITH_MSGTYPE:      {        event = LDP_EVENT_ADDR;        break;      }      default:      {        MPLS_ASSERT(0);      }    }    retval =      ldp_state_machine(g, session, adj, entity, event, &mesg, from);ldp_event_end_loop:    if (retval != MPLS_SUCCESS) {      break;    }  } while ((buf->current_size > 0) && (*more == MPLS_BOOL_TRUE));  if (buf->want < buf->size) {    buf->current_size = buf->size - buf->want;    buf->size = buf->current_size;    memmove(buf->buffer, buf->current, buf->current_size);  } else {    buf->size = 0;  }  buf->current = buf->buffer;  memset(&mesg, 0, sizeof(mesg));  buf->want = MPLS_LDP_HDRSIZE;  if (buf->current_size) {    goto decode_again;  }ldp_event_end:  LDP_EXIT(g->user_data, "ldp_buf_process");  return retval;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -