The stack decides to which transport to use based on the results of the DNS NAPTR lookup for the message destination. The NAPTR records can prefer TCP over UDP. (This seems to be a good writeup:
http://anders.com/cms/264/). Also if the stack blacklists a UDP DNS result because it is unreachable, then it will use TCP instead.
An application can force a particular protocol in many different ways:
1. Use a DUM profile outbound proxy setting (Profile::setOutboundProxy) with a transport=TCP parameter on the outbound URI.
2. Use the DUM profile setting setFixedTransportPort to force the transport selection logic to a particular transport - this only works if you use a different port for UDP and TCP.
3. Lower level - Add the transport parameter (ie: ;transport=TCP) to the request URI or Route header of any message.
4. Lower level - pre-populate the Via header in each SipMessage with an IP address/port of the transport and a transport parameter (ie: ;transport=TCP).
Note: All of these methods will end up circumventing the NAPTR lookup stage of the DNS records, since there is no point in checking which protocol to use, if the application is fixing it. Some will also circumvent SRV look ups as well (the ones that lock to a particular IP or port).
I'm sure there are more ways I'm forgetting.
Scott