示例#1
0
static void
flush_send_queue( int fd, void *user_data ) {
  UNUSED( fd );
  UNUSED( user_data );

  assert( send_queue != NULL );
  assert( connection.fd >= 0 );

  debug( "Flushing send queue ( length = %u ).", send_queue->length );

  set_writable( connection.fd, false );

  buffer *buf = NULL;
  while ( ( buf = peek_message( send_queue ) ) != NULL ) {
    ssize_t write_length = write( connection.fd, buf->data, buf->length );
    if ( write_length < 0 ) {
      if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) {
        set_writable( connection.fd, true );
        return;
      }
      error( "Failed to send a message to secure channel ( errno = %s [%d] ).",
             strerror( errno ), errno );
      return;
    }
    if ( ( size_t ) write_length < buf->length ) {
      remove_front_buffer( buf, ( size_t ) write_length );
      set_writable( connection.fd, true );
      return;
    }

    buf = dequeue_message( send_queue );
    free_buffer( buf );
  }
}
示例#2
0
int openssl_check_connect(struct connection *conn)
{
	int rc = mbedtls_ssl_handshake(conn->ssl);
	switch (rc) {
	case 0: /* success */
		conn->connected = 1;
		set_writable(conn);
		if (verbose)
			printf("Ciphersuite is %s\n",
				   mbedtls_ssl_get_ciphersuite(conn->ssl));
		return 0;
	case MBEDTLS_ERR_SSL_WANT_READ:
		set_readable(conn);
		return 0;
	case MBEDTLS_ERR_SSL_WANT_WRITE:
		set_writable(conn);
		return 0;
	case MBEDTLS_ERR_NET_CONN_RESET:
		reset_connection(conn);
		return 1;
	default:
		printf("Not read or write 0x%x\n", rc);
		return 1;
	}
}
示例#3
0
int
flush_secure_channel( struct switch_info *sw_info ) {
  assert( sw_info != NULL );
  assert( sw_info->send_queue != NULL );
  assert( sw_info->secure_channel_fd >= 0 );

  buffer *buf;
  ssize_t write_length;

  if ( sw_info->send_queue->length == 0 ) {
    return 0;
  }
  set_writable( sw_info->secure_channel_fd, false );
  writev_args args;
  args.iov = xmalloc( sizeof( struct iovec ) * ( size_t ) sw_info->send_queue->length );
  args.iovcnt = 0;
  foreach_message_queue( sw_info->send_queue, append_to_writev_args, &args );
  if ( args.iovcnt == 0 ) {
    xfree( args.iov );
    return 0;
  }
  write_length = writev( sw_info->secure_channel_fd, args.iov, args.iovcnt );
  xfree( args.iov );
  if ( write_length < 0 ) {
    if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) {
      set_writable( sw_info->secure_channel_fd, true );
      return 0;
    }
    error( "Failed to send a message to secure channel ( errno = %s [%d] ).",
           strerror( errno ), errno );
    return -1;
  }
  if ( write_length == 0 ) {
    return 0;
  }
  while ( ( buf = peek_message( sw_info->send_queue ) ) != NULL ) {
    if ( write_length == 0 ) {
      set_writable( sw_info->secure_channel_fd, true );
      return 0;
    }
    if ( ( size_t ) write_length < buf->length ) {
      remove_front_buffer( buf, ( size_t ) write_length );
      set_writable( sw_info->secure_channel_fd, true );
      return 0;
    }
    write_length -= ( ssize_t ) buf->length;
    buf = dequeue_message( sw_info->send_queue );
    free_buffer( buf );
  }

  return 0;
}
示例#4
0
static void
notify_http_client_actually( int fd, void *user_data ) {
  uint64_t *count = user_data;

  debug( "Notifying HTTP client from main thread ( fd = %d, count = %" PRIu64 " ).", fd, count != NULL ? *count : 0 );

  assert( fd >= 0 );
  assert( user_data != NULL );

  ssize_t ret = write( fd, count, sizeof( uint64_t ) );
  if ( ret < 0 ) {
    if ( errno == EAGAIN || errno == EINTR ) {
      return;
    }
    char buf[ 256 ];
    memset( buf, '\0', sizeof( buf ) );
    char *error_string = strerror_r( errno, buf, sizeof( buf ) - 1 );
    error( "Failed to notify an event to HTTP client ( count = %" PRIu64 ", fd = %d, ret = %zd, errno = %s [%d] ).",
           *count, fd, ret, error_string, errno );
    return;
  }
  else if ( ret != sizeof( uint64_t ) ) {
    error( "Failed to notify an event to HTTP client ( count = %" PRIu64 ", fd = %d, ret = %zd ).", *count, fd, ret );
  }

  set_writable( fd, false );
  *count = 0;

  debug( "Notification completed." );
}
示例#5
0
bool
init_http_client() {
  debug( "Initializaing HTTP client." );

  assert( http_client_thread == NULL );
  assert( http_client_efd == -1 );
  assert( main_efd == -1 );
  assert( transactions == NULL );

  http_client_efd = create_event_fd();
  assert( http_client_efd >= 0 );
  http_client_notify_count = 0;
  set_fd_handler( http_client_efd, NULL, NULL, notify_http_client_actually, &http_client_notify_count );
  set_writable( http_client_efd, false );

  main_efd = create_event_fd();
  assert( main_efd >= 0 );
  set_fd_handler( main_efd, retrieve_http_transactions_from_http_client, NULL, NULL, NULL );
  set_readable( main_efd, true );

  assert( main_to_http_client_queue == NULL );
  assert( http_client_to_main_queue == NULL );

  main_to_http_client_queue = create_queue();
  assert( main_to_http_client_queue != NULL );
  http_client_to_main_queue = create_queue();
  assert( http_client_to_main_queue != NULL );

  create_http_transaction_db();

  debug( "Initialization completed." );

  return true;
}
示例#6
0
static void
check_connected( void *user_data ) {
  UNUSED( user_data );

  debug( "Checking a connection ( fd = %d, ip = %#x, port = %u ).", connection.fd, connection.ip, connection.port );

  assert( secure_channel_initialized );
  assert( connection.fd >= 0 );

  set_writable( connection.fd, false );
  delete_fd_handler( connection.fd );

  int err = 0;
  socklen_t length = sizeof( error );
  int ret = getsockopt( connection.fd, SOL_SOCKET, SO_ERROR, &err, &length );
  if ( ret < 0 ) {
    error( "Failed to retrieve error code ( fd = %d, ret = %d, errno = %s [%d] ).",
           connection.fd, ret, strerror( errno ), errno );
    return;
  }

  switch ( err ) {
    case 0:
      connected();
      break;

    case EINTR:
    case EAGAIN:
    case ECONNREFUSED:
    case ENETUNREACH:
    case ETIMEDOUT:
      warn( "Failed to connect ( fd = %d, errno = %s [%d] ).", connection.fd, strerror( err ), err );
      backoff();
      return;

    case EINPROGRESS:
      set_fd_handler( connection.fd, NULL, NULL, ( event_fd_callback ) check_connected, NULL );
      set_writable( connection.fd, true );
      break;

    default:
      error( "Failed to connect ( fd = %d, errno = %s [%d] ).", connection.fd, strerror( err ), err );
      clear_connection();
      return;
  }
}
示例#7
0
static bool
notify_http_client() {
  debug( "Incrementing HTTP client notify count ( %" PRIu64 " ).", http_client_notify_count );

  assert( http_client_efd >= 0 );

  http_client_notify_count++;
  set_writable( http_client_efd, true );

  return true;
}
示例#8
0
static void
connected() {
  transit_state( CONNECTED );

  set_fd_handler( connection.fd, recv_from_secure_channel, NULL, flush_send_queue, NULL );
  set_readable( connection.fd, true );
  set_writable( connection.fd, false );

  if ( connection.connected_callback != NULL ) {
    connection.connected_callback();
  }
}
示例#9
0
static void
clear_connection() {
  if ( connection.fd >= 0 ) {
    close( connection.fd );
    set_readable( connection.fd, false );
    set_writable( connection.fd, false );
    delete_fd_handler( connection.fd );
  }

  connection.fd = -1;
  connection.state = INIT;
}
static int
flush_secure_channel_tls( struct switch_info *sw_info ) {
  assert( sw_info != NULL );
  assert( sw_info->tls );
  assert( sw_info->ssl != NULL );
  assert( sw_info->send_queue->length > 0 );

  buffer *buf = NULL;
  while ( ( buf = peek_message( sw_info->send_queue ) ) != NULL ) {
    int write_length = SSL_write( sw_info->ssl, buf->data, ( int ) buf->length );
    if ( write_length < 0 ) {
      int error_no = SSL_get_error( sw_info->ssl, write_length );
      switch ( error_no ) {
        case SSL_ERROR_WANT_READ:
          set_readable( sw_info->secure_channel_fd, true );
        case SSL_ERROR_WANT_WRITE:
          set_writable( sw_info->secure_channel_fd, true );
          return 0;

        default:
          error( "Failed to send a message to secure channel ( error = %d ).", error_no );
          return -1;
      }
    }
    if ( write_length == 0 ) {
      set_writable( sw_info->secure_channel_fd, true );
      return 0;
    }
    if ( ( size_t ) write_length < buf->length ) {
      remove_front_buffer( buf, ( size_t ) write_length );
      set_writable( sw_info->secure_channel_fd, true );
      return 0;
    }
    buf = dequeue_message( sw_info->send_queue );
    free_buffer( buf );
  }

  return 0;
}
int
send_to_secure_channel( struct switch_info *sw_info, buffer *buf ) {
  assert( sw_info != NULL );
  assert( buf != NULL );
  assert( buf->length > 0 );

  if ( sw_info->send_queue == NULL ) {
    return -1;
  }

  bool res = enqueue_message( sw_info->send_queue, buf );
  if ( res ) {
    set_writable( sw_info->secure_channel_fd, true );
  }
  return res ? 0 : -1;
}
示例#12
0
文件: switch.c 项目: Darma/trema
int
switch_event_disconnected( struct switch_info *sw_info ) {
  int old_state = sw_info->state;

  sw_info->state = SWITCH_STATE_DISCONNECTED;

  if ( old_state == SWITCH_STATE_COMPLETED ) {
    delete_timer_event( echo_request_interval, sw_info );
  }

  if ( sw_info->fragment_buf != NULL ) {
    free_buffer( sw_info->fragment_buf );
    sw_info->fragment_buf = NULL;
  }

  if ( sw_info->send_queue != NULL ) {
    delete_message_queue( sw_info->send_queue );
    sw_info->send_queue = NULL;
  }

  if ( sw_info->recv_queue != NULL ) {
    delete_message_queue( sw_info->recv_queue );
    sw_info->recv_queue = NULL;
  }

  if ( sw_info->secure_channel_fd >= 0 ) {
    set_readable( switch_info.secure_channel_fd, false );
    set_writable( switch_info.secure_channel_fd, false );
    delete_fd_handler( switch_info.secure_channel_fd );

    close( sw_info->secure_channel_fd );
    sw_info->secure_channel_fd = -1;
  }

  if ( old_state != SWITCH_STATE_COMPLETED ) {
    service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_FAILD_TO_CONNECT );
  }
  else {
    // send secure channle disconnect state to application
    service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_DISCONNECTED );
  }
  flush_messenger();

  stop_trema();

  return 0;
}
示例#13
0
bool
send_message_to_secure_channel( buffer *message ) {
  assert( send_queue != NULL );
  assert( message != NULL );
  assert( message->length > 0 );
  assert( connection.state == CONNECTED );
  assert( connection.fd >= 0 );

  debug( "Enqueuing a message to send queue ( queue length = %u, message length = %zu ).",
        send_queue->length, message->length );

  if ( send_queue->length == 0 ) {
    set_writable( connection.fd, true );
  }

  buffer *duplicated = duplicate_buffer( message );
  enqueue_message( send_queue, duplicated );

  return true;
}
int
flush_secure_channel( struct switch_info *sw_info ) {
  assert( sw_info != NULL );
  assert( sw_info->send_queue != NULL );
  assert( sw_info->secure_channel_fd >= 0 );

  if ( sw_info->send_queue->length == 0 ) {
    return 0;
  }

  set_writable( sw_info->secure_channel_fd, false );

  int ret = -1;
  if ( sw_info->tls ) {
    ret = flush_secure_channel_tls( sw_info );
  }
  else {
    ret = flush_secure_channel_tcp( sw_info );
  }

  return ret;
}
示例#15
0
文件: switch.c 项目: miyakz1192/trema
int
switch_event_disconnected( struct switch_info *sw_info ) {
  sw_info->state = SWITCH_STATE_DISCONNECTED;

  if ( sw_info->fragment_buf != NULL ) {
    free_buffer( sw_info->fragment_buf );
    sw_info->fragment_buf = NULL;
  }

  if ( sw_info->send_queue != NULL ) {
    delete_message_queue( sw_info->send_queue );
    sw_info->send_queue = NULL;
  }

  if ( sw_info->recv_queue != NULL ) {
    delete_message_queue( sw_info->recv_queue );
    sw_info->recv_queue = NULL;
  }

  if ( sw_info->secure_channel_fd >= 0 ) {
    set_readable( switch_info.secure_channel_fd, false );
    set_writable( switch_info.secure_channel_fd, false );
    delete_fd_handler( switch_info.secure_channel_fd );

    close( sw_info->secure_channel_fd );
    sw_info->secure_channel_fd = -1;
  }

  // send secure channle disconnect state to application
  service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_DISCONNECTED );
  flush_messenger();
  debug( "send disconnected state" );

  stop_event_handler();
  stop_messenger();

  return 0;
}
示例#16
0
bool
finalize_http_client() {
  debug( "Finalizaing HTTP client ( transactions = %p ).", transactions );

  assert( transactions != NULL );

  if ( http_client_thread != NULL ) {
    pthread_cancel( *http_client_thread );
    xfree( http_client_thread );
    http_client_thread = NULL;
  }

  if ( http_client_efd >= 0 ) {
    set_writable( http_client_efd, false );
    delete_fd_handler( http_client_efd );
    close( http_client_efd );
    http_client_efd = -1;
  }
  http_client_notify_count = 0;

  if ( main_efd >= 0 ) {
    set_readable( main_efd, false );
    delete_fd_handler( main_efd );
    close( main_efd );
    main_efd = -1;
  }

  delete_queue( main_to_http_client_queue );
  main_to_http_client_queue = NULL;
  delete_queue( http_client_to_main_queue );
  http_client_to_main_queue = NULL;

  delete_http_transaction_db();

  debug( "Finalization completed." );

  return true;
}
示例#17
0
文件: switch.c 项目: Milstein/trema
int
main( int argc, char *argv[] ) {
  int ret;
  int i;
  char *service_name;

  init_trema( &argc, &argv );
  option_parser( argc, argv );

  create_list( &switch_info.vendor_service_name_list );
  create_list( &switch_info.packetin_service_name_list );
  create_list( &switch_info.portstatus_service_name_list );
  create_list( &switch_info.state_service_name_list );

  for ( i = optind; i < argc; i++ ) {
    if ( strncmp( argv[ i ], VENDOR_PREFIX, strlen( VENDOR_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[ i ] + strlen( VENDOR_PREFIX ) );
      append_to_tail( &switch_info.vendor_service_name_list, service_name );
    }
    else if ( strncmp( argv[ i ], PACKET_IN_PREFIX, strlen( PACKET_IN_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[ i ] + strlen( PACKET_IN_PREFIX ) );
      append_to_tail( &switch_info.packetin_service_name_list, service_name );
    }
    else if ( strncmp( argv[ i ], PORTSTATUS_PREFIX, strlen( PORTSTATUS_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[ i ] + strlen( PORTSTATUS_PREFIX ) );
      append_to_tail( &switch_info.portstatus_service_name_list, service_name );
    }
    else if ( strncmp( argv[ i ], STATE_PREFIX, strlen( STATE_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[ i ] + strlen( STATE_PREFIX ) );
      append_to_tail( &switch_info.state_service_name_list, service_name );
    }
  }

  struct sigaction signal_exit;
  memset( &signal_exit, 0, sizeof( struct sigaction ) );
  signal_exit.sa_handler = handle_sigterm;
  sigaction( SIGINT, &signal_exit, NULL );
  sigaction( SIGTERM, &signal_exit, NULL );

  fcntl( switch_info.secure_channel_fd, F_SETFL, O_NONBLOCK );

  set_fd_handler( switch_info.secure_channel_fd, secure_channel_read, NULL, secure_channel_write, NULL );
  set_readable( switch_info.secure_channel_fd, true );
  set_writable( switch_info.secure_channel_fd, false );

  // default switch configuration
  switch_info.config_flags = OFPC_FRAG_NORMAL;
  switch_info.miss_send_len = UINT16_MAX;

  switch_info.fragment_buf = NULL;
  switch_info.send_queue = create_message_queue();
  switch_info.recv_queue = create_message_queue();
  switch_info.running_timer = false;
  switch_info.echo_request_xid = 0;

  init_xid_table();
  if ( switch_info.cookie_translation ) {
    init_cookie_table();
  }

  add_message_received_callback( get_trema_name(), service_recv );
  set_management_application_request_handler( management_recv, NULL );

  ret = switch_event_connected( &switch_info );
  if ( ret < 0 ) {
    error( "Failed to set connected state." );
    return -1;
  }
  ret = flush_secure_channel( &switch_info );
  if ( ret < 0 ) {
    error( "Failed to flush secure channel. Terminating %s.", argv[ 0 ] );
    return -1;
  }

  start_trema();

  // Note: init_event_forward_interface will be called on feature_reply.
  finalize_event_forward_interface();

  finalize_xid_table();
  if ( switch_info.cookie_translation ) {
    finalize_cookie_table();
  }

  if ( switch_info.secure_channel_fd >= 0 ) {
    delete_fd_handler( switch_info.secure_channel_fd );
  }

  return 0;
}
示例#18
0
static bool
try_connect() {
  assert( connection.state != CONNECTED );

  int fd = socket( PF_INET, SOCK_STREAM, 0 );
  if ( fd < 0 ) {
    error( "Failed to create a socket ( ret = %d, errno = %s [%d] ).",
           fd, strerror( errno ), errno );
    return false;
  }

  int flag = 1;
  int ret = setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof( flag ) );
  if ( ret < 0 ) {
    error( "Failed to set socket options ( fd = %d, ret = %d, errno = %s [%d] ).",
           fd, ret, strerror( errno ), errno );
    return false;
  }

  ret = fcntl( fd, F_SETFL, O_NONBLOCK );
  if ( ret < 0 ) {
    error( "Failed to enable non-blocking mode ( fd = %d, ret = %d, errno = %s [%d] ).",
           fd, ret, strerror( errno ), errno );

    close( fd );
    return false;
  }

  connection.fd = fd;

  struct sockaddr_in addr;
  memset( &addr, 0, sizeof( struct sockaddr_in ) );
  addr.sin_family = AF_INET;
  addr.sin_port = htons( connection.port );
  addr.sin_addr.s_addr = htonl( connection.ip );

  transit_state( CONNECTING );

  ret = connect( connection.fd, ( struct sockaddr * ) &addr, sizeof( struct sockaddr_in ) );
  if ( ret < 0 ) {
    switch ( errno ) {
      case EINTR:
      case EAGAIN:
      case ECONNREFUSED:
      case ENETUNREACH:
      case ETIMEDOUT:
        warn( "Failed to connect ( fd = %d, ret = %d, errno = %s [%d] ).",
              connection.fd, ret, strerror( errno ), errno );
        backoff();
        return true;

      case EINPROGRESS:
        break;

      default:
        error( "Failed to connect ( fd = %d, ret = %d, errno = %s [%d] ).",
               connection.fd, ret, strerror( errno ), errno );
        clear_connection();
        return false;
    }
  }

  set_fd_handler( connection.fd, NULL, NULL, ( event_fd_callback ) check_connected, NULL );
  set_writable( connection.fd, true );

  return true;
}
示例#19
0
文件: switch.c 项目: miyakz1192/trema
int
main( int argc, char *argv[] ) {
  int ret;
  int i;
  char *service_name;
  char management_service_name[ MESSENGER_SERVICE_NAME_LENGTH ];

  init_trema( &argc, &argv );
  option_parser( argc, argv );

  create_list( &switch_info.vendor_service_name_list );
  create_list( &switch_info.packetin_service_name_list );
  create_list( &switch_info.portstatus_service_name_list );
  create_list( &switch_info.state_service_name_list );

  // FIXME
#define VENDER_PREFIX "vendor::"
#define PACKET_IN_PREFIX "packet_in::"
#define PORTSTATUS_PREFIX "port_status::"
#define STATE_PREFIX "state_notify::"
  for ( i = optind; i < argc; i++ ) {
    if ( strncmp( argv[i], VENDER_PREFIX, strlen( VENDER_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[i] + strlen( VENDER_PREFIX ) );
      insert_in_front( &switch_info.vendor_service_name_list, service_name );
    }
    else if ( strncmp( argv[i], PACKET_IN_PREFIX, strlen( PACKET_IN_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[i] + strlen( PACKET_IN_PREFIX ) );
      insert_in_front( &switch_info.packetin_service_name_list, service_name );
    }
    else if ( strncmp( argv[i], PORTSTATUS_PREFIX, strlen( PORTSTATUS_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[i] + strlen( PORTSTATUS_PREFIX ) );
      insert_in_front( &switch_info.portstatus_service_name_list, service_name );
    }
    else if ( strncmp( argv[i], STATE_PREFIX, strlen( STATE_PREFIX ) ) == 0 ) {
      service_name = xstrdup( argv[i] + strlen( STATE_PREFIX ) );
      insert_in_front( &switch_info.state_service_name_list, service_name );
    }
  }

  fcntl( switch_info.secure_channel_fd, F_SETFL, O_NONBLOCK );

  set_fd_handler( switch_info.secure_channel_fd, secure_channel_read, NULL, secure_channel_write, NULL );
  set_readable( switch_info.secure_channel_fd, true );
  set_writable( switch_info.secure_channel_fd, false );

  // default switch configuration
  switch_info.config_flags = OFPC_FRAG_NORMAL;
  switch_info.miss_send_len = UINT16_MAX;

  switch_info.fragment_buf = NULL;
  switch_info.send_queue = create_message_queue();
  switch_info.recv_queue = create_message_queue();
  switch_info.running_timer = false;

  init_xid_table();
  init_cookie_table();

  add_message_received_callback( get_trema_name(), service_recv );

  snprintf( management_service_name , MESSENGER_SERVICE_NAME_LENGTH,
            "%s.m", get_trema_name() );
  management_service_name[ MESSENGER_SERVICE_NAME_LENGTH - 1 ] = '\0';
  add_message_received_callback( management_service_name, management_recv );

  ret = switch_event_connected( &switch_info );
  if ( ret < 0 ) {
    error( "Failed to set connected state." );
    return -1;
  }
  flush_secure_channel( &switch_info );

  start_trema();

  finalize_xid_table();
  finalize_cookie_table();

  if ( switch_info.secure_channel_fd >= 0 ) {
    delete_fd_handler( switch_info.secure_channel_fd );
  }

  return 0;
}
示例#20
0
文件: switch.c 项目: Milstein/trema
int
switch_event_disconnected( struct switch_info *sw_info ) {
  int old_state = sw_info->state;

  if ( sw_info->state == SWITCH_STATE_DISCONNECTED ||
       sw_info->state == SWITCH_STATE_CONNECTION_FAILED ) {
    debug( "already disconnected" );
    return -1;
  }

  if ( sw_info->state == SWITCH_STATE_COMPLETED ) {
    sw_info->state = SWITCH_STATE_DISCONNECTED;
  }
  else {
    sw_info->state = SWITCH_STATE_CONNECTION_FAILED;
  }

  if ( old_state == SWITCH_STATE_COMPLETED ) {
    switch_unset_timeout( echo_reply_timeout, NULL );
  }

  if ( sw_info->fragment_buf != NULL ) {
    free_buffer( sw_info->fragment_buf );
    sw_info->fragment_buf = NULL;
  }

  if ( sw_info->send_queue != NULL ) {
    delete_message_queue( sw_info->send_queue );
    sw_info->send_queue = NULL;
  }

  if ( sw_info->recv_queue != NULL ) {
    delete_message_queue( sw_info->recv_queue );
    sw_info->recv_queue = NULL;
  }

  if ( sw_info->secure_channel_fd >= 0 ) {
    set_readable( switch_info.secure_channel_fd, false );
    set_writable( switch_info.secure_channel_fd, false );
    delete_fd_handler( switch_info.secure_channel_fd );
  }

  uint8_t state = MESSENGER_OPENFLOW_DISCONNECTED;
  if ( sw_info->state == SWITCH_STATE_CONNECTION_FAILED ) {
    state = MESSENGER_OPENFLOW_FAILD_TO_CONNECT;
  }

  debug( "Notify switch_disconnected to switch manager." );
  char switch_manager[] =  SWITCH_MANAGER;
  list_element switch_manager_only_list;
  switch_manager_only_list.next = NULL;
  switch_manager_only_list.data = switch_manager;
  service_send_to_application( &switch_manager_only_list, state, &sw_info->datapath_id, NULL );

  // Check switch_manager registration
  debug( "Checking switch manager's switch list." );
  sw_info->retry_count = UNREGISTRATION_RETRY_COUNT;
  set_list_switches_reply_handler( confirm_self_dpid_is_unregistered );
  if ( send_list_switches_request( sw_info ) ) {
    switch_set_timeout( UNREGISTRATION_TIMEOUT, unregistration_timeout, sw_info );
  }
  else {
    error( "Failed to send switch list request to switch manager." );
    stop_switch();
  }

  return 0;
}