|
|
|
@ -19,7 +19,10 @@ import javax.sip.header.*; |
|
|
|
import javax.sip.message.MessageFactory; |
|
|
|
import javax.sip.message.Request; |
|
|
|
import javax.sip.message.Response; |
|
|
|
import java.io.BufferedReader; |
|
|
|
import java.io.InputStreamReader; |
|
|
|
import java.io.UnsupportedEncodingException; |
|
|
|
import java.net.*; |
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
import java.security.MessageDigest; |
|
|
|
import java.util.*; |
|
|
|
@ -81,6 +84,13 @@ public class SipClientService implements SipListener { |
|
|
|
|
|
|
|
private AtomicInteger cSeqCounter = new AtomicInteger(1); |
|
|
|
|
|
|
|
private static final String[] IP_SERVICES = { |
|
|
|
"https://api.ipify.org", |
|
|
|
"https://checkip.amazonaws.com", |
|
|
|
"https://ifconfig.me/ip", |
|
|
|
"https://icanhazip.com" |
|
|
|
}; |
|
|
|
|
|
|
|
private static class SubscriptionInfo { |
|
|
|
String callId; |
|
|
|
FromHeader from; |
|
|
|
@ -179,7 +189,25 @@ public class SipClientService implements SipListener { |
|
|
|
headerFactory = sipFactory.createHeaderFactory(); |
|
|
|
addressFactory = sipFactory.createAddressFactory(); |
|
|
|
messageFactory = sipFactory.createMessageFactory(); |
|
|
|
|
|
|
|
// 获取本地实际IP地址(不是0.0.0.0) |
|
|
|
if (localIp == null || localIp.equals("0.0.0.0")) { |
|
|
|
try { |
|
|
|
// 尝试获取公网IP |
|
|
|
String publicIp = getPublicIp(); |
|
|
|
if (publicIp != null && !publicIp.isEmpty()) { |
|
|
|
log.info("Detected public IP: {}", publicIp); |
|
|
|
localIp = publicIp; |
|
|
|
} else { |
|
|
|
// 使用本地IP作为备选 |
|
|
|
localIp = InetAddress.getLocalHost().getHostAddress(); |
|
|
|
log.info("Using local IP: {}", localIp); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.warn("Failed to get public IP, using local IP", e); |
|
|
|
localIp = InetAddress.getLocalHost().getHostAddress(); |
|
|
|
} |
|
|
|
} |
|
|
|
log.info("Local IP: " + localIp); |
|
|
|
Properties properties = new Properties(); |
|
|
|
properties.setProperty("javax.sip.STACK_NAME", "spring-boot-sip-stack"); |
|
|
|
properties.setProperty("gov.nist.javax.sip.IP_ADDRESS", localIp); |
|
|
|
@ -196,9 +224,50 @@ public class SipClientService implements SipListener { |
|
|
|
sendRegister(null); |
|
|
|
} |
|
|
|
|
|
|
|
public static String getPublicIp() { |
|
|
|
for (String service : IP_SERVICES) { |
|
|
|
try { |
|
|
|
URL url = new URL(service); |
|
|
|
try (BufferedReader in = new BufferedReader( |
|
|
|
new InputStreamReader(url.openStream(), "UTF-8"))) { |
|
|
|
String ip = in.readLine(); |
|
|
|
if (ip != null && !ip.trim().isEmpty()) { |
|
|
|
return ip.trim(); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
// 尝试下一个服务 |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
// 获取本地IP地址的方法 |
|
|
|
private String getLocalIpAddress() throws SocketException { |
|
|
|
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); |
|
|
|
while (interfaces.hasMoreElements()) { |
|
|
|
NetworkInterface iface = interfaces.nextElement(); |
|
|
|
// 排除回环接口和未启用的接口 |
|
|
|
if (iface.isLoopback() || !iface.isUp()) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
Enumeration<InetAddress> addresses = iface.getInetAddresses(); |
|
|
|
while (addresses.hasMoreElements()) { |
|
|
|
InetAddress addr = addresses.nextElement(); |
|
|
|
// 优先使用IPv4地址 |
|
|
|
if (addr instanceof Inet4Address && !addr.isLoopbackAddress()) { |
|
|
|
return addr.getHostAddress(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
public void sendRegister(AuthorizationHeader authHeader) throws Exception { |
|
|
|
SipURI requestUri = addressFactory.createSipURI(null, domain); |
|
|
|
requestUri.setTransportParam(transport.toUpperCase()); |
|
|
|
// requestUri.setTransportParam(transport.toUpperCase()); |
|
|
|
requestUri.setPort(port); |
|
|
|
|
|
|
|
Address fromAddress = addressFactory.createAddress(username, addressFactory.createSipURI(username, domain)); |
|
|
|
@ -214,7 +283,7 @@ public class SipClientService implements SipListener { |
|
|
|
SipURI contactUri = addressFactory.createSipURI(username, localIp); |
|
|
|
contactUri.setPort(localPort); |
|
|
|
contactUri.setTransportParam(transport.toUpperCase()); |
|
|
|
contactUri.setParameter("deviceid", "123456"); |
|
|
|
// contactUri.setParameter("deviceid", "123456"); |
|
|
|
|
|
|
|
Address contactAddress = addressFactory.createAddress(contactUri); |
|
|
|
ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress); |
|
|
|
@ -244,7 +313,7 @@ public class SipClientService implements SipListener { |
|
|
|
if (authHeader != null) { |
|
|
|
request.addHeader(authHeader); |
|
|
|
} |
|
|
|
|
|
|
|
log.info("Sending REGISTER request:\n" + request); |
|
|
|
lastRegisterTransaction = sipProvider.getNewClientTransaction(request); |
|
|
|
lastRegisterTransaction.sendRequest(); |
|
|
|
} |
|
|
|
@ -395,8 +464,8 @@ public class SipClientService implements SipListener { |
|
|
|
CSeqHeader cSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); |
|
|
|
if (cSeqHeader == null) return; |
|
|
|
String method = cSeqHeader.getMethod(); |
|
|
|
log.info("Received response: {}, method: {}", status, method); |
|
|
|
|
|
|
|
log.info("Received response: {} {}, method: {}", response.getStatusCode(), response.getReasonPhrase(), method); |
|
|
|
log.info("Response:\n {}", response); |
|
|
|
try { |
|
|
|
if (Request.REGISTER.equalsIgnoreCase(method)) { |
|
|
|
if (status == 401 || status == 407) { |
|
|
|
|