TT#48650 use constant string hashing for string lookups

To avoid repeated strcmp()s and make use of switch()'s optimised binary
lookup, we employ a second build step that preprocesses certain .c files
and uses gperf to substitute pseudomacros with their respective constant
hash value.

Change-Id: Id89c4728a0fc7aa911691d4dd1ba8e7b3916a983
changes/42/25442/8
Richard Fuchs 6 years ago
parent 9e6199c7b9
commit 98de5697e6

1
.gitignore vendored

@ -1 +1,2 @@
.*.sw?
*.strhash.c

@ -113,8 +113,8 @@ LDLIBS+= $(bcg729_lib)
endif
SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_udp.c redis.c \
bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c stun.c rtcp.c \
crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c ice.c socket.c \
bencode.c cookie_cache.c udp_listener.c control_ng.strhash.c sdp.strhash.c stun.c rtcp.c \
crypto.c rtp.c call_interfaces.strhash.c dtls.c log.c cli.c graphite.c ice.c socket.c \
media_socket.c homer.c recording.c statistics.c cdr.c ssrc.c iptables.c tcp_listener.c \
codec.c load.c dtmf.c
LIBSRCS= loglib.c auxlib.c rtplib.c str.c

@ -500,24 +500,41 @@ INLINE char *bencode_get_alt(bencode_item_t *i, const char *one, const char *two
}
INLINE void ng_sdes_option(struct sdp_ng_flags *out, str *s, void *dummy) {
if (!str_cmp(s, "no") || !str_cmp(s, "off") || !str_cmp(s, "disabled")
|| !str_cmp(s, "disable"))
out->sdes_off = 1;
else if (!str_cmp(s, "unencrypted_srtp") || !str_cmp(s, "UNENCRYPTED_SRTP"))
out->sdes_unencrypted_srtp = 1;
else if (!str_cmp(s, "unencrypted_srtcp") || !str_cmp(s, "UNENCRYPTED_SRTCP"))
out->sdes_unencrypted_srtcp = 1;
else if (!str_cmp(s, "unauthenticated_srtp") || !str_cmp(s, "UNAUTHENTICATED_SRTP"))
out->sdes_unauthenticated_srtp = 1;
else if (!str_cmp(s, "encrypted_srtp") || !str_cmp(s, "ENCRYPTED_SRTP"))
out->sdes_encrypted_srtp = 1;
else if (!str_cmp(s, "encrypted_srtcp") || !str_cmp(s, "ENCRYPTED_SRTCP"))
out->sdes_encrypted_srtcp = 1;
else if (!str_cmp(s, "authenticated_srtp") || !str_cmp(s, "AUTHENTICATED_SRTP"))
out->sdes_authenticated_srtp = 1;
else
ilog(LOG_WARN, "Unknown 'SDES' flag encountered: '"STR_FORMAT"'",
STR_FMT(s));
switch (__csh_lookup(s)) {
case CSH_LOOKUP("no"):
case CSH_LOOKUP("off"):
case CSH_LOOKUP("disabled"):
case CSH_LOOKUP("disable"):
out->sdes_off = 1;
break;
case CSH_LOOKUP("unencrypted_srtp"):
case CSH_LOOKUP("UNENCRYPTED_SRTP"):
out->sdes_unencrypted_srtp = 1;
break;
case CSH_LOOKUP("unencrypted_srtcp"):
case CSH_LOOKUP("UNENCRYPTED_SRTCP"):
out->sdes_unencrypted_srtcp = 1;
break;
case CSH_LOOKUP("unauthenticated_srtp"):
case CSH_LOOKUP("UNAUTHENTICATED_SRTP"):
out->sdes_unauthenticated_srtp = 1;
break;
case CSH_LOOKUP("encrypted_srtp"):
case CSH_LOOKUP("ENCRYPTED_SRTP"):
out->sdes_encrypted_srtp = 1;
break;
case CSH_LOOKUP("encrypted_srtcp"):
case CSH_LOOKUP("ENCRYPTED_SRTCP"):
out->sdes_encrypted_srtcp = 1;
break;
case CSH_LOOKUP("authenticated_srtp"):
case CSH_LOOKUP("AUTHENTICATED_SRTP"):
out->sdes_authenticated_srtp = 1;
break;
default:
ilog(LOG_WARN, "Unknown 'SDES' flag encountered: '"STR_FORMAT"'",
STR_FMT(s));
}
}
@ -535,19 +552,26 @@ static void call_ng_flags_list(struct sdp_ng_flags *out, bencode_item_t *input,
}
}
static void call_ng_flags_rtcp_mux(struct sdp_ng_flags *out, str *s, void *dummy) {
if (!str_cmp(s, "offer"))
out->rtcp_mux_offer = 1;
else if (!str_cmp(s, "require"))
out->rtcp_mux_require = 1;
else if (!str_cmp(s, "demux"))
out->rtcp_mux_demux = 1;
else if (!str_cmp(s, "accept"))
out->rtcp_mux_accept = 1;
else if (!str_cmp(s, "reject"))
out->rtcp_mux_reject = 1;
else
ilog(LOG_WARN, "Unknown 'rtcp-mux' flag encountered: '" STR_FORMAT "'",
STR_FMT(s));
switch (__csh_lookup(s)) {
case CSH_LOOKUP("offer"):
out->rtcp_mux_offer = 1;
break;
case CSH_LOOKUP("require"):
out->rtcp_mux_require = 1;
break;
case CSH_LOOKUP("demux"):
out->rtcp_mux_demux = 1;
break;
case CSH_LOOKUP("accept"):
out->rtcp_mux_accept = 1;
break;
case CSH_LOOKUP("reject"):
out->rtcp_mux_reject = 1;
break;
default:
ilog(LOG_WARN, "Unknown 'rtcp-mux' flag encountered: '" STR_FORMAT "'",
STR_FMT(s));
}
}
static void call_ng_flags_replace(struct sdp_ng_flags *out, str *s, void *dummy) {
str_hyphenate(s);
@ -590,65 +614,84 @@ INLINE int call_ng_flags_prefix(struct sdp_ng_flags *out, str *s_ori, const char
static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) {
str_hyphenate(s);
// XXX use internal hash tables for these
if (!str_cmp(s, "trust-address"))
out->trust_address = 1;
else if (!str_cmp(s, "SIP-source-address"))
out->trust_address = 0;
else if (!str_cmp(s, "asymmetric"))
out->asymmetric = 1;
else if (!str_cmp(s, "no-redis-update"))
out->no_redis_update = 1;
else if (!str_cmp(s, "unidirectional"))
out->unidirectional = 1;
else if (!str_cmp(s, "strict-source"))
out->strict_source = 1;
else if (!str_cmp(s, "media-handover"))
out->media_handover = 1;
else if (!str_cmp(s, "reset"))
out->reset = 1;
else if (!str_cmp(s, "all"))
out->all = 1;
else if (!str_cmp(s, "fragment"))
out->fragment = 1;
else if (!str_cmp(s, "port-latching"))
out->port_latching = 1;
else if (!str_cmp(s, "generate-mid"))
out->generate_mid = 1;
else if (!str_cmp(s, "record-call"))
out->record_call = 1;
else if (!str_cmp(s, "no-rtcp-attribute"))
out->no_rtcp_attr = 1;
else if (!str_cmp(s, "full-rtcp-attribute"))
out->full_rtcp_attr = 1;
else if (!str_cmp(s, "loop-protect"))
out->loop_protect = 1;
else if (!str_cmp(s, "always-transcode"))
out->always_transcode = 1;
else if (!str_cmp(s, "asymmetric-codecs"))
out->asymmetric_codecs = 1;
else if (!str_cmp(s, "pad-crypto"))
out->pad_crypto = 1;
else {
// handle values aliases from other dictionaries
if (call_ng_flags_prefix(out, s, "SDES-", ng_sdes_option, NULL))
return;
if (call_ng_flags_prefix(out, s, "codec-strip-", call_ng_flags_codec_ht, out->codec_strip))
return;
if (call_ng_flags_prefix(out, s, "codec-offer-", call_ng_flags_codec_list, &out->codec_offer))
return;
switch (__csh_lookup(s)) {
case CSH_LOOKUP("trust-address"):
out->trust_address = 1;
break;
case CSH_LOOKUP("SIP-source-address"):
out->trust_address = 0;
break;
case CSH_LOOKUP("asymmetric"):
out->asymmetric = 1;
break;
case CSH_LOOKUP("no-redis-update"):
out->no_redis_update = 1;
break;
case CSH_LOOKUP("unidirectional"):
out->unidirectional = 1;
break;
case CSH_LOOKUP("strict-source"):
out->strict_source = 1;
break;
case CSH_LOOKUP("media-handover"):
out->media_handover = 1;
break;
case CSH_LOOKUP("reset"):
out->reset = 1;
break;
case CSH_LOOKUP("all"):
out->all = 1;
break;
case CSH_LOOKUP("fragment"):
out->fragment = 1;
break;
case CSH_LOOKUP("port-latching"):
out->port_latching = 1;
break;
case CSH_LOOKUP("generate-mid"):
out->generate_mid = 1;
break;
case CSH_LOOKUP("record-call"):
out->record_call = 1;
break;
case CSH_LOOKUP("no-rtcp-attribute"):
out->no_rtcp_attr = 1;
break;
case CSH_LOOKUP("full-rtcp-attribute"):
out->full_rtcp_attr = 1;
break;
case CSH_LOOKUP("loop-protect"):
out->loop_protect = 1;
break;
case CSH_LOOKUP("always-transcode"):
out->always_transcode = 1;
break;
case CSH_LOOKUP("asymmetric-codecs"):
out->asymmetric_codecs = 1;
break;
case CSH_LOOKUP("pad-crypto"):
out->pad_crypto = 1;
break;
default:
// handle values aliases from other dictionaries
if (call_ng_flags_prefix(out, s, "SDES-", ng_sdes_option, NULL))
return;
if (call_ng_flags_prefix(out, s, "codec-strip-", call_ng_flags_codec_ht, out->codec_strip))
return;
if (call_ng_flags_prefix(out, s, "codec-offer-", call_ng_flags_codec_list, &out->codec_offer))
return;
#ifdef WITH_TRANSCODING
if (call_ng_flags_prefix(out, s, "transcode-", call_ng_flags_codec_list, &out->codec_transcode))
return;
if (call_ng_flags_prefix(out, s, "codec-transcode-", call_ng_flags_codec_list,
&out->codec_transcode))
return;
if (call_ng_flags_prefix(out, s, "codec-mask-", call_ng_flags_codec_ht, out->codec_mask))
return;
if (call_ng_flags_prefix(out, s, "transcode-", call_ng_flags_codec_list, &out->codec_transcode))
return;
if (call_ng_flags_prefix(out, s, "codec-transcode-", call_ng_flags_codec_list,
&out->codec_transcode))
return;
if (call_ng_flags_prefix(out, s, "codec-mask-", call_ng_flags_codec_ht, out->codec_mask))
return;
#endif
ilog(LOG_WARN, "Unknown flag encountered: '" STR_FORMAT "'",
STR_FMT(s));
ilog(LOG_WARN, "Unknown flag encountered: '" STR_FORMAT "'",
STR_FMT(s));
}
}
static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *input) {
@ -682,27 +725,39 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
}
if (bencode_dictionary_get_str(input, "ICE", &s)) {
if (!str_cmp(&s, "remove"))
out->ice_remove = 1;
else if (!str_cmp(&s, "force"))
out->ice_force = 1;
else if (!str_cmp(&s, "force_relay") || !str_cmp(&s, "force-relay")
|| !str_cmp(&s, "force relay"))
out->ice_force_relay = 1;
else
ilog(LOG_WARN, "Unknown 'ICE' flag encountered: '"STR_FORMAT"'",
STR_FMT(&s));
switch (__csh_lookup(&s)) {
case CSH_LOOKUP("remove"):
out->ice_remove = 1;
break;
case CSH_LOOKUP("force"):
out->ice_force = 1;
break;
case CSH_LOOKUP("force_relay"):
case CSH_LOOKUP("force-relay"):
case CSH_LOOKUP("force relay"):
out->ice_force_relay = 1;
break;
default:
ilog(LOG_WARN, "Unknown 'ICE' flag encountered: '"STR_FORMAT"'",
STR_FMT(&s));
}
}
if (bencode_dictionary_get_str(input, "DTLS", &s)) {
if (!str_cmp(&s, "passive"))
out->dtls_passive = 1;
else if (!str_cmp(&s, "no") || !str_cmp(&s, "off") || !str_cmp(&s, "disabled")
|| !str_cmp(&s, "disable"))
out->dtls_off = 1;
else
ilog(LOG_WARN, "Unknown 'DTLS' flag encountered: '"STR_FORMAT"'",
STR_FMT(&s));
switch (__csh_lookup(&s)) {
case CSH_LOOKUP("passive"):
out->dtls_passive = 1;
break;
case CSH_LOOKUP("no"):
case CSH_LOOKUP("off"):
case CSH_LOOKUP("disabled"):
case CSH_LOOKUP("disable"):
out->dtls_off = 1;
break;
default:
ilog(LOG_WARN, "Unknown 'DTLS' flag encountered: '"STR_FORMAT"'",
STR_FMT(&s));
}
}
call_ng_flags_list(out, input, "rtcp-mux", call_ng_flags_rtcp_mux, NULL);

@ -184,57 +184,59 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin
// start command timer
gettimeofday(&cmd_start, NULL);
if (!str_cmp(&cmd, "ping")) {
resultstr = "pong";
g_atomic_int_inc(&cur->ping);
}
else if (!str_cmp(&cmd, "offer")) {
errstr = call_offer_ng(dict, resp, addr, sin);
g_atomic_int_inc(&cur->offer);
}
else if (!str_cmp(&cmd, "answer")) {
errstr = call_answer_ng(dict, resp);
g_atomic_int_inc(&cur->answer);
}
else if (!str_cmp(&cmd, "delete")) {
errstr = call_delete_ng(dict, resp);
g_atomic_int_inc(&cur->delete);
}
else if (!str_cmp(&cmd, "query")) {
errstr = call_query_ng(dict, resp);
g_atomic_int_inc(&cur->query);
}
else if (!str_cmp(&cmd, "list")) {
errstr = call_list_ng(dict, resp);
g_atomic_int_inc(&cur->list);
}
else if (!str_cmp(&cmd, "start recording")) {
errstr = call_start_recording_ng(dict, resp);
g_atomic_int_inc(&cur->start_recording);
}
else if (!str_cmp(&cmd, "stop recording")) {
errstr = call_stop_recording_ng(dict, resp);
g_atomic_int_inc(&cur->stop_recording);
}
else if (!str_cmp(&cmd, "block DTMF")) {
errstr = call_block_dtmf_ng(dict, resp);
g_atomic_int_inc(&cur->block_dtmf);
}
else if (!str_cmp(&cmd, "unblock DTMF")) {
errstr = call_unblock_dtmf_ng(dict, resp);
g_atomic_int_inc(&cur->unblock_dtmf);
}
else if (!str_cmp(&cmd, "block media")) {
errstr = call_block_media_ng(dict, resp);
g_atomic_int_inc(&cur->block_media);
}
else if (!str_cmp(&cmd, "unblock media")) {
errstr = call_unblock_media_ng(dict, resp);
g_atomic_int_inc(&cur->unblock_media);
}
else
{
errstr = "Unrecognized command";
int cmdcode = __csh_lookup(&cmd);
switch (cmdcode) {
case CSH_LOOKUP("ping"):
resultstr = "pong";
g_atomic_int_inc(&cur->ping);
break;
case CSH_LOOKUP("offer"):
errstr = call_offer_ng(dict, resp, addr, sin);
g_atomic_int_inc(&cur->offer);
break;
case CSH_LOOKUP("answer"):
errstr = call_answer_ng(dict, resp);
g_atomic_int_inc(&cur->answer);
break;
case CSH_LOOKUP("delete"):
errstr = call_delete_ng(dict, resp);
g_atomic_int_inc(&cur->delete);
break;
case CSH_LOOKUP("query"):
errstr = call_query_ng(dict, resp);
g_atomic_int_inc(&cur->query);
break;
case CSH_LOOKUP("list"):
errstr = call_list_ng(dict, resp);
g_atomic_int_inc(&cur->list);
break;
case CSH_LOOKUP("start recording"):
errstr = call_start_recording_ng(dict, resp);
g_atomic_int_inc(&cur->start_recording);
break;
case CSH_LOOKUP("stop recording"):
errstr = call_stop_recording_ng(dict, resp);
g_atomic_int_inc(&cur->stop_recording);
break;
case CSH_LOOKUP("block DTMF"):
errstr = call_block_dtmf_ng(dict, resp);
g_atomic_int_inc(&cur->block_dtmf);
break;
case CSH_LOOKUP("unblock DTMF"):
errstr = call_unblock_dtmf_ng(dict, resp);
g_atomic_int_inc(&cur->unblock_dtmf);
break;
case CSH_LOOKUP("block media"):
errstr = call_block_media_ng(dict, resp);
g_atomic_int_inc(&cur->block_media);
break;
case CSH_LOOKUP("unblock media"):
errstr = call_unblock_media_ng(dict, resp);
g_atomic_int_inc(&cur->unblock_media);
break;
default:
errstr = "Unrecognized command";
}
// stop command timer
@ -248,15 +250,19 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin
bencode_dictionary_add_string(resp, "result", resultstr);
// update interval statistics
if (!str_cmp(&cmd, "offer")) {
atomic64_inc(&rtpe_statsps.offers);
timeval_update_request_time(&rtpe_totalstats_interval.offer, &cmd_process_time);
} else if (!str_cmp(&cmd, "answer")) {
atomic64_inc(&rtpe_statsps.answers);
timeval_update_request_time(&rtpe_totalstats_interval.answer, &cmd_process_time);
} else if (!str_cmp(&cmd, "delete")) {
atomic64_inc(&rtpe_statsps.deletes);
timeval_update_request_time(&rtpe_totalstats_interval.delete, &cmd_process_time);
switch (cmdcode) {
case CSH_LOOKUP("offer"):
atomic64_inc(&rtpe_statsps.offers);
timeval_update_request_time(&rtpe_totalstats_interval.offer, &cmd_process_time);
break;
case CSH_LOOKUP("answer"):
atomic64_inc(&rtpe_statsps.answers);
timeval_update_request_time(&rtpe_totalstats_interval.answer, &cmd_process_time);
break;
case CSH_LOOKUP("delete"):
atomic64_inc(&rtpe_statsps.deletes);
timeval_update_request_time(&rtpe_totalstats_interval.delete, &cmd_process_time);
break;
}
goto send_resp;

@ -793,84 +793,81 @@ static int parse_attribute(struct sdp_attribute *a) {
}
ret = 0;
switch (a->name.len) {
case 3:
if (!str_cmp(&a->name, "mid"))
a->attr = ATTR_MID;
switch (__csh_lookup(&a->name)) {
case CSH_LOOKUP("mid"):
a->attr = ATTR_MID;
break;
case 4:
if (!str_cmp(&a->name, "rtcp"))
ret = parse_attribute_rtcp(a);
else if (!str_cmp(&a->name, "ssrc"))
ret = parse_attribute_ssrc(a);
else if (!str_cmp(&a->name, "fmtp"))
ret = parse_attribute_fmtp(a);
case CSH_LOOKUP("rtcp"):
ret = parse_attribute_rtcp(a);
break;
case 5:
if (!str_cmp(&a->name, "group"))
ret = parse_attribute_group(a);
else if (!str_cmp(&a->name, "setup"))
ret = parse_attribute_setup(a);
else if (!str_cmp(&a->name, "ptime"))
a->attr = ATTR_PTIME;
case CSH_LOOKUP("ssrc"):
ret = parse_attribute_ssrc(a);
break;
case 6:
if (!str_cmp(&a->name, "crypto"))
ret = parse_attribute_crypto(a);
else if (!str_cmp(&a->name, "extmap"))
a->attr = ATTR_EXTMAP;
else if (!str_cmp(&a->name, "rtpmap"))
ret = parse_attribute_rtpmap(a);
case CSH_LOOKUP("fmtp"):
ret = parse_attribute_fmtp(a);
break;
case 7:
if (!str_cmp(&a->name, "ice-pwd"))
a->attr = ATTR_ICE_PWD;
case CSH_LOOKUP("group"):
ret = parse_attribute_group(a);
break;
case 8:
switch (a->name.s[0]) {
case 'i':
if (!str_cmp(&a->name, "ice-lite"))
a->attr = ATTR_ICE_LITE;
else if (!str_cmp(&a->name, "inactive"))
a->attr = ATTR_INACTIVE;
break;
case 's':
if (!str_cmp(&a->name, "sendrecv"))
a->attr = ATTR_SENDRECV;
else if (!str_cmp(&a->name, "sendonly"))
a->attr = ATTR_SENDONLY;
break;
case 'r':
if (!str_cmp(&a->name, "recvonly"))
a->attr = ATTR_RECVONLY;
if (!str_cmp(&a->name, "rtcp-mux"))
a->attr = ATTR_RTCP_MUX;
break;
}
case CSH_LOOKUP("setup"):
ret = parse_attribute_setup(a);
break;
case CSH_LOOKUP("ptime"):
a->attr = ATTR_PTIME;
break;
case CSH_LOOKUP("crypto"):
ret = parse_attribute_crypto(a);
break;
case CSH_LOOKUP("extmap"):
a->attr = ATTR_EXTMAP;
break;
case CSH_LOOKUP("rtpmap"):
ret = parse_attribute_rtpmap(a);
break;
case CSH_LOOKUP("ice-pwd"):
a->attr = ATTR_ICE_PWD;
break;
case CSH_LOOKUP("ice-lite"):
a->attr = ATTR_ICE_LITE;
break;
case CSH_LOOKUP("inactive"):
a->attr = ATTR_INACTIVE;
break;
case CSH_LOOKUP("sendrecv"):
a->attr = ATTR_SENDRECV;
break;
case CSH_LOOKUP("sendonly"):
a->attr = ATTR_SENDONLY;
break;
case CSH_LOOKUP("recvonly"):
a->attr = ATTR_RECVONLY;
break;
case CSH_LOOKUP("rtcp-mux"):
a->attr = ATTR_RTCP_MUX;
break;
case CSH_LOOKUP("candidate"):
ret = parse_attribute_candidate(a);
break;
case CSH_LOOKUP("ice-ufrag"):
a->attr = ATTR_ICE_UFRAG;
break;
case CSH_LOOKUP("rtpengine"):
a->attr = ATTR_RTPENGINE;
break;
case CSH_LOOKUP("ice-options"):
a->attr = ATTR_ICE_OPTIONS;
break;
case 9:
if (!str_cmp(&a->name, "candidate"))
ret = parse_attribute_candidate(a);
else if (!str_cmp(&a->name, "ice-ufrag"))
a->attr = ATTR_ICE_UFRAG;
else if (!str_cmp(&a->name, "rtpengine"))
a->attr = ATTR_RTPENGINE;
case CSH_LOOKUP("fingerprint"):
ret = parse_attribute_fingerprint(a);
break;
case 11:
if (!str_cmp(&a->name, "ice-options"))
a->attr = ATTR_ICE_OPTIONS;
else if (!str_cmp(&a->name, "fingerprint"))
ret = parse_attribute_fingerprint(a);
case CSH_LOOKUP("ice-mismatch"):
a->attr = ATTR_ICE;
break;
case 12:
if (!str_cmp(&a->name, "ice-mismatch"))
a->attr = ATTR_ICE;
case CSH_LOOKUP("remote-candidates"):
a->attr = ATTR_ICE;
break;
case 17:
if (!str_cmp(&a->name, "remote-candidates"))
a->attr = ATTR_ICE;
else if (!str_cmp(&a->name, "end-of-candidates"))
a->attr = ATTR_END_OF_CANDIDATES;
case CSH_LOOKUP("end-of-candidates"):
a->attr = ATTR_END_OF_CANDIDATES;
break;
}

1
debian/control vendored

@ -7,6 +7,7 @@ Standards-Version: 3.9.8
Build-Depends:
debhelper (>= 10~),
default-libmysqlclient-dev | libmysqlclient-dev,
gperf,
iptables-dev (>= 1.4),
libavcodec-dev (>= 6:10),
libavfilter-dev (>= 6:10),

@ -13,7 +13,7 @@ dep: .depend
clean:
rm -f $(OBJS) $(TARGET) $(LIBSRCS) $(DAEMONSRCS) $(ADD_CLEAN) .depend core core.*
rm -f fix_frame_channel_layout.h fix_frame_channel_layout-test.[co]
rm -f fix_frame_channel_layout.h fix_frame_channel_layout-test.[co] *.strhash.c $(HASHSRCS)
.depend: $(SRCS) $(LIBSRCS) $(DAEMONSRCS) Makefile
$(CC) $(CFLAGS) -M $(SRCS) $(LIBSRCS) $(DAEMONSRCS) | sed -e 's/:/ .depend:/' > .depend
@ -27,13 +27,16 @@ $(LIBSRCS): $(patsubst %,../lib/%,$(LIBSRCS))
echo '/******** GENERATED FILE ********/' > "$@"
cat ../lib/"$@" >> "$@"
$(DAEMONSRCS): $(patsubst %,../daemon/%,$(DAEMONSRCS))
$(DAEMONSRCS) $(HASHSRCS): $(patsubst %,../daemon/%,$(DAEMONSRCS)) $(patsubst %,../daemon/%,$(HASHSRCS))
rm -f "$@"
echo '/******** GENERATED FILE ********/' > "$@"
cat ../daemon/"$@" >> "$@"
resample.c: fix_frame_channel_layout.h
%.strhash.c: %.c ../utils/const_str_hash
../utils/const_str_hash < $< > $@
fix_frame_channel_layout.h: ../lib/fix_frame_channel_layout-*
echo "Looking for usable alternative for $@"; \
rm -f fix_frame_channel_layout-test.[co]; \

1
t/.gitignore vendored

@ -44,3 +44,4 @@ transcode-test
udp_listener.c
payload-tracker-test
dtmf.c
const_str_hash-test.strhash

@ -49,21 +49,21 @@ LDLIBS+= $(shell pkg-config xmlrpc_util --libs 2> /dev/null)
LDLIBS+= -lhiredis
endif
SRCS= bitstr-test.c aes-crypt.c payload-tracker-test.c
ifeq ($(with_transcoding),yes)
SRCS+= amr-decode-test.c amr-encode-test.c transcode-test.c
endif
SRCS= bitstr-test.c aes-crypt.c payload-tracker-test.c const_str_hash-test.strhash.c
LIBSRCS= loglib.c auxlib.c str.c rtplib.c
ifeq ($(with_transcoding),yes)
LIBSRCS+= codeclib.c resample.c
endif
DAEMONSRCS= crypto.c
HASHSRCS=
ifeq ($(with_transcoding),yes)
SRCS+= amr-decode-test.c amr-encode-test.c transcode-test.c
LIBSRCS+= codeclib.c resample.c
DAEMONSRCS+= codec.c ssrc.c call.c ice.c aux.c kernel.c media_socket.c stun.c bencode.c socket.c poller.c \
dtls.c recording.c statistics.c rtcp.c redis.c iptables.c graphite.c call_interfaces.c sdp.c \
rtp.c control_ng.c streambuf.c cookie_cache.c udp_listener.c homer.c load.c cdr.c dtmf.c
dtls.c recording.c statistics.c rtcp.c redis.c iptables.c graphite.c \
rtp.c streambuf.c cookie_cache.c udp_listener.c homer.c load.c cdr.c dtmf.c
HASHSRCS+= call_interfaces.c control_ng.c sdp.c
endif
OBJS= $(SRCS:.c=.o) $(LIBSRCS:.c=.o) $(DAEMONSRCS:.c=.o)
OBJS= $(SRCS:.c=.o) $(LIBSRCS:.c=.o) $(DAEMONSRCS:.c=.o) $(HASHSRCS:.c=.strhash.o)
COMMONOBJS= str.o auxlib.o rtplib.o loglib.o
@ -73,7 +73,7 @@ include .depend
.PHONY: unit-tests
TESTS= bitstr-test aes-crypt payload-tracker-test
TESTS= bitstr-test aes-crypt payload-tracker-test const_str_hash-test.strhash
ifeq ($(with_transcoding),yes)
TESTS+= amr-decode-test amr-encode-test transcode-test
endif
@ -93,7 +93,10 @@ aes-crypt: aes-crypt.o $(COMMONOBJS) crypto.o
transcode-test: transcode-test.o $(COMMONOBJS) codeclib.o resample.o codec.o ssrc.o call.o ice.o aux.o \
kernel.o media_socket.o stun.o bencode.o socket.o poller.o dtls.o recording.o statistics.o \
rtcp.o redis.o iptables.o graphite.o call_interfaces.o sdp.o rtp.o crypto.o control_ng.o \
rtcp.o redis.o iptables.o graphite.o call_interfaces.strhash.o sdp.strhash.o rtp.o crypto.o \
control_ng.strhash.o \
streambuf.o cookie_cache.o udp_listener.o homer.o load.o cdr.o dtmf.o
payload-tracker-test: payload-tracker-test.o $(COMMONOBJS) ssrc.o aux.o auxlib.o rtp.o crypto.o
const_str_hash-test.strhash: const_str_hash-test.strhash.o $(COMMONOBJS)

@ -0,0 +1,35 @@
#include <stdlib.h>
#include <stdio.h>
#include "str.h"
static int test_hash(char *p) {
str s;
str_init(&s, p);
switch (__csh_lookup(&s)) {
case CSH_LOOKUP("one"):
return 1;
case CSH_LOOKUP("two"):
return 2;
case CSH_LOOKUP("dashed-string"):
return 3;
default:
return 0;
}
// STR_LOOKUP("one") // catch duplicate
}
static void test(char *p, int exp) {
int h = test_hash(p);
if (h != exp) {
printf("%s:%i test failed: %u != %u (string '%s')\n", __FILE__, __LINE__, h, exp, p);
abort();
}
}
int main() {
test("one", 1);
test("two", 2);
test("dashed-string", 3);
test("doesn't exist", 0);
return 0;
}

@ -0,0 +1,73 @@
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
print("/******** GENERATED FILE ********/\n");
my $rewritten_input = '';
my $iter = 0;
my $keys = '';
my %key_vals;
# collect keywords and rewrite input file with in lookup keys
while (my $line = <>) {
if (!($line =~ s/CSH_LOOKUP\("(.*?)"\)/{}/)) {
$rewritten_input .= $line;
next;
}
my $key = $1;
if (exists($key_vals{$key})) {
$line =~ s/{}/$key_vals{$key}/;
}
else {
$line =~ s/{}/$iter/;
$keys .= "$key,$iter\n";
$key_vals{$key} = $iter;
$iter++;
}
$rewritten_input .= $line;
}
# pass collected output to gperf
my ($rd, $wr);
my $pid = open2($rd, $wr, qw(gperf -t -E -l -c -t -I -H __csh_hash -N __csh_lookup_raw));
# gperf header and keys
print { $wr } "struct __csh_hash_lookup { char *name; int num; };\n%%\n";
print { $wr } $keys;
# read gperf output
close($wr);
my $hash_func_code;
{
local $/ = undef;
$hash_func_code = <$rd>;
}
close($rd);
waitpid($pid, 0);
exit(1) if $?;
# convert lookup function to static
$hash_func_code =~ s/(^|\s)struct\s+__csh_hash_lookup\s*\*/\nstatic$&/s;
# print combined output
print $hash_func_code;
# add convenience function
print <<END;
#include "str.h"
static int __csh_lookup(const str *s) {
struct __csh_hash_lookup *h = __csh_lookup_raw(s->s, s->len);
if (!h)
return -1;
return h->num;
}
END
print $rewritten_input;
Loading…
Cancel
Save