void ph_dns_channel_query_raw( ph_dns_channel_t *chan, const char *name, int dnsclass, int type, ph_dns_channel_raw_query_func func, void *arg) { struct ph_dns_query *q; chan = fixup_chan(chan); q = ph_mem_alloc(mt.query); if (!q) { func(arg, ARES_ENOMEM, 0, NULL, 0); return; } q->chan = chan; q->arg = arg; q->qtype = PH_DNS_QUERY_NONE; q->func.raw = func; pthread_mutex_lock(&chan->chanlock); ares_search(chan->chan, name, dnsclass, type, result_cb, q); pthread_mutex_unlock(&chan->chanlock); }
ph_hook_point_t *ph_hook_point_get(ph_string_t *name, bool create) { ph_hook_point_t *hp = 0; ck_rwlock_read_lock(&rwlock); { ph_ht_lookup(&hook_hash, &name, &hp, false); } ck_rwlock_read_unlock(&rwlock); if (hp || !create) { return hp; } ck_rwlock_write_lock(&rwlock); { // Look again: someone may have populated while we were unlocked ph_ht_lookup(&hook_hash, &name, &hp, false); if (!hp) { hp = ph_mem_alloc(mt.hookpoint); if (hp) { if (ph_ht_set(&hook_hash, &name, &hp) != PH_OK) { ph_mem_free(mt.hookpoint, hp); hp = NULL; } } } } ck_rwlock_write_unlock(&rwlock); return hp; }
ph_variant_t *ph_var_int(int64_t ival) { ph_variant_t *var; var = ph_mem_alloc(mt.var); if (!var) { return NULL; } var->ref = 1; var->type = PH_VAR_INTEGER; var->u.ival = ival; return var; }
ph_variant_t *ph_var_double(double dval) { ph_variant_t *var; var = ph_mem_alloc(mt.var); if (!var) { return NULL; } var->ref = 1; var->type = PH_VAR_REAL; var->u.dval = dval; return var; }
// Called each time the listener has accepted a client connection static void acceptor(ph_listener_t *lstn, ph_sock_t *sock) { ph_unused_parameter(lstn); // Allocate an echo_state instance and stash it. // This is set to be zero'd on creation and will show up as the // `arg` parameter in `echo_processor` sock->job.data = ph_mem_alloc(mt_state); // Tell it how to dispatch sock->callback = echo_processor; ph_log(PH_LOG_ERR, "accepted `P{sockaddr:%p}", (void*)&sock->peername); ph_sock_enable(sock, true); }
ph_string_t *ph_string_make_slice(ph_string_t *str, uint32_t start, uint32_t len) { ph_string_t *slice; if (start == 0 && len == str->len) { ph_string_addref(str); return str; } slice = ph_mem_alloc(mt_string); if (!slice) { return NULL; } ph_string_init_slice(slice, str, start, len); return slice; }
void ph_dns_channel_query( ph_dns_channel_t *chan, const char *name, int query_type, ph_dns_channel_query_func func, void *arg) { struct ph_dns_query *q; int dnsclass = ns_c_in, type; chan = fixup_chan(chan); q = ph_mem_alloc(mt.query); if (!q) { func(arg, ARES_ENOMEM, 0, NULL, 0, NULL); return; } q->chan = chan; q->arg = arg; q->qtype = query_type; q->func.func = func; switch (query_type) { case PH_DNS_QUERY_A: type = ns_t_a; break; case PH_DNS_QUERY_AAAA: type = ns_t_aaaa; break; case PH_DNS_QUERY_SRV: type = ns_t_srv; break; case PH_DNS_QUERY_MX: type = ns_t_mx; break; default: ph_panic("invalid query type %d", query_type); } pthread_mutex_lock(&chan->chanlock); ares_search(chan->chan, name, dnsclass, type, result_cb, q); pthread_mutex_unlock(&chan->chanlock); }
ph_variant_t *ph_var_string_claim(ph_string_t *str) { ph_variant_t *var; if (str == NULL) { return ph_var_null(); } var = ph_mem_alloc(mt.var); if (!var) { return NULL; } var->ref = 1; var->type = PH_VAR_STRING; var->u.sval = str; return var; }
ph_string_t *ph_string_make_claim(ph_memtype_t mt, char *buf, uint32_t len, uint32_t size) { ph_string_t *str; str = ph_mem_alloc(mt_string); if (!str) { return NULL; } str->ref = 1; str->buf = buf; str->len = len; str->alloc = size; str->slice = 0; str->mt = mt; str->onstack = false; return str; }
ph_variant_t *ph_var_object(uint32_t nelems) { ph_variant_t *var; ph_result_t res; var = ph_mem_alloc(mt.var); if (!var) { return NULL; } var->ref = 1; var->type = PH_VAR_OBJECT; res = ph_ht_init(&var->u.oval, nelems, &ph_ht_string_key_def, &var_val_def); if (res != PH_OK) { ph_mem_free(mt.var, var); return 0; } return var; }
ph_variant_t *ph_var_array(uint32_t nelems) { ph_variant_t *var; var = ph_mem_alloc(mt.var); if (!var) { return NULL; } var->ref = 1; var->type = PH_VAR_ARRAY; var->u.aval.len = 0; var->u.aval.alloc = nelems; var->u.aval.arr = ph_mem_alloc_size(mt.arr, nelems * sizeof(ph_variant_t*)); if (!var->u.aval.arr) { ph_mem_free(mt.var, var); return NULL; } return var; }
/* called when ares creates a new socket */ static int sock_create_cb(ares_socket_t socket_fd, int type, void *data) { ph_dns_channel_t *chan = data; ph_job_t *job = ph_mem_alloc(mt.job); ph_unused_parameter(type); if (!job) { return -1; } ph_job_init(job); job->callback = process_ares; job->data = chan; job->fd = socket_fd; if (ph_ht_set(&chan->sock_map, &socket_fd, &job) != PH_OK) { ph_mem_free(mt.job, job); return -1; } return 0; }
static ph_dns_channel_t *create_chan(void) { ph_dns_channel_t *chan; struct ares_options opts; int res; pthread_mutexattr_t attr; chan = ph_mem_alloc(mt.chan); if (!chan) { return NULL; } pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&chan->chanlock, &attr); pthread_mutexattr_destroy(&attr); if (ph_ht_init(&chan->sock_map, 4, &sock_key, &ph_ht_ptr_val_def) != PH_OK) { ph_panic("failed to init sock map"); } memset(&opts, 0, sizeof(opts)); opts.sock_state_cb_data = chan; opts.sock_state_cb = sock_state_cb; opts.flags = ARES_FLAG_STAYOPEN; res = ares_init_options(&chan->chan, &opts, ARES_OPT_SOCK_STATE_CB|ARES_OPT_FLAGS); if (res != ARES_SUCCESS) { ph_panic("failed to ares_init_options: %s", ares_strerror(res)); } ares_set_socket_callback(chan->chan, sock_create_cb, chan); return chan; }
static ph_result_t do_unregister(ph_hook_point_t *hp, ph_hook_func func, void *closure) { ph_hook_point_head_t *old_head, *new_head; ph_result_t res = PH_ERR; uint16_t off = 0; bool found = false; struct ph_hook_item_free *unreg = 0; ck_rwlock_write_lock(&rwlock); { old_head = hp->head; if (!old_head) { goto done; } for (off = 0; off < old_head->nitems; off++) { if (old_head->items[off].func == func && old_head->items[off].closure == closure) { found = true; break; } } if (!found) { goto done; } new_head = ph_mem_alloc_size(mt.head, sizeof(*new_head) + (sizeof(ph_hook_item_t) * (old_head->nitems-1))); if (!new_head) { goto done; } if (old_head->items[off].unreg) { unreg = ph_mem_alloc(mt.unreg); if (!unreg) { ph_mem_free(mt.head, new_head); goto done; } unreg->closure = old_head->items[off].closure; unreg->func = old_head->items[off].func; unreg->unreg = old_head->items[off].unreg; } new_head->nitems = old_head->nitems - 1; // Copy before the item if (off) { memcpy(new_head->items, old_head->items, off * sizeof(ph_hook_item_t)); } // Copy after the item if (off + 1 <= old_head->nitems) { memcpy(new_head->items + off, old_head->items + off + 1, (old_head->nitems - (off+1)) * sizeof(ph_hook_item_t)); } // Don't need to re-sort, since we simply removed that item hp->head = new_head; ph_thread_epoch_defer(&old_head->entry, free_head); // Arrange to unregister if (unreg) { ph_thread_epoch_defer(&unreg->entry, call_unreg); } res = PH_OK; } done: ck_rwlock_write_unlock(&rwlock); return res; }