summaryrefslogtreecommitdiff
path: root/src/PeerConnection.cc
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-05-18 17:08:29 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-05-18 17:08:29 +0000
commitd018b3a609a9e6eb5f2adb550b39452254daa8c6 (patch)
tree8d346b4dfedd07a69585cc132c4cb05a8082e644 /src/PeerConnection.cc
parentbd5d11da3cb493c26fd3896bfee5ae6546828b57 (diff)
2006-05-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To remove a wait from download loop: * src/DownloadEngine.cc (run): Comment out shortSleep. To rewrite the message handling: * src/CancelMessage.h: Derived from SimplePeerMessage. (msg): New variable. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/CancelMessage.cc (create): New function. (receivedAction): Replaced deleteRequestMessageInQueue with rejectPieceMessageInQueue. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/BitfieldMessage.h: Derived from SimplePeerMessage. (msg): New variable. (msgLength): New variable. (~BitfieldMessage): Deleted msg. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/BitfieldMessage.cc (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/ChokeMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPredicate): New function. (onSendComplete): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. (create): New function. * src/ChokeMessage.cc (create): New function. (send): Removed. (sendPredicate): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/KeepAliveMessage.h: Derived from SimplePeerMessage. (msg): New variable. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/KeepAliveMessage.cc (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/PortMessage.h (create): New function. (receivedAction): Updated log message. * src/PortMessage.cc: New file. * src/UnchokeMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPredicate): New function. (onSendComplete): New function. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/UnchokeMessage.cc (create): New function. (send): Removed. (sendPredicate): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/PieceMessage.h (leftPieceDataLength): Removed. (leftDataLength): New variable. (headerSend): New variable. (pendingCount): New variable. (msgHeader): New variable. (sendPieceData): New function. (incrementPendingCount): New function. (isPendingCountMax): New function. (create): New function. (getMessageHeader): New function. (getMessageHeaderLength): New function. * src/PieceMessage.cc (create): New function. (getMessageHeader): New function. (getMessageHeaderLength): New function. (send): Rewritten. (sendPieceData): New function. * src/HaveMessage.h: Derived from SimplePeerMessage. (msg): New variable. (create): New function. (getMessage): New function. (getMessageLength): New function. * src/HaveMessage.cc (create): New function. (send): Removed. (sendPieceData): New function. (getMessage): New function. (getMessageLength): New function. * src/RequestMessage.h: Derived from SimplePeerMessage. (msg): New variable. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/RequestMessage.cc (create): New function. (receivedAction): Added the handling of fast extension. Deleted torrentMan->addUploadLength, torrentMan->addDeltaUploadLength. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/InterestedMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPredicate): New function. (onSendComplete): New function. (create): New function. (getMessage): New function. (getMessageLength): New function. * src/InterestedMessage.cc (create): New function. (send): Removed. (sendPieceData): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/NotInterestedMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPieceData): New function. (onSendComplete): New function. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/NotInterestedMessage.cc (create): New function. (send): Removed. (sendPredicate): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/AllowedFastMessage.h: New class. * src/AllowedFastMessage.cc: New class. * src/RejectMessage.h: New class. * src/RejectMessage.cc: New class. * src/SuggestPieceMessage.h: New class. * src/SuggestPieceMessage.cc: New class. * src/HaveAllMessage.h: New class. * src/HaveAllMessage.cc: New class. * src/HaveNoneMessage.h: New class. * src/HaveNoneMessage.cc: New class. * src/HandshakeMessage.h: Derived from SimplePeerMessage. (msg): New variable. (reserved): New variable. (create): New function. (getId): New function. (receivedAction): New function. (getMessage): New function. (getMessageLength): New function. (isFastExtensionSupported): New function. * src/HandshakeMessage.cc (HandshakeMessage): Moved here from HandshakeMessage.h. (create): New function. (getMessage): New function. (getMessageLength): New function. (toString): Added the output of reserved field. (check): Added const qualifier. (isFastExtensionSupported): New function. * src/PeerMessageUtil.h (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createHaveMessage): Removed. (createBitfieldMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createPortMessage): Removed. (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createHaveMessage): Removed. (createBitfieldMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createKeepAliveMessage): Removed. (createHandshakeMessage): Removed. (setIntParam): New function. (createPeerMessageString): New function. * src/PeerMessageUtil.cc (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createHaveMessage): Removed. (createBitfieldMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createPortMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createHaveMessage): Removed. (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createBitfieldMessage): Removed. (createKeepAliveMessage): Removed. (createHandshakeMessage): Removed. (setIntParam): New function. (createPeerMessageString): New function. * src/PeerConnection.h (peer): Removed. (torrentMan): Removed. (createNLengthMessage): Removed. (setIntParam): Removed. (writeOutgoingMessageLog): Removed all overloaded functions. (PeerConnection): Deleted peer and torrentMan from its arguments. (sendMessage): New function. (sendHandshake): Removed. (sendKeepAlive): Removed. (sendChoke): Removed. (sendUnchoke): Removed. (sendInterested): Removed. (sendNotInterested): Removed. (sendHave): Removed. (sendBitfield): Removed. (sendRequest): Removed. (sendPiece): Removed. (sendPieceHeader): Removed. (sendPieceData): Removed. (sendCancel): Removed. (getPeer): Removed. * src/PeerConnection.cc (PeerConnection): Deleted peer and torrentMan from its arguments. (sendHandshake): Removed. (sendKeepAlive): Removed. (createNLengthMessage): Removed. (setIntParam): Removed. (writeOutgoingMessageLog): Removed all overloaded functions. (sendChoke): Removed. (sendUnchoke): Removed. (sendInterested): Removed. (sendNotInterested): Removed. (sendHave): Removed. (sendBitfield): Removed. (sendRequest): Removed. (sendPiece): Removed. (sendPieceHeader): Removed. (sendPieceData): Removed. (sendMessage): New function. (sendCancel): Removed. * src/PeerInteractionCommand.cc (PeerInteractionCommand): Call setUploadLimit. (executeInternal): Call setUploadLimit. Added the handling of "inProgress" state of handshake message. Call sendBitfield() or sendAllowdFast() instead of deprecated sendNow(). (keepAlive): Call addMessage and sendMessage instead of deprecated sendNow(). (beforeSocketCheck): Call addMessage instead of deprecated trySendNow() * src/TorrentMan.h (PEER_ID_LENGTH): New definition. (hasAllPieces): New function. * src/TorrentMan.cc (getMissingPiece): Added the handling of fast extension. (cancelPiece): Call updatePiece(). (hasAllPieces): New function. * src/PeerInteraction.h (fastSet): New variable. (getNewPieceAndSendInterest): Changed the return type to void. (send): Renamed as sendMessages. (deleteAllRequestSlot): Removed. (deleteRequestMessageInQueue): Renamed as rejectPieceMessageInQueue. (cancelAllRequest): Removed all overloaded functions. (deleteAllRequestSlot): Removed. (deletePieceMessageInQueue): Renamed as rejectAllPieceMessageInQueue. (rejectPieceMessageInQueue): New function. (rejectAllPieceMessageInQueue): New function. (onChoked): New function. (isSendingMessageInProgress): New function. (getCorrespondingRequestSlot): Changed its arguments. (isInFastSet): New function. (addFastSetIndex): New function. (addRequests): New function. (sendNow): Removed. (trySendNow): Removed. (sendBitfield): New function. (sendAllowdFast): New function. (createHaveAllMessage): New function. (createHaveNoneMessage): New function. (createRejectMessage): New function. (createAllowedFastMessage): New function. * src/PeerInteraction.cc (send): Renamed as sendMessages. (sendMessages): New function. (MsgPushBack): New class. (isSendingMessageInProgress): New function. (deletePieceMessageInQueue): Renamed as rejectAllPieceMessageInQueue. (rejectAllPieceMessageInQueue): New function. Added the handling of fast extension. (deleteRequestMessageInQueue): Renamed as rejectPieceMessageInQueue. (rejectPieceMessageInQueue): New function. Added the handling of fast extension. (deleteRequestSlot): Replaced for loop with std::find. (onChoked): New function. (deleteAllRequestSlot): Removed. (abortPiece): Rewirtten. (deleteTimeoutRequestSlot): Updated log messages. (getCorrespondingRequestSlot): Changed its arguments. (cancelAllRequest): Removed all overloaded functions. (receiveHandshake): Added the check to see whether an incoming peer supports fast extension. (createHandshakeMessage): Use HandshakeMessage::create instead of PeerMessageUtil. (createPeerMessage): Use create() of each message class instead of PeerMessageUtil. HaveAllMessage, HaveNoneMessage, RejectMessage, SuggestPieceMessage, AllowedFastMessage were added. (getNewPieceAndSendInterest): Changed its return value type to void. Added the handling of fast extension. (addRequests): New function. (sendNow): Removed. (sendHandshake): Rewritten. (trySendNow): Removed. (sendBitfield): New function. (sendAllowdFast): New function. (isInFastSet): New function. (addFastSetIndex): New function. (createRequestMessage): Use RequestMessage::create instead of PeerMessageUtil. (createCancelMessage): Use CancelMessage::create instead of PeerMessageUtil. (createPieceMessage): Use PieceMessage::create instead of PeerMessageUtil. (createHaveMessage): Use HaveMessage::create instead of PeerMessageUtil. (createChokeMessage): Use ChokeMessage::create instead of PeerMessageUtil. (createUnchokeMessage): Use UnchokeMessage::create instead of PeerMessageUtil. (createInterestedMessage): Use InterestedMessage::create instead of PeerMessageUtil. (createNotInterestedMessage): Use NotInterestedMessage::create instead of PeerMessageUtil. (createBitfieldMessage): Use BitfieldMessage::create instead of PeerMessageUtil. (createKeepAliveMessage): Use KeepAliveMessage::create instead of PeerMessageUtil. (createHaveAllMessage): New function. (createHaveNoneMessage): New function. (createRejectMessage): New function. (createAllowedFastMessage: New function. * src/Util.h (sha1Sum): New function. (computeFastSet): New function. * src/Util.cc (sha1Sum): New function. (computeFastSet): New function. * src/Peer.h (fastExtensionEnabled): New variable. (fastSet): New variable. (setAllBitfield): New function. (setFastExtensionEnabled): New function. (isFastExtensionEnabled): New function. (addFastSetIndex): New function. (getFastSet): New function. (isInFastSet): New function. (countFastSet): New function. * src/Peer.cc (isInFastSet): New function. (addFastSetIndex): New function. (setAllBitfield): New function. * src/AbstractCommand.cc (execute): Changed the procedure of checking sockets. * src/PeerAbstractCommand.cc (PeerAbstractCommand): Added the initialization for uploadLimitCheck and uploadLimit. (execute): Changed the procedure of checking sockets. The upload speed checking were added. (setUploadLimit): New function. (setUploadLimitCheck): New function. * src/PeerAbstractCommand.h (setUploadLimit): New function. (setUploadLimitCheck): New function. (uploadLimit): New variable. (uploadLimitCheck): New variable. To contact a tracker regularly: * src/TrackerWatcherCommand.h (interval): New variable. (checkPoint): New variable. (TrackerWatcherCommand): Added interval argument. * src/TrackerWatcherCommand.cc (TrackerWatcherCommand): Initialized checkPoint. (execute): Now a tracker is contacted in every specified period. If peer list is not needed, send request with numwant=0. * src/TrackerUpdateCommand.cc (execute): Updated log messages. * src/DownloadEngine.cc (~DownloadEngine): Removed two asserts. (waitData): Uncommented wfds. May be a bug fix.
Diffstat (limited to 'src/PeerConnection.cc')
-rw-r--r--src/PeerConnection.cc275
1 files changed, 13 insertions, 262 deletions
diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc
index aeac89ed..42d64240 100644
--- a/src/PeerConnection.cc
+++ b/src/PeerConnection.cc
@@ -27,279 +27,30 @@
#include "LogFactory.h"
#include <netinet/in.h>
-PeerConnection::PeerConnection(int cuid, const Socket* socket,
- const Option* op,
- Peer* peer, TorrentMan* torrentMan)
- :cuid(cuid), socket(socket), option(op), logger(logger), peer(peer),
- torrentMan(torrentMan),
- resbufLength(0), currentPayloadLength(0), lenbufLength(0) {
+PeerConnection::PeerConnection(int cuid,
+ const Socket* socket,
+ const Option* op)
+ :cuid(cuid),
+ socket(socket),
+ option(op),
+ logger(logger),
+ resbufLength(0),
+ currentPayloadLength(0),
+ lenbufLength(0) {
logger = LogFactory::getInstance();
}
PeerConnection::~PeerConnection() {}
-void PeerConnection::sendHandshake() const {
- /**
- * pstrlen --- '19', 1byte
- * pstr --- "BitTorrent protocol", 19bytes
- * reserved --- \0 * 8, 8bytes
- * info_hash --- info_hash, 20bytes
- * peer_id --- peer_id, 20bytes
- * total: 68bytes
- */
- char msg[HANDSHAKE_MESSAGE_LENGTH];
- memset(msg, 0, sizeof(msg));
- msg[0] = 19;
- memcpy(&msg[1], PSTR, strlen(PSTR));
- memcpy(&msg[28], torrentMan->getInfoHash(), 20);
- memcpy(&msg[48], torrentMan->peerId.c_str(), 20);
- writeOutgoingMessageLog("handshake");
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::sendKeepAlive() const {
- /**
- * len --- 0, 4bytes
- * total: 4bytes
- */
- char msg[4];
- memset(msg, 0, sizeof(msg));
- writeOutgoingMessageLog("keep alive");
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) const {
- assert(msgLen >= 5);
- memset(msg, 0, msgLen);
- setIntParam(msg, payloadLen);
- msg[4] = (char)id;
-}
-
-void PeerConnection::setIntParam(char* dest, int param) const {
- int nParam = htonl(param);
- memcpy(dest, &nParam, 4);
-}
-
-void PeerConnection::writeOutgoingMessageLog(const char* msg) const {
- logger->info(MSG_SEND_PEER_MESSAGE, cuid, peer->ipaddr.c_str(), peer->port, msg);
-}
-
-void PeerConnection::writeOutgoingMessageLog(const char* msg, int index) const {
- logger->info(MSG_SEND_PEER_MESSAGE_WITH_INDEX, cuid, peer->ipaddr.c_str(), peer->port, msg, index);
-}
-
-void PeerConnection::writeOutgoingMessageLog(const char* msg, const unsigned char* bitfield, int bitfieldLength) const {
- logger->info(MSG_SEND_PEER_MESSAGE_WITH_BITFIELD, cuid, peer->ipaddr.c_str(), peer->port, msg, Util::toHex(bitfield, bitfieldLength).c_str());
-}
-
-void PeerConnection::writeOutgoingMessageLog(const char* msg, int index, int begin, int length) const {
- logger->info(MSG_SEND_PEER_MESSAGE_WITH_INDEX_BEGIN_LENGTH, cuid, peer->ipaddr.c_str(), peer->port, msg, index, begin, length);
-}
-
-void PeerConnection::sendChoke() const {
- /**
- * len --- 1, 4bytes
- * id --- 0, 1byte
- * total: 5bytes
- */
- char msg[5];
- createNLengthMessage(msg, sizeof(msg), 1, 0);
- writeOutgoingMessageLog("choke");
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::sendUnchoke() const {
- /**
- * len --- 1, 4bytes
- * id --- 1, 1byte
- * total: 5bytes
- */
- char msg[5];
- createNLengthMessage(msg, sizeof(msg), 1, 1);
- writeOutgoingMessageLog("unchoke");
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::sendInterested() const {
- /**
- * len --- 1, 4bytes
- * id --- 2, 1byte
- * total: 5bytes
- */
- char msg[5];
- createNLengthMessage(msg, sizeof(msg), 1, 2);
- writeOutgoingMessageLog("interested");
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::sendNotInterested() const {
- /**
- * len --- 1, 4bytes
- * id --- 3, 1byte
- * total: 5bytes
- */
- char msg[5];
- createNLengthMessage(msg, sizeof(msg), 1, 3);
- writeOutgoingMessageLog("not interested");
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::sendHave(int index) const {
- /**
- * len --- 5, 4bytes
- * id --- 4, 1byte
- * piece index --- index, 4bytes
- * total: 9bytes
- */
- char msg[9];
- createNLengthMessage(msg, sizeof(msg), 5, 4);
- setIntParam(&msg[5], index);
- writeOutgoingMessageLog("have", index);
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::sendBitfield() const {
- int len = torrentMan->getBitfieldLength();
- const unsigned char* bitfield = torrentMan->getBitfield();
- /**
- * len --- 1+len, 4bytes
- * id --- 5, 1byte
- * bitfield --- bitfield, len bytes
- * total: 5+len bytes
- */
- int msgLen = 5+len;
- char* msg = new char[msgLen];
- try {
- createNLengthMessage(msg, msgLen, 1+len, 5);
- writeOutgoingMessageLog("bitfield", bitfield, len);
- socket->writeData(msg, msgLen);
- delete [] msg;
- } catch(Exception* ex) {
- delete [] msg;
- throw;
- }
-}
-
-void PeerConnection::sendRequest(int index, int begin, int length) const {
- /**
- * len --- 13, 4bytes
- * id --- 6, 1byte
- * index --- index, 4bytes
- * begin --- begin, 4bytes
- * length --- length, 4bytes
- * total: 17bytes
- */
- char msg[17];
- createNLengthMessage(msg, sizeof(msg), 13, 6);
- setIntParam(&msg[5], index);
- setIntParam(&msg[9], begin);
- setIntParam(&msg[13], length);
- writeOutgoingMessageLog("request", index, begin, length);
- socket->writeData(msg, sizeof(msg));
-}
-
-void PeerConnection::sendPiece(int index, int begin, int length) const {
- /**
- * len --- 9+length, 4bytes
- * id --- 7, 1byte
- * index --- index, 4bytes
- * begin --- begin, 4bytes
- * sub total: 13bytes
- * additionally,
- * block --- data, X bytes
- */
- char msg[13];
- createNLengthMessage(msg, sizeof(msg), 9+length, 7);
- setIntParam(&msg[5], index);
- setIntParam(&msg[9], begin);
- writeOutgoingMessageLog("piece", index, begin, length);
- socket->writeData(msg, sizeof(msg));
- int BUF_SIZE = 4096;
- char buf[BUF_SIZE];
- int iteration = length/BUF_SIZE;
- long long int pieceOffset = ((long long int)index*torrentMan->pieceLength)+begin;
- for(int i = 0; i < iteration; i++) {
- if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, pieceOffset+i*BUF_SIZE) < BUF_SIZE) {
- throw new DlAbortEx("piece reading failed.");
- }
- socket->writeData(buf, BUF_SIZE);
- }
- int rem = length%BUF_SIZE;
- if(rem > 0) {
- if(torrentMan->diskAdaptor->readData(buf, rem, pieceOffset+iteration*BUF_SIZE) < rem) {
- throw new DlAbortEx("piece reading failed.");
- }
- socket->writeData(buf, rem);
- }
-}
-
-void PeerConnection::sendPieceHeader(int index, int begin, int length) const {
- /**
- * len --- 9+length, 4bytes
- * id --- 7, 1byte
- * index --- index, 4bytes
- * begin --- begin, 4bytes
- * sub total: 13bytes
- * additionally,
- * block --- data, X bytes
- */
- char msg[13];
- createNLengthMessage(msg, sizeof(msg), 9+length, 7);
- setIntParam(&msg[5], index);
- setIntParam(&msg[9], begin);
- writeOutgoingMessageLog("piece", index, begin, length);
- socket->writeData(msg, sizeof(msg));
-}
-
-int PeerConnection::sendPieceData(long long int offset, int length) const {
- int BUF_SIZE = 256;
- char buf[BUF_SIZE];
- int iteration = length/BUF_SIZE;
+int PeerConnection::sendMessage(const char* msg, int length) {
int writtenLength = 0;
- bool isWritable = true;
- for(int i = 0; i < iteration; i++) {
- isWritable = socket->isWritable(0);
- if(!isWritable) {
- return writtenLength;
- }
- if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
- throw new DlAbortEx("piece reading failed.");
- }
- socket->writeData(buf, BUF_SIZE);
- writtenLength += BUF_SIZE;
- }
if(socket->isWritable(0)) {
- int rem = length%BUF_SIZE;
- if(rem > 0) {
- if(torrentMan->diskAdaptor->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) {
- throw new DlAbortEx("piece reading failed.");
- }
- socket->writeData(buf, rem);
- writtenLength += rem;
- }
+ socket->writeData(msg, length);
+ writtenLength += length;
}
return writtenLength;
}
-
-void PeerConnection::sendCancel(int index, int begin, int length) const {
- /**
- * len --- 13, 4bytes
- * id --- 8, 1byte
- * index --- index, 4bytes
- * begin --- begin, 4bytes
- * length -- length, 4bytes
- * total: 17bytes
- */
- char msg[17];
- createNLengthMessage(msg, sizeof(msg), 13, 8);
- setIntParam(&msg[5], index);
- setIntParam(&msg[9], begin);
- setIntParam(&msg[13], length);
- writeOutgoingMessageLog("cancel", index, begin, length);
- socket->writeData(msg, sizeof(msg));
-}
-
bool PeerConnection::receiveMessage(char* msg, int& length) {
if(!socket->isReadable(0)) {
return false;