simplesip.pl
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. #!/usr/bin/perl
  2. # ====================================================================
  3. # The Vovida Software License, Version 1.0 
  4. # Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions
  7. # are met:
  8. # 1. Redistributions of source code must retain the above copyright
  9. #    notice, this list of conditions and the following disclaimer.
  10. # 2. Redistributions in binary form must reproduce the above copyright
  11. #    notice, this list of conditions and the following disclaimer in
  12. #    the documentation and/or other materials provided with the
  13. #    distribution.
  14. # 3. The names "VOCAL", "Vovida Open Communication Application Library",
  15. #    and "Vovida Open Communication Application Library (VOCAL)" must
  16. #    not be used to endorse or promote products derived from this
  17. #    software without prior written permission. For written
  18. #    permission, please contact vocal@vovida.org.
  19. # 4. Products derived from this software may not be called "VOCAL", nor
  20. #    may "VOCAL" appear in their name, without prior written
  21. #    permission of Vovida Networks, Inc.
  22. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  23. # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24. # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  25. # NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  26. # NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  27. # IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  28. # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  29. # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  30. # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  31. # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  33. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  34. # DAMAGE.
  35. # ====================================================================
  36. # This software consists of voluntary contributions made by Vovida
  37. # Networks, Inc. and many individuals on behalf of Vovida Networks,
  38. # Inc.  For more information on Vovida Networks, Inc., please see
  39. # <http://www.vovida.org/>.
  40. # $Id: simplesip.pl,v 1.4 2000/08/12 01:25:13 bogawa Exp $
  41. # simple script to manage UDP to TCP for SIP connections
  42. use Test2;
  43. use IO::Socket;
  44. use Socket;
  45. use Data::Dumper;
  46. &mkudpsocket(5060, S1);
  47. $local_addr = "192.168.5.31";
  48. $code_text{"180"} = "Ringing";
  49. $code_text{"200"} = "OK";
  50. sub start_rtp {
  51.     local($rtp) = @_;
  52.     open($rtp, "| ./rtpSimple > rtpsimple.log") 
  53.       || die "can't start rtpSimple: $!";
  54.     # unbuffer the filehandle
  55.     $a = select($rtp);
  56.     $| = 1;
  57.     select($a);
  58. }
  59. $rtp = "RTP";
  60. &start_rtp($rtp);
  61. while(1) {
  62.     $rin = '';
  63.     $max_fh = -1;
  64.     vec($rin, fileno(S1), 1) = 1;
  65. #    print "wheel!n";
  66.     if(select($rin, undef, undef, 10)) {
  67. @bits = split(//, unpack("b*", $rin));
  68. undef($data);
  69. undef($new_data);
  70. # print "inn";
  71. if($bits[fileno(S1)]) {
  72.     $his_address = &handle_udp(S1, $tcp_socket);
  73. }
  74.     } else {
  75. # nothing, so bye!
  76. # &bye_udp(S1);
  77.     }
  78. }
  79. sub bye_udp {
  80.     if(!$last_invite) {
  81. return;
  82.     }
  83.     local($bye) = &generate_bye($last_invite);
  84. #    print "bye:n";
  85. #    print $bye;
  86. #    print "n";
  87.     if(length($bye)) {
  88. &post_data_udp(S1, $bye, $his_address);
  89.     }
  90.     $last_invite = "";
  91. }
  92. sub handle_udp {
  93.     my($udp_socket, $tcp_socket) = @_;
  94.     my($his_address);
  95.     my($data);
  96. #    print "handling udpn";
  97.     $his_address = recv($udp_socket, $data, 60000, 0);
  98.     if($data) {
  99. # print "---------- UDP ----------n";
  100. # print $data;
  101. # print "---------- --- ----------n";
  102. open(JUNK, ">junk.txt");
  103. print JUNK $data;
  104. close(JUNK);
  105.     }
  106.     $data = &filter_udp2tcp($data);
  107.     if(length($data)) {
  108. &post_data_udp(S1, $data, $his_address);
  109.     }
  110.     return $his_address;
  111. }
  112. sub post_data_udp {
  113.     my($socket, $data, $his_address) = @_;
  114.     ($hisport, $hisiaddr) = sockaddr_in($his_address);
  115.     $hishost = inet_ntoa($hisiaddr);
  116. #    print "returns: $hishost:$hisport:n----$datan----n";
  117.     ($sin) = pack_sockaddr_in(5060, $hisiaddr);
  118.     
  119. # defined(send(S1,$return_data,0,$sin)) || die $!;
  120.     defined(send($socket, $data, 0,$sin)) || die "send: $!";
  121.     $them_S2 = pack($sockaddr,PF_INET, 5060, 192.168);
  122. #    print "returns: donen";
  123.     return;
  124. }
  125. sub mkudpsocket {
  126.   local($port, $socket) = @_;
  127.   
  128.   ($name,$aliases,$proto) = getprotobyname('udp');
  129.   socket($socket, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!";
  130.   $paddr = sockaddr_in($port, INADDR_ANY); # 0 means let kernel pick
  131.   bind($socket , $paddr) || die "died with port $port $!";
  132.   
  133. }
  134. sub filter_udp2tcp {
  135.     local($_) = @_;
  136.     if(/^invite/i) {
  137. # $_ = &respond($_, 180, "", "");
  138. # respond w/ 200, natch!
  139. $last_invite = $_;
  140. $hostport = &process_sdp($_);
  141. ($remote_host, $remote_port) = split(/:/, $hostport);
  142. $_ = &respond($_, 200, &make_sdp($local_addr, "3466"), "application/sdp");
  143. print $rtp "n 3466 $remote_host $remote_portn";
  144. #    local($hostip) = "192.168.5.3";
  145. #    local($port) = "3466";
  146.     } else {
  147. if(/^sip/i) {
  148. } elsif(/^ack/i) {
  149.     $_ = "";
  150. #     print RTP "p sample.rawn";
  151. #     print RTP "r record.rawn";
  152.     print $rtp "v p:sample.raw p:beep.raw r:record.rawn";
  153. } elsif(/^bye/i) {
  154.     $_ = &respond($_, 200, "", "");
  155.     $last_invite = "";
  156.     print $rtp "dn";
  157.     system("sleep 1; sox -r 8000 -U -b record.raw record.au &");
  158. } else {
  159.     $_ = &respond($_, 200, "", "");
  160. }
  161.     }
  162. #    print Dumper(&turntohash($_));
  163. #    print $_;
  164.     return $_;
  165. }
  166. sub respond {
  167.     local($old_msg, $code, $content, $content_type) = @_;
  168.     local($msg);
  169.     # take an incoming message, and form1 an outgoing message from it
  170.     $msg = "SIP/2.0 $code $code_text{$code}rn";
  171.     $msg .= &strip_extraneous($old_msg);
  172.     $msg = &add_content($msg, $content, $content_type);
  173. }
  174. sub generate_bye {
  175.     # byes are a special case -- they need a different CSeq, and the
  176.     # From/To may need to be reversed as appropriate
  177.     local($invite_msg) = @_;
  178.     local($bye_msg);
  179.     $bye_msg = &inc_cseq($invite_msg, "BYE");
  180.     local($msg_hash) = &turntohash($bye_msg);
  181.     local($old_from) = $msg_hash->{"from"};
  182.     local($old_to) = $msg_hash->{"to"};
  183.     $bye_msg = "BYE $msg_hash->{MSG_URL} SIP/2.0rn" 
  184.       . &strip_extraneous($bye_msg);
  185. #    print $bye_msg;
  186.     if($old_from =~ /$local_addr[^0-9]/) {
  187.     } else {
  188. $bye_msg = &replace_header($bye_msg, "from", $old_to);
  189. $bye_msg = &replace_header($bye_msg, "to", $old_from);
  190.     }
  191.     print $rtp "dn";
  192.     # do something here
  193.     return $bye_msg;
  194. }
  195. sub replace_header {
  196.     local($msg, $header, $new_contents) = @_;
  197.     @split_msg = split(/r?n/, $msg);
  198.     $linecount = 0;
  199.     local($new_msg) = "";
  200.     $past_headers = 0;
  201.     $header =~ y/A-Z/a-z/;
  202.     foreach(@split_msg) {
  203. if($linecount == 0) {
  204.     $new_msg .= $_ . "rn";
  205. } else {
  206.     if(/^[srn]*$/) {
  207. $past_headers = 1;
  208.     }
  209.     if (!$past_headers) {
  210. ($header_name, $header_body) = split(/:/, $_, 2);
  211. $header_name =~ y/A-Z/a-z/;
  212. if($header_name eq $header) {
  213.     # do something!
  214.     $header_body = $new_contents;
  215. }
  216. $new_msg .= $header_name . ":" . $header_body . "rn" ;
  217.     } else {
  218. # gobble everything else and put it into a thingy
  219. $new_msg .= $_ . "rn";
  220.     }
  221. }
  222. $linecount++;
  223.     }
  224.     return $new_msg;
  225. }
  226. sub turntohash {
  227.     local($msg) = @_;
  228.     local($hash);
  229.     $hash = {};
  230.     @split_msg = split(/r?n/, $msg);
  231.     $linecount = 0;
  232.     $newmsg = "";
  233.     $past_headers = 0;
  234.     $header =~ y/A-Z/a-z/;
  235.     foreach(@split_msg) {
  236. if($linecount == 0) {
  237.     $hash->{"FIRST_LINE"} = $_;
  238.     # figure out if this is a request or a response
  239.     @stuff = split(/s+/);
  240.     if($stuff[0] !~ /^SIP/) {
  241. $stuff[0] =~ y/A-Z/a-z/;
  242. $stuff[2] =~ y/A-Z/a-z/;
  243. $hash->{"MSG_TYPE"} = $stuff[0];
  244. $hash->{"MSG_URL"} = $stuff[1];
  245. $hash->{"SIP_VERSION"} = $stuff[2];
  246.     } else {
  247. $stuff[0] =~ y/A-Z/a-z/;
  248. $stuff[2] =~ y/A-Z/a-z/;
  249. $hash->{"SIP_VERSION"} = $stuff[0];
  250. $hash->{"MSG_TYPE"} = "response";
  251. $hash->{"RESPONSE_CODE"} = $stuff[1];
  252. $hash->{"RESPONSE_TEXT"} = $stuff[2];
  253.     }
  254. } else {
  255.     if(/^[srn]*$/) {
  256. $past_headers = 1;
  257. next;
  258.     }
  259.     if (!$past_headers) {
  260. ($header_name, $header_body) = split(/:/, $_, 2);
  261. $header_name =~ y/A-Z/a-z/;
  262. $hash->{$header_name} = $header_body;
  263.     } else {
  264. # gobble everything else and put it into a thingy
  265. $hash->{"CONTENTS"} .= $_ . "rn";
  266.     }
  267. }
  268. $linecount++;
  269.     }
  270.     return $hash;
  271. }
  272. sub turntomsg {
  273.     local($hash) = @_;
  274.     local($msg);
  275.     if($hash->{"MSG_TYPE"} eq "response") {
  276. # this is a response
  277.     } else {
  278.     }
  279. }
  280. sub inc_cseq {
  281.     local($msg, $type) = @_;
  282.     local($stuff, $num);
  283.     $msg =~ s/cseq:s*(.*)r?n/CSeq: rn/i;
  284.     $stuff = $1;
  285.     $stuff =~ /^([0-9]+)/;
  286.     $num = $1; 
  287.     $num++;
  288.     $msg =~ s/CSeq: rn/CSeq: $num $typern/;
  289.     return $msg;
  290. }
  291. sub process_sdp {
  292.     local($sdp) = @_;
  293.     local($host, $port);
  294.     # chomp out the appropriate stuff
  295.     if(/o=.*IP4s+([0-9.]+)/) {
  296. $host = $1;
  297.     }
  298.     if(/m=.*audios+([0-9]+)/) {
  299. $port = $1;
  300.     }
  301.     return "$host:$port";
  302. }
  303. sub make_sdp {
  304.     local($hostip, $port) = @_;
  305. #    local($hostip) = "192.168.5.3";
  306. #    local($port) = "3466";
  307.     local($sdp_info);
  308.     $sdp_info  = "v=0rn";
  309.     $sdp_info .= "o=- 305743370 305743370 IN IP4 $hostiprn";
  310.     $sdp_info .= "s=VOVIDA Sessionrn";
  311.     $sdp_info .= "c=IN IP4 $hostiprn";
  312.     $sdp_info .= "t=957844468 0rn";
  313.     $sdp_info .= "m=audio $port RTP/AVP 0rn";
  314.     $sdp_info .= "a=rtpmap:0 PCMU/8000rn";
  315.     $sdp_info .= "a=ptime:40rn";
  316.     return $sdp_info;
  317. }
  318. sub add_content {
  319.     local($msg, $content, $content_type) = @_;
  320. #    print "content: n", $content, "n ---------- n";
  321.     if(!$content) {
  322. $msg .= "Content-Length: 0rnrn";
  323.     } else {
  324. $msg .= "Content-Type: $content_typern";
  325. $msg .= "Content-Length: " . length($content) . "rn";
  326. $msg .= "rn";
  327. $msg .= $content;
  328.     }
  329.     return $msg;
  330. }
  331. sub strip_extraneous {
  332.     local($msg) = $_[0];
  333.     # take an incoming message, and form an outgoing message from it
  334.     @split_msg = split(/r?n/, $msg);
  335.     $linecount = 0;
  336.     $newmsg = "";
  337.     $past_headers = 0;
  338.     foreach(@split_msg) {
  339. if($linecount == 0) {
  340.     if(/^SIP/2.0/ || /^INVITE/i || /^BYE/i || /^ACK/i || /^CANCEL/i) {
  341.     # get rid of this
  342.     } else {
  343. $newmsg .= $_ . "rn";
  344.     }
  345. } else {
  346.     if(/^[srn]*$/) {
  347. # print "past headers!nn";
  348. $past_headers = 1;
  349.     } else {
  350. # print "ok:$linecount:$_:n";
  351.     }
  352.     if(!/^content-length:/i 
  353.        && !/^content-type:/i 
  354.        && !($past_headers)) {
  355. # print "got $_n";
  356. $newmsg .= $_ . "rn";
  357.     }
  358. }
  359. $linecount++;
  360.     }
  361.     return $newmsg;
  362. }
  363. __END__