From 309947a4316a94f4c5d43c9b39b733cc3bbab459 Mon Sep 17 00:00:00 2001 From: Javier Date: Wed, 16 Dec 2015 02:10:10 +0100 Subject: implement session termination requests --- sapbtpeer.cc | 2 ++ sapconnection.cc | 5 ---- sapconnection.h | 3 --- sappeer.cc | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- sappeer.h | 2 ++ saprotocol.cc | 12 ++++----- sapsocket.cc | 15 +++++++++-- sapsocket.h | 3 +++ webproxyconn.cc | 2 +- 9 files changed, 107 insertions(+), 18 deletions(-) diff --git a/sapbtpeer.cc b/sapbtpeer.cc index 3926cdf..bf3bddb 100644 --- a/sapbtpeer.cc +++ b/sapbtpeer.cc @@ -113,6 +113,8 @@ void SAPBTPeer::handleFrame(const QByteArray &data) // This must be a peer description frame! SAProtocol::PeerDescription peerDesc = SAProtocol::unpackPeerDescription(data); qDebug() << peerDesc.product << peerDesc.manufacturer << peerDesc.name; + qDebug() << "apdu=" << peerDesc.APDUSize << "ssdu=" << peerDesc.SSDUSize + << "sessions=" << peerDesc.sessions << "timeout=" << peerDesc.timeout; SAProtocol::PeerDescription myDesc = peerDesc; myDesc.messageType = 6; // Why? diff --git a/sapconnection.cc b/sapconnection.cc index 3d8ef5d..9a624b6 100644 --- a/sapconnection.cc +++ b/sapconnection.cc @@ -26,11 +26,6 @@ QList SAPConnection::sockets() return _sockets.values(); } -void SAPConnection::close() -{ - // TODO implement termination of connections -} - void SAPConnection::setSocket(int channelId, SAPSocket *socket) { Q_ASSERT(!_sockets.contains(channelId)); diff --git a/sapconnection.h b/sapconnection.h index 7702e43..0fdd025 100644 --- a/sapconnection.h +++ b/sapconnection.h @@ -22,9 +22,6 @@ public: QList sockets(); -public slots: - void close(); - signals: void connected(); void error(int errorCode); diff --git a/sappeer.cc b/sappeer.cc index 1e5be61..960e515 100644 --- a/sappeer.cc +++ b/sappeer.cc @@ -72,12 +72,44 @@ SAPConnection * SAPPeer::createServiceConnection(const QString &profile, const Q _sessions.insert(sessionId, socket); } + _conns.insert(profile, conn); + writeDataToSession(SAProtocol::defaultSessionId, SAProtocol::packServiceConnectionRequestFrame(request)); return conn; } +bool SAPPeer::terminateServiceConnection(const QString &profile, const QString &requesterProfile, SAPServiceInfo::Role requesterRole) +{ + SAPManager *manager = SAPManager::instance(); + + int initiator = manager->registeredAgentId(requesterProfile, requesterRole); + + if (initiator < 0) { + qWarning() << "Requester profile not found:" << requesterProfile; + return false; + } + + // Search remote agent id in capability database. + CapabilityPeer *capPeer = capabilityPeer(); + + int acceptor = capPeer->remoteAgentId(profile, SAPServiceInfo::oppositeRole(requesterRole)); + if (acceptor < 0) { + qWarning() << "Remote profile not found:" << profile; + return false; + } + + SAPConnection *conn = _conns.value(profile, 0); + if (conn) { + // TODO send terminaterequest message + return true; + } else { + qWarning() << "Connection does not exist:" << profile; + return false; + } +} + SAProtocol::Role SAPPeer::role() const { return _role; @@ -100,6 +132,7 @@ CapabilityPeer *SAPPeer::capabilityPeer() void SAPPeer::writeDataToSession(int session, const QByteArray &data) { + qDebug() << "frame size" << data.size(); sendFrame(SAProtocol::packFrame(session, data, SAProtocol::FrameData)); } @@ -149,7 +182,8 @@ void SAPPeer::acceptServiceConnection(SAPConnectionRequest *connReq, int statusC _sessions.remove(socket->sessionId()); delete socket; } - delete conn; // Also deletes child sockets + _conns.remove(conn->profile()); + delete conn; } // Can't delete connReq now because we must return to it. @@ -320,6 +354,51 @@ void SAPPeer::handleDefaultSessionMessage(const QByteArray &message) break; } + case SAProtocol::ServiceTerminationRequest: { + SAProtocol::ServiceTerminationRequestFrame req = SAProtocol::unpackServiceTerminationRequestFrame(message); + SAPConnection *conn = _conns.value(req.profile, 0); + + qDebug() << "Service termination request to profile" << req.profile; + + if (!conn) { + // We did not find this profile; send a error back + SAProtocol::ServiceTerminationResponseFrame resp; + resp.messageType = SAProtocol::ServiceTerminationResponse; + resp.acceptorId = req.acceptorId; + resp.initiatorId = req.initiatorId; + resp.profile = req.profile; + resp.statusCode = 1; + + qWarning() << "Profile" << req.profile << "not connected, sending negative response"; + + writeDataToSession(SAProtocol::defaultSessionId, + SAProtocol::packServiceTerminationResponseFrame(resp)); + return; + } + + // Ok, proceed to terminate the connection + foreach (SAPSocket *socket, conn->sockets()) { + emit socket->disconnected(); + _sessions.remove(socket->sessionId()); + delete socket; + } + emit conn->disconnected(); + _conns.remove(conn->profile()); + delete conn; + + // Acknowledge everything was succesful + SAProtocol::ServiceTerminationResponseFrame resp; + resp.messageType = SAProtocol::ServiceTerminationResponse; + resp.acceptorId = req.acceptorId; + resp.initiatorId = req.initiatorId; + resp.profile = req.profile; + resp.statusCode = 0; + + writeDataToSession(SAProtocol::defaultSessionId, + SAProtocol::packServiceTerminationResponseFrame(resp)); + + break; + } default: qWarning() << "Unknown default session message type:" << message_type; } diff --git a/sappeer.h b/sappeer.h index 8ac81b7..abb36e4 100644 --- a/sappeer.h +++ b/sappeer.h @@ -21,6 +21,7 @@ public: explicit SAPPeer(SAProtocol::Role role, const QString &localName, const QString &peerName, QObject *parent = 0); SAPConnection* createServiceConnection(const QString &profile, const QString &requesterProfile, SAPServiceInfo::Role requesterRole); + bool terminateServiceConnection(const QString &profile, const QString &requesterProfile, SAPServiceInfo::Role requesterRole); SAProtocol::Role role() const; QString localName() const; @@ -62,6 +63,7 @@ private: const QString _localName; const QString _peerName; + QMap _conns; QMap _sessions; friend class SAPSocket; diff --git a/saprotocol.cc b/saprotocol.cc index 94594a1..00c083f 100644 --- a/saprotocol.cc +++ b/saprotocol.cc @@ -392,8 +392,8 @@ SAProtocol::ServiceConnectionResponseFrame SAProtocol::unpackServiceConnectionRe int offset = 0; frame.messageType = read(data, offset); - frame.acceptorId = read(data, offset); - frame.initiatorId = read(data, offset); + frame.acceptorId = read(data, offset); + frame.initiatorId = read(data, offset); int marker = data.indexOf(';', offset); if (marker == -1) { @@ -446,8 +446,8 @@ SAProtocol::ServiceTerminationRequestFrame SAProtocol::unpackServiceTerminationR int offset = 0; frame.messageType = read(data, offset); - frame.acceptorId = read(data, offset); - frame.initiatorId = read(data, offset); + frame.acceptorId = read(data, offset); + frame.initiatorId = read(data, offset); int marker = data.indexOf(';', offset); if (marker == -1) { @@ -480,8 +480,8 @@ SAProtocol::ServiceTerminationResponseFrame SAProtocol::unpackServiceTermination int offset = 0; frame.messageType = read(data, offset); - frame.acceptorId = read(data, offset); - frame.initiatorId = read(data, offset); + frame.acceptorId = read(data, offset); + frame.initiatorId = read(data, offset); int marker = data.indexOf(';', offset); if (marker == -1) { diff --git a/sapsocket.cc b/sapsocket.cc index e7376d9..e9a69ec 100644 --- a/sapsocket.cc +++ b/sapsocket.cc @@ -6,10 +6,11 @@ #include "sapsocket.h" #define DELAYED_ACK_TIME 1000 +#define WINDOW_SIZE_MSGS 10 SAPSocket::SAPSocket(SAPConnection *conn, int sessionId, const SAPChannelInfo &chanInfo) : QObject(conn), _sessionId(sessionId), _info(chanInfo), _open(false), - _outLastSeqNum(0), _inLastSeqNum(0), _inLastAck(0) + _outLastSeqNum(0), _outLastAck(0), _inLastSeqNum(0), _inLastAck(0) { } @@ -56,13 +57,23 @@ bool SAPSocket::send(const QByteArray &data) return false; } + if (data.size() > 65000) { + qWarning() << "Fragmentation is not yet supported"; + return false; + } + + if (_out.size() > WINDOW_SIZE_MSGS) { + // Send buffer is not empty; enqueue + // TODO Realiability + } + frame.withSeqNum = isWithSeqNum(); if (isReliable()) { frame.seqNum = ++_outLastSeqNum; } else { frame.seqNum = 0; } - frame.unk_1 = 0; + frame.unk_1 = 0; // Is this related to fragmentation? frame.data = data; peer()->writeDataToSession(_sessionId, SAProtocol::packDataFrame(frame)); diff --git a/sapsocket.h b/sapsocket.h index a2a360a..0452e9d 100644 --- a/sapsocket.h +++ b/sapsocket.h @@ -50,10 +50,13 @@ private: const SAPChannelInfo _info; bool _open; QQueue _in; + QQueue _out; QBasicTimer _timer; /** Outgoing sequence number */ quint16 _outLastSeqNum; + /** Last acknowledged sent message. */ + quint16 _outLastAck; /** Next expected incoming sequence number */ quint16 _inLastSeqNum; diff --git a/webproxyconn.cc b/webproxyconn.cc index d1590ca..8369417 100644 --- a/webproxyconn.cc +++ b/webproxyconn.cc @@ -104,7 +104,7 @@ void WebProxyConn::handleRequest(const Message &msg) if (!trans) { RequestHeader hdr = parseRequestHeader(msg.payload); - qDebug() << "Starting transaction to" << hdr.host << hdr.port << (hdr.connect ? "tunnel" : "http"); + qDebug() << "Starting transaction" << msg.transactionId << "to" << hdr.host << hdr.port << (hdr.connect ? "tunnel" : "http"); trans = new WebProxyTrans(msg.transactionId, hdr.connect, hdr.host, hdr.port, this); connect(trans, SIGNAL(dataReceived(QByteArray)), this, SLOT(handleTransDataReceived(QByteArray))); -- cgit v1.2.3