Exemple #1
0
static void
_handle_caps(const char *const jid, XMPPCaps *caps)
{
    // hash supported, xep-0115, cache against ver
    if (g_strcmp0(caps->hash, "sha-1") == 0) {
        log_info("Hash %s supported", caps->hash);
        if (caps->ver) {
            if (caps_cache_contains(caps->ver)) {
                log_info("Capabilities cache hit: %s, for %s.", caps->ver, jid);
                caps_map_jid_to_ver(jid, caps->ver);
            } else {
                log_info("Capabilities cache miss: %s, for %s, sending service discovery request", caps->ver, jid);
                char *id = create_unique_id("caps");
                iq_send_caps_request(jid, id, caps->node, caps->ver);
                free(id);
            }
        }

    // unsupported hash, xep-0115, associate with JID, no cache
    } else if (caps->hash) {
        log_info("Hash %s not supported: %s, sending service discovery request", caps->hash, jid);
        char *id = create_unique_id("caps");
        iq_send_caps_request_for_jid(jid, id, caps->node, caps->ver);
        free(id);

   // no hash, legacy caps, cache against node#ver
   } else if (caps->node && caps->ver) {
        log_info("No hash specified: %s, legacy request made for %s#%s", jid, caps->node, caps->ver);
        char *id = create_unique_id("caps");
        iq_send_caps_request_legacy(jid, id, caps->node, caps->ver);
        free(id);
    } else {
        log_info("No hash specified: %s, could not create ver string, not sending service discovery request.", jid);
    }
}
Exemple #2
0
ClientSession_t * client_session_new(client_sock *c)
{
	char unique_id[UID_SIZE];

	ClientSession_t * session = g_new0(ClientSession_t,1);
	clientbase_t *ci;

	if (c)
		ci = client_init(c);
	else
		ci = client_init(NULL);

	session->state = CLIENTSTATE_INITIAL_CONNECT;

	gethostname(session->hostname, sizeof(session->hostname));

	memset(unique_id,0,sizeof(unique_id));
	create_unique_id(unique_id, 0);
	session->apop_stamp = g_strdup_printf("<%s@%s>", unique_id, session->hostname);

        event_set(ci->rev, ci->rx, EV_READ|EV_PERSIST, socket_read_cb, (void *)session);
        event_set(ci->wev, ci->tx, EV_WRITE, socket_write_cb, (void *)session);

	session->ci = ci;
	session->rbuff = g_string_new("");

	return session;
}
Exemple #3
0
char*
message_send_chat_otr(const char *const barejid, const char *const msg)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();

    char *state = _session_state(barejid);
    char *jid = _session_jid(barejid);
    char *id = create_unique_id("msg");

    xmpp_stanza_t *message = stanza_create_message(ctx, id, barejid, STANZA_TYPE_CHAT, msg);
    free(jid);

    if (state) {
        stanza_attach_state(ctx, message, state);
    }

    stanza_attach_carbons_private(ctx, message);
    stanza_attach_hints_no_copy(ctx, message);
    stanza_attach_hints_no_store(ctx, message);

    if (prefs_get_boolean(PREF_RECEIPTS_REQUEST)) {
        stanza_attach_receipt_request(ctx, message);
    }

    xmpp_send(conn, message);
    xmpp_stanza_release(message);

    return id;
}
Exemple #4
0
void
roster_send_remove_from_group(const char * const group, PContact contact)
{
    GSList *groups = p_contact_groups(contact);
    GSList *new_groups = NULL;
    while (groups) {
        if (strcmp(groups->data, group) != 0) {
            new_groups = g_slist_append(new_groups, strdup(groups->data));
        }
        groups = g_slist_next(groups);
    }

    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();

    // add an id handler to handle the response
    char *unique_id = create_unique_id(NULL);
    GroupData *data = malloc(sizeof(GroupData));
    data->group = strdup(group);
    if (p_contact_name(contact)) {
        data->name = strdup(p_contact_name(contact));
    } else {
        data->name = strdup(p_contact_barejid(contact));
    }

    xmpp_id_handler_add(conn, _group_remove_handler, unique_id, data);
    xmpp_stanza_t *iq = stanza_create_roster_set(ctx, unique_id, p_contact_barejid(contact),
        p_contact_name(contact), new_groups);
    xmpp_send(conn, iq);
    xmpp_stanza_release(iq);
    free(unique_id);
}
Exemple #5
0
void
roster_send_add_to_group(const char *const group, PContact contact)
{
    GSList *groups = p_contact_groups(contact);
    GSList *new_groups = NULL;
    while (groups) {
        new_groups = g_slist_append(new_groups, strdup(groups->data));
        groups = g_slist_next(groups);
    }

    new_groups = g_slist_append(new_groups, strdup(group));
    // add an id handler to handle the response
    char *unique_id = create_unique_id(NULL);
    GroupData *data = malloc(sizeof(GroupData));
    data->group = strdup(group);
    if (p_contact_name(contact)) {
        data->name = strdup(p_contact_name(contact));
    } else {
        data->name = strdup(p_contact_barejid(contact));
    }

    xmpp_ctx_t * const ctx = connection_get_ctx();
    iq_id_handler_add(unique_id, _group_add_id_handler, (ProfIdFreeCallback)_free_group_data, data);
    xmpp_stanza_t *iq = stanza_create_roster_set(ctx, unique_id, p_contact_barejid(contact),
        p_contact_name(contact), new_groups);
    iq_send_stanza(iq);
    xmpp_stanza_release(iq);
    free(unique_id);
}
Exemple #6
0
void
blocking_request(void)
{
    char *id = create_unique_id("blocked_list_request");
    xmpp_ctx_t *ctx = connection_get_ctx();
    xmpp_stanza_t *iq;

    if (blocked) {
        g_list_free_full(blocked, free);
        blocked = NULL;
    }

    if (blocked_ac) {
        autocomplete_free(blocked_ac);
    }
    blocked_ac = autocomplete_new();

    iq_id_handler_add(id, _blocklist_result_handler, NULL, NULL);

    iq = stanza_create_blocked_list_request(ctx);
    xmpp_stanza_set_id(iq, id);
    iq_send_stanza(iq);
    xmpp_stanza_release(iq);
    free(id);
}
Exemple #7
0
static int store_ids(GtFeatureNode *fn, void *data, GtError *err)
{
  GtGFF3Visitor *gff3_visitor = (GtGFF3Visitor*) data;
  AddIDInfo add_id_info;
  int had_err = 0;
  GtStr *id;

  gt_error_check(err);
  gt_assert(fn && gff3_visitor);

  if (gt_feature_node_has_children(fn) || gt_feature_node_is_multi(fn) ||
      (gff3_visitor->retain_ids && gt_feature_node_get_attribute(fn, "ID"))) {
    if (gt_feature_node_is_multi(fn)) {
      id = gt_hashmap_get(gff3_visitor->feature_node_to_unique_id_str,
                          gt_feature_node_get_multi_representative(fn));
      if (!id) {
        /* the representative does not have its own id yet -> create it */
        if (gff3_visitor->retain_ids) {
          id = make_id_unique(gff3_visitor,
                              gt_feature_node_get_multi_representative(fn));
        }
        else {
          id = create_unique_id(gff3_visitor,
                                gt_feature_node_get_multi_representative(fn));
        }
      }
      /* store id for feature, if the feature was not the representative */
      if (gt_feature_node_get_multi_representative(fn) != fn) {
        gt_hashmap_add(gff3_visitor->feature_node_to_unique_id_str, fn,
                       gt_str_ref(id));
      }
    }
    else {
      if (gff3_visitor->retain_ids)
        id = make_id_unique(gff3_visitor, fn);
      else
        id = create_unique_id(gff3_visitor, fn);
    }
    /* for each child -> store the parent feature in the hash map */
    add_id_info.gt_feature_node_to_id_array =
      gff3_visitor->feature_node_to_id_array,
    add_id_info.id = gt_str_get(id);
    had_err = gt_feature_node_traverse_direct_children(fn, &add_id_info, add_id,
                                                       err);
  }
  return had_err;
}
Exemple #8
0
char*
message_send_chat_pgp(const char *const barejid, const char *const msg)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();

    char *state = _session_state(barejid);
    char *jid = _session_jid(barejid);
    char *id = create_unique_id("msg");

    xmpp_stanza_t *message = NULL;
#ifdef HAVE_LIBGPGME
    char *account_name = jabber_get_account_name();
    ProfAccount *account = accounts_get_account(account_name);
    if (account->pgp_keyid) {
        Jid *jidp = jid_create(jid);
        char *encrypted = p_gpg_encrypt(jidp->barejid, msg);
        if (encrypted) {
            message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, "This message is encrypted.");
            xmpp_stanza_t *x = xmpp_stanza_new(ctx);
            xmpp_stanza_set_name(x, STANZA_NAME_X);
            xmpp_stanza_set_ns(x, STANZA_NS_ENCRYPTED);
            xmpp_stanza_t *enc_st = xmpp_stanza_new(ctx);
            xmpp_stanza_set_text(enc_st, encrypted);
            xmpp_stanza_add_child(x, enc_st);
            xmpp_stanza_release(enc_st);
            xmpp_stanza_add_child(message, x);
            xmpp_stanza_release(x);
            free(encrypted);
        } else {
            message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
        }
        jid_destroy(jidp);
    } else {
        message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
    }
    account_free(account);
#else
    message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
#endif
    free(jid);

    if (state) {
        stanza_attach_state(ctx, message, state);
    }

    stanza_attach_carbons_private(ctx, message);

    if (prefs_get_boolean(PREF_RECEIPTS_REQUEST)) {
        stanza_attach_receipt_request(ctx, message);
    }

    xmpp_send(conn, message);
    xmpp_stanza_release(message);

    return id;
}
Exemple #9
0
void
roster_send_add_new(const char *const barejid, const char *const name)
{
    xmpp_ctx_t * const ctx = connection_get_ctx();
    char *id = create_unique_id("roster");
    xmpp_stanza_t *iq = stanza_create_roster_set(ctx, id, barejid, name, NULL);
    free(id);
    send_iq_stanza(iq);
    xmpp_stanza_release(iq);
}
Exemple #10
0
void
roster_send_name_change(const char *const barejid, const char *const new_name, GSList *groups)
{
    xmpp_ctx_t * const ctx = connection_get_ctx();
    char *id = create_unique_id("roster");
    xmpp_stanza_t *iq = stanza_create_roster_set(ctx, id, barejid, new_name, groups);
    free(id);
    send_iq_stanza(iq);
    xmpp_stanza_release(iq);
}
Exemple #11
0
void read_unique_id(uint32_t * id) {
  if (!unique_id_created) {
      create_unique_id();
      unique_id_created = true;
  }

  id[0] = unique_id[0];
  id[1] = unique_id[1];
  id[2] = unique_id[2];
  id[3] = unique_id[3];
}
Exemple #12
0
void
message_send_groupchat(const char *const roomjid, const char *const msg)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();
    char *id = create_unique_id("muc");
    xmpp_stanza_t *message = stanza_create_message(ctx, id, roomjid, STANZA_TYPE_GROUPCHAT, msg);
    free(id);

    xmpp_send(conn, message);
    xmpp_stanza_release(message);
}
Exemple #13
0
void
message_send_private(const char *const fulljid, const char *const msg)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();
    char *id = create_unique_id("prv");
    xmpp_stanza_t *message = stanza_create_message(ctx, id, fulljid, STANZA_TYPE_CHAT, msg);
    free(id);

    xmpp_send(conn, message);
    xmpp_stanza_release(message);
}
Exemple #14
0
static void
_iq_disco_info_request(gchar *jid)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();
    char *id = create_unique_id("disco_info");
    xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, jid, NULL);

    xmpp_id_handler_add(conn, _disco_info_response_handler, id, NULL);

    xmpp_send(conn, iq);
    xmpp_stanza_release(iq);
}
Exemple #15
0
static char *
_get_caps_key(xmpp_stanza_t * const stanza)
{
    char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
    char *hash_type = stanza_caps_get_hash(stanza);
    char *node = stanza_get_caps_str(stanza);
    char *caps_key = NULL;
    char *id = NULL;

    log_debug("Presence contains capabilities.");

    if (node == NULL) {
        return NULL;
    }

    // xep-0115
    if ((hash_type != NULL) && (strcmp(hash_type, "sha-1") == 0)) {
        log_debug("Hash type %s supported.", hash_type);
        caps_key = strdup(node);
        id = create_unique_id("caps");

        _send_caps_request(node, caps_key, id, from);
        free(id);

    // unsupported hash or legacy capabilities
    } else {
        if (hash_type != NULL) {
            log_debug("Hash type %s unsupported.", hash_type);
        } else {
            log_debug("No hash type, using legacy capabilities.");
        }

        guint from_hash = g_str_hash(from);
        char from_hash_str[9];
        g_snprintf(from_hash_str, sizeof(from_hash_str), "%08x", from_hash);
        caps_key = strdup(from_hash_str);
        GString *id_str = g_string_new("capsreq_");
        g_string_append(id_str, from_hash_str);
        id = id_str->str;

        _send_caps_request(node, caps_key, id, from);

        g_string_free(id_str, TRUE);
    }

    g_free(node);

    return caps_key;
}
Exemple #16
0
static void
_presence_update(const resource_presence_t presence_type, const char * const msg,
    const int idle)
{
    if (jabber_get_connection_status() != JABBER_CONNECTED) {
        log_warning("Error setting presence, not connected.");
        return;
    }

    if (msg != NULL) {
        log_debug("Updating presence: %s, \"%s\"",
            string_from_resource_presence(presence_type), msg);
    } else {
        log_debug("Updating presence: %s",
            string_from_resource_presence(presence_type));
    }

    xmpp_ctx_t * const ctx = connection_get_ctx();
    xmpp_conn_t * const conn = connection_get_conn();
    const int pri =
        accounts_get_priority_for_presence_type(jabber_get_account_name(),
                                                presence_type);
    const char *show = stanza_get_presence_string_from_type(presence_type);

    connection_set_presence_message(msg);
    connection_set_priority(pri);

    xmpp_stanza_t *presence = stanza_create_presence(ctx);
    char *id = create_unique_id("presence");
    xmpp_stanza_set_id(presence, id);
    stanza_attach_show(ctx, presence, show);
    stanza_attach_status(ctx, presence, msg);
    stanza_attach_priority(ctx, presence, pri);
    stanza_attach_last_activity(ctx, presence, idle);
    stanza_attach_caps(ctx, presence);
    xmpp_send(conn, presence);
    _send_room_presence(conn, presence);
    xmpp_stanza_release(presence);

    // set last presence for account
    const char *last = show;
    if (last == NULL) {
        last = STANZA_TEXT_ONLINE;
    }
    accounts_set_last_presence(jabber_get_account_name(), last);
    free(id);
}
Exemple #17
0
void
presence_subscription(const char *const jid, const jabber_subscr_t action)
{
    assert(jid != NULL);

    Jid *jidp = jid_create(jid);
    autocomplete_remove(sub_requests_ac, jidp->barejid);

    const char *type = NULL;
    switch (action)
    {
        case PRESENCE_SUBSCRIBE:
            log_debug("Sending presence subscribe: %s", jid);
            type = STANZA_TYPE_SUBSCRIBE;
            break;
        case PRESENCE_SUBSCRIBED:
            log_debug("Sending presence subscribed: %s", jid);
            type = STANZA_TYPE_SUBSCRIBED;
            break;
        case PRESENCE_UNSUBSCRIBED:
            log_debug("Sending presence usubscribed: %s", jid);
            type = STANZA_TYPE_UNSUBSCRIBED;
            break;
        default:
            break;
    }
    if (!type) {
        log_error("Attempt to send unknown subscription action: %s", jid);
        return;
    }

    xmpp_ctx_t * const ctx = connection_get_ctx();
    xmpp_stanza_t *presence = xmpp_presence_new(ctx);

    char *id = create_unique_id("sub");
    xmpp_stanza_set_id(presence, id);
    free(id);

    xmpp_stanza_set_type(presence, type);
    xmpp_stanza_set_to(presence, jidp->barejid);
    jid_destroy(jidp);

    _send_presence_stanza(presence);

    xmpp_stanza_release(presence);
}
Exemple #18
0
static void
_presence_subscription(const char * const jid, const jabber_subscr_t action)
{
    assert(jid != NULL);

    xmpp_ctx_t * const ctx = connection_get_ctx();
    xmpp_conn_t * const conn = connection_get_conn();
    const char *type = NULL;

    Jid *jidp = jid_create(jid);

    autocomplete_remove(sub_requests_ac, jidp->barejid);

    switch (action)
    {
        case PRESENCE_SUBSCRIBE:
            log_debug("Sending presence subscribe: %s", jid);
            type = STANZA_TYPE_SUBSCRIBE;
            break;
        case PRESENCE_SUBSCRIBED:
            log_debug("Sending presence subscribed: %s", jid);
            type = STANZA_TYPE_SUBSCRIBED;
            break;
        case PRESENCE_UNSUBSCRIBED:
            log_debug("Sending presence usubscribed: %s", jid);
            type = STANZA_TYPE_UNSUBSCRIBED;
            break;
        default:
            log_warning("Attempt to send unknown subscription action: %s", jid);
            break;
    }

    xmpp_stanza_t *presence = xmpp_stanza_new(ctx);
    char *id = create_unique_id("sub");
    xmpp_stanza_set_id(presence, id);
    xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE);
    xmpp_stanza_set_type(presence, type);
    xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, jidp->barejid);
    xmpp_send(conn, presence);
    xmpp_stanza_release(presence);

    jid_destroy(jidp);
    free(id);
}
Exemple #19
0
static void
_handle_caps(xmpp_stanza_t *const stanza)
{
    char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);

    if (from) {
        char *hash = stanza_caps_get_hash(stanza);

        // hash supported xep-0115
        if (g_strcmp0(hash, "sha-1") == 0) {
            log_info("Hash %s supported");

            char *ver = stanza_get_caps_ver(stanza);
            if (ver) {
                if (caps_contains(ver)) {
                    log_info("Capabilities cached: %s", ver);
                    caps_map(from, ver);
                } else {
                    log_info("Capabilities not cached: %s, sending service discovery request", ver);
                    char *node = stanza_caps_get_node(stanza);
                    char *id = create_unique_id("caps");

                    iq_send_caps_request(from, id, node, ver);

                    free(id);
                }
            }

        // no hash, or not supported
        } else {
            if (hash) {
                log_info("Hash %s not supported, not sending service discovery request");
                // send service discovery request, cache against from full jid
            } else {
                log_info("No hash specified, not sending service discovery request");
                // do legacy
            }
        }
    }
}
Exemple #20
0
gboolean
blocked_remove(char *jid)
{
    GList *found = g_list_find_custom(blocked, jid, (GCompareFunc)g_strcmp0);
    if (!found) {
        return FALSE;
    }

    xmpp_ctx_t *ctx = connection_get_ctx();

    xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
    xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
    char *id = create_unique_id("unblock");
    xmpp_stanza_set_id(iq, id);

    xmpp_stanza_t *block = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(block, STANZA_NAME_UNBLOCK);
    xmpp_stanza_set_ns(block, STANZA_NS_BLOCKING);

    xmpp_stanza_t *item = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(item, STANZA_NAME_ITEM);
    xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid);

    xmpp_stanza_add_child(block, item);
    xmpp_stanza_release(item);

    xmpp_stanza_add_child(iq, block);
    xmpp_stanza_release(block);

    iq_id_handler_add(id, _block_remove_result_handler, free, strdup(jid));

    iq_send_stanza(iq);
    xmpp_stanza_release(iq);
    free(id);

    return TRUE;
}
Exemple #21
0
void
_message_send_receipt(const char *const fulljid, const char *const message_id)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();
    xmpp_stanza_t *message = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(message, STANZA_NAME_MESSAGE);
    char *id = create_unique_id("receipt");
    xmpp_stanza_set_id(message, id);
    free(id);
    xmpp_stanza_set_attribute(message, STANZA_ATTR_TO, fulljid);

    xmpp_stanza_t *receipt = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(receipt, "received");
    xmpp_stanza_set_ns(receipt, STANZA_NS_RECEIPTS);
    xmpp_stanza_set_attribute(receipt, STANZA_ATTR_ID, message_id);

    xmpp_stanza_add_child(message, receipt);
    xmpp_stanza_release(receipt);

    xmpp_send(conn, message);
    xmpp_stanza_release(message);
}
Exemple #22
0
void board_init(void)
{
  create_unique_id();
}
Exemple #23
0
void
presence_send(const resource_presence_t presence_type, const int idle, char *signed_status)
{
    if (connection_get_status() != JABBER_CONNECTED) {
        log_warning("Error setting presence, not connected.");
        return;
    }

    char *msg = connection_get_presence_msg();
    if (msg) {
        log_debug("Updating presence: %s, \"%s\"", string_from_resource_presence(presence_type), msg);
    } else {
        log_debug("Updating presence: %s", string_from_resource_presence(presence_type));
    }

    const int pri = accounts_get_priority_for_presence_type(session_get_account_name(), presence_type);
    connection_set_priority(pri);

    xmpp_ctx_t * const ctx = connection_get_ctx();
    xmpp_stanza_t *presence = xmpp_presence_new(ctx);

    char *id = create_unique_id("presence");
    xmpp_stanza_set_id(presence, id);
    free(id);

    const char *show = stanza_get_presence_string_from_type(presence_type);
    stanza_attach_show(ctx, presence, show);

    stanza_attach_status(ctx, presence, msg);

    if (signed_status) {
        xmpp_stanza_t *x = xmpp_stanza_new(ctx);
        xmpp_stanza_set_name(x, STANZA_NAME_X);
        xmpp_stanza_set_ns(x, STANZA_NS_SIGNED);

        xmpp_stanza_t *signed_text = xmpp_stanza_new(ctx);
        xmpp_stanza_set_text(signed_text, signed_status);

        xmpp_stanza_add_child(x, signed_text);
        xmpp_stanza_release(signed_text);

        xmpp_stanza_add_child(presence, x);
        xmpp_stanza_release(x);
    }

    stanza_attach_priority(ctx, presence, pri);

    if (idle > 0) {
        stanza_attach_last_activity(ctx, presence, idle);
    }

    stanza_attach_caps(ctx, presence);

    _send_presence_stanza(presence);
    _send_room_presence(presence);

    xmpp_stanza_release(presence);

    // set last presence for account
    const char *last = show;
    if (last == NULL) {
        last = STANZA_TEXT_ONLINE;
    }

    char *account = session_get_account_name();
    accounts_set_last_presence(account, last);
    accounts_set_last_status(account, msg);
}
Exemple #24
0
static void
_send_bookmarks(void)
{
    xmpp_conn_t *conn = connection_get_conn();
    xmpp_ctx_t *ctx = connection_get_ctx();

    xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
    char *id = create_unique_id("bookmarks_update");
    xmpp_stanza_set_id(iq, id);
    free(id);
    xmpp_stanza_set_type(iq, STANZA_TYPE_SET);

    xmpp_stanza_t *query = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(query, STANZA_NAME_QUERY);
    xmpp_stanza_set_ns(query, "jabber:iq:private");

    xmpp_stanza_t *storage = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(storage, STANZA_NAME_STORAGE);
    xmpp_stanza_set_ns(storage, "storage:bookmarks");

    GList *curr = bookmark_list;
    while (curr) {
        Bookmark *bookmark = curr->data;
        xmpp_stanza_t *conference = xmpp_stanza_new(ctx);
        xmpp_stanza_set_name(conference, STANZA_NAME_CONFERENCE);
        xmpp_stanza_set_attribute(conference, STANZA_ATTR_JID, bookmark->jid);

        Jid *jidp = jid_create(bookmark->jid);
        if (jidp->localpart) {
            xmpp_stanza_set_attribute(conference, STANZA_ATTR_NAME, jidp->localpart);
        }
        jid_destroy(jidp);

        if (bookmark->autojoin) {
            xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "true");
        } else {
            xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "false");
        }

        if (bookmark->nick) {
            xmpp_stanza_t *nick_st = xmpp_stanza_new(ctx);
            xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
            xmpp_stanza_t *nick_text = xmpp_stanza_new(ctx);
            xmpp_stanza_set_text(nick_text, bookmark->nick);
            xmpp_stanza_add_child(nick_st, nick_text);
            xmpp_stanza_add_child(conference, nick_st);

            xmpp_stanza_release(nick_text);
            xmpp_stanza_release(nick_st);
        }

        if (bookmark->password) {
            xmpp_stanza_t *password_st = xmpp_stanza_new(ctx);
            xmpp_stanza_set_name(password_st, STANZA_NAME_PASSWORD);
            xmpp_stanza_t *password_text = xmpp_stanza_new(ctx);
            xmpp_stanza_set_text(password_text, bookmark->password);
            xmpp_stanza_add_child(password_st, password_text);
            xmpp_stanza_add_child(conference, password_st);

            xmpp_stanza_release(password_text);
            xmpp_stanza_release(password_st);
        }

        xmpp_stanza_add_child(storage, conference);
        xmpp_stanza_release(conference);

        curr = curr->next;
    }

    xmpp_stanza_add_child(query, storage);
    xmpp_stanza_add_child(iq, query);
    xmpp_stanza_release(storage);
    xmpp_stanza_release(query);

    xmpp_send(conn, iq);
    xmpp_stanza_release(iq);
}
Exemple #25
0
int main(int argc, char **argv)
{
    if (argc != 3 && argc != 4) {
        usage(argv[0]);
        exit(0);
    }
    
    char cfg_file[MAX_LINE] = {0};
    int make_deamon = 0;
    
    int ch;
    const char *args = "c:dh";
    while ((ch = getopt(argc, argv, args)) != -1) {
        switch (ch) {
            case 'c':
                snprintf(cfg_file, sizeof(cfg_file), "%s", optarg);
                break;
            case 'd':
                make_deamon = 1;
                break;
                
            case 'h':
            default:
                usage(argv[0]);
                exit(0);
                break;
        }
    }
    
    if (make_deamon == 1) {
        // create deamon
        create_daemon(config_st.chdir_path);
    }
    
    // init log
    ctlog("ctserver", LOG_PID|LOG_NDELAY, LOG_MAIL);
    
    // read config
    dict_conf = open_config(cfg_file);
    if (dict_conf == NULL) {
        printf("parse config fail");
        return 1;
    }
    if (read_config(dict_conf) != 0) {
        return 1;
    }
    log_level = atoi(config_st.log_level);
    
    if (chdir(config_st.chdir_path) == -1) {
        log_error("can not start: unable to change directory:%s", config_st.chdir_path);
        return 1;
    }
    log_debug("bind_port:%s", config_st.bind_port);
    log_debug("log_level:%s", config_st.log_level);
    log_debug("chdir_path:%s", config_st.chdir_path);
    log_debug("max_childs:%s", config_st.max_childs);
    log_debug("child_prog:%s", config_st.child_prog);
    log_debug("child_cf:%s", config_st.child_cf);
    
    // Get Local Host Name
    char local_hostname[MAX_LINE] = {0};
    if (gethostname(local_hostname, sizeof(local_hostname)) != 0) {
        snprintf(local_hostname, sizeof(local_hostname), "unknown");
    }
    log_debug("local_hostname:%s", local_hostname);
    
    
    // ---------- ----------
    
    childs_st = (struct childs_t *)malloc((atoi(config_st.max_childs) + 1) * sizeof(struct childs_t));
    if (childs_st == NULL) {
        log_error("malloc childs [%d] faild:[%d]:%s", (atoi(config_st.max_childs) + 1), errno, strerror(errno));
        exit(1);
    }
    
    int i = 0;
    for (i=0; i<(atoi(config_st.max_childs) +1); i++) {
        init_child_with_idx(i);
    }
    
    
    // Start Server
    int connfd, epfd, sockfd, n, nread, nwrite;
    struct sockaddr_in local, remote;
    socklen_t addrlen;
    
    
    // Create Listen Socket
    int bind_port = atoi(config_st.bind_port);
    if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        log_error("socket fail:[%d]:%s", errno, strerror(errno));
        exit(1);
    }

	// 设置套接字选项避免地址使用错误,解决: Address already in use
	int on = 1;
    if ((setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
        log_error("setsockopt failed");
        exit(1);
    }
    
    // Set Listen FD Nonblock
    if (set_nonblocking(listen_fd) != 0) {
        exit(1);
    }
    
    bzero(&local, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    local.sin_port = htons(bind_port);
    if (bind(listen_fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
        log_error("bind local %d failed:[%d]%s", bind_port, errno, strerror(errno));
        exit(1);
    }
    log_info("bind local %d succ", bind_port);
    
    if (listen(listen_fd, atoi(config_st.max_childs)) != 0) {
        log_error("listen fd[%d] max_number[%d] failed:[%d]%s", listen_fd, atoi(config_st.max_childs), errno, strerror(errno));
        exit(1);
    }
    
    // Ignore pipe signal
    sig_pipeignore();
    // Catch signal which is child program exit
    sig_catch(SIGCHLD, sigchld_exit);
    
    // epoll create fd
    epoll_event_num = atoi(config_st.max_childs) + 1;
    epoll_evts = NULL;
    epoll_fd = -1;
    epoll_nfds = -1;
    
    int epoll_i = 0;
    
    epoll_evts = (struct epoll_event *)malloc(epoll_event_num * sizeof(struct epoll_event));
    if (epoll_evts == NULL) {
        log_error("malloc for epoll event fail");
        exit(1);
    }
    
    epoll_fd = epoll_create(epoll_event_num);
    if (epoll_fd == -1) {
        log_error("epoll_create max_number[%d] failed:[%d]%s", epoll_event_num, errno, strerror(errno));
        exit(1);
    }
    
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = listen_fd;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) {
        log_error("epoll_ctl: listen_socket failed:[%d]%s", errno, strerror(errno));
        exit(1);
    }
    
    epoll_num_running = 0;
    
    for (;;) {
        
        epoll_nfds = epoll_wait(epoll_fd, epoll_evts, epoll_event_num, -1);
        
        if (epoll_nfds == -1) {
            if (errno == EINTR) {
                // 收到中断信号
                log_info("epoll_wait recive EINTR signal, continue");
                continue;
            }
            
            exit(1);
        }
        
        log_debug("epoll_num_running:%d nfds:%d", epoll_num_running, epoll_nfds);
        for (epoll_i = 0; epoll_i < epoll_nfds; epoll_i++) {
            sig_childblock();
            
            int evt_fd = epoll_evts[epoll_i].data.fd;
            if (evt_fd == listen_fd) {
                // new connect
                if ((connfd = accept(listen_fd, (struct sockaddr *)&remote, &addrlen)) > 0) {

                    char *ipaddr = inet_ntoa(remote.sin_addr);
                    log_debug("accept client:%s", ipaddr);
                    
                    char greet_buf[MAX_LINE] = {0};
                    
                    // get a new index from child list
                    int i = get_idle_idx_from_childs();
                    if (i == -1) {
                        log_error("get_idle_idx_from_childs_t fail: maybe client queue is full.");
                        
                        // send to client error information
                        n = snprintf(greet_buf, sizeof(greet_buf), "%s ERR %s%s", FAIL_CODE, local_hostname, DATA_END);
                        nwrite = write(connfd, greet_buf, n);
                        log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf);
                        
                        continue;
                    }
                    childs_st[i].used = 1;
                    
                    // get client ip and port.
                    struct sockaddr_in sa;
                    int len = sizeof(sa);
                    if (!getpeername(connfd, (struct sockaddr *)&sa, &len)) {
                        n = snprintf(childs_st[i].client_info.ip, sizeof(childs_st[i].client_info.ip), "%s", inet_ntoa(sa.sin_addr));
                        n = snprintf(childs_st[i].client_info.port, sizeof(childs_st[i].client_info.port), "%d", ntohs(sa.sin_port));
                        log_info("accept client:%s:%s", childs_st[i].client_info.ip, childs_st[i].client_info.port);
                    }
                    
                    
                    int pi1[2];
                    int pi2[2];
                    if (pipe(pi1) == -1) {
                        log_error("unable to create pipe:[%d]%s", errno, strerror(errno));
                        
                        // send to client error information
                        n = snprintf(greet_buf, sizeof(greet_buf), "%s ERR %s%s", FAIL_CODE, local_hostname, DATA_END);
                        nwrite = write(connfd, greet_buf, n);
                        log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf);
                        
                        continue;
                    }
                    if (pipe(pi2) == -1) {
                        log_error("unable to create pipe:[%d]%s", errno, strerror(errno));
                        
                        close(pi1[0]);
                        close(pi1[1]);
                        pi1[0] = -1;
                        pi1[1] = -1;
                        
                        // send to client error information
                        n = snprintf(greet_buf, sizeof(greet_buf), "%s ERR %s%s", FAIL_CODE, local_hostname, DATA_END);
                        nwrite = write(connfd, greet_buf, n);
                        log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf);
                        
                        continue;
                    }
                    log_debug("create pi1[0]:%d pi1[1]:%d", pi1[0], pi1[1]);
                    log_debug("create pi2[0]:%d pi2[1]:%d", pi2[0], pi2[1]);
                    
                    // create unique id
                    n = create_unique_id(childs_st[i].sid, sizeof(childs_st[i].sid));
                    if (n != 16) {
                        log_error("create unique id fail");
                        
                        close(pi1[0]);
                        close(pi1[1]);
                        close(pi2[0]);
                        close(pi2[1]);
                        
                        // send to client error information
                        n = snprintf(greet_buf, sizeof(greet_buf), "%s SYSTEM ERR %s%s", FAIL_CODE, local_hostname, DATA_END);
                        nwrite = write(connfd, greet_buf, n);
                        log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf);
                        
                        continue;
                    }
                    log_debug("create mid:%s", childs_st[i].sid);
                    
                    // 当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程
                    fcntl(pi1[1], F_SETFD, FD_CLOEXEC);
                    fcntl(pi2[0], F_SETFD, FD_CLOEXEC);
                    fcntl(listen_fd, F_SETFD, FD_CLOEXEC);
                    
                    
                    int f = fork();
                    if (f < 0) {
                        log_error("fork fail:[%d]%s", errno, strerror(errno));
                        
                        close(pi1[0]);
                        close(pi1[1]);
                        pi1[0] = -1;
                        pi1[1] = -1;
                        
                        close(pi2[0]);
                        close(pi2[1]);
                        pi2[0] = -1;
                        pi2[1] = -1;
                        
                        // send to client error information
                        n = snprintf(greet_buf, sizeof(greet_buf), "%s SYSTEM ERR %s%s", FAIL_CODE, local_hostname, DATA_END);
                        nwrite = write(connfd, greet_buf, n);
                        log_debug("send client fd[%d]:[%d]%s", connfd, nwrite, greet_buf);
                        
                        continue;
                    
                    } else if (f == 0) {
                        // 子进程
                        close(pi1[1]);
                        close(pi2[0]);
                        pi1[1] = -1;
                        pi2[0] = -1;
                        
                        close(listen_fd);
                        listen_fd = -1;
                        
                        if (fd_move(2, connfd) == -1) {
                            log_error("%s fd_move(2, %d) failed:[%d]%s", childs_st[i].sid, connfd, errno, strerror(errno));
                            _exit(111);
                        }
                        
                        // read from 0
                        if (fd_move(0, pi1[0])) {
                            log_error("%s fd_move(0, %d) failed:[%d]%s", childs_st[i].sid, pi1[0], errno, strerror(errno));
                            _exit(111);
                        }
                        
                        // write to 1
                        if (fd_move(1, pi2[1])) {
                            log_error("%s fd_move(1, %d) failed:[%d]%s", childs_st[i].sid, pi2[1], errno, strerror(errno));
                            _exit(111);
                        }
                        
                        // lunach child program
                        char exe_sid[MAX_LINE] = {0};
                        char exe_cfg[MAX_LINE] = {0};
                        char exe_remote[MAX_LINE] = {0};
                        
                        snprintf(exe_sid, sizeof(exe_sid), "-m%s", childs_st[i].sid);
                        snprintf(exe_cfg, sizeof(exe_cfg), "-c%s", config_st.child_cf);
                        snprintf(exe_remote, sizeof(exe_remote), "-r%s:%s", childs_st[i].client_info.ip, childs_st[i].client_info.port);
                        
                        char *args[5];
                        args[0] = config_st.child_prog;
                        args[1] = exe_sid;
                        args[2] = exe_cfg;
                        args[3] = exe_remote;
                        args[4] = 0;
                        
						char log_exec[MAX_LINE*3] = {0};
						char *plog_exec = log_exec;
						int len = 0;
						int i=0;
						while (args[i] != 0) {
							int n = snprintf(plog_exec + len, sizeof(log_exec) - len, "%s ", args[i]);
							len += n;	
							i++;
						}

                        log_info("Exec:[%s]", log_exec);
                        
                        if (execvp(*args, args) == -1) {
                            log_error("execvp fail:[%d]%s", errno, strerror(errno));
                            _exit(111);
                        }
                        
                        _exit(100);
                        
                    }
                    
                    // 父进程
                    log_debug("add child index:%d pid:%lu", i, f);
                    childs_st[i].pid = f;
                    
                    close(pi1[0]);
                    close(pi2[1]);
                    pi1[0] = -1;
                    pi2[1] = -1;
                    
                    close(connfd);
                    connfd = -1;
                    
                    childs_st[i].pfd_r = pi2[0];
                    childs_st[i].pfd_w = pi1[1];
                    
                    if (set_nonblocking(childs_st[i].pfd_r)) {
                        log_error("set nonblocking fd[%d] fail", childs_st[i].pfd_r);
                    }
                    
                    struct epoll_event pipe_r_ev;
                    pipe_r_ev.events = EPOLLIN | EPOLLET;
                    pipe_r_ev.data.fd = childs_st[i].pfd_r;
                    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_r_ev.data.fd, &pipe_r_ev) == -1) {
                        log_error("epoll_ctl client fd[%d] EPOLL_CTL_ADD failed:[%d]%s", pipe_r_ev.data.fd, errno, strerror(errno));
                    }
                    log_debug("epoll_add fd[%d]", pipe_r_ev.data.fd);
                    
                    epoll_num_running++;
                    
                } else if (connfd == -1) {
                    if (errno != EAGAIN && errno != ECONNABORTED && errno != EPROTO && errno != EINTR) {
                        log_error("accept failed:[%d]%s", errno, strerror(errno));
                    }
                    
                    continue;
                }
                
            } else if (epoll_evts[epoll_i].events & EPOLLIN) {
                // 有可读事件从子进程过来
                int idx = get_idx_with_sockfd(evt_fd);
                if (idx < 0) {
                    log_error("get_idx_with_sockfd(%d) fail, so not process", evt_fd);
                    continue;
                }
                log_debug("%s get event EPOLLIN: epoll_i[%d] fd[%d] get fd[%d], used[%d]", childs_st[idx].sid, epoll_i, epoll_evts[epoll_i].data.fd, childs_st[idx].pfd_r, childs_st[idx].used);
                
                // 读取内容
                char cbuf[MAX_LINE] = {0};
                nread = read(childs_st[idx].pfd_r, cbuf, sizeof(cbuf));
                log_debug("read buf:'[%d]%s' from child", n, cbuf);

                
            } else if ((epoll_evts[epoll_i].events & EPOLLHUP)
                       && (epoll_evts[epoll_i].data.fd != listen_fd)) {
                // 有子进程退出
                int idx = get_idx_with_sockfd(evt_fd);
                if (idx < 0) {
                    log_error("get_idx_with_sockfd(%d) fail, so not process", evt_fd);
                    
                    continue;
                }
                log_debug("%s get event EPOLLHUP: epoll_i[%d] fd[%d] get fd[%d], used[%d]", childs_st[idx].sid, epoll_i, epoll_evts[epoll_i].data.fd, childs_st[idx].pfd_r, childs_st[idx].used);
                
                epoll_delete_evt(epoll_fd, childs_st[idx].pfd_r);
                
                // 子进程清理
                clean_child_with_idx(idx);
                
                continue;
                
            }
            
        }
        
        sig_childunblock();
    }
    
    close(epoll_fd);
    close(listen_fd);
    
    epoll_fd = -1;
    listen_fd = -1;

	if (childs_st != NULL) {
		free(childs_st);
		childs_st = NULL;
	}

	if (epoll_evts != NULL) {
		free(epoll_evts);
		epoll_evts = NULL;
	}
    
    log_info("I'm finish");
    
    return 0;
    
}