static void php_swoole_dns_timeout_coro(swTimer *timer, swTimer_node *tnode) { zval *retval = NULL; zval *zaddress; php_context *cxt = (php_context *) tnode->data; dns_request *req = (dns_request *) cxt->coro_params.value.ptr; SW_MAKE_STD_ZVAL(zaddress); dns_cache *cache = swHashMap_find(request_cache_map, Z_STRVAL_P(req->domain), Z_STRLEN_P(req->domain)); if (cache != NULL && cache->update_time > (int64_t) swTimer_get_now_msec) { SW_ZVAL_STRINGL(zaddress, (*cache->zaddress).str, (*cache->zaddress).length, 1); } else { SW_ZVAL_STRING(zaddress, "", 1); } int ret = coro_resume(req->context, zaddress, &retval); if (ret > 0) { goto free_zdata; } if (retval != NULL) { sw_zval_ptr_dtor(&retval); } free_zdata: sw_zval_ptr_dtor(&zaddress); efree(req->context); req->useless = 1; }
static PHP_METHOD(swoole_coroutine_util, resume) { char *id; int id_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) { return; } swLinkedList *coros_list = swHashMap_find(defer_coros, id, id_len); if (coros_list == NULL) { swoole_php_fatal_error(E_WARNING, "Nothing can coroResume."); RETURN_FALSE; } php_context *context = swLinkedList_shift(coros_list); if (context == NULL) { swoole_php_fatal_error(E_WARNING, "Nothing can coroResume."); RETURN_FALSE; } SwooleG.main_reactor->defer(SwooleG.main_reactor, swoole_coroutine_util_resume, context); RETURN_TRUE; }
static PHP_METHOD(swoole_coroutine_util, suspend) { char *id; int id_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&id, &id_len) == FAILURE) { return; } swLinkedList *coros_list = swHashMap_find(defer_coros, id, id_len); if (coros_list == NULL) { coros_list = swLinkedList_new(2, NULL); if (coros_list == NULL) { RETURN_FALSE; } if (swHashMap_add(defer_coros, id, id_len, coros_list) == SW_ERR) { swLinkedList_free(coros_list); RETURN_FALSE; } } php_context *context = emalloc(sizeof(php_context)); coro_save(context); if (swLinkedList_append(coros_list, (void *)context) == SW_ERR) { efree(context); RETURN_FALSE; } coro_yield(); }
void* swoole_get_function(char *name, uint32_t length) { if (!SwooleG.functions) { return NULL; } return swHashMap_find(SwooleG.functions, name, length); }
int swoole_add_function(const char *name, void* func) { if (SwooleG.functions == NULL) { SwooleG.functions = swHashMap_new(64, NULL); if (SwooleG.functions == NULL) { return SW_ERR; } } if (swHashMap_find(SwooleG.functions, (char *) name, strlen(name)) != NULL) { swWarn("Function '%s' has already been added.", name); return SW_ERR; } return swHashMap_add(SwooleG.functions, (char *) name, strlen(name), func); }
static int swClient_inet_addr(swClient *cli, char *host, int port) { struct hostent *host_entry; void *s_addr = NULL; if (cli->type == SW_SOCK_TCP || cli->type == SW_SOCK_UDP) { cli->server_addr.addr.inet_v4.sin_family = AF_INET; cli->server_addr.addr.inet_v4.sin_port = htons(port); cli->server_addr.len = sizeof(cli->server_addr.addr.inet_v4); s_addr = &cli->server_addr.addr.inet_v4.sin_addr.s_addr; if (inet_pton(AF_INET, host, s_addr)) { return SW_OK; } } else if (cli->type == SW_SOCK_TCP6 || cli->type == SW_SOCK_UDP6) { cli->server_addr.addr.inet_v6.sin6_family = AF_INET6; cli->server_addr.addr.inet_v6.sin6_port = htons(port); cli->server_addr.len = sizeof(cli->server_addr.addr.inet_v6); s_addr = cli->server_addr.addr.inet_v6.sin6_addr.s6_addr; if (inet_pton(AF_INET6, host, s_addr)) { return SW_OK; } } else if (cli->type == SW_SOCK_UNIX_STREAM || cli->type == SW_SOCK_UNIX_DGRAM) { cli->server_addr.addr.un.sun_family = AF_UNIX; strncpy(cli->server_addr.addr.un.sun_path, host, sizeof(cli->server_addr.addr.un.sun_path)); cli->server_addr.len = sizeof(cli->server_addr.addr.un); return SW_OK; } if (!swoole_dns_cache) { swoole_dns_cache = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, free); } swDNS_cache *cache = swHashMap_find(swoole_dns_cache, host, strlen(host)); if (cache == NULL) { if (cli->async) { swWarn("DNS lookup will block the process. Please use swoole_async_dns_lookup."); } if (!(host_entry = gethostbyname(host))) { swWarn("gethostbyname('%s') failed.", host); return SW_ERR; } if (host_entry->h_addrtype != AF_INET) { swWarn("Host lookup failed: Non AF_INET domain returned on AF_INET socket."); return 0; } cache = sw_malloc(sizeof(int) + host_entry->h_length); if (cache == NULL) { swWarn("malloc() failed."); memcpy(s_addr, host_entry->h_addr_list[0], host_entry->h_length); return SW_OK; } else { memcpy(cache->addr, host_entry->h_addr_list[0], host_entry->h_length); cache->length = host_entry->h_length; } swHashMap_add(swoole_dns_cache, host, strlen(host), cache); } memcpy(s_addr, cache->addr, cache->length); return SW_OK; }
/** * DNS lookup */ int swoole_gethostbyname(int flags, char *name, char *addr) { SwooleGS->lock.lock(&SwooleGS->lock); swHashMap *cache_table; int __af = flags & (~SW_DNS_LOOKUP_CACHE_ONLY) & (~SW_DNS_LOOKUP_RANDOM); if (__af == AF_INET) { if (!swoole_dns_cache_v4) { swoole_dns_cache_v4 = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, free); } cache_table = swoole_dns_cache_v4; } else if (__af == AF_INET6) { if (!swoole_dns_cache_v6) { swoole_dns_cache_v6 = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, free); } cache_table = swoole_dns_cache_v6; } else { SwooleGS->lock.unlock(&SwooleGS->lock); return SW_ERR; } int name_length = strlen(name); int index = 0; swDNS_cache *cache = swHashMap_find(cache_table, name, name_length); if (cache == NULL && (flags & SW_DNS_LOOKUP_CACHE_ONLY)) { SwooleGS->lock.unlock(&SwooleGS->lock); return SW_ERR; } if (cache == NULL) { struct hostent *host_entry; if (!(host_entry = gethostbyname2(name, __af))) { SwooleGS->lock.unlock(&SwooleGS->lock); return SW_ERR; } cache = sw_malloc(sizeof(swDNS_cache)); if (cache == NULL) { SwooleGS->lock.unlock(&SwooleGS->lock); memcpy(addr, host_entry->h_addr_list[0], host_entry->h_length); return SW_OK; } bzero(cache, sizeof(swDNS_cache)); int i = 0; for (i = 0; i < SW_DNS_LOOKUP_CACHE_SIZE; i++) { if (host_entry->h_addr_list[i] == NULL) { break; } if (__af == AF_INET) { memcpy(&cache->addr[i].v4, host_entry->h_addr_list[i], host_entry->h_length); } else { memcpy(&cache->addr[i].v6, host_entry->h_addr_list[i], host_entry->h_length); } } cache->number = i; cache->addr_length = host_entry->h_length; swHashMap_add(cache_table, name, name_length, cache); } SwooleGS->lock.unlock(&SwooleGS->lock); if (flags & SW_DNS_LOOKUP_RANDOM) { index = rand() % cache->number; } if (__af == AF_INET) { memcpy(addr, &cache->addr[index].v4, cache->addr_length); } else { memcpy(addr, &cache->addr[index].v6, cache->addr_length); } return SW_OK; }
static void php_swoole_dns_callback_coro(char *domain, swDNSResolver_result *result, void *data) { SWOOLE_GET_TSRMLS; dns_request *req = data; zval *retval = NULL; zval *zaddress; char *address; SW_MAKE_STD_ZVAL(zaddress); if (result->num > 0) { if (SwooleG.dns_lookup_random) { address = result->hosts[rand() % result->num].address; } else { address = result->hosts[0].address; } SW_ZVAL_STRING(zaddress, address, 1); } else { SW_ZVAL_STRING(zaddress, "", 1); } //update cache dns_cache *cache = swHashMap_find(request_cache_map, Z_STRVAL_P(req->domain), Z_STRLEN_P(req->domain)); if (cache == NULL ) { cache = emalloc(sizeof(dns_cache)); swHashMap_add(request_cache_map, Z_STRVAL_P(req->domain), Z_STRLEN_P(req->domain), cache); cache->zaddress = swString_new(20); } swString_write_ptr(cache->zaddress, 0, Z_STRVAL_P(zaddress), Z_STRLEN_P(zaddress)); cache->update_time = (int64_t) swTimer_get_now_msec + (int64_t) (SwooleG.dns_cache_refresh_time * 1000); //timeout if (req->timer) { swTimer_del(&SwooleG.timer, req->timer); req->timer = NULL; } if (req->useless) { efree(req); return; } int ret = coro_resume(req->context, zaddress, &retval); if (ret > 0) { goto free_zdata; } if (retval != NULL) { sw_zval_ptr_dtor(&retval); } //说明已经yield走了 free_zdata: // free 上下文 sw_zval_ptr_dtor(&zaddress); efree(req->context); efree(req); }
static PHP_METHOD(swoole_module, __call) { zval *params; char *name; zend_size_t name_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, ¶ms) == FAILURE) { return; } swModule *module = swoole_get_object(getThis()); if (module == NULL) { swoole_php_fatal_error(E_ERROR, "Please use swoole_load_module()."); return; } swModule_function func = swHashMap_find(module->functions, name, name_len); if (func == NULL) { swoole_php_fatal_error(E_ERROR, "Module[%s] does not have [%s] function.", module->name, name); return; } swArgs_clear(); zval *value; SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(params), value) switch(SW_Z_TYPE_P(value)) { case IS_STRING: swParam_string(Z_STRVAL_P(value), Z_STRLEN_P(value)); break; case IS_LONG: swParam_long(Z_LVAL_P(value)); break; case IS_DOUBLE: swParam_double(Z_DVAL_P(value)); break; #if PHP_MAJOR_VERSION < 7 case IS_BOOL: swParam_bool(Z_BVAL_P(value)); break; #else case IS_TRUE: swParam_bool(1); break; case IS_FALSE: swParam_bool(0); break; #endif default: swWarn("unknown type."); RETURN_FALSE; } SW_HASHTABLE_FOREACH_END(); swString *args = swString_dup2(SwooleG.call_php_func_args); if (args == NULL) { return; } swVal *retval = func(module, args, Z_ARRVAL_P(params)->nNumOfElements); if (swVal_to_zval(retval, return_value) < 0) { RETURN_NULL(); } swString_free(args); }