Allow for HRD to fragment command replies

Also cleaned up some debugging messages.

Merged from wsjtx-1.4 branch.



git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5141 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2015-04-02 10:28:10 +00:00
parent a7a60412c5
commit aa7e6b7a86
2 changed files with 60 additions and 42 deletions

View File

@ -52,7 +52,7 @@ struct HRDMessage
delete [] reinterpret_cast<char *> (p); // Mirror allocation in operator new above. delete [] reinterpret_cast<char *> (p); // Mirror allocation in operator new above.
} }
qint32 size_; quint32 size_;
qint32 magic_1_; qint32 magic_1_;
qint32 magic_2_; qint32 magic_2_;
qint32 checksum_; // Apparently not used. qint32 checksum_; // Apparently not used.
@ -931,7 +931,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
if (QTcpSocket::ConnectedState != hrd_->state ()) if (QTcpSocket::ConnectedState != hrd_->state ())
{ {
#if WSJT_TRACE_CAT #if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command \"" << cmd << "\" failed" << hrd_->errorString (); qDebug () << "HRDTransceiver::send_command" << cmd << "failed" << hrd_->errorString ();
#endif #endif
throw error { throw error {
@ -947,7 +947,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
if (!write_to_port (message.constData (), message.size ())) if (!write_to_port (message.constData (), message.size ()))
{ {
#if WSJT_TRACE_CAT #if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command failed to write command \"" << cmd << "\" to HRD"; qDebug () << "HRDTransceiver::send_command failed to write command" << cmd << "to HRD";
#endif #endif
throw error { throw error {
@ -959,11 +959,11 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
else else
{ {
auto string = prepend_context ? context + cmd : cmd; auto string = prepend_context ? context + cmd : cmd;
QScopedPointer<HRDMessage> message (new (string) HRDMessage); QScopedPointer<HRDMessage> message {new (string) HRDMessage};
if (!write_to_port (reinterpret_cast<char const *> (message.data ()), message->size_)) if (!write_to_port (reinterpret_cast<char const *> (message.data ()), message->size_))
{ {
#if WSJT_TRACE_CAT #if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command failed to write command \"" << cmd << "\" to HRD"; qDebug () << "HRDTransceiver::send_command failed to write command" << cmd << "to HRD";
#endif #endif
throw error { throw error {
@ -973,40 +973,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
} }
} }
// waitForReadReady appears to be occasionally unreliable on Windows auto buffer = read_reply (cmd);
// timing out when data is waiting so retry a few times
unsigned retries {3};
bool replied {false};
while (!replied && retries--)
{
replied = hrd_->waitForReadyRead ();
if (!replied && hrd_->error () != hrd_->SocketTimeoutError)
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command \"" << cmd << "\" failed to reply" << hrd_->errorString ();
#endif
throw error {
tr ("Ham Radio Deluxe failed to reply to command \"%1\" %2\n")
.arg (cmd)
.arg (hrd_->errorString ())
};
}
}
if (!replied)
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command \"" << cmd << "\" retries exhausted";
#endif
throw error {
tr ("Ham Radio Deluxe retries exhausted sending command \"%1\"")
.arg (cmd)
};
}
QByteArray buffer (hrd_->readAll ());
if (v4 == protocol_) if (v4 == protocol_)
{ {
@ -1014,12 +981,12 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
} }
else else
{ {
HRDMessage const * reply (new (buffer) HRDMessage); HRDMessage const * reply {new (buffer) HRDMessage};
if (reply->magic_1_value_ != reply->magic_1_ && reply->magic_2_value_ != reply->magic_2_) if (reply->magic_1_value_ != reply->magic_1_ && reply->magic_2_value_ != reply->magic_2_)
{ {
#if WSJT_TRACE_CAT #if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command \"" << cmd << "\" invalid reply"; qDebug () << "HRDTransceiver::send_command" << cmd << "invalid reply";
#endif #endif
throw error { throw error {
@ -1028,6 +995,17 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
}; };
} }
// keep reading until expected size arrives
while (buffer.size () - offsetof (HRDMessage, size_) < reply->size_)
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command" << cmd << "reading more reply data";
#endif
buffer += read_reply (cmd);
reply = new (buffer) HRDMessage;
}
result = QString {reply->payload_}; // this is not a memory leak (honest!) result = QString {reply->payload_}; // this is not a memory leak (honest!)
} }
@ -1057,12 +1035,50 @@ bool HRDTransceiver::write_to_port (char const * data, qint64 length)
return true; return true;
} }
QByteArray HRDTransceiver::read_reply (QString const& cmd)
{
// waitForReadReady appears to be occasionally unreliable on Windows
// timing out when data is waiting so retry a few times
unsigned retries {3};
bool replied {false};
while (!replied && retries--)
{
replied = hrd_->waitForReadyRead ();
if (!replied && hrd_->error () != hrd_->SocketTimeoutError)
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command" << cmd << "failed to reply" << hrd_->errorString ();
#endif
throw error {
tr ("Ham Radio Deluxe failed to reply to command \"%1\" %2\n")
.arg (cmd)
.arg (hrd_->errorString ())
};
}
}
if (!replied)
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command" << cmd << "retries exhausted";
#endif
throw error {
tr ("Ham Radio Deluxe retries exhausted sending command \"%1\"")
.arg (cmd)
};
}
return hrd_->readAll ();
}
void HRDTransceiver::send_simple_command (QString const& command, bool no_debug) void HRDTransceiver::send_simple_command (QString const& command, bool no_debug)
{ {
if ("OK" != send_command (command, no_debug)) if ("OK" != send_command (command, no_debug))
{ {
#if WSJT_TRACE_CAT #if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_simple_command \"" << command << "\" unexpected response"; qDebug () << "HRDTransceiver::send_simple_command" << command << "unexpected response";
#endif #endif
throw error { throw error {

View File

@ -14,6 +14,7 @@
class QRegExp; class QRegExp;
class QTcpSocket; class QTcpSocket;
class QByteArray;
// //
// Ham Radio Deluxe Transceiver Interface // Ham Radio Deluxe Transceiver Interface
@ -50,6 +51,7 @@ protected:
private: private:
QString send_command (QString const&, bool no_debug = false, bool prepend_context = true, bool recurse = false); QString send_command (QString const&, bool no_debug = false, bool prepend_context = true, bool recurse = false);
QByteArray read_reply (QString const& command);
void send_simple_command (QString const&, bool no_debug = false); void send_simple_command (QString const&, bool no_debug = false);
bool write_to_port (char const *, qint64 length); bool write_to_port (char const *, qint64 length);
int find_button (QRegExp const&) const; int find_button (QRegExp const&) const;