Пример #1
0
/**
 * Bind an iSCSI connection to an iSCSI session.
 * (If an iSCSI session is not exist, create an iSCSI session)
 */
int iscsi_bind_connection(
    const char *target_name,
    union iscsi_sid sid,
    struct iscsi_conn *conn)
{
    struct iscsi_target *target = NULL;
    struct iscsi_session *session = NULL;
    int rv = 0;

    ASSERT((conn != NULL), "conn == NULL\n");
    ASSERT((conn->siso != NULL), "conn->siso == NULL\n");
    ASSERT((conn->session == NULL), "conn->session != NULL\n");
    ASSERT((conn->target == NULL), "conn->target != NULL\n");

    log_dbg1("target_name=%s\n", target_name);
    target = siso_lookup_target(conn->siso, target_name);
    if (target == NULL) {
	return -ENOENT;
    }
    conn->target = target;
    
    LOCK_SESSIONS(target);
    {
	session = lookup_session(target, conn->sid);

	if (conn->sid.id.tsih[0] == 0x00 || conn->sid.id.tsih[1] == 0x00) {
	    // Create session and attach connection to the session.
	    ASSERT((session == NULL), "session != NULL\n");
	    log_dbg1("create iscsi session\n");
	    session = iscsi_create_session(target, sid, conn);
	    if (session == NULL) {
		rv = -ENOMEM;
		goto done;
	    }
	    log_dbg1("conn->session=%p\n", conn->session);
	    // Enlink this iSCSI session to iSCSI session list.
	    list_add_elem(&(target->list_session), &(session->listelem));
	} else {
	    // Current implementation doesn't support multi-connection.
	    log_err("Current implementation doesn't support multi-connection.\n");
	    rv = -EINVAL;
	}
    }
done:
    UNLOCK_SESSIONS(target);

    if (!rv) {
	// detach iSCSI connection from tempolary list.
	siso_detach_connection(conn->siso, conn);
    }

    return rv;
} // iscsi_bind_connection
/**
 * Creates a new outbound session the transport service will use to send data to the
 * peer
 *
 * @param cls the plugin
 * @param address the address
 * @return the session or NULL of max connections exceeded
 */
static struct Session *
http_get_session (void *cls,
                  const struct GNUNET_HELLO_Address *address)
{
  struct Plugin *plugin = cls;
  struct Session * s = NULL;
  struct GNUNET_ATS_Information ats;
  size_t addrlen;

  GNUNET_assert (plugin != NULL);
  GNUNET_assert (address != NULL);
  GNUNET_assert (address->address != NULL);

  ats.type = htonl (GNUNET_ATS_ARRAY_TERMINATOR);
  ats.value = htonl (GNUNET_ATS_ARRAY_TERMINATOR);

  /* find existing session */
  s = lookup_session (plugin, address);
  if (s != NULL)
    return s;

  if (plugin->max_connections <= plugin->cur_connections)
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
                     "Maximum number of connections reached, "
                     "cannot connect to peer `%s'\n", GNUNET_i2s (&address->peer));
    return NULL;
  }

  /* create new session */
  addrlen = address->address_length;

  GNUNET_assert ((addrlen == sizeof (struct IPv6HttpAddress)) ||
                 (addrlen == sizeof (struct IPv4HttpAddress)));

  s = create_session (plugin, &address->peer, address->address, address->address_length);

  /* Get ATS type */
  if (addrlen == sizeof (struct IPv4HttpAddress))
  {
    struct IPv4HttpAddress *a4 = (struct IPv4HttpAddress *) address->address;
    struct sockaddr_in s4;

    s4.sin_family = AF_INET;
    s4.sin_addr.s_addr = a4->ipv4_addr;
    s4.sin_port = a4->u4_port;
#if HAVE_SOCKADDR_IN_SIN_LEN
    s4.sin_len = sizeof (struct sockaddr_in);
#endif
    ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &s4, sizeof (struct sockaddr_in));
  }
  if (addrlen == sizeof (struct IPv6HttpAddress))
  {
    struct IPv6HttpAddress *a6 = (struct IPv6HttpAddress *) address->address;
    struct sockaddr_in6 s6;

    s6.sin6_family = AF_INET6;
    s6.sin6_addr = a6->ipv6_addr;
    s6.sin6_port = a6->u6_port;
#if HAVE_SOCKADDR_IN_SIN_LEN
    s6.sin6_len = sizeof (struct sockaddr_in6);
#endif
    ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &s6, sizeof (struct sockaddr_in6));
  }
  s->ats_address_network_type = ats.value;

  /* add new session */
  GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s);
  /* initiate new connection */
  if (GNUNET_SYSERR == client_connect (s))
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
                     "Cannot connect to peer `%s' address `%s''\n",
                     http_plugin_address_to_string(NULL, s->addr, s->addrlen),
                     GNUNET_i2s (&s->target));
    GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s);
    delete_session (s);
    return NULL;
  }

  return s;
}