summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2015-12-16 02:10:10 +0100
committerJavier <dev.git@javispedro.com>2015-12-16 02:10:10 +0100
commit309947a4316a94f4c5d43c9b39b733cc3bbab459 (patch)
treea339058f8e1c3045240d71ab961c7ec1effdd947
parentaabf2deebb9619e21f1ebac0690c6b206b16b251 (diff)
downloadsapd-309947a4316a94f4c5d43c9b39b733cc3bbab459.tar.gz
sapd-309947a4316a94f4c5d43c9b39b733cc3bbab459.zip
implement session termination requests
-rw-r--r--sapbtpeer.cc2
-rw-r--r--sapconnection.cc5
-rw-r--r--sapconnection.h3
-rw-r--r--sappeer.cc81
-rw-r--r--sappeer.h2
-rw-r--r--saprotocol.cc12
-rw-r--r--sapsocket.cc15
-rw-r--r--sapsocket.h3
-rw-r--r--webproxyconn.cc2
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<SAPSocket*> 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<SAPSocket*> 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<QString, SAPConnection*> _conns;
QMap<int, SAPSocket*> _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<quint8>(data, offset);
- frame.acceptorId = read<quint8>(data, offset);
- frame.initiatorId = read<quint8>(data, offset);
+ frame.acceptorId = read<quint16>(data, offset);
+ frame.initiatorId = read<quint16>(data, offset);
int marker = data.indexOf(';', offset);
if (marker == -1) {
@@ -446,8 +446,8 @@ SAProtocol::ServiceTerminationRequestFrame SAProtocol::unpackServiceTerminationR
int offset = 0;
frame.messageType = read<quint8>(data, offset);
- frame.acceptorId = read<quint8>(data, offset);
- frame.initiatorId = read<quint8>(data, offset);
+ frame.acceptorId = read<quint16>(data, offset);
+ frame.initiatorId = read<quint16>(data, offset);
int marker = data.indexOf(';', offset);
if (marker == -1) {
@@ -480,8 +480,8 @@ SAProtocol::ServiceTerminationResponseFrame SAProtocol::unpackServiceTermination
int offset = 0;
frame.messageType = read<quint8>(data, offset);
- frame.acceptorId = read<quint8>(data, offset);
- frame.initiatorId = read<quint8>(data, offset);
+ frame.acceptorId = read<quint16>(data, offset);
+ frame.initiatorId = read<quint16>(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<QByteArray> _in;
+ QQueue<QByteArray> _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)));