| 201 | } |
| 202 | |
| 203 | bool PanadapterStream::start(RadioConnection* conn) |
| 204 | { |
| 205 | if (isRunning()) stop(); // clean up previous session before rebinding (#561) |
| 206 | |
| 207 | resetAudioStreamStats(); |
| 208 | |
| 209 | m_isWanMode = false; |
| 210 | m_hasReceivedPacket = false; |
| 211 | |
| 212 | QHostAddress chosenAddress; |
| 213 | QString chosenReason; |
| 214 | RadioBindMode bindMode = RadioBindMode::Auto; |
| 215 | const QHostAddress bindAddr = chooseLanBindAddress(conn, &chosenReason, &chosenAddress, &bindMode); |
| 216 | const QString bindReason = chosenReason.isEmpty() ? QStringLiteral("auto") : chosenReason; |
| 217 | |
| 218 | const bool bound = m_socket->bind(bindAddr, 0, kLanVitaBindMode); |
| 219 | if (bound) |
| 220 | qCInfo(lcVita49).noquote() |
| 221 | << "PanadapterStream: LAN VITA UDP bind" |
| 222 | << QStringLiteral("addr=%1").arg(bindAddr.toString()) |
| 223 | << QStringLiteral("port=%1").arg(m_socket->localPort()) |
| 224 | << QStringLiteral("flags=DontShareAddress") |
| 225 | << QStringLiteral("reason=%1").arg(bindReason); |
| 226 | if (!bound) { |
| 227 | qCWarning(lcVita49) << "PanadapterStream: failed to bind UDP socket:" |
| 228 | << m_socket->errorString() |
| 229 | << "mode=" << (bindMode == RadioBindMode::Explicit ? "Explicit" : "Auto") |
| 230 | << "chosen=" << (chosenAddress.isNull() ? QStringLiteral("<none>") |
| 231 | : chosenAddress.toString()); |
| 232 | return false; |
| 233 | } |
| 234 | |
| 235 | applyReceiveBufferSize(); // #3810 — absorb VITA-49 bursts so they don't drop |
| 236 | m_localAddress = m_socket->localAddress(); |
| 237 | m_localPort = m_socket->localPort(); |
| 238 | qCDebug(lcVita49) << "PanadapterStream: local UDP endpoint" |
| 239 | << m_localAddress.toString() << ":" << m_localPort; |
| 240 | |
| 241 | // Send a one-byte UDP registration datagram to the radio's VITA-49 port. |
| 242 | // The radio learns our IP:port from the source address of this datagram. |
| 243 | // This is required on firmware v1.4.0.0 where the TCP "client udpport" |
| 244 | // command may return 0x50001000 ("command not supported"). |
| 245 | const QHostAddress radioAddr = conn->radioAddress(); |
| 246 | if (!radioAddr.isNull()) { |
| 247 | const QByteArray reg(1, '\x00'); |
| 248 | const qint64 sent = m_socket->writeDatagram(reg, radioAddr, 4992); |
| 249 | if (sent == 1) { |
| 250 | m_totalTxBytes.fetch_add(sent); |
| 251 | qCDebug(lcVita49) << "PanadapterStream: sent UDP registration to" |
| 252 | << radioAddr.toString() << ":4992"; |
| 253 | m_routedPrimeElapsed.restart(); |
| 254 | m_routedPrimeTimer->start(250); |
| 255 | } else { |
| 256 | qCWarning(lcVita49) << "PanadapterStream: UDP registration send failed:" |
| 257 | << m_socket->errorString(); |
| 258 | } |
| 259 | } else { |
| 260 | qCWarning(lcVita49) << "PanadapterStream: radio address unknown — skipping UDP registration"; |
no test coverage detected