如何在php中使用SIP / SDP协议发送消息

时间:2013-03-19 13:36:11

标签: php udp sip sdp

我要做的是实现一个侦听SIP消息的SIP客户端。所以我在服务器192.168.0.246上运行了SIP客户端,而SIP服务器正在192.168.2.40上运行。现在看看下面的屏幕截图。

enter image description here

它是在192.168.0.246上运行客户端代码的服务器的跟踪文件。您可以看到服务器使用SIP / SDP协议从192.168.2.40接收消息,但是当运行在192.168.0.246上的客户端程序使用UDP协议将消息发送回192.168.2.40时,它显示为UDP协议,这是正确的。但是此后没有来自192.168.2.40的回复。 所以我假设它与显示为UDP的协议有关。所以,如果我是仪式,我应该把它转到SIP / SDP。

所以我的问题是如何将此UDP更改为SIP / SDP。

这是我的PHP代码:

<?php

//Reduce errors
error_reporting(~E_WARNING);

//Create a UDP socket
if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0)))
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);

    die("Couldn't create socket: [$errorcode] $errormsg \n");
}

echo "Socket created \n";

// Bind the source address
if( !socket_bind($sock, "192.168.0.246" , 5060) )
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);

    die("Could not bind socket : [$errorcode] $errormsg \n");
}

echo "Socket bind OK \n";

//Do some communication, this loop can handle multiple clients

function GetBranchValue($message)
{
    $data = "";
    if(preg_match('/branch=.*/i', $message, $output))
        $data = explode("=",$output[0]);
    if(sizeOf($data)>1)
        return $data[1];
    else
        return "None";
}

function GetTag($message)
{
    $data = "";
    if(preg_match('/tag=.*/i',$message, $output))
        $data = explode("=", $output[0]);
    if(sizeOf($data)>1)
        return $data[1];
    else
        return "None";
}

function GetCallId($message)
{
    $data = "";
    if(preg_match('/Call-ID:.*/i', $message, $output))
        $data = explode(":",$output[0]);
    if(sizeOf($data)>1)
        return $data[1];
    else
        return "None";
}

function GetCSeq($message)
{ 
    $data = "";
    if(preg_match('/CSeq:.*/i', $message, $output))
    {
        $data = explode(":", $output[0]);
        $data = explode(" ",$data[1]);
    }
    if(sizeOf($data[1])>0)
        return $data[1];
    else
        return "None";
}

function CreateResponse($message)
{
    $msg = "SIP/2.0 302 Moved temporarily
Via:SIP/2.0/UDP 192.168.2.40:5060;branch=".GetBranchValue($message)."
From: <sip:+12012030008@192.168.2.40:5060>;tag=".GetTag($message)."
To:<sip:+17066458407@192.168.0.246:5060;user=phone>;tag=883069368-1363286882583
Call-ID:".GetCallId($message)."
CSeq:".GetCSeq($message)." INVITE
Contact:<sip:+17066458407@192.168.0.246:5060;user=phone>;q=0.5,<sip:+17066458407@192.168.0.246:5060;user=phone>;q=0.25
Content-Length:0";
    return $msg;
}

function Create300Response($message)
{
    $msg = "SIP/2.0 300 Multiple Choices
Via: SIP/2.0/UDP 192.168.2.40:5060;branch=".GetBranchValue($message)."
From: <sip:+12012030008@192.168.2.40:5060>;tag=".GetTag($message).";isup-oli;isup-oli=00
To:<sip:+17066458407@192.168.0.246:5060;user=phone>;tag=123
Contact: <sip: +17066458407@192.168.0.246:5060;dtg=16>
Contact: <sip: +17066458407@192.168.0.246:5060;dtg=16>
Contact: <sip: +17066458407@192.168.0.246:5060;dtg=16>
Contact: <sip: +17066458407@192.168.0.246:5060;dtg=16>";
    return $msg;
}

while(1)
{
    echo "Waiting for data ... \n";

    //Receive some data
    $r = socket_recvfrom($sock, $buf, 512, 0, $remote_ip, $remote_port);
    echo "$remote_ip : $remote_port -- " . $buf;
    file_put_contents("Log.txt","\n",FILE_APPEND);
    file_put_contents("Log.txt","Received Response------\n",FILE_APPEND);
    file_put_contents("Log.txt",$buf,FILE_APPEND);
    $respMessage = Create300Response($buf);
    //Send back the data to the client
    socket_sendto($sock, "OK " . $respMessage , 100 , 0 , $remote_ip , $remote_port);
    file_put_contents("Log.txt","\n",FILE_APPEND);
    file_put_contents("Log.txt","\n",FILE_APPEND);
    file_put_contents("Log.txt",$respMessage,FILE_APPEND);
}

socket_close($sock);

1 个答案:

答案 0 :(得分:5)

socket_sendto($sock, "OK " . $respMessage , 100 , 0 , $remote_ip , $remote_port);
//                    ^^ remove this

您发送的OK无效,违反了SIP协议,因此Wireshark中的内置SIP解码器无法将该消息识别为有效的SIP数据包。

您应该只是回复$respMessage

此外,我强烈建议您使用适当的解析器来传入消息,并使用适当的面向对象的编写器来构造传出消息。 SIP是一种(有些人可能会说是不必要的)复杂的协议,你需要的不仅仅是你提取的小块信息,而是建立一个甚至可以做任何远程有用的端点。

我的This small library可能会为您的解析器提供一个良好的基础,而this one如果用HTTP替换SIP,{{3}}几乎完全符合您的要求。