def test_stripping(self): """Test for correct stripping of whitespaces from SDP lines""" sessionDescription, mediaDescriptions = parseSdpMessage( "v=0\n\t\t o=1 2 3 4 5 6\n s=Subject \t\ni= Info \n" + \ " \t m=audio 41000 RTP/AVP 0\t \t") assert_equals(sessionDescription["v"], "0") assert_equals(sessionDescription["o"], "1 2 3 4 5 6") assert_equals(sessionDescription["s"], "Subject") assert_equals(sessionDescription["i"], "Info") assert_equals(mediaDescriptions[0]["m"], "audio 41000 RTP/AVP 0")
def test_multiple_media_sections(self): """Test for correct parsing of multiple media sections (valid)""" sessionDescription, mediaDescriptions = parseSdpMessage( "v=0\no=Foo\n" + \ "m=audio 12345 RTP/AVP 0\na=audioattribute\n" + \ "m=video 12346 RTP/AVP 0\na=videoattribute\n") assert_equals(sessionDescription["v"], "0") assert_equals(sessionDescription["o"], "Foo") assert_equals(len(mediaDescriptions), 2) assert_equals(mediaDescriptions[0]["m"][:5], "audio") assert_equals(mediaDescriptions[0]["a"], "audioattribute") assert_equals(mediaDescriptions[1]["m"][:5], "video") assert_equals(mediaDescriptions[1]["a"], "videoattribute")
def test_correct_parsing(self): """Test normal SDP message parsing for correctness""" msg = "v=0\no=Foo 123 456 IN IP4 1.1.1.1\ns=SDP test\n" + \ "i=Just a unit test\nu=http://voiphpc.blogspot.com\n" + \ "[email protected]\nt=112233 445566\n" + \ "m=audio 12345 RTP/AVP 0\na=rtpmap:0 PCMU/8000" sessionDescription, mediaDescriptions = parseSdpMessage(msg) assert_equals(sessionDescription["v"], "0") assert_equals(sessionDescription["o"][:3], "Foo") assert_equals(sessionDescription["s"], "SDP test") assert_equals(sessionDescription["i"], "Just a unit test") assert_equals(sessionDescription["u"], "http://voiphpc.blogspot.com") assert_equals(sessionDescription["e"], "*****@*****.**") assert_equals(sessionDescription["t"], "112233 445566") assert_equals(mediaDescriptions[0]["m"], "audio 12345 RTP/AVP 0") assert_equals(mediaDescriptions[0]["a"], "rtpmap:0 PCMU/8000") assert_equals(len(mediaDescriptions), 1)
def sip_INVITE(self, requestLine, headers, body): global g_sipconfig # Print SIP header logger.info("Received INVITE") for k, v in headers.items(): logger.info("SIP header {}: {}".format(k, v)) if self.__checkForMissingHeaders(headers, ["accept", "content-type"]): return # Check authentication if g_sipconfig['use_authentication']: r = self.__challengeINVITE(headers) if not r: return # Header has to define Content-Type: application/sdp if body contains # SDP message. Also, Accept has to be set to sdp so that we can send # back a SDP response. if headers["content-type"] != "application/sdp": logger.error("INVITE without SDP message: exit") return if headers["accept"] != "application/sdp": logger.error("INVITE without SDP message: exit") return # Check for SDP body if not body: logger.error("INVITE without SDP message: exit") return # Parse SDP part of session invite try: sessionDescription, mediaDescriptions = parseSdpMessage(body) except SdpParsingError as e: logger.error(e) return # Check for all necessary fields sdpSessionOwnerParts = sessionDescription['o'].split(' ') if len(sdpSessionOwnerParts) < 6: logger.error("SDP session owner field to short: exit") return logger.debug("Parsed SDP message:") logger.debug(sessionDescription) logger.debug(mediaDescriptions) # Get RTP port from SDP media description if len(mediaDescriptions) < 1: logger.error("SDP message has to include a media description: exit") return mediaDescriptionParts = mediaDescriptions[0]['m'].split(' ') if mediaDescriptionParts[0] != 'audio': logger.error("SDP media description has to be of audio type: exit") return rtpPort = mediaDescriptionParts[1] # Read Call-ID field and create new SipSession instance on first INVITE # request received (remote host might send more than one because of time # outs or because he wants to flood the honeypot) callId = headers["call-id"] if callId in self.__sessions: logger.info("SIP session with Call-ID {} already exists".format( callId)) return # Establish a new SIP session newSession = SipSession((self.__remoteAddress, self.__remoteSipPort), rtpPort, headers) # Store session object in sessions dictionary self.__sessions[callId] = newSession
def test_multiple_lines_with_same_type(self): """Test for correct parsing of multiple lines with same type""" sessionDescription, _ = parseSdpMessage( "v=0\no=foo1\ns=test\ni=test\no=foo2\nt=12345\n") assert_equals(sessionDescription["o"], "foo2")
def test_parsing_malformed_message_line(self): """Test SDP parsing of a malformed line (no '=')""" parseSdpMessage("\\" * 10)
def test_correct_parsing_only_whitespaces(self): """Test for correct handling of an SDP message with whitespaces only""" sessionDescription, mediaDescriptions = parseSdpMessage( " \n\r\n\r \t\t ") assert_equals(len(sessionDescription), 0) assert_equals(len(mediaDescriptions), 0)
def test_correct_parsing_empty_message(self): """Test for correct handling of an empty SDP message""" sessionDescription, mediaDescriptions = parseSdpMessage("") assert_equals(len(sessionDescription), 0) assert_equals(len(mediaDescriptions), 0)
def sip_INVITE(self, requestLine, headers, body): global g_sipconfig # Print SIP header logger.info("Received INVITE") for k, v in headers.items(): logger.info("SIP header {}: {}".format(k, v)) if self.__checkForMissingHeaders(headers, ["accept", "content-type"]): return # Check authentication if g_sipconfig['use_authentication']: r = self.__challengeINVITE(headers) if not r: return # Header has to define Content-Type: application/sdp if body contains # SDP message. Also, Accept has to be set to sdp so that we can send # back a SDP response. if headers["content-type"] != "application/sdp": logger.error("INVITE without SDP message: exit") return if headers["accept"] != "application/sdp": logger.error("INVITE without SDP message: exit") return # Check for SDP body if not body: logger.error("INVITE without SDP message: exit") return # Parse SDP part of session invite try: sessionDescription, mediaDescriptions = parseSdpMessage(body) except SdpParsingError as e: logger.error(e) return # Check for all necessary fields sdpSessionOwnerParts = sessionDescription['o'].split(' ') if len(sdpSessionOwnerParts) < 6: logger.error("SDP session owner field to short: exit") return logger.debug("Parsed SDP message:") logger.debug(sessionDescription) logger.debug(mediaDescriptions) # Get RTP port from SDP media description if len(mediaDescriptions) < 1: logger.error( "SDP message has to include a media description: exit") return mediaDescriptionParts = mediaDescriptions[0]['m'].split(' ') if mediaDescriptionParts[0] != 'audio': logger.error("SDP media description has to be of audio type: exit") return rtpPort = mediaDescriptionParts[1] # Read Call-ID field and create new SipSession instance on first INVITE # request received (remote host might send more than one because of time # outs or because he wants to flood the honeypot) callId = headers["call-id"] if callId in self.__sessions: logger.info( "SIP session with Call-ID {} already exists".format(callId)) return # Establish a new SIP session newSession = SipSession((self.__remoteAddress, self.__remoteSipPort), rtpPort, headers) # Store session object in sessions dictionary self.__sessions[callId] = newSession