There's an extensive discussion on this point starting on Nov 15 2011 on the rtcweb mailing list (started by me), under the title "Data channel setup and signalling". http://www.ietf.org/mail-archive/web/rtcweb/current/msg02861.html
Summary: I propose that (some) data channels be opened without use of offer-answer signaling, based on the application, perhaps using a data channel initially set up to let the application request data channels using application-specific messages. In particular, applications should be allowed to avoid a re-negotiation of all channels to open data channels, when the application knows it's talking to another copy of itself (or equivalent).
This proposal mostly covered the IETF side of things; how these would be exposed to the JS app is something I hadn't answered and would enjoy suggestions on.
Quoting one bit to highlight:
A use-case would be a background http proxy-server during chat. If you have to re-OFFER for each data channel that comes and goes to transfer a resource, it will both swamp the server and be slow (due to the triangle signalling). If instead the application can open a single control data channel, and invoke transfers over it, the application can efficiently transfer a high number of URIs. Are there other ways to do this without re-OFFERing constantly? yes. But they generally involve building protocols on top of an array of long-lasting generic connections.
For example, the control data channel might pass messages (directly browser-to-browser) like
{
id: 1,
command: "GET",
URI: "blah/foo/bar",
channel: 5,
}
with an answer:
{
id: 1,
result: "ok",
size: 1234,
}
followed by transfer of the URI on data channel 5. (Note: in this I'm assuming an API that lets the app open a specific data channel of the peer connection.)

(In reply to comment #3)
> Created attachment 1061[details]
> DataStreams proposal downloaded from google docs 2012 Jan 6
>
> Downloaded Justins doc from google docs just to get a version into the bug
Some more comments (refering to https://www.w3.org/Bugs/Public/attachment.cgi?id=1061):
* As a dataStream can be added to several PeerConnections, bufferedAmount should be a PeerConnection property, since the throughput can vary. The same applies to "onreadytosend". An alternative could be to allow a dataStream to be connected to one PeerConnection only, but that defeats the purpose of the dataStream - you could just as well have "send()" methods on the PeerConnection object.
* For the "return -1 if unsuccessful, non-neg integer if successful" part: is this supported by the protocol (i.e. is there a feedback mechanism in SCTP)?
* Does it really make sense that dataStream inherits from Stream? The natural thing would rather be that the "send" method of dataStream could take DOMString, blob, ArrayBuffer and *Stream* as arguments; Stream to be introduced once it has been added to the File API spec. This would align it closer to WebSockets and XHR. For unreliable dataStream's, probably only DOMString's would make sense (no point in sending a file unreliably). Note also that there need to be some info on how to handle incoming binary data (as blob or as ArrayBuffer; WebSocket has the "binaryType" attribute).
* The proposal is inconsistent with regards to how a DataStream is created. The text says PeerConnection.createDataStream() while the examples and idls uses a DataStream constructor.
* Why introduce new methods for adding/removing data streams (addDataStream() and removeDataStream()) when the localStreams/remoteStreams attributes and onaddstream/onremovestream event listeners are reused?
* Re-use of MessageEvent's as defined in http://dev.w3.org/html5/postmsg/ should be considered for "onmessage" - it is already used for Server-Sent Events and Web Sockets. Perhaps channel messaging could be used to align more with the rest of the web platform?

Sorry for taking so long to reply. These are good questions, answers below.
> Some more comments (refering to
> https://www.w3.org/Bugs/Public/attachment.cgi?id=1061):
>
> * As a dataStream can be added to several PeerConnections, bufferedAmount
> should be a PeerConnection property, since the throughput can vary. The same
> applies to "onreadytosend". An alternative could be to allow a dataStream to be
> connected to one PeerConnection only, but that defeats the purpose of the
> dataStream - you could just as well have "send()" methods on the PeerConnection
> object.
This is a good point regarding attaching a DataStream to multiple PeerConnections. It may well be that this is more trouble than it is worth; I will re-evaluate whether it makes sense to allow DataStreams to be created independently from a PeerConnection.
However, regarding the existence of DataStream vs send() on PeerConnection, I think DataStream provides a nice object-oriented API, especially when you have multiple simultaneous data streams.
>
> * For the "return -1 if unsuccessful, non-neg integer if successful" part: is
> this supported by the protocol (i.e. is there a feedback mechanism in SCTP)?
This is local feedback regarding whether there is enough buffer space to queue the outgoing packet; it should be independent of protocol.
> * Does it really make sense that dataStream inherits from Stream?
Agree. At this time, the Stream stuff seems too immature to tie ourselves to; while I liked having it as a parent class for MediaStream and DataStream, we could just use Object instead.
The natural
> thing would rather be that the "send" method of dataStream could take
> DOMString, blob, ArrayBuffer and *Stream* as arguments; Stream to be introduced
> once it has been added to the File API spec. This would align it closer to
> WebSockets and XHR. For unreliable dataStream's, probably only DOMString's
> would make sense (no point in sending a file unreliably).
Agree, will address this.
Note also that there
> need to be some info on how to handle incoming binary data (as blob or as
> ArrayBuffer; WebSocket has the "binaryType" attribute).
Agree.
> * The proposal is inconsistent with regards to how a DataStream is created. The
> text says PeerConnection.createDataStream() while the examples and idls uses a
> DataStream constructor.
My oversight. Will rework based on what I decide regarding question #1.
> * Why introduce new methods for adding/removing data streams (addDataStream()
> and removeDataStream()) when the localStreams/remoteStreams attributes and
> onaddstream/onremovestream event listeners are reused?
Mainly, because the existing methods have media-specific syntax (MediaStreamHints in addStream, etc).
> * Re-use of MessageEvent's as defined in http://dev.w3.org/html5/postmsg/
> should be considered for "onmessage" - it is already used for Server-Sent
> Events and Web Sockets. Perhaps channel messaging could be used to align more
> with the rest of the web platform?
I don't think channel messaging is a perfect fit here, but using MessageEvent like WebSocket makes a lot of sense. Main question is how we can expose metadata like seqnum when using MessageEvent, will think this over.