int _font_init_stubs (void) { static int inited = FALSE; static void *handle = NULL; if (inited) return inited; if (!handle) handle = DLOPEN_SELF(); INIT_SYMBOL(client_auth_generation); INIT_SYMBOL(ClientSignal); INIT_SYMBOL(DeleteFontClientID); INIT_SYMBOL(VErrorF); INIT_SYMBOL(find_old_font); INIT_SYMBOL(GetClientResolutions); INIT_SYMBOL(GetDefaultPointSize); INIT_SYMBOL(GetNewFontClientID); INIT_SYMBOL(GetTimeInMillis); INIT_SYMBOL(init_fs_handlers); INIT_SYMBOL(RegisterFPEFunctions); INIT_SYMBOL(remove_fs_handlers); INIT_SYMBOL(set_font_authorizations); INIT_SYMBOL(StoreFontClientFont); INIT_SYMBOL(MakeAtom); INIT_SYMBOL(ValidAtom); INIT_SYMBOL(NameForAtom); INIT_SYMBOL(register_fpe_functions); INIT_DATA(serverClient); INIT_DATA(serverGeneration); inited = TRUE; return inited; }
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); CHECK_INIT(ht); if (flag & HASH_NEXT_INSERT) { h = ht->nNextFreeElement; } nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if ((p->nKeyLength == 0) && (p->h == h)) { if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) { return FAILURE; } ZEND_ASSERT(p->pData != pData); HANDLE_BLOCK_INTERRUPTIONS(); if (ht->pDestructor) { ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); HANDLE_UNBLOCK_INTERRUPTIONS(); if (pDest) { *pDest = p->pData; } return SUCCESS; } p = p->pNext; } p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent); p->arKey = NULL; p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */ p->h = h; INIT_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); HANDLE_BLOCK_INTERRUPTIONS(); ht->arBuckets[nIndex] = p; CONNECT_TO_GLOBAL_DLLIST(p, ht); HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE(ht); return SUCCESS; }
/* nr_turn_stun_ctx functions */ static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int mode, NR_async_cb success_cb, NR_async_cb error_cb, nr_turn_stun_ctx **ctxp) { nr_turn_stun_ctx *sctx = 0; int r,_status; char label[256]; if (!(sctx=RCALLOC(sizeof(nr_turn_stun_ctx)))) ABORT(R_NO_MEMORY); /* TODO([email protected]): label by phase */ snprintf(label, sizeof(label), "%s:%s", tctx->label, ":TURN"); if ((r=nr_stun_client_ctx_create(label, tctx->sock, &tctx->turn_server_addr, TURN_RTO, &sctx->stun))) { ABORT(r); } /* Set the STUN auth parameters, but don't set authentication on. For that we need the nonce, set in nr_turn_stun_set_auth_params. */ sctx->stun->auth_params.username=tctx->username; INIT_DATA(sctx->stun->auth_params.password, tctx->password->data, tctx->password->len); sctx->tctx=tctx; sctx->success_cb=success_cb; sctx->error_cb=error_cb; sctx->mode=mode; sctx->last_error_code=0; /* Add ourselves to the tctx's list */ STAILQ_INSERT_TAIL(&tctx->stun_ctxs, sctx, entry); *ctxp=sctx; _status=0; abort: if (_status) { nr_turn_stun_ctx_destroy(&sctx); } return(_status); }
int nr_turn_client_deallocate(nr_turn_client_ctx *ctx) { int r,_status; nr_stun_message *aloc = 0; nr_stun_client_auth_params auth; nr_stun_client_refresh_request_params refresh; if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED) return(0); r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): deallocating", ctx->label); refresh.lifetime_secs = 0; auth.username = ctx->username; INIT_DATA(auth.password, ctx->password->data, ctx->password->len); auth.realm = ctx->realm; auth.nonce = ctx->nonce; auth.authenticate = 1; if ((r=nr_stun_build_refresh_request(&auth, &refresh, &aloc))) ABORT(r); // We are only sending a single request here because we are in the process of // shutting everything down. Theoretically we should probably start a seperate // STUN transaction which outlives the TURN context. if ((r=nr_turn_client_send_stun_request(ctx, aloc, 0))) ABORT(r); ctx->state = NR_TURN_CLIENT_STATE_DEALLOCATING; _status=0; abort: nr_stun_message_destroy(&aloc); return(_status); }
ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); if (nKeyLength == 0) { return zend_hash_index_update(ht, h, pData, nDataSize, pDest); } CHECK_INIT(ht); nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if (p->arKey == arKey || ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { if (flag & HASH_ADD) { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; } p = p->pNext; } if (IS_INTERNED(arKey)) { p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } p->arKey = arKey; } else { p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent); if (!p) { return FAILURE; } p->arKey = (const char*)(p + 1); memcpy((char*)p->arKey, arKey, nKeyLength); } p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); if (pDest) { *pDest = p->pData; } HANDLE_BLOCK_INTERRUPTIONS(); ht->arBuckets[nIndex] = p; CONNECT_TO_GLOBAL_DLLIST(p, ht); HANDLE_UNBLOCK_INTERRUPTIONS(); ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */ return SUCCESS; }
/* 数字键值的插入修改 */ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); // 调试信息 CHECK_INIT(ht); // 如果是新增元素,则h等于下一个数字索引的位置 if (flag & HASH_NEXT_INSERT) { h = ht->nNextFreeElement; } // 计算键值在HashTable中的存储位置为nIndex nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; /* 取得索引对应的Bucket的指针 */ // 循环Bucket中含有nIndex键值的链表 while (p != NULL) { // p 不为NULL说明Bucket中存在键值为nIndex的元素 if ((p->nKeyLength == 0) && (p->h == h)) { // 如果是数字键值且键值相同 if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) { // 如果是新增元素,则插入失败 return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in " "zend_hash_index_update: p->pData == " "pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif // 上面的代码return ,说明是更新Bucket中已有键值元素值 if (ht->pDestructor) { // 如果数据元素存在,则将原来的数据销毁 ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); // 更新数据值 HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } // 如果需要返回更新值,则将返回值赋值给pDest if (pDest) { *pDest = p->pData; } return SUCCESS; } // 移动到链表的下一个元素 p = p->pNext; } // 如果是新增,为新增元素分配一个Bucket空间 p = (Bucket *)pemalloc_rel(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } // 赋值 p->arKey = NULL; p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */ p->h = h; INIT_DATA(ht, p, pData, nDataSize); // 如果需要返回更新值,则将返回值赋值给pDest if (pDest) { *pDest = p->pData; } CONNECT_TO_BUCKET_DLLIST( p, ht->arBuckets[nIndex]); // 将Bucket加入到对应的桶双向链表中 HANDLE_BLOCK_INTERRUPTIONS(); ht->arBuckets[nIndex] = p; CONNECT_TO_GLOBAL_DLLIST( p, ht); // 将新的Bucket元素添加到哈希表的双向链表中 HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE( ht); /* 如果此时数组的容量满了,则重新分配空间。*/ return SUCCESS; }
/* 插入新值到哈希表中 */ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { ulong h; uint nIndex; Bucket *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif IS_CONSISTENT(ht); /* 键值不能为空字符串 */ if (nKeyLength <= 0) { #if ZEND_DEBUG ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); #endif return FAILURE; } /* 检查哈希表是否以及初始化,如果没有初始化则进行初始化 */ CHECK_INIT(ht); /* 计算key代表的哈希值以及获取其在arBuckets数组中的下标 */ h = zend_inline_hash_func(arKey, nKeyLength); nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if (p->arKey == arKey || ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { /* 需要更新 */ if (flag & HASH_ADD) { /* 如果是插入的话就返回,不能插入具有相同键值的元素 */ return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_update: " "p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { /* 如果有析构函数,则将指向数据的指针释放掉 */ ht->pDestructor(p->pData); } /* 更新数据 */ UPDATE_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; } /* 移动到具有相同hash值的bucket链表中的下一个bucket */ p = p->pNext; } if (IS_INTERNED(arKey)) { p = (Bucket *)pemalloc(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } p->arKey = arKey; } else { p = (Bucket *)pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent); if (!p) { return FAILURE; } p->arKey = (const char *)(p + 1); memcpy((char *)p->arKey, arKey, nKeyLength); } /* 设置新的bucket的属性值及添加到哈希表中 */ p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); if (pDest) { *pDest = p->pData; } HANDLE_BLOCK_INTERRUPTIONS(); CONNECT_TO_GLOBAL_DLLIST(p, ht); ht->arBuckets[nIndex] = p; HANDLE_UNBLOCK_INTERRUPTIONS(); ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE( ht); /* If the Hash table is full, resize it */ return SUCCESS; }
int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp) { nr_ice_cand_pair *pair=0; UINT8 o_priority, a_priority; char *lufrag,*rufrag; char *lpwd,*rpwd; char *l2ruser=0,*r2lpass=0; int r,_status; UINT4 RTO; nr_ice_candidate tmpcand; UINT8 t_priority; if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair)))) ABORT(R_NO_MEMORY); pair->pctx=pctx; nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand); if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|", rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0)) ABORT(r); nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN); pair->local=lcand; pair->remote=rcand; /* Priority computation S 5.7.2 */ if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_OFFERER) { assert(!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER)); o_priority=lcand->priority; a_priority=rcand->priority; } else{ o_priority=rcand->priority; a_priority=lcand->priority; } pair->priority=(MIN(o_priority, a_priority))<<32 | (MAX(o_priority, a_priority))<<1 | (o_priority > a_priority?0:1); r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx) codeword=%s",pctx->ctx->label,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority,pair->codeword); /* Foundation */ if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|", rcand->foundation,0)) ABORT(r); /* OK, now the STUN data */ lufrag=lcand->stream->ufrag?lcand->stream->ufrag:pctx->ctx->ufrag; lpwd=lcand->stream->pwd?lcand->stream->pwd:pctx->ctx->pwd; rufrag=rcand->stream->ufrag?rcand->stream->ufrag:pctx->peer_ufrag; rpwd=rcand->stream->pwd?rcand->stream->pwd:pctx->peer_pwd; /* Compute the RTO per S 16 */ RTO = MAX(100, (pctx->ctx->Ta * pctx->waiting_pairs)); /* Make a bogus candidate to compute a theoretical peer reflexive * priority per S 7.1.1.1 */ memcpy(&tmpcand, lcand, sizeof(tmpcand)); tmpcand.type = PEER_REFLEXIVE; if (r=nr_ice_candidate_compute_priority(&tmpcand)) ABORT(r); t_priority = tmpcand.priority; /* Our sending context */ if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,0)) ABORT(r); if(r=nr_stun_client_ctx_create(pair->as_string, lcand->osock, &rcand->addr,RTO,&pair->stun_client)) ABORT(r); if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(l2ruser))) ABORT(R_NO_MEMORY); if(r=r_data_make(&pair->stun_client->params.ice_binding_request.password,(UCHAR *)lpwd,strlen(lpwd))) ABORT(r); pair->stun_client->params.ice_binding_request.priority=t_priority; pair->stun_client->params.ice_binding_request.control = pctx->controlling? NR_ICE_CONTROLLING:NR_ICE_CONTROLLED; pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker; /* Our receiving username/passwords. Stash these for later injection into the stun server ctx*/ if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,0)) ABORT(r); if(!(r2lpass=r_strdup(rpwd))) ABORT(R_NO_MEMORY); INIT_DATA(pair->r2l_pwd,(UCHAR *)r2lpass,strlen(r2lpass)); *pairp=pair; _status=0; abort: RFREE(l2ruser); if(_status){ RFREE(r2lpass); } return(_status); }
ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { ulong h; uint nIndex; Bucket *p; IS_CONSISTENT(ht); if (nKeyLength <= 0) { #if ZEND_DEBUG ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); #endif return FAILURE; } h = zend_inline_hash_func(arKey, nKeyLength); nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if ((p->h == h) && (p->nKeyLength == nKeyLength)) { if (!memcmp(p->arKey, arKey, nKeyLength)) { if (flag & HASH_ADD) { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; } } p = p->pNext; } p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent); if (!p) { return FAILURE; } memcpy(p->arKey, arKey, nKeyLength); p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); if (pDest) { *pDest = p->pData; } HANDLE_BLOCK_INTERRUPTIONS(); CONNECT_TO_GLOBAL_DLLIST(p, ht); ht->arBuckets[nIndex] = p; HANDLE_UNBLOCK_INTERRUPTIONS(); ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */ return SUCCESS; }
// flag参数: HASH_UPDATE HASH_NEXT_INSERT ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) { uint nIndex; Bucket *p; IS_CONSISTENT(ht); if (flag & HASH_NEXT_INSERT) { h = ht->nNextFreeElement; } nIndex = h & ht->nTableMask; p = ht->arBuckets[nIndex]; while (p != NULL) { if ((p->nKeyLength == 0) && (p->h == h)) { // 没看到有针对HAHS_ADD的宏 // 这个case什么时候会触发? if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); #if ZEND_DEBUG if (p->pData == pData) { ZEND_PUTS("Fatal error in zend_hash_index_update: p->pData == pData\n"); HANDLE_UNBLOCK_INTERRUPTIONS(); return FAILURE; } #endif if (ht->pDestructor) { ht->pDestructor(p->pData); } UPDATE_DATA(ht, p, pData, nDataSize); HANDLE_UNBLOCK_INTERRUPTIONS(); if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } if (pDest) { *pDest = p->pData; } return SUCCESS; } p = p->pNext; } p = (Bucket *) pemalloc_rel(sizeof(Bucket) - 1, ht->persistent); if (!p) { return FAILURE; } p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */ p->h = h; INIT_DATA(ht, p, pData, nDataSize); if (pDest) { *pDest = p->pData; } CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]); HANDLE_BLOCK_INTERRUPTIONS(); ht->arBuckets[nIndex] = p; CONNECT_TO_GLOBAL_DLLIST(p, ht); HANDLE_UNBLOCK_INTERRUPTIONS(); // 上线就是LONG_MAX // max(h+1, nNextFreeElement) if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX; } ht->nNumOfElements++; ZEND_HASH_IF_FULL_DO_RESIZE(ht); return SUCCESS; }