예제 #1
0
/**
 * Verify the peer's    certificate, if successfully verified,
 * save the peer's certificate
 */
static gint
ssl_verify_certs(SSL *ssl)
{
    FILE  *f;
    X509  *x;
    gchar *cert_path;
    gchar *cert_file;
    gchar  buf[256];
    gchar *pos;

    hybrid_debug_info("ssl", "verifying the peer's certificate");

    if ((x = SSL_get_peer_certificate(ssl)) != NULL) {
        if (SSL_get_verify_result(ssl)        == X509_V_OK) {

            X509_NAME_oneline(X509_get_subject_name(x), buf, 256);

            hybrid_debug_info("ssl", "client verification succeeded.");

            cert_path = hybrid_config_get_cert_path();

            if ((pos = strstr(buf, "CN="))) {
                cert_file = g_strdup_printf("%s/%s", cert_path, pos + 3);
            } else {
                cert_file = g_strdup_printf("%s/%s", cert_path, buf);
            }

            g_free(cert_path);

            f = fopen(cert_file, "w+");
            PEM_write_X509(f, x);
            fclose(f);
            g_free(cert_file);

        } else {
            hybrid_debug_error("ssl", "client verification failed.");
            return HYBRID_OK;
        }
    } else {
        hybrid_debug_error("ssl", "the peer certificate was not presented.\n");
    }

    return HYBRID_OK;
}
예제 #2
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
static gint
invite_buddy_cb(fetion_account *account, const gchar *sipmsg,
				fetion_transaction *trans)
{
	hybrid_debug_info("fetion", "invite buddy response:\n%s", sipmsg);

	if (trans->msg && *(trans->msg) != '\0') {
		fetion_message_send(account, trans->userid, trans->msg);
	}

	return HYBRID_OK;
}
예제 #3
0
파일: connect.c 프로젝트: celiachen/hybrid
gint
hybrid_ssl_read(HybridSslConnection *ssl, gchar *buf, gint len)
{
    gint ret;

    hybrid_debug_info("ssl", "start ssl read.");

    ret = BIO_read(ssl->rbio, buf, len);

    switch (SSL_get_error(ssl->ssl, ret)) {
    case SSL_ERROR_NONE:
        hybrid_debug_info("ssl", "ssl read %d bytes, success!", ret);
        return ret;
    case SSL_ERROR_WANT_WRITE:
    case SSL_ERROR_WANT_READ:
        hybrid_debug_info("ssl", "ssl read WANT RW with ret %d.", ret);
        break;
    case SSL_ERROR_SYSCALL:
        hybrid_debug_info("ssl", "ssl read io error.");
        return -1;
    case SSL_ERROR_WANT_X509_LOOKUP:
        hybrid_debug_info("ssl", "ssl read X509.");
        return -1;
    case SSL_ERROR_ZERO_RETURN:
        hybrid_debug_info("ssl", "ssl connection permaturely closed.");
        return 0;
    case SSL_ERROR_SSL:
    default:
        hybrid_debug_error("ssl", "ssl read error:%s",
                           ERR_reason_error_string(ERR_get_error()));
        return -1;
    }

    return -1;
}
예제 #4
0
파일: fx_login.c 프로젝트: GCrean/hybrid
/**
 * Callback function to handle the pic-code download event.
 */
static gboolean
pic_download_cb(gint sk, gpointer user_data)
{
    gchar          *cookie = NULL;
    gchar          *http;
    fetion_account *ac     = (fetion_account*)user_data;

    hybrid_debug_info("fetion", "start downloading pic-cocde.");

    if(ac->ssic) {
        cookie = g_strdup_printf("Cookie: ssic=%s\r\n", ac->ssic);
    }

    http = g_strdup_printf("GET /nav/GetPicCodeV4.aspx?algorithm=%s HTTP/1.1\r\n"
                           "%sHost: %s\r\n"
                           "User-Agent: IIC2.0/PC "PROTO_VERSION"\r\n"
                           "Connection: close\r\n\r\n",
                           ac->verification->algorithm == NULL ? "" : ac->verification->algorithm,
                           ac->ssic == NULL ? "" : cookie, NAV_SERVER);

    hybrid_debug_info("fetion", "download pic request:\n%s", http);

    if (send(sk, http, strlen(http), 0) == -1) {

        g_free(cookie);
        g_free(http);

        return FALSE;
    }

    ac->buffer = (char*)0;

       ac->source = hybrid_event_add(sk, HYBRID_EVENT_READ, pic_read_cb, user_data);

    g_free(cookie);
    g_free(http);

    return FALSE;
}
예제 #5
0
gint
xmpp_message_send_typing(XmppStream *stream, const gchar *to, HybridInputState state)
{
    xmlnode *root;
    xmlnode *node;
    gchar   *xml_string;

    g_return_val_if_fail(stream != NULL, HYBRID_ERROR);
    g_return_val_if_fail(to != NULL, HYBRID_ERROR);

    root = xmlnode_create("message");
    xmlnode_new_prop(root, "from", stream->jid);
    xmlnode_new_prop(root, "to", to);
    xmlnode_new_prop(root, "type", "chat");

    switch (state) {
    case INPUT_STATE_TYPING:
      node = xmlnode_new_child(root, "composing");
      break;
    case INPUT_STATE_ACTIVE:
      node = xmlnode_new_child(root, "active");
      break;
    case INPUT_STATE_PAUSED:
      node = xmlnode_new_child(root, "paused");
      break;
    default:
      node = NULL;
      break;
    }

    if (node) {
        xmlnode_new_namespace(node, NULL, NS_CHANGESTATES);
    }

    xml_string = xmlnode_to_string(root);
    xmlnode_free(root);

    hybrid_debug_info("xmpp", "send message to %s:\n%s", to, xml_string);

    if (hybrid_ssl_write(stream->ssl, xml_string, strlen(xml_string)) == -1) {

        hybrid_debug_error("xmpp", "send message to %s failed\n", to);
        g_free(xml_string);

        return HYBRID_ERROR;
    }

    g_free(xml_string);

    return HYBRID_OK;
}
예제 #6
0
파일: fx_login.c 프로젝트: GCrean/hybrid
/**
 * Callback function to handle the sipc reg response.
 */
static gboolean
sipc_reg_cb(gint sk, gpointer user_data)
{
    gchar  buf[BUF_LENGTH];
    gchar *digest;
    gchar *nonce, *key, *aeskey;
    gchar *response;
    gint   n;

    fetion_account *ac = (fetion_account*)user_data;

    if ((n = recv(sk, buf, sizeof(buf), 0)) == -1) {
        hybrid_account_error_reason(ac->account, _("sipc reg error."));
        return FALSE;
    }

    buf[n] = '\0';

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

    /* parse response, we need the key and nouce */
    digest = sip_header_get_attr(buf, "W");

    if (parse_sipc_reg_response(digest, &nonce, &key) != HYBRID_OK) {
        g_free(digest);
        return FALSE;
    }

    aeskey = generate_aes_key();

    response = generate_response(nonce, ac->userid, ac->password, key, aeskey);

    /* fill verify_data for pic confirm */
    strncpy(verify_data.response, response, sizeof(verify_data.response));

    /* now we start to handle the pushed messages */
    ac->source = hybrid_event_add(sk, HYBRID_EVENT_READ, hybrid_push_cb, ac);

    /* start sipc authencation action. */
    sipc_aut_action(sk, ac, response);

    g_free(digest);
    g_free(nonce);
    g_free(key);
    g_free(aeskey);
    g_free(response);

    return FALSE;
}
예제 #7
0
파일: fetion.c 프로젝트: celiachen/hybrid
static gboolean
fx_login(HybridAccount *imac)
{
    HybridSslConnection *conn;

    hybrid_debug_info("fetion", "fetion is now logging in...");

    ac = fetion_account_create(imac, imac->username, imac->password);

    hybrid_account_set_protocol_data(imac, ac);

    conn = hybrid_ssl_connect(SSI_SERVER, 443, ssi_auth_action, ac);

    return TRUE;
}
예제 #8
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
/**
 * Callback function to handle the invite-connect event, when we
 * get this acknowledge message, we should start to invite the buddy
 * to the conversation.
 *
 * The message received is:
 *
 * SIP-C/4.0 200 OK
 * I: 5
 * Q: 2 R
 * XI: 3d2ef745db9741a8946a57c40b0eb4d5
 * X: 1200
 * K: text/plain
 * K: text/html-fragment
 * K: multiparty
 * K: nudge
 *
 * then we send out invite-buddy request:
 */
static gint
chat_reg_cb(fetion_account *account, const gchar *sipmsg,
			fetion_transaction *trans)
{
	fetion_sip *sip;
	sip_header *eheader;
	gchar *body;
	gchar *sip_text;
	fetion_transaction *new_trans;
	fetion_buddy *buddy;

	sip = account->sip;

	fetion_sip_set_type(sip, SIP_SERVICE);

	if (!(buddy = fetion_buddy_find_by_userid(account, trans->userid))) {

		hybrid_debug_error("fetion", "invite new buddy failed");

		return HYBRID_ERROR;
	}

	eheader = sip_event_header_create(SIP_EVENT_INVITEBUDDY);
	fetion_sip_add_header(sip, eheader);

	body = generate_invite_buddy_body(buddy->sipuri);

	new_trans = transaction_clone(trans);
	transaction_set_callid(new_trans, sip->callid);
	transaction_set_callback(new_trans, invite_buddy_cb);
	transaction_add(account, new_trans);

	sip_text = fetion_sip_to_string(sip, body);
	g_free(body);

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

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

		hybrid_debug_error("fetion", "invite new buddy failed");

		return HYBRID_ERROR;
	}

	g_free(sip_text);

	return HYBRID_OK;
}
예제 #9
0
파일: fetion.c 프로젝트: celiachen/hybrid
/**
 * Process the synchronization message, when the contact list or the personal info
 * changed, the server will push this message to tell the client to update its
 * local cache file, well, we will not update the local cache file, we keep the
 * old version numbers, and reload it after the next logining.
 */
static void
process_sync_info(fetion_account *ac, const gchar *sipmsg)
{
    GSList       *list;
    gchar        *sid;
    fetion_buddy *buddy;
    HybridBuddy  *hb;

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

    if (!(list = sip_parse_sync(ac, sipmsg))) {
        return;
    }

    while (list) {
        buddy = (fetion_buddy*)list->data;

        list = g_slist_remove(list, buddy);

        if (buddy->status == 0) {
            continue;
        }

        if (!(hb = hybrid_blist_find_buddy(ac->account, buddy->userid))) {
            continue;
        }

        if (buddy->status == 1) {

            hybrid_blist_set_buddy_status(hb, TRUE);

        } else {
            hybrid_blist_set_buddy_status(hb, FALSE);
        }

        sid = get_sid_from_sipuri(buddy->sipuri);

        hybrid_message_box_show(HYBRID_MESSAGE_INFO,
                _("Buddy <b>%s</b> has %s your add-buddy request."),
                buddy->localname && *(buddy->localname) != '\0' ?
                buddy->localname : sid,
                buddy->status == 1 ? _("accepted") : _("declined"));
    }

}
예제 #10
0
파일: fx_login.c 프로젝트: GCrean/hybrid
static void
pic_code_ok_cb(HybridAccount *account, const gchar *code, gpointer user_data)
{
    fetion_account *ac = (fetion_account*)user_data;

    hybrid_debug_info("fetion", "pic code %s inputed.", code);

    g_free(ac->verification->code);
    ac->verification->code = g_strdup(code);

    if (VERIFY_TYPE_SSI == verify_data.type) {
        hybrid_ssl_connect(SSI_SERVER, 443, ssi_auth_action, ac);

    } else {
        printf("%s\n", verify_data.response);
        sipc_aut_action(verify_data.sipc_conn, ac, verify_data.response);
    }
}
예제 #11
0
파일: pref.c 프로젝트: CinsonChen/hybrid
gboolean
hybrid_pref_get_boolean(const gchar *name)
{
    xmlnode *node;
    gchar   *type;
    gchar   *value;

    g_return_val_if_fail(hybrid_pref != NULL, FALSE);
    g_return_val_if_fail(hybrid_pref->root != NULL, FALSE);

    if (!(node = xmlnode_find(hybrid_pref->root, name))) {
        return FALSE;
    }

    if (!xmlnode_has_prop(node, "type")) {

        hybrid_debug_info("pref", "invalid pref node.");
        
        return FALSE;
    }

    type = xmlnode_prop(node, "type");

    if (g_strcmp0(type, "bool") != 0) {

        hybrid_debug_error("pref",
                "bool pref node with a type which is not bool.");

        return FALSE;
    }

    value = xmlnode_content(node);

    if (g_strcmp0(value, "0") == 0) {

        g_free(value);
        return FALSE;

    } else {

        g_free(value);
        return TRUE;
    }
}
예제 #12
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
gint
fetion_message_send_to_me(fetion_account *account, const gchar *text)
{
	sip_header *toheader;
	sip_header *eheader;
	gchar *sip_text;
	fetion_sip *sip;
	fetion_transaction *trans;

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

	sip = account->sip;

	fetion_sip_set_type(sip, SIP_MESSAGE);

	toheader = sip_header_create("T", account->sipuri);
	eheader  = sip_event_header_create(SIP_EVENT_SENDCATMESSAGE);

	fetion_sip_add_header(sip, toheader);
	fetion_sip_add_header(sip, eheader);

	trans = transaction_create();
	transaction_set_callid(trans, sip->callid);
	transaction_set_callback(trans, sms_to_me_cb);
	transaction_add(account, trans);

	sip_text = fetion_sip_to_string(sip, text);

	hybrid_debug_info("fetion", "send sms to youself,send:\n%s", sip_text);

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

		hybrid_debug_error("fetion", "send message to yourself error.");

		return HYBRID_ERROR;
	}

	g_free(sip_text);

	return HYBRID_OK;
}
예제 #13
0
gint
fetion_buddy_add(fetion_account *account, const gchar *groupid,
					const gchar *no, const gchar *alias)
{
	fetion_sip *sip;
	sip_header *eheader;
	fetion_transaction *trans;
	gchar *body;
	gchar *sip_text;

	g_return_val_if_fail(account != NULL, HYBRID_ERROR);
	g_return_val_if_fail(groupid != NULL, HYBRID_ERROR);
	g_return_val_if_fail(no != NULL, HYBRID_ERROR);

	sip = account->sip;

	fetion_sip_set_type(sip, SIP_SERVICE);
	eheader = sip_event_header_create(SIP_EVENT_ADDBUDDY);
	fetion_sip_add_header(sip, eheader);

	trans = transaction_create();
	transaction_set_callid(trans, sip->callid);
	transaction_set_callback(trans, buddy_add_cb);
	transaction_add(account, trans);

	body = generate_buddy_add_body(no, groupid, alias, account->nickname);
	sip_text = fetion_sip_to_string(sip, body);
	g_free(body);

	hybrid_debug_info("fetion", "add buddy,send:\n%s", sip_text);

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

		hybrid_debug_error("fetion", "add buddy failed");

		return HYBRID_ERROR;
	}

	g_free(sip_text);

	return HYBRID_OK;
}
예제 #14
0
파일: fetion.c 프로젝트: celiachen/hybrid
static void
process_add_buddy(fetion_account *ac, const gchar *sipmsg)
{
    gchar                *sipuri;
    gchar                *userid;
    gchar                *desc;
    HybridBuddyReqWindow *req;

    hybrid_debug_info("fetion", "received add-buddy request:\n%s", sipmsg);

    if (sip_parse_appbuddy(sipmsg, &userid, &sipuri, &desc) != HYBRID_OK) {
        return;
    }

    req = hybrid_buddy_request_window_create(ac->account, userid, desc);
    hybrid_buddy_request_set_user_data(req, sipuri, g_free);

    g_free(userid);
    g_free(desc);
}
예제 #15
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
gint
fetion_message_new_chat(fetion_account *account, const gchar *userid,
								const gchar *text)
{
	fetion_sip *sip;
	sip_header *eheader;
	fetion_transaction *trans;
	gchar *sip_text;

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

	sip = account->sip;

	/*start chat*/
	fetion_sip_set_type(sip, SIP_SERVICE);
	eheader = sip_event_header_create(SIP_EVENT_STARTCHAT);
	fetion_sip_add_header(sip, eheader);

	trans = transaction_create();
	transaction_set_callid(trans, sip->callid);
	transaction_set_userid(trans, userid);
	transaction_set_msg(trans, text);
	transaction_set_callback(trans, new_chat_cb);
	transaction_add(account, trans);

	sip_text = fetion_sip_to_string(sip, NULL);

	hybrid_debug_info("fetion", "new chat,send:\n%s", sip_text);

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

		hybrid_debug_error("fetion", "new chat failed");

		return HYBRID_ERROR;
	}
	
	g_free(sip_text); 

	return HYBRID_OK;
}
예제 #16
0
gint
fetion_buddy_get_info(fetion_account *ac, const gchar *userid,
		TransCallback callback, gpointer data)
{
	fetion_transaction *trans;
	fetion_sip *sip;
	sip_header *eheader;
	gchar *body;
	gchar *res;

	g_return_val_if_fail(ac != NULL, HYBRID_ERROR);
	g_return_val_if_fail(userid != NULL, HYBRID_ERROR);

	sip = ac->sip;

	fetion_sip_set_type(sip , SIP_SERVICE);
	eheader = sip_event_header_create(SIP_EVENT_GETCONTACTINFO);

	trans = transaction_create();
	transaction_set_callid(trans, sip->callid);
	transaction_set_userid(trans, userid);
	transaction_set_callback(trans, callback);
	transaction_set_data(trans, data);
	transaction_add(ac, trans);

	fetion_sip_add_header(sip, eheader);
	body = generate_get_info_body(userid);
	res = fetion_sip_to_string(sip, body);
	g_free(body);

	hybrid_debug_info("fetion", "send:\n%s", res);

	if (send(ac->sk, res, strlen(res), 0) == -1) {
		g_free(res);
		return HYBRID_ERROR;
	}

	g_free(res);

	return HYBRID_OK;
}
예제 #17
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
static gint
sms_response_cb(fetion_account *account, const gchar *sipmsg, 
						fetion_transaction *trans)
{
	gint code;

	g_source_remove(trans->timer);

	code = fetion_sip_get_code(sipmsg);

	hybrid_debug_info("fetion", "send message response:\n%s", sipmsg);

	if (code != 200 && code != 280) {
		return HYBRID_ERROR;
	}

	/* TODO add error message to textview */


	return HYBRID_OK;
}
예제 #18
0
gboolean
xmpp_stream_init(gint sk, XmppStream *stream)
{
    gchar *msg;

    stream->sk = sk;

    /* send version. */
    msg = "<?xml version='1.0' ?>";

    if (send(sk, msg, strlen(msg), 0) == -1) {

        hybrid_account_error_reason(stream->account->account,
                                    "send initial jabber request failed");

        return FALSE;
    }

    /* send initiate stream request. */
    msg = create_initiate_stream(stream);

    hybrid_debug_info("xmpp", "send initite jabber stream:\n%s", msg);

    if (send(sk, msg, strlen(msg), 0) == -1) {

        hybrid_account_error_reason(stream->account->account,
                                    "send initial jabber request failed");
        g_free(msg);

        return FALSE;
    }

    g_free(msg);

    stream->source = hybrid_event_add(sk, HYBRID_EVENT_READ,
                                      (input_func)stream_recv_cb, stream);

    return FALSE;
}
예제 #19
0
파일: pref.c 프로젝트: CinsonChen/hybrid
gint
hybrid_pref_get_int(const gchar *name)
{
    xmlnode *node;
    gchar   *type;
    gchar   *value;
    gint     value_int;

    g_return_val_if_fail(hybrid_pref != NULL, FALSE);
    g_return_val_if_fail(hybrid_pref->root != NULL, FALSE);

    if (!(node = xmlnode_find(hybrid_pref->root, name))) {
        return -1;
    }

    if (!xmlnode_has_prop(node, "type")) {

        hybrid_debug_info("pref", "invalid pref node.");
        
        return -1;
    }

    type = xmlnode_prop(node, "type");

    if (g_strcmp0(type, "int") != 0) {

        hybrid_debug_error("pref",
                "integer pref node with a type which is not int.");

        return -1;
    }

    value = xmlnode_content(node);
    value_int = atoi(value);
    g_free(value);

    return value_int;
}
예제 #20
0
파일: connect.c 프로젝트: celiachen/hybrid
/**
 * set the socket to be nonblock
 */
static gint
nonblock(gint sk)
{
    gint flag;

    g_return_val_if_fail(sk != 0, HYBRID_ERROR);

    hybrid_debug_info("option", "set socket to be nonblock");

    if ((flag = fcntl(sk, F_GETFL, 0)) == -1) {
        hybrid_debug_error("socket", "set socket to be nonblock:%s",
                strerror(errno));
        return HYBRID_ERROR;
    }

    if ((flag = fcntl(sk, F_SETFL, flag | O_NONBLOCK)) == -1) {
        hybrid_debug_error("socket", "set socket to be nonblock:%s",
                strerror(errno));
        return HYBRID_ERROR;
    }

    return HYBRID_OK;
}
예제 #21
0
/**
 * Start a new stream on the sasl layer.
 */
static void
xmpp_stream_new_on_sasl(XmppStream *stream)
{
    gchar *msg;

    g_return_if_fail(stream != NULL);

    msg = create_initiate_stream(stream);

    xmpp_stream_set_id(stream, NULL);
    xmpp_stream_set_state(stream, XMPP_STATE_SASL_STREAM_STARTING);

    hybrid_debug_info("xmpp", "new stream on sasl,send:\n%s", msg);

    if (hybrid_ssl_write(stream->ssl, msg, strlen(msg)) == -1) {
        
        hybrid_account_error_reason(stream->account->account,
                "start new stream on sasl layer error.");
        return;
    }

    g_free(msg);
}
예제 #22
0
파일: fx_login.c 프로젝트: GCrean/hybrid
/**
 * Callback function to handle the pushed message.
 */
gboolean
hybrid_push_cb(gint sk, gpointer user_data)
{
    gchar           sipmsg[BUF_LENGTH];
    gchar          *pos;
    gchar          *h;
    gchar          *msg;
    fetion_account *ac = (fetion_account*)user_data;
    gint            n;
    guint           len, data_len;

    if ((n = recv(sk, sipmsg, sizeof(sipmsg), 0)) == -1) {
        hybrid_account_error_reason(ac->account, _("connection terminated"));
        return FALSE;
    } else if (0 == n) {
        hybrid_debug_info("fetion", "hybrid_push_cb in fetion received 0 bytes,"
                          "connection closed.");
        channel_list = g_slist_remove(channel_list, ac);
        fetion_account_destroy(ac);
        close(sk);
        return FALSE;
    }

    sipmsg[n] = '\0';

    data_len = ac->buffer ? strlen(ac->buffer) : 0;
    ac->buffer = (gchar*)realloc(ac->buffer, data_len + n + 1);
    memcpy(ac->buffer + data_len, sipmsg, n + 1);

recheck:
    data_len = ac->buffer ? strlen(ac->buffer) : 0;

    if ((pos = strstr(ac->buffer, "\r\n\r\n"))) {
        pos += 4;
        h = (gchar*)g_malloc0(data_len - strlen(pos) + 1);
        memcpy(h, ac->buffer, data_len - strlen(pos));
        h[data_len - strlen(pos)] = '\0';

        if (strstr(h, "L: ")) {
            len = fetion_sip_get_length(ac->buffer);

            if (len <= strlen(pos)) {
                msg = (gchar*)g_malloc0(strlen(h) + len + 1);
                memcpy(msg, ac->buffer, strlen(h) + len);
                msg[strlen(h) + len] = '\0';
                /* A message is complete, process it. */
                process_pushed(ac, msg);

                memmove(ac->buffer, ac->buffer + strlen(msg), data_len - strlen(msg));
                ac->buffer = (gchar*)realloc(ac->buffer, data_len - strlen(msg) + 1);
                ac->buffer[data_len - strlen(msg)] = '\0';

                g_free(msg);
                g_free(h);
                msg = NULL;
                h = NULL;

                goto recheck;
            }

        } else {
            /* A message is complete, process it. */
            process_pushed(ac, h);

            memmove(ac->buffer, ac->buffer + strlen(h), data_len - strlen(h));
            ac->buffer = (gchar*)realloc(ac->buffer, data_len - strlen(h) + 1);
            ac->buffer[data_len - strlen(h)] = '\0';

            g_free(h);
            h = NULL;
            goto recheck;
        }
        g_free(h);
    }

    return TRUE;
}
예제 #23
0
파일: network.c 프로젝트: celiachen/hybrid
gint
resolve_host(const gchar *hostname, gchar *ip)
{
    g_return_val_if_fail(hostname != NULL, HYBRID_ERROR);

    struct addrinfo    *result;
    struct addrinfo    *rp;
    struct sockaddr_in *addr;
    gchar              *hash_value;
    gchar               buf[32];

    hybrid_debug_info("dns", "resolve host \'%s\'", hostname);

    if (host_hash && (hash_value = g_hash_table_lookup(host_hash, hostname))) {
        strcpy(ip, (gchar*)hash_value);
        hybrid_debug_info("dns", "ip of \'%s\' is \'%s\'[cached]", hostname, ip);
        return HYBRID_OK;
    }

    if (getaddrinfo(hostname, NULL, NULL, &result) != 0) {
        hybrid_debug_error("resolve_host", "resolve host \'%s\' failed",
                hostname);
        return HYBRID_ERROR;
    }

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        addr = (struct sockaddr_in*)rp->ai_addr;

        memset(buf, 0, sizeof(buf));

        if (!inet_ntop(AF_INET, (void*)&addr->sin_addr, buf, 16)) {

            hybrid_debug_error("dns", "reslove host \'%s\' failed when"
                               " transforming binary ip address to doted ip address",
                               hostname);

            continue;
        }

        if (g_strcmp0(buf, "0.0.0.0") == 0    ||
            g_strcmp0(buf, "127.0.0.1")          == 0) {
            continue;
        }

        strncpy(ip, buf, strlen(buf));
        goto addr_success;
    }

    return HYBRID_ERROR;

 addr_success:

    if (!host_hash) {
        host_hash = g_hash_table_new(g_str_hash, g_str_equal);
    }

    hash_value = g_strdup(ip);

    g_hash_table_insert(host_hash, (gchar*)hostname, hash_value);

    hybrid_debug_info("dns", "ip of \'%s\' is \'%s\'[new]", hostname, ip);

    return HYBRID_OK;
}
예제 #24
0
파일: fx_login.c 프로젝트: GCrean/hybrid
/**
 * 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;
}
예제 #25
0
/**
 * Start sasl authentication.
 */
static void
xmpp_stream_startsasl(XmppStream *stream)
{
    guchar  *auth;
    gchar   *auth_encoded;
    gchar   *xml_string;
    gint     username_len;
    gint     password_len;
    xmlnode *node;

    g_return_if_fail(stream != NULL);

    hybrid_debug_info("xmpp", "start sasl authentication.");

    hybrid_account_set_connection_string(stream->account->account,
                                         "Start sasl authentication.");

    xmpp_stream_set_state(stream, XMPP_STATE_SASL_AUTHENTICATING);
    /*
     * construct the authentication string to be base64 encoded,
     * which is in form of '\0 + username + \0 + password '
     */
    username_len = strlen(stream->account->username);
    password_len = strlen(stream->account->password);

    auth = g_malloc0(username_len + password_len + 2);

    auth[0] = '\0';
    memcpy(auth + 1, stream->account->username, username_len);

    auth[username_len + 1] = '\0';
    memcpy(auth + 2 + username_len, stream->account->password,
            password_len);

    auth_encoded = hybrid_base64_encode(auth, username_len + password_len + 2);

    g_free(auth);

    /* construct the xml string, which is in form of:
     *
     * <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" 
     * mechanism="PLAIN">encoded sasl string</auth> 
     */
    node = xmlnode_create("auth");

    xmlnode_new_namespace(node, NULL, NS_XMPP_SASL);
    xmlnode_new_namespace(node, "ga", "http://www.google.com/talk/protocol/auth");
    xmlnode_new_prop(node, "ga:client-uses-full-bind-result", "true");
    xmlnode_new_prop(node, "mechanism", "PLAIN");
    xmlnode_set_content(node, auth_encoded);

    g_free(auth_encoded);
    
    xml_string = xmlnode_to_string(node);
    xmlnode_free(node);

    hybrid_debug_info("xmpp", "sasl send:\n%s", xml_string);

    if (hybrid_ssl_write(stream->ssl, xml_string,
                strlen(xml_string)) == -1) {

        hybrid_account_error_reason(stream->account->account,
                "SASL authentication error.");

        return;
    }

    g_free(xml_string);

}
예제 #26
0
파일: fx_login.c 프로젝트: GCrean/hybrid
/**
 * Start sipc authencation with the response string.
 *
 * @param response It is generated by generate_response().
 */
static gint
sipc_aut_action(gint sk, fetion_account *ac, const gchar *response)
{
    gchar              *sipmsg;
    gchar              *body;
    sip_header         *aheader;
    sip_header         *akheader;
    sip_header         *ackheader;
    fetion_transaction *trans;
    fetion_sip         *sip = ac->sip;

    ac->sk = sk;

    hybrid_debug_info("fetion", "sipc authencation action");

    hybrid_account_set_connection_string(ac->account,
                                         _("start sipc authentication..."));

    body = generate_auth_body(ac);

    fetion_sip_set_type(sip, SIP_REGISTER);

    aheader     = sip_authentication_header_create(response);
    akheader = sip_header_create("AK", "ak-value");

    trans = transaction_create();
    transaction_set_callid(trans, sip->callid);
    transaction_set_callback(trans, sipc_auth_cb);
    transaction_add(ac, trans);

    fetion_sip_add_header(sip, aheader);
    fetion_sip_add_header(sip, akheader);

    if(ac->verification != NULL && ac->verification->algorithm != NULL)    {
        ackheader = sip_ack_header_create(ac->verification->code,
                                          ac->verification->algorithm,
                                          ac->verification->type,
                                          ac->verification->guid);
        fetion_sip_add_header(sip , ackheader);
    }
    fetion_verification_destroy(ac->verification);
    ac->verification = NULL;

    sipmsg = fetion_sip_to_string(sip, body);

    g_free(body);

    hybrid_debug_info("fetion", "Start sipc authentication , with ak-value");
    hybrid_debug_info("fetion", "send:\n%s", sipmsg);

    if(send(sk, sipmsg, strlen(sipmsg), 0) == -1) {
        hybrid_debug_error("fetion", "send sipc auth request:%s\n",
                strerror(errno));
        g_free(sipmsg);

        return HYBRID_ERROR;
    }
    g_free(sipmsg);

    return 0;
}
예제 #27
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
gint
fetion_message_send(fetion_account *account, const gchar *userid,
						const gchar *text)
{
	fetion_sip *sip;
	sip_header *toheader;
	sip_header *cheader;
	sip_header *kheader;
	sip_header *nheader;
	gchar *sip_text;
	fetion_buddy *buddy;

	g_return_val_if_fail(account != NULL, HYBRID_ERROR);
	g_return_val_if_fail(userid != NULL && *userid != '\0', HYBRID_ERROR);
	g_return_val_if_fail(text != NULL, HYBRID_ERROR);

	sip = account->sip;

	if (!(buddy = fetion_buddy_find_by_userid(account, userid))) {
		hybrid_debug_error("fetion", "FATAL, can't find specified buddy");

		return HYBRID_ERROR;
	}

	fetion_transaction *trans = transaction_create();

	transaction_set_userid(trans, userid);
	transaction_set_msg(trans, text);

	if (!account->channel_ready) {
		/* If the channel is not ready, make the transaction to wait
		 * until the transaction is ready */
		transaction_wait(account, trans);

		hybrid_debug_info("fetion", "channel not ready, transaction sleep.");

		return HYBRID_OK;
	}

	fetion_sip_set_type(sip, SIP_MESSAGE);

	nheader  = sip_event_header_create(SIP_EVENT_CATMESSAGE);
	toheader = sip_header_create("T", buddy->sipuri);
	cheader  = sip_header_create("C", "text/plain");
	kheader  = sip_header_create("K", "SaveHistory");
	fetion_sip_add_header(sip, toheader);
	fetion_sip_add_header(sip, cheader);
	fetion_sip_add_header(sip, kheader);
	fetion_sip_add_header(sip, nheader);

	transaction_set_callid(trans, sip->callid);
	transaction_set_callback(trans, sms_response_cb);

	transaction_set_data(trans, account);
	transaction_set_timeout(trans, (GSourceFunc)sms_timeout_cb, trans);
	transaction_add(account, trans);

	sip_text = fetion_sip_to_string(sip, text);

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

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

		return HYBRID_ERROR;
	}

	g_free(sip_text);

	return HYBRID_OK;
}
예제 #28
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
gint
fetion_process_message(fetion_account *account, const gchar *sipmsg)
{
	gchar *from;
	gchar *sid;
	gchar *callid;
	gchar *sequence;
	gchar *sendtime;
	gchar *text;
	gchar *sip_text;
	fetion_buddy *buddy;

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

	if (!(text = strstr(sipmsg, "\r\n\r\n"))) {
		hybrid_debug_error("fetion", "invalid message received\n");

		return HYBRID_ERROR;
	}

	text += 4;

	from     = sip_header_get_attr(sipmsg, "F");
	callid   = sip_header_get_attr(sipmsg, "I");
	sendtime = sip_header_get_attr(sipmsg, "D");
	sequence = sip_header_get_attr(sipmsg, "Q");

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

	hybrid_debug_info("fetion", "message response, send:\n%s", sip_text);

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

		return HYBRID_ERROR;
	}

	g_free(sip_text);

	sid = get_sid_from_sipuri(from);
	g_free(from);

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

		hybrid_debug_error("fetion", "invalid message received\n");
		g_free(sid);

		return HYBRID_ERROR;
	}

	hybrid_conv_got_message(account->account, buddy->userid, text, time(NULL));

	g_free(sid);


	return HYBRID_OK;
}
예제 #29
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
static gint
process_invite_conn_cb(gint sk, gpointer user_data)
{
	invite_conn_data *data;
	fetion_account *account;
	fetion_sip *sip;
	gchar *credential;
	gchar *sip_text;
	sip_header *aheader;
	sip_header *theader;
	sip_header *mheader;
	sip_header *nheader;

	data = (invite_conn_data*)user_data;
	account = data->account;
	credential = data->credential;
	g_free(data);

	account->sk = sk;
	sip = account->sip;

	account->source = hybrid_event_add(sk, HYBRID_EVENT_READ,
							hybrid_push_cb, account);

	if (account->source == 0) {

		hybrid_debug_error("fetion", "add read event error");

		return HYBRID_ERROR;
	}

	fetion_sip_set_type(sip, SIP_REGISTER);
	aheader = sip_credential_header_create(credential);
	theader = sip_header_create("K", "text/html-fragment");
	mheader = sip_header_create("K", "multiparty");
	nheader = sip_header_create("K", "nudge");

	g_free(credential);

	fetion_sip_add_header(sip, aheader);
	fetion_sip_add_header(sip, theader);
	fetion_sip_add_header(sip, mheader);
	fetion_sip_add_header(sip, nheader);

	sip_text = fetion_sip_to_string(sip, NULL);

	hybrid_debug_info("feiton", "register to a new channel:\n%s", sip_text);

	if (send(sk, sip_text, strlen(sip_text), 0) == -1) {
		
		hybrid_debug_error("fetion", "register to new channel error.");

		g_free(sip_text);

		return HYBRID_ERROR;
	}

	g_free(sip_text);

	return HYBRID_OK;
}
예제 #30
0
파일: fx_msg.c 프로젝트: chenyukang/hybrid
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;
}