コード例 #1
0
ファイル: net.c プロジェクト: kiwanami/mongo-c-driver
static int mongo_set_blocking_status( mongo *conn ) {
    int flags;
    int blocking;

    blocking = ( conn->conn_timeout_ms == 0 );
    if( blocking )
        return MONGO_OK;
    else {
        if( ( flags = fcntl( conn->sock, F_GETFL ) ) == -1 ) {
            conn->err = MONGO_IO_ERROR;
            mongo_close_socket( conn->sock );
            return MONGO_ERROR;
        }

        flags |= O_NONBLOCK;

        if( ( flags = fcntl( conn->sock, F_SETFL, flags ) ) == -1 ) {
            conn->err = MONGO_IO_ERROR;
            mongo_close_socket( conn->sock );
            return MONGO_ERROR;
        }
    }

    return MONGO_OK;
}
コード例 #2
0
ファイル: mongo.c プロジェクト: chitr/mongo-c-driver
/* Find out whether the current connected node is master, and
 * verify that the node's replica set name matched the provided name
 */
static int mongo_replset_check_host( mongo *conn ) {

    bson out;
    bson_iterator it;
    bson_bool_t ismaster = 0;
    const char *set_name;

    out.data = NULL;

    if ( mongo_simple_int_command( conn, "admin", "ismaster", 1, &out ) == MONGO_OK ) {
        if( bson_find( &it, &out, "ismaster" ) )
            ismaster = bson_iterator_bool( &it );

        if( bson_find( &it, &out, "setName" ) ) {
            set_name = bson_iterator_string( &it );
            if( strcmp( set_name, conn->replset->name ) != 0 ) {
                bson_destroy( &out );
                conn->err = MONGO_CONN_BAD_SET_NAME;
                return MONGO_ERROR;
            }
        }
    }

    bson_destroy( &out );

    if( ismaster ) {
        conn->replset->primary_connected = 1;
    } else {
        mongo_close_socket( conn->sock );
    }

    return MONGO_OK;
}
コード例 #3
0
int mongo_replset_connect(mongo_connection* conn) {

    int res = 0;
    mongo_host_port* node;

    conn->sock = 0;
    conn->connected = 0;

    /* First iterate over the seed nodes to get the canonical list of hosts
     * from the replica set. Break out once we have a host list.
     */
    node = conn->replset->seeds;
    while( node != NULL ) {
        res = mongo_socket_connect( conn, (const char*)&node->host, node->port );
        if( res != MONGO_OK )
            return MONGO_ERROR;

        mongo_replset_check_seed( conn );

        if( conn->replset->hosts )
            break;

        node = node->next;
    }

    /* Iterate over the host list, checking for the primary node. */
    if( !conn->replset->hosts ) {
        conn->err = MONGO_CONN_CANNOT_FIND_PRIMARY;
        return MONGO_ERROR;
    }
    else {
        node = conn->replset->hosts;

        while( node != NULL ) {
            res = mongo_socket_connect( conn, (const char*)&node->host, node->port );

            if( res == MONGO_OK ) {
                if( mongo_replset_check_host( conn ) != MONGO_OK )
                    return MONGO_ERROR;

                /* Primary found, so return. */
                else if( conn->replset->primary_connected )
                     return MONGO_OK;

                /* No primary, so close the connection. */
                else {
                    mongo_close_socket( conn->sock );
                    conn->sock = 0;
                    conn->connected = 0;
                }
            }

            node = node->next;
        }
    }


    conn->err = MONGO_CONN_CANNOT_FIND_PRIMARY;
    return MONGO_ERROR;
}
コード例 #4
0
ファイル: net.c プロジェクト: kiwanami/mongo-c-driver
int mongo_socket_connect( mongo *conn, const char *host, int port ) {
    struct sockaddr_in sa;
    socklen_t addressSize;
    int flag = 1;

    if( mongo_create_socket( conn ) != MONGO_OK )
        return MONGO_ERROR;

    memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) );
    sa.sin_family = AF_INET;
    sa.sin_port = htons( port );
    sa.sin_addr.s_addr = inet_addr( host );
    addressSize = sizeof( sa );

    if ( connect( conn->sock, ( struct sockaddr * )&sa, addressSize ) == -1 ) {
        mongo_close_socket( conn->sock );
        conn->connected = 0;
        conn->sock = 0;
        conn->err = MONGO_CONN_FAIL;
        return MONGO_ERROR;
    }

    setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * ) &flag, sizeof( flag ) );

    if( conn->op_timeout_ms > 0 )
        mongo_set_socket_op_timeout( conn, conn->op_timeout_ms );

    conn->connected = 1;

    return MONGO_OK;
}
コード例 #5
0
ファイル: mongo.c プロジェクト: alex-python/restpose
/* Find out whether the current connected node is master, and
 * verify that the node's replica set name matched the provided name
 */
static int mongo_replset_check_host( mongo_connection* conn ) {

    bson out;
    bson_iterator it;
    bson_bool_t ismaster = 0;
    const char* set_name;

    out.data = NULL;
    out.owned = 1;

    if (mongo_simple_int_command(conn, "admin", "ismaster", 1, &out)) {
        if( bson_find(&it, &out, "ismaster") )
            ismaster = bson_iterator_bool( &it );

        if( bson_find( &it, &out, "setName" ) ) {
            set_name = bson_iterator_string( &it );
            if( strcmp( set_name, conn->replset->name ) != 0 ) {
                return mongo_conn_bad_set_name;
            }
        }
    }
    bson_destroy( &out );

    if(ismaster) {
        conn->replset->primary_connected = 1;
    }
    else {
        mongo_close_socket( conn->sock );
    }

    return 0;
}
コード例 #6
0
ファイル: mongo.c プロジェクト: alex-python/restpose
static int mongo_socket_connect( mongo_connection * conn, const char * host, int port ){
    struct sockaddr_in sa;
    socklen_t addressSize;

    memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) );
    sa.sin_family = AF_INET;
    sa.sin_port = htons( port );
    sa.sin_addr.s_addr = inet_addr( host );
    addressSize = sizeof( sa );

    conn->sock = socket( AF_INET, SOCK_STREAM, 0 );
    if ( conn->sock < 0 ){
        mongo_close_socket( conn->sock );
        return mongo_conn_no_socket;
    }

    if ( connect( conn->sock, (struct sockaddr *)&sa, addressSize ) ){
        return mongo_conn_fail;
    }

    setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one) );

    conn->connected = 1;
    return 0;
}
コード例 #7
0
ファイル: mongo.c プロジェクト: alex-python/restpose
mongo_conn_return mongo_replset_connect(mongo_connection* conn) {

    int connect_error = 0;
    mongo_host_port* node;

    conn->sock = 0;
    conn->connected = 0;

    /* First iterate over the seed nodes to get the canonical list of hosts
     * from the replica set. Break out once we have a host list.
     */
    node = conn->replset->seeds;
    while( node != NULL ) {
        connect_error = mongo_socket_connect( conn, (const char*)&node->host, node->port );

        if( connect_error == 0 ) {
            if ( (connect_error = mongo_replset_check_seed( conn )) )
                return connect_error;
        }

        if( conn->replset->hosts )
            break;

        node = node->next;
    }

    /* Iterate over the host list, checking for the primary node. */
    if( !conn->replset->hosts )
        return mongo_conn_cannot_find_primary;
    else {
        node = conn->replset->hosts;

        while( node != NULL ) {
            connect_error = mongo_socket_connect( conn, (const char*)&node->host, node->port );

            if( connect_error == 0 ) {
                if ( (connect_error = mongo_replset_check_host( conn )) )
                    return connect_error;

                /* Primary found, so return. */
                else if( conn->replset->primary_connected )
                     return 0;

                /* No primary, so close the connection. */
                else {
                    mongo_close_socket( conn->sock );
                    conn->sock = 0;
                    conn->connected = 0;
                }
            }

            node = node->next;
        }
    }

    return mongo_conn_cannot_find_primary;
}
コード例 #8
0
ファイル: mongo.c プロジェクト: alex-python/restpose
static int mongo_socket_connect( mongo_connection * conn, const char * host, int port ){

    struct addrinfo* addrs = NULL;
    struct addrinfo hints;
    char port_str[12];
    int ret;

    conn->sock = 0;
    conn->connected = 0;

    memset( &hints, 0, sizeof( hints ) );
    hints.ai_family = AF_INET;

    sprintf( port_str, "%d", port );

    conn->sock = socket( AF_INET, SOCK_STREAM, 0 );
    if ( conn->sock < 0 ){
        mongo_close_socket( conn->sock );
        return mongo_conn_no_socket;
    }

    ret = getaddrinfo( host, port_str, &hints, &addrs );
    if(ret) {
        fprintf( stderr, "getaddrinfo failed: %s", gai_strerror( ret ) );
        return mongo_conn_fail;
    }

    if ( connect( conn->sock, addrs->ai_addr, addrs->ai_addrlen ) ){
        mongo_close_socket( conn->sock );
        freeaddrinfo( addrs );
        return mongo_conn_fail;
    }

    setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one) );

    conn->connected = 1;
    freeaddrinfo( addrs );
    return 0;
}
コード例 #9
0
ファイル: mongo.c プロジェクト: chitr/mongo-c-driver
MONGO_EXPORT void mongo_disconnect( mongo *conn ) {
    if( ! conn->connected )
        return;

    if( conn->replset ) {
        conn->replset->primary_connected = 0;
        mongo_replset_free_list( &conn->replset->hosts );
        conn->replset->hosts = NULL;
    }

    mongo_close_socket( conn->sock );

    conn->sock = 0;
    conn->connected = 0;
}
コード例 #10
0
static void mongo_replset_check_seed( mongo_connection* conn ) {
    bson out;
    bson hosts;
    const char* data;
    bson_iterator it;
    bson_iterator it_sub;
    const char* host_string;
    mongo_host_port *host_port = NULL;

    out.data = NULL;
    out.owned = 1;

    hosts.data = NULL;
    hosts.owned = 1;

    if( mongo_simple_int_command(conn, "admin", "ismaster", 1, &out) == MONGO_OK ) {

        if( bson_find( &it, &out, "hosts" ) ) {
            data = bson_iterator_value( &it );
            bson_iterator_init( &it_sub, data );

            /* Iterate over host list, adding each host to the
             * connection's host list. */
            while( bson_iterator_next( &it_sub ) ) {
                host_string = bson_iterator_string( &it_sub );

                host_port = bson_malloc( sizeof( mongo_host_port ) );
                mongo_parse_host( host_string, host_port );

                if( host_port ) {
                    mongo_replset_add_node( &conn->replset->hosts,
                        host_port->host, host_port->port );

                    free( host_port );
                    host_port = NULL;
                }
            }
        }
    }

    bson_destroy( &out );
    bson_destroy( &hosts );
    mongo_close_socket( conn->sock );
    conn->sock = 0;
    conn->connected = 0;

}
コード例 #11
0
ファイル: mongo.c プロジェクト: alex-python/restpose
bson_bool_t mongo_disconnect( mongo_connection * conn ){
    if( ! conn->connected )
        return 1;

    if( conn->replset ) {
        conn->replset->primary_connected = 0;
        mongo_replset_free_list( &conn->replset->hosts );
        conn->replset->hosts = NULL;
        return mongo_replset_connect( conn );
    }

    mongo_close_socket( conn->sock );

    conn->sock = 0;
    conn->connected = 0;

    return 0;
}
コード例 #12
0
ファイル: net.c プロジェクト: ghesketh/mongo-c-driver
int mongo_socket_connect( mongo *conn, const char *host, int port ) {

    struct addrinfo *addrs = NULL;
    struct addrinfo hints;
    int flag = 1;
    char port_str[12];
    int ret;

    conn->sock = 0;
    conn->connected = 0;

    memset( &hints, 0, sizeof( hints ) );
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    bson_sprintf( port_str, "%d", port );

    if( mongo_create_socket( conn ) != MONGO_OK )
        return MONGO_ERROR;

    if( (ret = getaddrinfo( host, port_str, &hints, &addrs )) != 0 ) {
        bson_errprintf( "getaddrinfo failed: %s", gai_strerror( ret ) );
        conn->err = MONGO_CONN_ADDR_FAIL;
        return MONGO_ERROR;
    }

    if ( connect( conn->sock, addrs->ai_addr, addrs->ai_addrlen ) == -1 ) {
        mongo_close_socket( conn->sock );
        freeaddrinfo( addrs );
        conn->err = MONGO_CONN_FAIL;
        return MONGO_ERROR;
    }

    setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * )&flag, sizeof( flag ) );
    if( conn->op_timeout_ms > 0 )
        mongo_set_socket_op_timeout( conn, conn->op_timeout_ms );

    conn->connected = 1;
    freeaddrinfo( addrs );

    return MONGO_OK;
}
コード例 #13
0
int mongo_socket_connect( mongo *conn, const char *host, int port ) {
    char port_str[NI_MAXSERV];
    int status;

    struct addrinfo ai_hints;
    struct addrinfo *ai_list = NULL;
    struct addrinfo *ai_ptr = NULL;

    conn->sock = 0;
    conn->connected = 0;
    sprintf(port_str,"%d",port);

    bson_sprintf( port_str, "%d", port );

    memset( &ai_hints, 0, sizeof( ai_hints ) );
#ifdef AI_ADDRCONFIG
    ai_hints.ai_flags = AI_ADDRCONFIG;
#endif
    ai_hints.ai_family = AF_UNSPEC;
    ai_hints.ai_socktype = SOCK_STREAM;

    status = getaddrinfo( host, port_str, &ai_hints, &ai_list );
    if ( status != 0 ) {
        bson_errprintf( "getaddrinfo failed: %s", gai_strerror( status ) );
        conn->err = MONGO_CONN_ADDR_FAIL;
        return MONGO_ERROR;
    }

    for ( ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) {
        conn->sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
        if ( conn->sock < 0 ) {
            conn->sock = 0;
            continue;
        }

        status = connect( conn->sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen );
        if ( status != 0 ) {
            mongo_close_socket( conn->sock );
            conn->sock = 0;
            continue;
        }

        if ( ai_ptr->ai_protocol == IPPROTO_TCP ) {
            int flag = 1;

            setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY,
                        ( void * ) &flag, sizeof( flag ) );
            if ( conn->op_timeout_ms > 0 )
                mongo_set_socket_op_timeout( conn, conn->op_timeout_ms );
        }

        conn->connected = 1;
        break;
    }

    freeaddrinfo( ai_list );

    if ( ! conn->connected ) {
        conn->err = MONGO_CONN_FAIL;
        return MONGO_ERROR;
    }

    return MONGO_OK;
}
コード例 #14
0
void mongo_connection_close(mongo_connection *con, int why)
{
	mongo_close_socket((int) (long) con->socket, why);
}
コード例 #15
0
/**
* This function does the actual connecting
* The results of this function are stored in mongo_connection->socket,
* which is a void* to be able to store various different backends
* (f.e. the PHP io_streams stores a php_stream*)
*
* Returns an integer (masquerading as a void*) on success, NULL on failure.
*/
void* mongo_connection_connect(mongo_con_manager *manager, mongo_server_def *server, mongo_server_options *options, char **error_message)
{
	struct sockaddr*   sa;
	struct sockaddr_in si;
	socklen_t          sn;
	int                family;
	struct timeval     tval;
	int                connected;
	int                status;
	int                tmp_socket;

#ifdef WIN32
	WORD       version;
	WSADATA    wsaData;
	int        size, error;
	u_long     no = 0;
	const char yes = 1;
#else
	struct sockaddr_un su;
	uint               size;
	int                yes = 1;
#endif

	*error_message = NULL;

#ifdef WIN32
	family = AF_INET;
	sa = (struct sockaddr*)(&si);
	sn = sizeof(si);

	version = MAKEWORD(2,2);
	error = WSAStartup(version, &wsaData);

	if (error != 0) {
		return NULL;
	}

	/* create socket */
	tmp_socket = socket(family, SOCK_STREAM, 0);
	if (tmp_socket == INVALID_SOCKET) {
		*error_message = strdup(strerror(errno));
		return NULL;
	}

#else
	/* domain socket */
	if (server->port == 0) {
		family = AF_UNIX;
		sa = (struct sockaddr*)(&su);
		sn = sizeof(su);
	} else {
		family = AF_INET;
		sa = (struct sockaddr*)(&si);
		sn = sizeof(si);
	}

	/* create socket */
	if ((tmp_socket = socket(family, SOCK_STREAM, 0)) == -1) {
		*error_message = strdup(strerror(errno));
		return NULL;
	}
#endif

	/* TODO: Move this to within the loop & use real timeout setting */
	/* connection timeout: set in ms (current default 1 sec) */
	tval.tv_sec = options->connectTimeoutMS <= 0 ? 1 : options->connectTimeoutMS / 1000;
	tval.tv_usec = options->connectTimeoutMS <= 0 ? 0 : (options->connectTimeoutMS % 1000) * 1000;

	/* get addresses */
	if (mongo_util_connect__sockaddr(sa, family, server->host, server->port, error_message) == 0) {
		goto error;
	}

	setsockopt(tmp_socket, SOL_SOCKET, SO_KEEPALIVE, &yes, INT_32);
	setsockopt(tmp_socket, IPPROTO_TCP, TCP_NODELAY, &yes, INT_32);

#ifdef WIN32
	ioctlsocket(tmp_socket, FIONBIO, (u_long*)&yes);
#else
	fcntl(tmp_socket, F_SETFL, FLAGS|O_NONBLOCK);
#endif

	/* connect */
	status = connect(tmp_socket, sa, sn);
	if (status < 0) {
#ifdef WIN32
		errno = WSAGetLastError();
		if (errno != WSAEINPROGRESS && errno != WSAEWOULDBLOCK) {
#else
		if (errno != EINPROGRESS) {
#endif
			*error_message = strdup(strerror(errno));
			goto error;
		}

		while (1) {
			fd_set rset, wset, eset;

			FD_ZERO(&rset);
			FD_SET(tmp_socket, &rset);
			FD_ZERO(&wset);
			FD_SET(tmp_socket, &wset);
			FD_ZERO(&eset);
			FD_SET(tmp_socket, &eset);

			if (select(tmp_socket+1, &rset, &wset, &eset, &tval) == 0) {
				*error_message = malloc(256);
				snprintf(*error_message, 256, "Timed out after %d ms", options->connectTimeoutMS);
				goto error;
			}

			/* if our descriptor has an error */
			if (FD_ISSET(tmp_socket, &eset)) {
				*error_message = strdup(strerror(errno));
				goto error;
			}

			/* if our descriptor is ready break out */
			if (FD_ISSET(tmp_socket, &wset) || FD_ISSET(tmp_socket, &rset)) {
				break;
			}
		}

		size = sn;

		connected = getpeername(tmp_socket, sa, &size);
		if (connected == -1) {
			*error_message = strdup(strerror(errno));
			goto error;
		}
	}

	/* reset flags */
#ifdef WIN32
	ioctlsocket(tmp_socket, FIONBIO, &no);
#else
	fcntl(tmp_socket, F_SETFL, FLAGS);
#endif

	return (void *) (long) tmp_socket;

error:
	mongo_close_socket(tmp_socket, MONGO_CLOSE_BROKEN);
	return NULL;
}

static void mongo_close_socket(int socket, int why)
{
#ifdef WIN32
	shutdown(socket, SD_BOTH);
	closesocket(socket);
	WSACleanup();
#else
	shutdown(socket, SHUT_RDWR);
	close(socket);
#endif
}
コード例 #16
0
ファイル: mongo.c プロジェクト: alex-python/restpose
static int mongo_replset_check_seed( mongo_connection* conn ) {
    bson out;
    bson hosts;
    const char* data;
    bson_iterator it;
    bson_iterator it_sub;
    const char* host_string;
    char* host;
    int len, idx, port, split;

    out.data = NULL;
    out.owned = 1;

    hosts.data = NULL;
    hosts.owned = 1;

    if (mongo_simple_int_command(conn, "admin", "ismaster", 1, &out)) {

        if( bson_find( &it, &out, "hosts" ) ) {
            data = bson_iterator_value( &it );
            bson_iterator_init( &it_sub, data );

            /* Iterate over host list, adding each host to the
             * connection's host list.
             */
            while( bson_iterator_next( &it_sub ) ) {
                host_string = bson_iterator_string( &it_sub );
                len = split = idx = 0;

                /* Split the host_port string at the ':' */
                while(1) {
                    if( *(host_string + len) == 0)
                      break;
                    if( *(host_string + len) == ':' )
                      split = len;
                    len++;
                }

                /* If 'split' is set, we know the that port exists;
                 * Otherwise, we set the default port.
                 */
                if( len > 0 ) {
                    idx = split ? split : len;
                    host = (char *)bson_malloc( idx + 1 );
                    memcpy( host, host_string, idx );
                    memcpy( host + idx, "\0", 1 );
                    if( split )
                        port = atoi( host_string + idx + 1 );
                    else
                        port = 27017;

                    mongo_replset_add_node( &conn->replset->hosts, host, port );
                }
            }
        }
    }

    bson_destroy( &out );
    bson_destroy( &hosts );
    mongo_close_socket( conn->sock );
    conn->sock = 0;
    conn->connected = 0;

    return 0;
}