📄 srtp_driver.c
字号:
/* * srtp_driver.c * * a test driver for libSRTP * * David A. McGrew * Cisco Systems, Inc. *//* * * Copyright (c) 2001-2006, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the Cisco Systems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */#include <string.h> /* for memcpy() */#include <time.h> /* for clock() */#include <stdlib.h> /* for malloc(), free() */#include <stdio.h> /* for print(), fflush() */#include "getopt_s.h" /* for local getopt() */#include "srtp_priv.h"#ifdef HAVE_NETINET_IN_H# include <netinet/in.h>#elif defined HAVE_WINSOCK2_H# include <winsock2.h>#endif#define PRINT_REFERENCE_PACKET 1err_status_tsrtp_validate(void);err_status_tsrtp_create_big_policy(srtp_policy_t **list);err_status_tsrtp_test_remove_stream(void);doublesrtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy);doublesrtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy);voidsrtp_do_timing(const srtp_policy_t *policy);voidsrtp_do_rejection_timing(const srtp_policy_t *policy);err_status_tsrtp_test(const srtp_policy_t *policy);err_status_tsrtcp_test(const srtp_policy_t *policy);err_status_tsrtp_session_print_policy(srtp_t srtp);err_status_tsrtp_print_policy(const srtp_policy_t *policy); char *srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);doublemips_estimate(int num_trials, int *ignore);extern uint8_t test_key[30];voidusage(char *prog_name) { printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n" " -t run timing test\n" " -r run rejection timing test\n" " -c run codec timing test\n" " -v run validation tests\n" " -d <mod> turn on debugging module <mod>\n" " -l list debugging modules\n", prog_name); exit(1);}/* * The policy_array is a null-terminated array of policy structs. it * is declared at the end of this file */extern const srtp_policy_t *policy_array[];/* the wildcard_policy is declared below; it has a wildcard ssrc */extern const srtp_policy_t wildcard_policy;/* * mod_driver debug module - debugging module for this test driver * * we use the crypto_kernel debugging system in this driver, which * makes the interface uniform and increases portability */ debug_module_t mod_driver = { 0, /* debugging is off by default */ "driver" /* printable name for module */};intmain (int argc, char *argv[]) { char q; unsigned do_timing_test = 0; unsigned do_rejection_test = 0; unsigned do_codec_timing = 0; unsigned do_validation = 0; unsigned do_list_mods = 0; err_status_t status; /* * verify that the compiler has interpreted the header data * structure srtp_hdr_t correctly */ if (sizeof(srtp_hdr_t) != 12) { printf("error: srtp_hdr_t has incorrect size" "(size is %ld bytes, expected 12)\n", sizeof(srtp_hdr_t)); exit(1); } /* initialize srtp library */ status = srtp_init(); if (status) { printf("error: srtp init failed with error code %d\n", status); exit(1); } /* load srtp_driver debug module */ status = crypto_kernel_load_debug_module(&mod_driver); if (status) { printf("error: load of srtp_driver debug module failed " "with error code %d\n", status); exit(1); } /* process input arguments */ while (1) { q = getopt_s(argc, argv, "trcvld:"); if (q == -1) break; switch (q) { case 't': do_timing_test = 1; break; case 'r': do_rejection_test = 1; break; case 'c': do_codec_timing = 1; break; case 'v': do_validation = 1; break; case 'l': do_list_mods = 1; break; case 'd': status = crypto_kernel_set_debug_module(optarg_s, 1); if (status) { printf("error: set debug module (%s) failed\n", optarg_s); exit(1); } break; default: usage(argv[0]); } } if (!do_validation && !do_timing_test && !do_codec_timing && !do_list_mods && !do_rejection_test) usage(argv[0]); if (do_list_mods) { status = crypto_kernel_list_debug_modules(); if (status) { printf("error: list of debug modules failed\n"); exit(1); } } if (do_validation) { const srtp_policy_t **policy = policy_array; srtp_policy_t *big_policy; /* loop over policy array, testing srtp and srtcp for each policy */ while (*policy != NULL) { printf("testing srtp_protect and srtp_unprotect\n"); if (srtp_test(*policy) == err_status_ok) printf("passed\n\n"); else { printf("failed\n"); exit(1); } printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n"); if (srtcp_test(*policy) == err_status_ok) printf("passed\n\n"); else { printf("failed\n"); exit(1); } policy++; } /* create a big policy list and run tests on it */ status = srtp_create_big_policy(&big_policy); if (status) { printf("unexpected failure with error code %d\n", status); exit(1); } printf("testing srtp_protect and srtp_unprotect with big policy\n"); if (srtp_test(big_policy) == err_status_ok) printf("passed\n\n"); else { printf("failed\n"); exit(1); } /* run test on wildcard policy */ printf("testing srtp_protect and srtp_unprotect on " "wildcard ssrc policy\n"); if (srtp_test(&wildcard_policy) == err_status_ok) printf("passed\n\n"); else { printf("failed\n"); exit(1); } /* * run validation test against the reference packets - note * that this test only covers the default policy */ printf("testing srtp_protect and srtp_unprotect against " "reference packets\n"); if (srtp_validate() == err_status_ok) printf("passed\n\n"); else { printf("failed\n"); exit(1); } /* * test the function srtp_remove_stream() */ printf("testing srtp_remove_stream()..."); if (srtp_test_remove_stream() == err_status_ok) printf("passed\n"); else { printf("failed\n"); exit(1); } } if (do_timing_test) { const srtp_policy_t **policy = policy_array; /* loop over policies, run timing test for each */ while (*policy != NULL) { srtp_print_policy(*policy); srtp_do_timing(*policy); policy++; } } if (do_rejection_test) { const srtp_policy_t **policy = policy_array; /* loop over policies, run rejection timing test for each */ while (*policy != NULL) { srtp_print_policy(*policy); srtp_do_rejection_timing(*policy); policy++; } } if (do_codec_timing) { srtp_policy_t policy; int ignore; double mips = mips_estimate(1000000000, &ignore); crypto_policy_set_rtp_default(&policy.rtp); crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xdecafbad; policy.key = test_key; policy.next = NULL; printf("mips estimate: %e\n", mips); printf("testing srtp processing time for voice codecs:\n"); printf("codec\t\tlength (octets)\t\tsrtp instructions/second\n"); printf("G.711\t\t%d\t\t\t%e\n", 80, (double) mips * (80 * 8) / srtp_bits_per_second(80, &policy) / .01 ); printf("G.711\t\t%d\t\t\t%e\n", 160, (double) mips * (160 * 8) / srtp_bits_per_second(160, &policy) / .02); printf("G.726-32\t%d\t\t\t%e\n", 40, (double) mips * (40 * 8) / srtp_bits_per_second(40, &policy) / .01 ); printf("G.726-32\t%d\t\t\t%e\n", 80, (double) mips * (80 * 8) / srtp_bits_per_second(80, &policy) / .02); printf("G.729\t\t%d\t\t\t%e\n", 10, (double) mips * (10 * 8) / srtp_bits_per_second(10, &policy) / .01 ); printf("G.729\t\t%d\t\t\t%e\n", 20, (double) mips * (20 * 8) / srtp_bits_per_second(20, &policy) / .02 ); printf("Wideband\t%d\t\t\t%e\n", 320, (double) mips * (320 * 8) / srtp_bits_per_second(320, &policy) / .01 ); printf("Wideband\t%d\t\t\t%e\n", 640, (double) mips * (640 * 8) / srtp_bits_per_second(640, &policy) / .02 ); } return 0; }/* * srtp_create_test_packet(len, ssrc) returns a pointer to a * (malloced) example RTP packet whose data field has the length given * by pkt_octet_len and the SSRC value ssrc. The total length of the * packet is twelve octets longer, since the header is at the * beginning. There is room at the end of the packet for a trailer, * and the four octets following the packet are filled with 0xff * values to enable testing for overwrites. * * note that the location of the test packet can (and should) be * deallocated with the free() call once it is no longer needed. */srtp_hdr_t *srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc) { int i; uint8_t *buffer; srtp_hdr_t *hdr; int bytes_in_hdr = 12; /* allocate memory for test packet */ hdr = (srtp_hdr_t*) malloc(pkt_octet_len + bytes_in_hdr + SRTP_MAX_TRAILER_LEN + 4); if (!hdr) return NULL; hdr->version = 2; /* RTP version two */ hdr->p = 0; /* no padding needed */ hdr->x = 0; /* no header extension */ hdr->cc = 0; /* no CSRCs */ hdr->m = 0; /* marker bit */ hdr->pt = 0xf; /* payload type */ hdr->seq = htons(0x1234); /* sequence number */ hdr->ts = htonl(0xdecafbad); /* timestamp */ hdr->ssrc = htonl(ssrc); /* synch. source */ buffer = (uint8_t *)hdr; buffer += bytes_in_hdr; /* set RTP data to 0xab */ for (i=0; i < pkt_octet_len; i++) *buffer++ = 0xab; /* set post-data value to 0xffff to enable overrun checking */ for (i=0; i < SRTP_MAX_TRAILER_LEN+4; i++) *buffer++ = 0xff; return hdr;}voidsrtp_do_timing(const srtp_policy_t *policy) { int len; /* * note: the output of this function is formatted so that it * can be used in gnuplot. '#' indicates a comment, and "\r\n" * terminates a record */ printf("# testing srtp throughput:\r\n"); printf("# mesg length (octets)\tthroughput (megabits per second)\r\n"); for (len=16; len <= 2048; len *= 2) printf("%d\t\t\t%f\r\n", len, srtp_bits_per_second(len, policy) / 1.0E6); /* these extra linefeeds let gnuplot know that a dataset is done */ printf("\r\n\r\n"); }voidsrtp_do_rejection_timing(const srtp_policy_t *policy) { int len; /* * note: the output of this function is formatted so that it * can be used in gnuplot. '#' indicates a comment, and "\r\n" * terminates a record */ printf("# testing srtp rejection throughput:\r\n"); printf("# mesg length (octets)\trejections per second\r\n"); for (len=8; len <= 2048; len *= 2) printf("%d\t\t\t%e\r\n", len, srtp_rejections_per_second(len, policy)); /* these extra linefeeds let gnuplot know that a dataset is done */ printf("\r\n\r\n"); }#define MAX_MSG_LEN 1024doublesrtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) { srtp_t srtp; srtp_hdr_t *mesg; int i; clock_t timer; int num_trials = 100000; int len; uint32_t ssrc; err_status_t status; /* * allocate and initialize an srtp session */ status = srtp_create(&srtp, policy); if (status) { printf("error: srtp_create() failed with error code %d\n", status); exit(1); } /* * if the ssrc is unspecified, use a predetermined one */ if (policy->ssrc.type != ssrc_specific) { ssrc = 0xdeadbeef; } else { ssrc = policy->ssrc.value; } /* * create a test packet */ mesg = srtp_create_test_packet(msg_len_octets, ssrc); if (mesg == NULL) return 0.0; /* indicate failure by returning zero */ timer = clock(); for (i=0; i < num_trials; i++) { err_status_t status; len = msg_len_octets + 12; /* add in rtp header length */ /* srtp protect message */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -