static void account_realloc(void *p, void *ptr, size_t size) { // Do not account itself no_hook = 1; // ptr == NULL is equivalent to malloc(size) if (ptr == NULL) { account_alloc(p, size); } // size == 0 is equivalent to free(ptr), // and p will be NULL else if (size == 0) { account_alloc(ptr, size); } // Now the real realloc else { log("Realloc: %p -> %d\n", ptr, size); // if ptr was moved previous area will be freed if (p != ptr) { log("Realloc: Replacing pointer %p to %p\n", ptr, p); account_alloc(ptr, 0); account_alloc(p, size); } else { struct malloc_item *found; int alloc_diff; HASH_FIND_PTR(HT, &ptr, found); if (found) { // alloc_diff may be negative when shrinking memory alloc_diff = size - found->size; mem_allocated += alloc_diff; found->size += alloc_diff; log("Realloc: diff %p -> %d\n", ptr, alloc_diff); } else { log("Reallocating unaccounted pointer %p\n", ptr); } } } log(" [[[::: %d (%u) :::]]] \n", mem_allocated, HASH_COUNT(HT)); no_hook = 0; }
void free(void *ptr) { if (libc_free == NULL) SAVE_LIBC_FUNC(libc_free, "free"); init_env(); libc_free(ptr); if (!no_hook) account_alloc(ptr, 0); }
void *calloc(size_t nmemb, size_t size) { void *p = NULL; if (libc_calloc == NULL) SAVE_LIBC_FUNC(libc_calloc, "calloc"); init_env(); if (mem_allocated + nmemb * size <= mem_threshold) { p = libc_calloc(nmemb, size); } else { log("Restricting calloc of %zu elements per %zu size\n", nmemb, size); errno = ENOMEM; return NULL; } if (!no_hook) account_alloc(p, nmemb * size); return p; }
void *malloc(size_t size) { void *p = NULL; if (libc_malloc == NULL) SAVE_LIBC_FUNC(libc_malloc, "malloc"); init_env(); if (mem_allocated + size <= mem_threshold) { p = libc_malloc(size); } else { log("Restricting malloc of %zu bytes\n", size); errno = ENOMEM; return NULL; } if (!no_hook) account_alloc(p, size); return p; }
/** * Allocate a SIP User-Agent * * @param uap Pointer to allocated User-Agent object * @param aor SIP Address-of-Record (AOR) * * @return 0 if success, otherwise errorcode */ int ua_alloc(struct ua **uap, const char *aor) { struct ua *ua; int err; if (!aor) return EINVAL; ua = mem_zalloc(sizeof(*ua), ua_destructor); if (!ua) return ENOMEM; MAGIC_INIT(ua); list_init(&ua->calls); #if HAVE_INET6 ua->af = uag.prefer_ipv6 ? AF_INET6 : AF_INET; #else ua->af = AF_INET; #endif /* Decode SIP address */ err = account_alloc(&ua->acc, aor); if (err) goto out; /* generate a unique contact-user, this is needed to route incoming requests when using multiple useragents */ err = re_sdprintf(&ua->cuser, "%r-%p", &ua->acc->luri.user, ua); if (err) goto out; if (ua->acc->sipnat) { ua_printf(ua, "Using sipnat: `%s'\n", ua->acc->sipnat); } if (ua->acc->mnat) { ua_printf(ua, "Using medianat `%s'\n", ua->acc->mnat->id); if (0 == str_casecmp(ua->acc->mnat->id, "ice")) add_extension(ua, "ice"); } if (ua->acc->menc) { ua_printf(ua, "Using media encryption `%s'\n", ua->acc->menc->id); } /* Register clients */ if (str_isset(uag.cfg->uuid)) add_extension(ua, "gruu"); if (0 == str_casecmp(ua->acc->sipnat, "outbound")) { size_t i; add_extension(ua, "path"); add_extension(ua, "outbound"); if (!str_isset(uag.cfg->uuid)) { warning("ua: outbound requires valid UUID!\n"); err = ENOSYS; goto out; } for (i=0; i<ARRAY_SIZE(ua->acc->outbound); i++) { if (ua->acc->outbound[i] && ua->acc->regint) { err = reg_add(&ua->regl, ua, (int)i+1); if (err) break; } } } else if (ua->acc->regint) { err = reg_add(&ua->regl, ua, 0); } if (err) goto out; list_append(&uag.ual, &ua->le, ua); if (ua->acc->regint) { err = ua_register(ua); } if (!uag_current()) uag_current_set(ua); out: if (err) mem_deref(ua); else if (uap) { *uap = ua; ua->uap = uap; } return err; }