static int add_to_poll (struct pollfd* pollfd, hstack_t cont) { ssize_t add_fd = mlist_add (s_pollfd_list, pollfd); ssize_t add_pfd = mlist_add (s_pollfd_ptrs, &pollfd); ssize_t add_cont = mlist_add (s_waiters, &cont); if (add_fd < 0 || add_pfd < 0 || add_cont < 0) { if (add_fd >= 0) mlist_remove (s_pollfd_list, add_fd); if (add_pfd >= 0) mlist_remove (s_pollfd_ptrs, add_pfd); if (add_cont >= 0) mlist_remove (s_waiters, add_cont); return -1; } ASSERT (add_fd == add_pfd && add_pfd == add_cont); return 0; }
static void _new_map_del_node (MAP map, struct map_node *n) { /* remove node from old hash list */ mhlist_del_init(&n->hnode); /* remove from entry list */ mlist_del(&n->lnode); /* add it back to the pool */ mlist_add(&n->lnode, &map->pool); map->num--; }
static void _stp_map_sort (MAP map, int keynum, int dir, map_get_key_fn get_key) { struct mlist_head *p, *q, *e, *tail; int nmerges, psize, qsize, i, insize = 1; struct mlist_head *head = &map->head; if (mlist_empty(head)) return; do { tail = head; p = mlist_next(head); nmerges = 0; while (p) { nmerges++; q = p; psize = 0; for (i = 0; i < insize; i++) { psize++; q = mlist_next(q) == head ? NULL : mlist_next(q); if (!q) break; } qsize = insize; while (psize > 0 || (qsize > 0 && q)) { if (psize && (!qsize || !q || !_stp_cmp(p, q, keynum, dir, get_key))) { e = p; p = mlist_next(p) == head ? NULL : mlist_next(p); psize--; } else { e = q; q = mlist_next(q) == head ? NULL : mlist_next(q); qsize--; } /* now put 'e' on tail of list and make it our new tail */ mlist_del(e); mlist_add(e, tail); tail = e; } p = q; } insize += insize; } while (nmerges > 1); }
/** Get the top values from an array. * Sorts an array such that the start of the array contains the top * or bottom 'n' values. Use this when sorting the entire array * would be too time-consuming and you are only interested in the * highest or lowest values. * * @param map Map * @param n Top (or bottom) number of elements. 0 sorts the entire array. * @param keynum 0 for the value, or a positive number for the key number to sort on. * @param dir Sort Direction. -1 for low-to-high. 1 for high-to-low. * @sa _stp_map_sort() */ static void _stp_map_sortn(MAP map, int n, int keynum, int dir, map_get_key_fn get_key) { if (n == 0 || n > 30) { _stp_map_sort(map, keynum, dir, get_key); } else { struct mlist_head *head = &map->head; struct mlist_head *c, *a, *last, *tmp; int num, swaps = 1; if (mlist_empty(head)) return; /* start off with a modified bubble sort of the first n elements */ while (swaps) { num = n; swaps = 0; a = mlist_next(head); c = mlist_next(mlist_next(a)); while ((mlist_next(a) != head) && (--num > 0)) { if (_stp_cmp(a, mlist_next(a), keynum, dir, get_key)) { swaps++; _stp_swap(a, mlist_next(a)); } a = mlist_prev(c); c = mlist_next(c); } } /* Now use a kind of insertion sort for the rest of the array. */ /* Each element is tested to see if it should be be in the top 'n' */ last = a; a = mlist_next(a); while (a != head) { tmp = mlist_next(a); c = last; while (c != head && _stp_cmp(c, a, keynum, dir, get_key)) c = mlist_prev(c); if (c != last) { mlist_del(a); mlist_add(a, c); last = mlist_prev(last); } a = tmp; } } }
static void _stp_map_clear(MAP map) { struct map_node *m; map->num = 0; while (!mlist_empty(&map->head)) { m = mlist_map_node(mlist_next(&map->head)); /* remove node from old hash list */ mhlist_del_init(&m->hnode); /* remove from entry list */ mlist_del(&m->lnode); /* add to free pool */ mlist_add(&m->lnode, &map->pool); } }
/*----------------------------------------------------------------------------*/ zrtp_status_t zrtp_session_init( zrtp_global_t* zrtp, zrtp_profile_t* profile, zrtp_zid_t zid, zrtp_signaling_role_t role, zrtp_session_t **session) { uint32_t i = 0; zrtp_status_t s = zrtp_status_fail; zrtp_session_t* new_session = NULL; if (!zrtp) { return zrtp_status_bad_param; } new_session = zrtp_sys_alloc(sizeof(zrtp_session_t)); if (!new_session) { return zrtp_status_alloc_fail; } zrtp_memset(new_session, 0, sizeof(zrtp_session_t)); new_session->id = zrtp->sessions_count++; { zrtp_uchar32_t buff; ZRTP_LOG(3, (_ZTU_,"START SESSION INITIALIZATION. sID=%u.\n", new_session->id)); ZRTP_LOG(3, (_ZTU_,"ZID=%s.\n", hex2str((const char*)zid, sizeof(zrtp_uchar12_t), (char*)buff, sizeof(buff)) )); } do { /* * Apply profile for the stream context: set flags and prepare Hello packet. * If profile structure isn't provided, generate default. */ if (!profile) { ZRTP_LOG(1, (_ZTU_,"Profile in NULL - loading default one.\n")); zrtp_profile_defaults(&new_session->profile, zrtp); } else { ZRTP_LOG(1, (_ZTU_,"Loading User's profile:\n")); if (zrtp_status_ok != zrtp_profile_check(profile, zrtp)) { ZRTP_LOG(1, (_ZTU_,"ERROR! Can't apply wrong profile to the session sID=%u.\n", new_session->id)); break; } /* Adjust user's settings: force SHA-384 hash for ECDH-384P */ if (zrtp_profile_find(profile, ZRTP_CC_PKT, ZRTP_PKTYPE_EC384P) > 0) { ZRTP_LOG(3, (_ZTU_,"User wants ECDH384 - auto-adjust profile to use SHA-384.\n")); profile->hash_schemes[0] = ZRTP_HASH_SHA384; profile->hash_schemes[1] = ZRTP_HASH_SHA256; profile->hash_schemes[2] = 0; } zrtp_memcpy(&new_session->profile, profile, sizeof(zrtp_profile_t)); { int i; ZRTP_LOG(3, (_ZTU_," allowclear: %s\n", profile->allowclear?"ON":"OFF")); ZRTP_LOG(3, (_ZTU_," autosecure: %s\n", profile->autosecure?"ON":"OFF")); ZRTP_LOG(3, (_ZTU_," disclose_bit: %s\n", profile->disclose_bit?"ON":"OFF")); ZRTP_LOG(3, (_ZTU_," signal. role: %s\n", zrtp_log_sign_role2str(role))); ZRTP_LOG(3, (_ZTU_," TTL: %u\n", profile->cache_ttl)); ZRTP_LOG(3, (_ZTU_," SAS schemes: ")); i=0; while (profile->sas_schemes[i]) { ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_SAS, profile->sas_schemes[i++]))); } ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_," Ciphers: ")); i=0; while (profile->cipher_types[i]) { ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_CIPHER, profile->cipher_types[i++]))); } ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_," PK schemes: ")); i=0; while (profile->pk_schemes[i]) { ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_PKT, profile->pk_schemes[i++]))); } ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_," ATL: ")); i=0; while (profile->auth_tag_lens[i]) { ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_ATL, profile->auth_tag_lens[i++]))); } ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_," Hashes: ")); i=0; while (profile->hash_schemes[i]) { ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_HASH, profile->hash_schemes[i++]))); } ZRTP_LOGC(3, ("\n")); } } /* Set ZIDs */ ZSTR_SET_EMPTY(new_session->zid); ZSTR_SET_EMPTY(new_session->peer_zid); zrtp_zstrncpyc(ZSTR_GV(new_session->zid), (const char*)zid, sizeof(zrtp_zid_t)); new_session->zrtp = zrtp; new_session->signaling_role = role; new_session->mitm_alert_detected = 0; /* * Allocate memory for holding secrets and initialize with random values. * Actual values will be written from the cache at the beginning of the protocol. */ new_session->secrets.rs1 = _zrtp_alloc_shared_secret(new_session); new_session->secrets.rs2 = _zrtp_alloc_shared_secret(new_session); new_session->secrets.auxs = _zrtp_alloc_shared_secret(new_session); new_session->secrets.pbxs = _zrtp_alloc_shared_secret(new_session); if ( !new_session->secrets.rs1 || !new_session->secrets.rs2 || !new_session->secrets.auxs || !new_session->secrets.pbxs) { ZRTP_LOG(1, (_ZTU_,"ERROR! Can't allocate shared secrets sID=%u\n.", new_session->id)); s = zrtp_status_alloc_fail; break; } /* Initialize SAS values */ ZSTR_SET_EMPTY(new_session->sas1); ZSTR_SET_EMPTY(new_session->sas2); ZSTR_SET_EMPTY(new_session->sasbin); ZSTR_SET_EMPTY(new_session->zrtpsess); /* Clear all stream structures */ for (i=0; i<ZRTP_MAX_STREAMS_PER_SESSION ; i++) { new_session->streams[i].state = ZRTP_STATE_NONE; new_session->streams[i].prev_state = ZRTP_STATE_NONE; new_session->streams[i].mode = ZRTP_STREAM_MODE_UNKN; } /* Initialize synchronization objects */ s = zrtp_mutex_init(&new_session->streams_protector); if (zrtp_status_ok != s) { ZRTP_LOG(1, (_ZTU_,"ERROR! can't initialize Stream protector. sID=%u.\n", new_session->id)); break; } s = zrtp_mutex_init(&new_session->init_protector); if (zrtp_status_ok != s) { ZRTP_LOG(1, (_ZTU_,"ERROR! can't initialize Init protector. sID=%u.\n", new_session->id)); break; } s = zrtp_status_ok; } while (0); if (zrtp_status_ok != s) { zrtp_sys_free(new_session); return s; } /* Add new session to the global list */ zrtp_mutex_lock(zrtp->sessions_protector); mlist_add(&zrtp->sessions_head, &new_session->_mlist); zrtp_mutex_unlock(zrtp->sessions_protector); *session = new_session; ZRTP_LOG(3, (_ZTU_,"Session initialization - DONE. sID=%u.\n\n", new_session->id)); return zrtp_status_ok; }
/* swap function for bubble sort */ static inline void _stp_swap (struct mlist_head *a, struct mlist_head *b) { mlist_del(a); mlist_add(a, b); }