Ticket #2198: Twisted_2198.2.patch

File Twisted_2198.2.patch, 4.2 KB (added by moijes12, 2 years ago)

I hadn't attached the news file.

  • twisted/topfiles/2198.feature

     
     1twisted.protocols.sip.MessageParser now handles multiline headers. 
     2 No newline at end of file 
  • twisted/test/test_sip.py

     
    8686 
    8787""".replace("\n", "\r\n") 
    8888 
     89# multiline headers (example from RFC 3621). 
     90response_multiline = """\ 
     91SIP/2.0 200 OK 
     92Via: SIP/2.0/UDP server10.biloxi.com 
     93    ;branch=z9hG4bKnashds8;received=192.0.2.3 
     94Via: SIP/2.0/UDP bigbox3.site3.atlanta.com 
     95    ;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2 
     96Via: SIP/2.0/UDP pc33.atlanta.com 
     97    ;branch=z9hG4bK776asdhds ;received=192.0.2.1 
     98To: Bob <sip:bob@biloxi.com>;tag=a6c85cf 
     99From: Alice <sip:alice@atlanta.com>;tag=1928301774 
     100Call-ID: a84b4c76e66710@pc33.atlanta.com 
     101CSeq: 314159 INVITE 
     102Contact: <sip:bob@192.0.2.4> 
     103Content-Type: application/sdp 
     104Content-Length: 0 
     105\n""".replace("\n", "\r\n") 
     106 
    89107class TestRealm: 
    90108    def requestAvatar(self, avatarId, mind, *interfaces): 
    91109        return sip.IContact, None, lambda: None 
     
    178196        self.assertEqual(m.finished, 1) 
    179197 
    180198 
     199    def testMultiLine(self): 
     200        l = self.l 
     201        self.feedMessage(response_multiline) 
     202        self.assertEquals(len(l), 1) 
     203        m = l[0] 
     204        self.assertEquals(m.headers['via'][0], "SIP/2.0/UDP server10.biloxi.com;branch=z9hG4bKnashds8;received=192.0.2.3") 
     205        self.assertEquals(m.headers['via'][1], "SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2") 
     206        self.assertEquals(m.headers['via'][2], "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.1") 
     207 
     208 
     209 
    181210class MessageParsingTestCase2(MessageParsingTestCase): 
    182211    """Same as base class, but feed data char by char.""" 
    183212 
  • twisted/protocols/sip.py

     
    632632        self.length = None # body length 
    633633        self.bodyReceived = 0 # how much of the body we received 
    634634        self.message = None 
     635        self.header = None 
    635636        self.setLineMode(remainingData) 
    636637 
    637638    def invalidMessage(self): 
     
    699700        else: 
    700701            assert self.state == "headers" 
    701702        if line: 
    702             # XXX support multi-line headers 
    703             try: 
    704                 name, value = line.split(":", 1) 
    705             except ValueError: 
    706                 self.invalidMessage() 
    707                 return 
    708             self.message.addHeader(name, value.lstrip()) 
    709             if name.lower() == "content-length": 
     703            # multiline header 
     704            if line.startswith(" ") or line.startswith("\t"): 
     705                name, value = self.header 
     706                self.header = name, (value + line.lstrip()) 
     707            else: 
     708                # new header 
     709                if self.header: 
     710                    self.message.addHeader(*self.header) 
     711                    self.header = None 
    710712                try: 
    711                     self.length = int(value.lstrip()) 
     713                    name, value = line.split(":", 1) 
    712714                except ValueError: 
    713715                    self.invalidMessage() 
    714716                    return 
     717                self.header = name, value.lstrip() 
     718                # XXX we assume content-length won't be multiline 
     719                if name.lower() == "content-length": 
     720                    try: 
     721                        self.length = int(value.lstrip()) 
     722                    except ValueError: 
     723                        self.invalidMessage() 
     724                        return 
    715725        else: 
    716726            # CRLF, we now have message body until self.length bytes, 
    717727            # or if no length was given, until there is no more data 
    718728            # from the connection sending us data. 
    719729            self.state = "body" 
     730            if self.header: 
     731                self.message.addHeader(*self.header) 
     732                self.header = None 
    720733            if self.length == 0: 
    721734                self.messageDone() 
    722735                return