python 模拟SIP消息传递

   #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author  : hu_cl
# @Email   : 760730895@qq.com
# @Date    : 2021/6/9 10:04
# @File    : sippackets.py
from scapy.all import *

sipVer = 'SIP/2.0'
protocols = 'UDP'
contentType = 'application/sdp'
methods = {'BYE': 21, 'INVITE': 20, 'MESSAGE': 20}


class SipBody(object):
    def __init__(self, srcAddr, srcSipId, dstAddr, dstSipId, message, CmdType):
        self.srcSipId = srcSipId
        self.srcAddr = srcAddr
        self.dstAddr = dstAddr
        self.dstSipId = dstSipId
        self.CmdType = CmdType
        self.message = message

    def sip_body_invite(self):
        body = "v=0\r\n"
        body += "o={srcSip} 0 0 IN IP4 {srcIP}\r\n"
        body += "s=Play\r\n"
        body += "c=IN IP4 {srcIP}\r\n"
        body += "t=0 0\r\n"
        body += "m=video 45056 RTP/AVP 96 97 98\r\n"
        body += "a=recvonly\r\n"
        body += "a=rtpmap:96 PS/90000\r\n"
        body += "a=rtpmap:97 H264/90000\r\n"
        body += "a=rtpmap:98 MPEG4/90000\r\n"
        body += "y=0000001027\r\n"
        return body.format(srcSip=self.srcSipId, srcIP=self.srcAddr.split(':')[0])

    def sip_body_message(self):
        body = '<?xml version="1.0"?>\r\n'
        body += '<Query>\r\n'
        body += "<CmdType>{CmdType}</CmdType >\r\n"
        body += "<SN>1583</SN >\r\n"
        body += "<DeviceID>{dstSipId}</DeviceID>\r\n"
        body += "</Query>\r\n"
        return body.format(CmdType=self.CmdType, dstSipId=self.dstSipId)

    def sip_body_bye(self):
        body = self.message
        return body


class SipHead(SipBody):
    def __init__(self, srcAddr, srcSipId, dstAddr, dstSipId, tag, callId, method, message, CmdType,
                 protocols=protocols, sipVer=sipVer, contentType=contentType):
        self.srcAddr = srcAddr
        self.srcSipId = srcSipId
        self.dstAddr = dstAddr
        self.dstSipId = dstSipId
        self.tag = tag
        self.callId = callId
        self.method = method
        self.maxWards = 70
        self.protocols = protocols
        self.branch = str(random.randint(1000, 9999))
        self.sipVer = sipVer
        self.contentType = contentType
        self.CmdType = CmdType
        self.message = message
        self.lines = f'{method} sip:{dstSipId}@{dstAddr} {sipVer}\r\n'
        super(SipHead, self).__init__(srcAddr, srcSipId, dstAddr, dstSipId, message, CmdType)

    def sip_head_invite(self):
        heard = 'Via: {sipVer}/{protocols} {srcAddr};rport;branch=z9hG4bK34202{branch}\r\n'
        heard += 'From: <sip:{srcSipId}@{srcAddr}>;tag={fromTag}\r\n'
        heard += 'To: <sip:{dstSipId}@{dstAddr}>\r\n'
        heard += 'Call-ID: {callId}\r\n'
        heard += 'CSeq: {methodNum} {method}\r\n'
        heard += 'Max-Forwards: {maxWards}\r\n'
        heard += 'User-Agent: eXosip/4.1.0\r\n'
        heard += 'Content-Length: {contentLeng}\r\n\r\n'
        return heard.format(sipVer=self.sipVer, protocols=self.protocols, srcAddr=self.srcAddr, branch=self.branch,
                            srcSipId=self.srcSipId, fromTag=self.tag, dstSipId=self.dstSipId, dstAddr=self.dstAddr,
                            callId=self.callId, methodNum=methods.get(self.method), method=self.method,
                            maxWards=self.maxWards, contentLeng=len(self.sip_body_invite()))

    def sip_head_message(self):
        heard = 'Via: {sipVer}/{protocols} {srcAddr};rport;branch=z9hG4bK34202{branch}\r\n'
        heard += 'From: <sip:{srcSipId}@{srcAddr}>;tag={fromTag}\r\n'
        heard += 'To: <sip:{dstSipId}@{dstAddr}>\r\n'
        heard += 'Call-ID: {callId}\r\n'
        heard += 'CSeq: {methodNum} {method}\r\n'
        heard += 'Content-Type: application/MANSCDP+xml\r\n'
        heard += 'Max-Forwards: {maxWards}\r\n'
        heard += 'User-Agent: eXosip/4.1.0\r\n'
        heard += 'Content-Length: {contentLeng}\r\n\r\n'
        return heard.format(sipVer=self.sipVer, protocols=self.protocols, srcAddr=self.srcAddr, branch=self.branch,
                            srcSipId=self.srcSipId, fromTag=self.tag, dstSipId=self.dstSipId, dstAddr=self.dstAddr,
                            callId=self.callId, methodNum=methods.get(self.method), method=self.method,
                            maxWards=self.maxWards, contentLeng=len(self.sip_body_message()))

    def sip_head_bye(self):
        heard = 'Via: {sipVer}/{protocols} {srcAddr};rport;branch=z9hG4bK34202{branch}\r\n'
        heard += 'From: <sip:{srcSipId}@{srcAddr}>;tag={fromTag}\r\n'
        heard += 'To: <sip:{dstSipId}@{dstAddr}>;tag=3982398926\r\n'
        heard += 'Call-ID: {callId}\r\n'
        heard += 'CSeq: {methodNum} {method}\r\n'
        heard += 'Max-Forwards: {maxWards}\r\n'
        heard += 'User-Agent: eXosip/4.1.0\r\n'
        heard += 'Content-Length: {contentLeng}\r\n\r\n'
        return heard.format(sipVer=self.sipVer, protocols=self.protocols, srcAddr=self.srcAddr, branch=self.branch,
                            srcSipId=self.srcSipId, fromTag=self.tag, dstSipId=self.dstSipId, dstAddr=self.dstAddr,
                            callId=self.callId, methodNum=methods.get(self.method), method=self.method,
                            maxWards=self.maxWards, contentLeng=len(self.sip_body_bye()))


class SipMethod(SipHead):

    def __init__(self, srcAddr, srcSipId, dstAddr, dstSipId, tag, callId, method, message, CmdType,
                 protocols=protocols, sipVer=sipVer, contentType=contentType):
        self.srcAddr = srcAddr
        self.dstAddr = dstAddr
        self.lines = f'{method} sip:{dstSipId}@{dstAddr} {sipVer}\r\n'
        super(SipMethod, self).__init__(srcAddr, srcSipId, dstAddr, dstSipId, tag, callId, method, message, CmdType,
                                        protocols=protocols, sipVer=sipVer, contentType=contentType)

    def send_msg(self):
        if self.method == 'BYE':
            self.message = self.lines + self.sip_head_bye() + self.sip_body_bye()
        elif self.method == 'INVITE':
            self.message = self.lines + self.sip_head_invite() + self.sip_body_invite()
        elif self.method == 'MESSAGE':
            self.message = self.lines + self.sip_head_message() + self.sip_body_message()

        print('\r\n*******send_message的信息*******\r\n', self.message, '\r\n*******END*******\r\n')

        src_ip = self.srcAddr.split(':')[0]
        src_port = self.srcAddr.split(':')[1]
        dst_ip = self.dstAddr.split(':')[0]
        dst_port = self.dstAddr.split(':')[1]

        send(IP(src=src_ip, dst=dst_ip) / UDP(sport=int(src_port), dport=int(dst_port)) / self.message)


if __name__ == '__main__':
    """
    暂时支持的SIP方法  ['INVITE','BYE','MESSAGE']
    """
    srcAddr = '192.168.2.153:5080'
    srcSip = '34020000002000000001'
    dstAddr = '192.168.2.245:5060'
    # dstSip = '34020000002000000765'
    # message 使用 CmdType 字段
    CmdType = 'DeviceInfo'
    # CmdType = 'Catalog' 查询目录
    # CmdType = 'DeviceInfo' 查询设备详情
    # 不需要查询时候 CmdType = None

    dstSip = '34020000002000000011'
    tag = '1376790544'
    callId = '1710724471'
    method = 'MESSAGE'
    msg = ''

    sendsip = SipMethod(srcAddr=srcAddr, srcSipId=srcSip, dstAddr=dstAddr, dstSipId=dstSip, tag=tag, callId=callId,
                        method=method, message=msg, CmdType=CmdType)
    sendsip.send_msg()
原文地址:https://www.cnblogs.com/hls91/p/15772018.html