コード例 #1
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
char const *pubnub_last_publish_result(pubnub_t const *pb)
{
    char *end;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    if (PUBNUB_DYNAMIC_REPLY_BUFFER && (NULL == pb->core.http_reply)) {
        return "";
    }
    if ((pb->trans != PBTT_PUBLISH) || (pb->core.http_reply[0] == '\0')) {
        return "";
    }
    for (end = pb->core.http_reply + 1; isdigit((unsigned)*end); ++end) {
        continue;
    }
    return end + 1;
}
コード例 #2
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
pubnub_t* pubnub_init(pubnub_t *p, const char *publish_key, const char *subscribe_key)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(p));

    pbcc_init(&p->core, publish_key, subscribe_key);
    if (PUBNUB_TIMERS_API) {
        p->transaction_timeout_ms = PUBNUB_DEFAULT_TRANSACTION_TIMER;
    }
    if (PUBNUB_ORIGIN_SETTABLE) {
        p->origin = PUBNUB_ORIGIN;
    }
    p->state = PBS_IDLE;
    p->trans = PBTT_NONE;
    pbpal_init(p);

    return p;
}
コード例 #3
0
enum pubnub_res pbpal_resolv_and_connect(pubnub_t *pb)
{
    struct addrinfo *result;
    struct addrinfo *it;
    struct addrinfo hint;
    int error;
    char const* origin = PUBNUB_ORIGIN_SETTABLE ? pb->origin : PUBNUB_ORIGIN;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    PUBNUB_ASSERT_OPT((pb->state == PBS_IDLE) || (pb->state == PBS_WAIT_DNS));

    hint.ai_socktype = SOCK_STREAM;
    hint.ai_family = AF_UNSPEC;
    hint.ai_protocol = hint.ai_flags = hint.ai_addrlen = 0;
    hint.ai_addr = NULL;
    hint.ai_canonname = NULL;
    hint.ai_next = NULL; 
    error = getaddrinfo(origin, HTTP_PORT_STRING, &hint, &result);
    if (error != 0) {
        return PNR_ADDR_RESOLUTION_FAILED;
    }

    for (it = result; it != NULL; it = it->ai_next) {
        pb->pal.socket = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
        if (pb->pal.socket == SOCKET_INVALID) {
            continue;
        }
        if (connect(pb->pal.socket, it->ai_addr, it->ai_addrlen) == -1) {
            socket_close(pb->pal.socket);
            pb->pal.socket = -1;
            continue;
        }
        break;
    }
    freeaddrinfo(result);

    if (NULL == it) {
        return PNR_CONNECT_FAILED;
    }

    socket_set_rcv_timeout(pb->pal.socket, pb->transaction_timeout_ms);

    return PNR_OK;
}
コード例 #4
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_publishv2(pubnub_t *pb, const char *channel, const char *message, bool store_in_history, bool eat_after_reading)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    
    if (pb->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }

    rslt = pbcc_publish_prep(&pb->core, channel, message, store_in_history, eat_after_reading);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_PUBLISH;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }
    
    return rslt;
}
コード例 #5
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_subscribe(pubnub_t *p, const char *channel, const char *channel_group)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(p));
    
    if (p->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }
    
    rslt = pbcc_subscribe_prep(&p->core, channel, channel_group);
    if (PNR_STARTED == rslt) {
        p->trans = PBTT_SUBSCRIBE;
        p->core.last_result = PNR_STARTED;
        pbnc_fsm(p);
        rslt = p->core.last_result;
    }
    
    return rslt;
}
コード例 #6
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_list_channel_group(pubnub_t *pb, char const *channel_group)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    if (pb->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }
    
    rslt = pbcc_channel_registry_prep(&pb->core, channel_group, NULL, NULL);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_LIST_CHANNEL_GROUP;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }
    
    return rslt;
}
コード例 #7
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_publish(pubnub_t *pb, const char *channel, const char *message)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    
    if (pb->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }

    rslt = pbcc_publish_prep(&pb->core, channel, message, true, false);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_PUBLISH;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }
    
    return rslt;
}
コード例 #8
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_state_get(pubnub_t *pb, char const *channel, char const *channel_group, const char *uuid)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    if (pb->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }
    
    rslt = pbcc_state_get_prep(&pb->core, channel, channel_group, uuid ? uuid : pb->core.uuid);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_STATE_GET;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }
    
    return rslt;
}
コード例 #9
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_where_now(pubnub_t *pb, const char *uuid)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    if (pb->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }
    
    rslt = pbcc_where_now_prep(&pb->core, uuid ? uuid : pb->core.uuid);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_WHERENOW;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }
    
    return rslt;
}
コード例 #10
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_global_here_now(pubnub_t *pb)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    if (pb->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }
    
    rslt = pbcc_here_now_prep(&pb->core, NULL, NULL);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_GLOBAL_HERENOW;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }
    
    return rslt;
}
コード例 #11
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_history(pubnub_t *pb, const char *channel, unsigned count, bool include_token)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    if (pb->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }
    
    rslt = pbcc_history_prep(&pb->core, channel, count, include_token);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_HISTORY;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }
    
    return rslt;
}
コード例 #12
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
enum pubnub_res pubnub_time(pubnub_t *p)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(p));

    if (p->state != PBS_IDLE) {
        return PNR_IN_PROGRESS;
    }
    
    rslt = pbcc_time_prep(&p->core);
    if (PNR_STARTED == rslt) {
        p->trans = PBTT_TIME;
        p->core.last_result = PNR_STARTED;
        pbnc_fsm(p);
        rslt = p->core.last_result;
    }
    
    return rslt;
}
コード例 #13
0
ファイル: pubnub_fntest.c プロジェクト: anovikov1984/c-core
bool pnfntst_got_messages(pubnub_t *p, ...)
{
    char const *aMsgs[16];
    uint16_t missing;
    size_t count = 0;
    va_list vl;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(p));

    va_start(vl, p);
    while (count < 16) {
        char const *msg = va_arg(vl, char*);
        if (NULL == msg) {
            break;
        }
        aMsgs[count++] = msg;
    }
    va_end(vl);

    if ((0 == count) || (count > 16)) {
        return false;
    }

    missing = (0x01 << count) - 1;
    while (missing) {
        size_t i;
        char const *msg = pubnub_get(p);
        if (NULL == msg) {
            break;
        }
        for (i = 0; i < count; ++i) {
            if ((missing & (0x01 << i)) && (strcmp(msg, aMsgs[i]) == 0)) {
                missing &= ~(0x01 << i);
                break;
            }
        }
    }
    return !missing;
}
コード例 #14
0
ファイル: pubnub_coreapi.c プロジェクト: sjaeckel/c-core
enum pubnub_res pubnub_add_channel_to_group(pubnub_t *pb, char const *channel, char const *channel_group)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    pubnub_mutex_lock(pb->monitor);
    if (pb->state != PBS_IDLE) {
        pubnub_mutex_unlock(pb->monitor);
        return PNR_IN_PROGRESS;
    }

    rslt = pbcc_channel_registry_prep(&pb->core, channel_group, "add", channel);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_ADD_CHANNEL_TO_GROUP;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }

    pubnub_mutex_unlock(pb->monitor);
    return rslt;
}
コード例 #15
0
ファイル: pubnub_coreapi.c プロジェクト: sjaeckel/c-core
enum pubnub_res pubnub_set_state(pubnub_t *pb, char const *channel, char const *channel_group, const char *uuid, char const *state)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    pubnub_mutex_lock(pb->monitor);
    if (pb->state != PBS_IDLE) {
        pubnub_mutex_unlock(pb->monitor);
        return PNR_IN_PROGRESS;
    }

    rslt = pbcc_set_state_prep(&pb->core, channel, channel_group, uuid ? uuid : pb->core.uuid, state);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_SET_STATE;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }

    pubnub_mutex_unlock(pb->monitor);
    return rslt;
}
コード例 #16
0
enum pbpal_resolv_n_connect_result pbpal_check_connect(pubnub_t *pb)
{
    fd_set write_set;
    int rslt;
    struct timeval timev = { 0, 300000 };

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    PUBNUB_ASSERT_OPT(pb->state == PBS_WAIT_CONNECT);

    FD_ZERO(&write_set);
    FD_SET(pb->pal.socket, &write_set);
    rslt = select(pb->pal.socket + 1, NULL, &write_set, NULL, &timev);
    if (SOCKET_ERROR == rslt) {
        PUBNUB_LOG_ERROR("pbpal_connected(): select() Error!\n");
        return pbpal_connect_resource_failure;
    }
    else if (rslt > 0) {
        PUBNUB_LOG_TRACE("pbpal_connected(): select() event\n");
        return pbpal_connect_success;
    }
    PUBNUB_LOG_TRACE("pbpal_connected(): no select() events\n");
    return pbpal_connect_wouldblock;
}
コード例 #17
0
ファイル: pubnub_coreapi.c プロジェクト: sjaeckel/c-core
enum pubnub_res pubnub_leave(pubnub_t *p, const char *channel, const char *channel_group)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(p));

    pubnub_mutex_lock(p->monitor);
    if (p->state != PBS_IDLE) {
        pubnub_mutex_unlock(p->monitor);
        return PNR_IN_PROGRESS;
    }

    rslt = pbcc_leave_prep(&p->core, channel, channel_group);
    if (PNR_STARTED == rslt) {
        p->trans = PBTT_LEAVE;
        p->core.last_result = PNR_STARTED;
        pbnc_fsm(p);
        rslt = p->core.last_result;
    }

    pubnub_mutex_unlock(p->monitor);
    return rslt;
}
コード例 #18
0
ファイル: pubnub_coreapi.c プロジェクト: sjaeckel/c-core
enum pubnub_res pubnub_here_now(pubnub_t *pb, const char *channel, const char *channel_group)
{
    enum pubnub_res rslt;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    pubnub_mutex_lock(pb->monitor);
    if (pb->state != PBS_IDLE) {
        pubnub_mutex_unlock(pb->monitor);
        return PNR_IN_PROGRESS;
    }

    rslt = pbcc_here_now_prep(&pb->core, channel, channel_group, pbccNotSet, pbccNotSet);
    if (PNR_STARTED == rslt) {
        pb->trans = PBTT_HERENOW;
        pb->core.last_result = PNR_STARTED;
        pbnc_fsm(pb);
        rslt = pb->core.last_result;
    }

    pubnub_mutex_unlock(pb->monitor);
    return rslt;
}
コード例 #19
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
void pubnub_set_auth(pubnub_t *pb, const char *auth)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    pbcc_set_auth(&pb->core, auth);
}
コード例 #20
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
void pubnub_cancel(pubnub_t *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    pbnc_stop(pb, PNR_CANCELLED);
}
コード例 #21
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
void pubnub_set_uuid(pubnub_t *pb, const char *uuid)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    pbcc_set_uuid(&pb->core, uuid);
}
コード例 #22
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
char const *pubnub_get_channel(pubnub_t *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));

    return pbcc_get_channel(&pb->core);
}
コード例 #23
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
char const *pubnub_uuid_get(pubnub_t const *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    return pb->core.uuid;
}
コード例 #24
0
void *pubnub_get_user_data(pubnub_t *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    return pb->user_data;
}
コード例 #25
0
enum pubnub_res pubnub_last_result(pubnub_t *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    return pb->core.last_result;
}
コード例 #26
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
char const *pubnub_auth_get(pubnub_t const *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    return pb->core.auth;
}
コード例 #27
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
int pubnub_last_http_code(pubnub_t const *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    return pb->http_code;
}
コード例 #28
0
ファイル: pubnub_coreapi.c プロジェクト: ramshenai/c-core
char const *pubnub_last_time_token(pubnub_t const *pb)
{
    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    return pb->core.timetoken;
}
コード例 #29
0
ファイル: pubnub_fntest.c プロジェクト: anovikov1984/c-core
bool pnfntst_subscribe_and_check(pubnub_t *p, char const *channel, char const*chgroup, unsigned ms, ...)
{
	char const *aMsgs[16];
    char const *aChan[16];
    uint16_t missing;
    size_t count = 0;
	pnfntst_timer_t *tmr;
    va_list vl;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(p));

    va_start(vl, ms);
    while (count < 16) {
        char const *msg = va_arg(vl, char*);
        if (NULL == msg) {
            break;
        }
        aMsgs[count] = msg;
		msg = va_arg(vl, char*);
        if (NULL == msg) {
            return false;
        }
		aChan[count] = msg;
		++count;
    }
    va_end(vl);

    if ((0 == count) || (count > 16)) {
        return false;
    }

    missing = (0x01 << count) - 1;
    tmr = pnfntst_alloc_timer();
    if (NULL == tmr) {
		puts("subscribe and check: timer alloc failed");
		return false;
	}
    pnfntst_start_timer(tmr, ms);
    while (pnfntst_timer_is_running(tmr) && missing) {
		enum pubnub_res pbres;
		if (PNR_STARTED != pubnub_subscribe(p, channel, chgroup)) {
			puts("subscribe and check: subscribe failed");
			break;
		}
		while (pnfntst_timer_is_running(tmr)) {
			pbres = pubnub_last_result(p);
			if (pbres != PNR_STARTED) {
				break;
			}
		}
		if (pbres != PNR_OK) {
			printf("subscribe and check: subscribe error %d\n", pbres);
			break;
		}
	
        do {
			size_t i;
			char const *msg = pubnub_get(p);
			char const *chan = pubnub_get_channel(p);
			if ((NULL == msg) || (NULL == chan)) {
				break;
			}
			for (i = 0; i < count; ++i) {
				if ((missing & (0x01 << i)) && (strcmp(msg, aMsgs[i]) == 0)
					 && (strcmp(chan, aChan[i]) == 0)
				 ) {
					missing &= ~(0x01 << i);
					break;
				}
			}
		} while (missing);
    }
    
	pnfntst_free_timer(tmr);
    
	return !missing;
}
コード例 #30
0
enum pbpal_resolv_n_connect_result pbpal_resolv_and_connect(pubnub_t *pb)
{
    SSL *ssl = NULL;
    int rslt;
    char const* origin = PUBNUB_ORIGIN_SETTABLE ? pb->origin : PUBNUB_ORIGIN;

    PUBNUB_ASSERT(pb_valid_ctx_ptr(pb));
    PUBNUB_ASSERT_OPT((pb->state == PBS_READY) || (pb->state == PBS_WAIT_CONNECT));

    if (!pb->options.useSSL) {
        return resolv_and_connect_wout_SSL(pb);
    }

    if (NULL == pb->pal.ctx) {
        PUBNUB_LOG_TRACE("pb=%p: Don't have SSL_CTX\n", pb);
        pb->pal.ctx = SSL_CTX_new(SSLv23_client_method());
        if (NULL == pb->pal.ctx) {
            ERR_print_errors_cb(print_to_pubnub_log, NULL);
            PUBNUB_LOG_ERROR("pb=%p SSL_CTX_new failed\n", pb);
            return pbpal_resolv_resource_failure;
        }
        PUBNUB_LOG_TRACE("pb=%p: Got SSL_CTX\n", pb);
        add_pubnub_cert(pb->pal.ctx);
    }

    if (NULL == pb->pal.socket) {
        PUBNUB_LOG_TRACE("pb=%p: Don't have BIO\n", pb);
        pb->pal.socket = BIO_new_ssl_connect(pb->pal.ctx);
        if (PUBNUB_TIMERS_API) {
            pb->pal.connect_timeout = time(NULL)  + pb->transaction_timeout_ms/1000;
        }
    }
    else {
        BIO_get_ssl(pb->pal.socket, &ssl);
        if (NULL == ssl) {
            return resolv_and_connect_wout_SSL(pb);
        }
        ssl = NULL;
    }
    if (NULL == pb->pal.socket) {
        ERR_print_errors_cb(print_to_pubnub_log, NULL);
        return pbpal_resolv_resource_failure;
    }

    PUBNUB_LOG_TRACE("pb=%p: Using BIO == %p\n", pb, pb->pal.socket);

    BIO_get_ssl(pb->pal.socket, &ssl);
    PUBNUB_ASSERT(NULL != ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* maybe not auto_retry? */
    if (pb->pal.session != NULL) {
        SSL_set_session(ssl, pb->pal.session);
    }

    BIO_set_conn_hostname(pb->pal.socket, origin);
    BIO_set_conn_port(pb->pal.socket, "https");
    if (pb->pal.ip_timeout != 0) {
        if (pb->pal.ip_timeout < time(NULL)) {
            pb->pal.ip_timeout = 0;
        }
        else {
            PUBNUB_LOG_TRACE("SSL re-connect to: %d.%d.%d.%d\n", pb->pal.ip[0], pb->pal.ip[1], pb->pal.ip[2], pb->pal.ip[3]);
            BIO_set_conn_ip(pb->pal.socket, pb->pal.ip);
        }
    }
    
    BIO_set_nbio(pb->pal.socket, !pb->options.use_blocking_io);
    
    WATCH_ENUM(pb->options.use_blocking_io);
    if (BIO_do_connect(pb->pal.socket) <= 0) {
        if (BIO_should_retry(pb->pal.socket) && PUBNUB_TIMERS_API && (pb->pal.connect_timeout > time(NULL))) {
            PUBNUB_LOG_TRACE("pb=%p: BIO_should_retry\n", pb);
            return pbpal_connect_wouldblock;
        }
        /* Expire the IP for the next connect */
        pb->pal.ip_timeout = 0;
        ERR_print_errors_cb(print_to_pubnub_log, NULL);
        if (pb->pal.session != NULL) {
            SSL_SESSION_free(pb->pal.session);
            pb->pal.session = NULL;
        }
        PUBNUB_LOG_ERROR("pb=%p: BIO_do_connect failed\n", pb);
        return pbpal_connect_failed;
    }

    PUBNUB_LOG_TRACE("pb=%p: BIO connected\n", pb);
    {
        int fd = BIO_get_fd(pb->pal.socket, NULL);
        socket_set_rcv_timeout(fd, pb->transaction_timeout_ms);
    }

    rslt = SSL_get_verify_result(ssl);
    if (rslt != X509_V_OK) {
        PUBNUB_LOG_WARNING("pb=%p: SSL_get_verify_result() failed == %d(%s)\n", pb, rslt, X509_verify_cert_error_string(rslt));
        ERR_print_errors_cb(print_to_pubnub_log, NULL);
        if (pb->options.fallbackSSL) {
            BIO_free_all(pb->pal.socket);
            pb->pal.socket = NULL;
            return resolv_and_connect_wout_SSL(pb);
        }
        return pbpal_connect_failed;
    }

    PUBNUB_LOG_INFO("pb=%p: SSL session reused: %s\n", pb, SSL_session_reused(ssl) ? "yes" : "no");
    if (pb->pal.session != NULL) {
        SSL_SESSION_free(pb->pal.session);
    }
    pb->pal.session = SSL_get1_session(ssl);
    if (0 == pb->pal.ip_timeout) {
        pb->pal.ip_timeout = SSL_SESSION_get_time(pb->pal.session) + SSL_SESSION_get_timeout(pb->pal.session);
        memcpy(pb->pal.ip, BIO_get_conn_ip(pb->pal.socket), 4);
    }
    PUBNUB_LOG_TRACE("pb=%p: SSL connected to IP: %d.%d.%d.%d\n", pb, pb->pal.ip[0], pb->pal.ip[1], pb->pal.ip[2], pb->pal.ip[3]);

    return pbpal_connect_success;
}