Index: twisted/topfiles/2198.feature
===================================================================
--- twisted/topfiles/2198.feature	(revision 0)
+++ twisted/topfiles/2198.feature	(revision 0)
@@ -0,0 +1 @@
+twisted.protocols.sip.MessageParser now handles multiline headers.
\ No newline at end of file
Index: twisted/test/test_sip.py
===================================================================
--- twisted/test/test_sip.py	(revision 34303)
+++ twisted/test/test_sip.py	(working copy)
@@ -86,6 +86,24 @@
 
 """.replace("\n", "\r\n")
 
+# multiline headers (example from RFC 3621).
+response_multiline = """\
+SIP/2.0 200 OK
+Via: SIP/2.0/UDP server10.biloxi.com
+    ;branch=z9hG4bKnashds8;received=192.0.2.3
+Via: SIP/2.0/UDP bigbox3.site3.atlanta.com
+    ;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2
+Via: SIP/2.0/UDP pc33.atlanta.com
+    ;branch=z9hG4bK776asdhds ;received=192.0.2.1
+To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
+From: Alice <sip:alice@atlanta.com>;tag=1928301774
+Call-ID: a84b4c76e66710@pc33.atlanta.com
+CSeq: 314159 INVITE
+Contact: <sip:bob@192.0.2.4>
+Content-Type: application/sdp
+Content-Length: 0
+\n""".replace("\n", "\r\n")
+
 class TestRealm:
     def requestAvatar(self, avatarId, mind, *interfaces):
         return sip.IContact, None, lambda: None
@@ -178,6 +196,17 @@
         self.assertEqual(m.finished, 1)
 
 
+    def testMultiLine(self):
+        l = self.l
+        self.feedMessage(response_multiline)
+        self.assertEquals(len(l), 1)
+        m = l[0]
+        self.assertEquals(m.headers['via'][0], "SIP/2.0/UDP server10.biloxi.com;branch=z9hG4bKnashds8;received=192.0.2.3")
+        self.assertEquals(m.headers['via'][1], "SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2")
+        self.assertEquals(m.headers['via'][2], "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.1")
+
+
+
 class MessageParsingTestCase2(MessageParsingTestCase):
     """Same as base class, but feed data char by char."""
 
Index: twisted/protocols/sip.py
===================================================================
--- twisted/protocols/sip.py	(revision 34303)
+++ twisted/protocols/sip.py	(working copy)
@@ -632,6 +632,7 @@
         self.length = None # body length
         self.bodyReceived = 0 # how much of the body we received
         self.message = None
+        self.header = None
         self.setLineMode(remainingData)
 
     def invalidMessage(self):
@@ -699,24 +700,36 @@
         else:
             assert self.state == "headers"
         if line:
-            # XXX support multi-line headers
-            try:
-                name, value = line.split(":", 1)
-            except ValueError:
-                self.invalidMessage()
-                return
-            self.message.addHeader(name, value.lstrip())
-            if name.lower() == "content-length":
+            # multiline header
+            if line.startswith(" ") or line.startswith("\t"):
+                name, value = self.header
+                self.header = name, (value + line.lstrip())
+            else:
+                # new header
+                if self.header:
+                    self.message.addHeader(*self.header)
+                    self.header = None
                 try:
-                    self.length = int(value.lstrip())
+                    name, value = line.split(":", 1)
                 except ValueError:
                     self.invalidMessage()
                     return
+                self.header = name, value.lstrip()
+                # XXX we assume content-length won't be multiline
+                if name.lower() == "content-length":
+                    try:
+                        self.length = int(value.lstrip())
+                    except ValueError:
+                        self.invalidMessage()
+                        return
         else:
             # CRLF, we now have message body until self.length bytes,
             # or if no length was given, until there is no more data
             # from the connection sending us data.
             self.state = "body"
+            if self.header:
+                self.message.addHeader(*self.header)
+                self.header = None
             if self.length == 0:
                 self.messageDone()
                 return
