Esempio n. 1
0
void
fetion_update_portrait(fetion_account *ac, fetion_buddy *buddy)
{
	portrait_data *data;
	HybridBuddy *hybrid_buddy;
	const gchar *checksum;

	g_return_if_fail(ac != NULL);
	g_return_if_fail(buddy != NULL);

	data = g_new0(portrait_data, 1);
	data->buddy = buddy;
	data->ac = ac;
	data->portrait_type = PORTRAIT_TYPE_BUDDY;

	if (!(hybrid_buddy = hybrid_blist_find_buddy(ac->account, buddy->userid))) {
		hybrid_debug_error("fetion", "FATAL, update portrait,"
				" unable to find a buddy.");
		return;
	}

	checksum = hybrid_blist_get_buddy_checksum(hybrid_buddy);

	if (checksum != NULL && g_strcmp0(checksum, buddy->portrait_crc) == 0) {
		hybrid_debug_info("fetion", "portrait for %s(%s) up to date",
		buddy->nickname && *(buddy->nickname) != '\0' ? buddy->nickname : buddy->userid,
		buddy->portrait_crc);
		return;
	}

	hybrid_proxy_connect(ac->portrait_host_name, 80, portrait_conn_cb, data);
}
Esempio n. 2
0
/**
 * Callback function to handle the new_chat response message, if success
 * we would get the following message:
 *
 * SIP-C/4.0 200 OK
 * I: 4
 * Q: 2 S
 * A: CS address="221.176.31.128:8080;221.176.31.128:443",credential="439333922.916967705"
 *
 * Now we should start a new socket connect to 221.176.31.128:8080 with port 443 as
 * a back port if 8080 failed to connect.
 */
gint
new_chat_cb(fetion_account *account, const gchar *sipmsg,
				fetion_transaction *trans)
{
	gchar *auth;
	gchar *ip;
	gint port;
	gchar *credential;
	invite_data *data;
	fetion_transaction *new_trans;
	fetion_account *new_account;

	printf("%s\n", sipmsg);

	if (!(auth = sip_header_get_attr(sipmsg, "A"))) {

		hybrid_debug_error("fetion", "invalid invitation response.");

		return HYBRID_ERROR;
	}

	if (sip_header_get_auth(auth, &ip, &port, &credential) != HYBRID_OK) {

		hybrid_debug_error("fetion", "invalid invitation response.");

		return HYBRID_ERROR;
	}

	g_free(auth);

	new_trans = transaction_clone(trans);

	new_account = fetion_account_clone(account);
	fetion_account_set_who(new_account, trans->userid);

	transaction_set_data(new_trans, new_account);

	data = g_new0(invite_data, 1);
	data->trans = new_trans;
	data->credential = credential;

	hybrid_proxy_connect(ip, port, invite_connect_cb, data);

	g_free(ip);

	return HYBRID_OK;
}
Esempio n. 3
0
HybridSslConnection*
hybrid_ssl_connect(const gchar *hostname, gint port, ssl_callback func,
                   gpointer user_data)
{
    BIO                 *buf_io;
    BIO                 *ssl_bio;
    HybridSslConnection *conn;

    g_return_val_if_fail(hostname != NULL, NULL);
    g_return_val_if_fail(port != 0, NULL);
    g_return_val_if_fail(func != NULL, NULL);

    SSLeay_add_all_algorithms();
    SSL_load_error_strings();
    SSL_library_init();

    conn = g_new0(HybridSslConnection, 1);

    if (!(conn->ssl_ctx = SSL_CTX_new(SSLv23_client_method()))) {
        hybrid_debug_error("ssl", "initialize SSL CTX: %s",
                           ERR_reason_error_string(ERR_get_error()));
        hybrid_ssl_connection_destory(conn);
        return NULL;
    }

    if (!(conn->ssl = ssl_new_with_certs(conn->ssl_ctx))) {
        hybrid_ssl_connection_destory(conn);
        return NULL;
    }

    SSL_set_mode(conn->ssl, SSL_MODE_AUTO_RETRY);

    buf_io  = BIO_new(BIO_f_buffer());
    ssl_bio = BIO_new(BIO_f_ssl());

    BIO_set_ssl(ssl_bio, conn->ssl, BIO_NOCLOSE);
    BIO_push(buf_io, ssl_bio);

    conn->conn_cb   = func;
    conn->conn_data = user_data;
    conn->rbio      = buf_io;

    conn->conn = hybrid_proxy_connect(hostname, port, ssl_connect_cb, conn);

    return conn;
}
Esempio n. 4
0
gint
fetion_process_invite(fetion_account *account, const gchar *sipmsg)
{
	gchar *from;
	gchar *auth;
	gchar *ip;
	gchar *credential;
	gchar *sid;
	gint port;
	gchar *sip_text;
	fetion_account *new_account;
	fetion_buddy *buddy;
	invite_conn_data *data;

	g_return_val_if_fail(account != NULL, HYBRID_ERROR);
	g_return_val_if_fail(sipmsg != NULL, HYBRID_ERROR);

	from = sip_header_get_attr(sipmsg, "F");
	auth = sip_header_get_attr(sipmsg, "A");

	sip_header_get_auth(auth, &ip, &port, &credential);
	g_free(auth);

	sip_text = g_strdup_printf("SIP-C/4.0 200 OK\r\n"
								"F: %s\r\n"
								"I: 61\r\n"
								"Q: 200002 I\r\n\r\n", from);

	hybrid_debug_info("fetion", "invite, send back:\n%s", sip_text);

	if (send(account->sk, sip_text, strlen(sip_text), 0) == -1) {

		hybrid_debug_error("fetion", "process an invitation error.");

		g_free(from);
		g_free(ip);
		g_free(credential);
		g_free(sip_text);

		return HYBRID_ERROR;
	}
	
	g_free(sip_text);

	sid = get_sid_from_sipuri(from);

	if (!(buddy = fetion_buddy_find_by_sid(account, sid))) {

		hybrid_debug_error("fetion", "can't find buddy %s", from);

		g_free(from);
		g_free(ip);
		g_free(credential);
		g_free(sid);

		return HYBRID_ERROR;
	}

	g_free(sid);

	new_account = fetion_account_clone(account);
	fetion_account_set_who(new_account, buddy->userid);

	data = g_new0(invite_conn_data, 1);
	data->account = new_account;
	data->credential = credential;

	hybrid_proxy_connect(ip, port, process_invite_conn_cb, data);

	g_free(from);
	g_free(ip);

	return HYBRID_OK;
}
Esempio n. 5
0
/**
 * Callback function to handle the read event after
 * rendered sipc authentication.
 */
static gint
sipc_auth_cb(fetion_account *ac, const gchar *sipmsg,
             fetion_transaction *trans)
{
    gint   code;
    gint   length;
    gchar *pos;

    code = fetion_sip_get_code(sipmsg);

    hybrid_debug_info("fetion", "sipc recv:\n%s", sipmsg);

    if (code == FETION_SIP_OK) { /**< ok, we got the contact list */

        /* update the portrait. */
        fetion_account_update_portrait(ac);

        length = fetion_sip_get_length(sipmsg);
        pos = strstr(ac->buffer, "\r\n\r\n") + 4;

        parse_sipc_resp(ac, pos, length);

        /* set the nickname of the hybrid account. */
        hybrid_account_set_nickname(ac->account, ac->nickname);

        /* set the mood phrase of the hybrid account. */
        hybrid_account_set_status_text(ac->account, ac->mood_phrase);

        hybrid_account_set_state(ac->account, HYBRID_STATE_INVISIBLE);

        /* set the connection status. */
        hybrid_account_set_connection_status(ac->account,
                HYBRID_CONNECTION_CONNECTED);

        /* init group list */
        fetion_groups_init(ac);

        /* init buddy list */
        fetion_buddies_init(ac);

        /* start scribe the pushed msg */
        fetion_buddy_scribe(ac);

    } else if (420 == code || 421 == code) {

        if (HYBRID_ERROR == parse_sipc_verification(ac, sipmsg)) {
            hybrid_account_error_reason(ac->account,
                                        _("Fetion Protocol ERROR."));
            return FALSE;
        }

        hybrid_debug_error("fetion", "sipc authentication need Verification.");

        verify_data.sipc_conn = ac->sk;
        verify_data.type      = VERIFY_TYPE_SIP;

        hybrid_proxy_connect(NAV_SERVER, 80, pic_download_cb, ac);

        g_free(ac->buffer);
        ac->buffer = NULL;

        return HYBRID_OK;
    } else {
        g_free(ac->buffer);
        ac->buffer = NULL;

        return HYBRID_ERROR;
    }

    return HYBRID_ERROR;
}
Esempio n. 6
0
/**
 * Callback function to handle the ssi read event. We get the response
 * string from the ssi server here.
 */
static gboolean
ssi_auth_cb(HybridSslConnection *ssl, gpointer user_data)
{
    gchar           buf[BUF_LENGTH];
    gchar          *pos;
    gchar          *pos1;
    gint            ret;
    gint            code;
    fetion_account *ac = (fetion_account*)user_data;

    ret = hybrid_ssl_read(ssl, buf, sizeof(buf));

    if (ret == -1 || ret == 0) {
        hybrid_debug_error("ssi", "ssi server response error");
        return FALSE;
    }

    buf[ret] = '\0';

    hybrid_ssl_connection_destory(ssl);

    hybrid_debug_info("fetion", "recv:\n%s", buf);

    code = hybrid_get_http_code(buf);

    if (421 == code || 420 == code) {            /* confirm code needed. */
        if (HYBRID_ERROR == parse_ssi_fail_resp(ac, buf)) {
            goto ssi_auth_err;
        }

        verify_data.ssl     = ssl;
        verify_data.type = VERIFY_TYPE_SSI;

        hybrid_proxy_connect(NAV_SERVER, 80, pic_download_cb, ac);

        return FALSE;
    }

    if (200 != code) {
        goto ssi_auth_err;
    }

    if (!(pos = strstr(buf, "ssic="))) {
        goto ssi_auth_err;
    }

    pos += 5;

    for (pos1 = pos; *pos1 && *pos1 != ';'; pos1 ++);

    ac->ssic = g_strndup(pos, pos1 - pos);

    if (!(pos = g_strrstr(buf, "\r\n\r\n"))) {
        goto ssi_auth_err;
    }

    pos += 4;

    if (strlen(pos) != hybrid_get_http_length(buf)) {
        goto ssi_auth_err;
    }

    if (parse_ssi_response(ac, pos) != HYBRID_OK) {
        goto ssi_auth_err;
    }

    /*
     * First of all, we load the account's version information from the disk,
     * so that we can use it for authenticating, if the server find the versions
     * are up-to-date, it would return a brief response message in stead of the
     * full version, so that we can use the information store locally. This method
     * makes account logining more faster.
     */
    fetion_config_load_account(ac);

    /* now we will download the configuration */
    hybrid_proxy_connect(NAV_SERVER, 80, cfg_connect_cb, ac);

    return FALSE;

ssi_auth_err:

    hybrid_account_error_reason(ac->account, _("ssi authentication failed"));

    return FALSE;
}
Esempio n. 7
0
/**
 * Callback function to handle the cfg read event.
 */
static gboolean
cfg_read_cb(gint sk, gpointer user_data)
{
    gchar           buf[BUF_LENGTH];
    gint            n;
    gint            length = 0;
    gchar          *pos;
    fetion_account *ac     = (fetion_account*)user_data;

    if ((n = recv(sk, buf, sizeof(buf), 0)) == -1) {
        hybrid_account_error_reason(ac->account, _("read cfg failed"));
        return FALSE;
    }

    buf[n] = '\0';

    if (n != 0) {

        /* larger the recv buffer, and copy the new
         * received bytes to the buffer */
        length = ac->buffer ? strlen(ac->buffer) : 0;
        ac->buffer = g_realloc(ac->buffer, length + n + 1);
        memcpy(ac->buffer + length, buf, n + 1);

        return TRUE;

    } else { /* receive complete, start process */

        if (hybrid_get_http_code(ac->buffer) != 200) {
            goto error;
        }

        hybrid_debug_info("fetion", "cfg recv:\n%s", ac->buffer);

        if (!(pos = g_strrstr(ac->buffer, "\r\n\r\n"))) {
            goto error;
        }

        pos += 4;

        if (strlen(pos) != hybrid_get_http_length(ac->buffer)) {
            goto error;
        }

        if (parse_configuration(ac, pos) != HYBRID_OK) {
            g_free(ac->buffer);
            ac->buffer = NULL;
            goto error;
        }

        g_free(ac->buffer);
        ac->buffer = NULL;

        /* now we start sipc register */

        hybrid_proxy_connect(ac->sipc_proxy_ip, ac->sipc_proxy_port,
                sipc_reg_action, ac);
    }

    return FALSE;
error:
    hybrid_account_error_reason(ac->account, _("read cfg failed"));
    return FALSE;
}