From: <fon...@us...> - 2009-12-28 11:00:32
|
Revision: 5757 http://kmess.svn.sourceforge.net/kmess/?rev=5757&view=rev Author: fontknocker Date: 2009-12-28 11:00:09 +0000 (Mon, 28 Dec 2009) Log Message: ----------- General improvements. Add MessagePrivate::setBody() method; improve the logic in MsnChat::sendMessage() and MsnChat::isConnected(). Do not delete switchboard when all contacts leave the chat - we can reuse the object. Properly set the body of nudge messages so now they should work properly when sent. Modified Paths: -------------- trunk/kmess/lib/ChangeLog trunk/kmess/lib/include/KMess/message.h trunk/kmess/lib/src/connections/msnswitchboardconnection.cpp trunk/kmess/lib/src/connections/msnswitchboardconnection.h trunk/kmess/lib/src/messages/message.cpp trunk/kmess/lib/src/messages/message_p.cpp trunk/kmess/lib/src/messages/nudgemessage.cpp trunk/kmess/lib/src/msnchat.cpp Modified: trunk/kmess/lib/ChangeLog =================================================================== --- trunk/kmess/lib/ChangeLog 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/ChangeLog 2009-12-28 11:00:09 UTC (rev 5757) @@ -1,3 +1,17 @@ +2009-12-28 Adam Goossens <ad...@km...> + + * msnchat.cpp: Simplify sendMessage(), including the sending of offline IM and restarting switchboard. + Do not delete the switchboard when all contacts leave the chat - simply close the connection. Set + connectionState_ appropriately. + * msnchat.cpp: improve the logic in isConnected(). + * msnswitchboardconnection.cpp: Remove connectionClosed() signal; it was really a duplicate of disconnected(). + * message.cpp: Put in a catch for the application/x-msmsgsp2p mimetype, as well as a warning so we get to with + with the new P2P stack. + * message_p.cpp: Add setBody() method to set the application body. Also appends the \r\n to the body. + * nudgemessage.cpp: Add call to set the message body. + * msnswitchboardconnection.cpp: Improve the code flow in sendMessage(). Clear unacked messages when + starting a new switchboard connection. + 2009-12-23 Adam Goossens <ad...@km...> * Building on Diederik's work, Message classes are now implicitly Modified: trunk/kmess/lib/include/KMess/message.h =================================================================== --- trunk/kmess/lib/include/KMess/message.h 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/include/KMess/message.h 2009-12-28 11:00:09 UTC (rev 5757) @@ -84,6 +84,8 @@ bool hasField(const QString& field) const; // Parse the message into type, body, and fields and values void parseMessage( const QByteArray& message, bool &ok ); + // Set the body of the message. + void setBody( const QString& body ); // Set the P2P data of the message void setBinaryBody(const QByteArray &header, const QByteArray &body, const char footer[4]); // Split the message header and store it in the string list Modified: trunk/kmess/lib/src/connections/msnswitchboardconnection.cpp =================================================================== --- trunk/kmess/lib/src/connections/msnswitchboardconnection.cpp 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/src/connections/msnswitchboardconnection.cpp 2009-12-28 11:00:09 UTC (rev 5757) @@ -141,8 +141,6 @@ { disconnectFromServer(); - emit connectionClosed(); - debug() << "Session ended"; } @@ -567,6 +565,7 @@ debug() << "Connecting to" << ip << ":" << port << "in response to an user request"; // Store the authentication information, for the USR command + unAckedMessages_.clear(); isInvitationSession_ = false; authorization_ = authorization; @@ -589,6 +588,7 @@ debug() << "Connecting to" << ip << ":" << port << "in response to an invitation"; // Store the authentication information, for the USR command + unAckedMessages_.clear(); isInvitationSession_ = true; authorization_ = authorization; chatId_ = chatId; Modified: trunk/kmess/lib/src/connections/msnswitchboardconnection.h =================================================================== --- trunk/kmess/lib/src/connections/msnswitchboardconnection.h 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/src/connections/msnswitchboardconnection.h 2009-12-28 11:00:09 UTC (rev 5757) @@ -123,8 +123,6 @@ signals: // The switchboard is done authenticating and is ready to invite contacts. void connectionAuthenticated(); - // The switchboard has closed, all contacts have left - void connectionClosed(); // The switchboard is now connected void connectionOpened(); // The switchboard is ready to send messages Modified: trunk/kmess/lib/src/messages/message.cpp =================================================================== --- trunk/kmess/lib/src/messages/message.cpp 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/src/messages/message.cpp 2009-12-28 11:00:09 UTC (rev 5757) @@ -355,7 +355,8 @@ // Recognize known mimetypes, and clone this message into a specialized one. if( mimeType == "text/plain" ) { - if( tempMessage.field( "X-OIM-Message-Type" ) == "OfflineMessage" ) + if( tempMessage.hasField( "X-OIM-Message-Type" ) && + tempMessage.field( "X-OIM-Message-Type" ) == "OfflineMessage" ) { debug() << "Message is an offline message"; @@ -377,6 +378,8 @@ else if( mimeType == "text/x-msnmsgr-datacast" ) { + tempMessage.appendToHeader( tempMessage.body() ); + debug() << "Message is a datacast message of type" << tempMessage.field( "ID" ) << ", analyzing it..."; switch( tempMessage.field( "ID" ).toInt() ) @@ -430,7 +433,13 @@ debug() << "Message is a keepalive message, ignoring it"; } else + if ( mimeType == "application/x-msmsgsp2p" ) { + debug() << "Message is a Peer-to-Peer message; will be handled when P2P stack is complete."; + #warning TODO-P2P: Handle application/x-msmsgsp2p mimetype + } + else + { debug() << "Message is of unknown type!"; } Modified: trunk/kmess/lib/src/messages/message_p.cpp =================================================================== --- trunk/kmess/lib/src/messages/message_p.cpp 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/src/messages/message_p.cpp 2009-12-28 11:00:09 UTC (rev 5757) @@ -48,7 +48,8 @@ * Copy constructor for another MessagePrivate instance. */ MessagePrivate::MessagePrivate( const MessagePrivate &other ) - : body_( other.body_ ) + : QSharedData( other ) + , body_( other.body_ ) , header_ ( other.header_ ) , chat_ ( other.chat_ ) , confirmationMode_ ( other.confirmationMode_ ) @@ -240,10 +241,10 @@ QByteArray MessagePrivate::getMessage() const { QByteArray message( getFields() + "\r\n" + getBody() ); - + // for messages with an empty body must use two \r\n sequences. // This fixes typing notifications not showing in WLM 2009. - if( body_.isEmpty() ) + if( body_.isEmpty() || ! body_.endsWith( "\r\n" ) ) { message += "\r\n"; } @@ -372,6 +373,16 @@ +// Set the body of the message. The QString is converted +// to a UTF8-encoded QByteArray. +void MessagePrivate::setBody( const QString &body ) +{ + // don't forget the \r\n! + body_ = body.toUtf8() + "\r\n"; +} + + + // Set the P2P data of the message void MessagePrivate::setBinaryBody(const QByteArray &header, const QByteArray &body, const char footer[4]) { Modified: trunk/kmess/lib/src/messages/nudgemessage.cpp =================================================================== --- trunk/kmess/lib/src/messages/nudgemessage.cpp 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/src/messages/nudgemessage.cpp 2009-12-28 11:00:09 UTC (rev 5757) @@ -25,8 +25,10 @@ * Default constructor. */ NudgeMessage::NudgeMessage() -: Message( 0, DirectionOutgoing, 0, ConfirmNever, NudgeMessageType ) +: Message( 0, DirectionOutgoing, 0, ConfirmNever, NudgeMessageType, "text/x-msnmsgr-datacast" ) { + K_D(Message); + d->setBody("ID: 1"); } @@ -37,8 +39,10 @@ * Use it to create a nudge message. */ NudgeMessage::NudgeMessage( MsnChat* chat, MsnContact* peer ) -: Message( peer, DirectionOutgoing, chat, ConfirmNever, NudgeMessageType ) +: Message( peer, DirectionOutgoing, chat, ConfirmNever, NudgeMessageType, "text/x-msnmsgr-datacast" ) { + K_D(Message); + d->setBody("ID: 1"); } @@ -68,4 +72,3 @@ // delete d; } - Modified: trunk/kmess/lib/src/msnchat.cpp =================================================================== --- trunk/kmess/lib/src/msnchat.cpp 2009-12-26 23:19:45 UTC (rev 5756) +++ trunk/kmess/lib/src/msnchat.cpp 2009-12-28 11:00:09 UTC (rev 5757) @@ -60,6 +60,11 @@ , session_( session ) { debug() << "Creating chat"; + + offlineImService_ = new OfflineImService( session_, this ); + + connect( offlineImService_, SIGNAL( sendMessageFailed(QString,MimeMessage) ), + this, SIGNAL( sendingFailed(QString,MimeMessage) ) ); } @@ -74,6 +79,11 @@ delete switchboard_; } + if ( offlineImService_ ) + { + delete offlineImService_; + } + // Cleanup pending messages pendingMessages_.clear(); } @@ -88,7 +98,7 @@ */ void MsnChat::startConnecting() { - if( switchboard_ ) + if( isConnected() ) { return; } @@ -122,8 +132,8 @@ } // Connect the switchboard's signals - connect( switchboard_, SIGNAL( connectionClosed() ), - this, SLOT ( slotSwitchboardClosed() ) ); + connect( switchboard_, SIGNAL( disconnected() ), + this, SLOT ( slotSwitchboardClosed() ) ); connect( switchboard_, SIGNAL( connectionAuthenticated() ), this, SLOT ( slotInviteInitialContacts() ) ); connect( switchboard_, SIGNAL( connectionReady() ), @@ -251,6 +261,8 @@ // Now call the other user to the conversation. switchboard_->inviteContact( firstContact_ ); + connectionState_ = SB_INVITING_CONTACTS; + // If there are other pending invites, send them now foreach( const QString &handle, pendingInvitations_ ) { @@ -338,7 +350,10 @@ */ bool MsnChat::isConnected() const { - return switchboard_ != 0; + // we're connected if switchboard is valid, switchboard is connected and + return ( switchboard_ != 0 && + switchboard_->isConnected() && + connectionState_ != SB_DISCONNECTED ); } @@ -536,150 +551,71 @@ // Store the message pendingMessages_.append( message ); - // See what needs to be done to restore the chat. - if( isConnected() ) + // if we're still connected, but nobody is in the chat, + // try to re-invite somebody. + if ( isConnected() ) { - switch( connectionState_ ) + if ( message.hasField( "P2P-Dest" ) && message.field( "P2P-Dest" ) != lastContact_ ) { - case SB_AUTHORIZING: - // Connected but contacts are not in the chat yet. - // See if we need to invite the contacts - - debug() << "Already waiting for the connection to be authorized..."; - return; - - case SB_CONNECTING: - // Still waiting for a connection to the switchboard server. - // This condition verifies when we're connected but the USR has not been sent yet: - // without it, isConnected() returns true, so any unsent message gets sent before USR, causing a disconnection. - - debug() << "Already waiting for connection to establish..."; - return; - - case SB_INVITING_CONTACTS: - debug() << "Already waiting for contacts to join the chat..."; - return; - - default: - debug() << "Current state is: " << connectionState_; - -#warning TODO FIXME: cannot check this now, just assume only one left... - /* - if( contactsInChat_.count() > 1 ) - { - warning() << "failed to re-connect; multiple contacts are left in chat!"; - return; - } */ - - // Can't do this, either, so MsnChat will have to do this - /* - if( message.hasField("P2P-Dest") && message.getValue("P2P-Dest") != lastContact_ ) - { - debug() << "All contacts left the chat, calling the contact from the P2P-Dest field."; - connectionState_ = SB_INVITING_CONTACTS; - sendCommand( "CAL", message.getValue("P2P-Dest") ); - } - else - { - debug() << "All contacts left the chat, calling the last contact left."; - - if( lastContact_.isEmpty() ) - { - warning() << "Switchboard failed to re-connect; no contact left to invite!"; - return; - } - - connectionState_ = SB_INVITING_CONTACTS; - sendCommand( "CAL", lastContact_ ); - } */ - - break; + lastContact_ = message.field( "P2P-Dest" ); } - + + if ( lastContact_.isEmpty() ) + { + warning() << "Don't have last contact details; cannot restart switchboard."; + return; + } + + switchboard_->inviteContact( lastContact_ ); + connectionState_ = SB_INVITING_CONTACTS; return; - } // if( isConnected() ) + } - - // There is no active connection. - switch( connectionState_ ) + MsnContact *contact = session_->getContact( lastContact_ ); + + if ( connectionState_ != SB_DISCONNECTED ) { - case SB_REQUESTING_CHAT: - // The connection was closed, request a new one from the notification server. - // It's not possible to simply re-open it, because we need a new authcookie for the USR command. - - debug() << "Already waiting for MsnNotificationConnection to request a new chat..."; + // at this point if it's not disconnected it is somewhere + // in the process of re-establishing a SB session. so + // return from this method. once connection is established + // the pending messages will be sent. + return; + } + + KMESS_ASSERT( connectionState_ == SB_DISCONNECTED ); + + // No active connection. If the user is valid but offline, send an offline IM. + if ( contact && ! contact->isOnline() ) + { + // Send offline messages if the contact is not online + if( lastContact_.isEmpty() ) + { + warning() << "No last contact info: cannot find a contact to send offline messages to."; return; + } - case SB_CHAT_STARTED: - // Chat was open but the connection has been closed: - // this condition verifies in case of a network disconnect, when we've received a BYE or all contacts - // have left but the connection state has not been changed yet, and other similar improbable events. - // Simply restore it. - - debug() << "Connection was closed unexpectedly."; - - // Reset the connection's status - connectionState_ = SB_DISCONNECTED; - break; // Will run the connection reestablishment code below - - case SB_DISCONNECTED: + // Only send chat messages + if ( message.type() != TextMessageType ) { - // Send offline messages if the contact is not online - - if( lastContact_.isEmpty() ) - { - warning() << "Cannot find a contact to send offline messages to."; - return; - } - - MsnContact *contact = session_->getContact( lastContact_ ); - - // Only send the offline message if the contact definitely appears to be offline. - // If it's online, we'll just reestablish a switchboard connection to it. - if( ! contact || contact->isOnline() ) - { - debug() << "Not sending offline message to an" << (contact?"online":"unknown") << "contact."; - break; - } - - // Only send chat messages - const QString& contentType( message.field( "Content-Type" ) ); - if( ! contentType.startsWith( "text/plain" ) ) - { - debug() << "Ignoring message of type" << contentType << "in an offline messaging session."; - pendingMessages_.removeAll( message ); - return; - } - - debug() << "Sending offline message..."; - - // TODO: find a better code flow for this - // Only load the OIM service on demand - if( offlineImService_ == 0 ) - { - offlineImService_ = new OfflineImService( session_, this ); - - connect( offlineImService_, SIGNAL( sendMessageFailed(QString,MimeMessage) ), - this, SIGNAL( sendingFailed(QString,MimeMessage) ) ); - } - - // Send the message (only the text contained in the body) - offlineImService_->sendMessage( lastContact_, message.body() ); - - // The message has been sent as an OIM, remove it to avoid it - // being sent twice + debug() << "Ignoring message of type" << message.field("Content-Type") << "in an offline messaging session."; pendingMessages_.removeAll( message ); return; } - default: - // For other states, just try reestablishing a connection. + debug() << "Sending offline message to" << lastContact_; - break; - } // Switch for connectionState_ ends here + // Send the message (only the text contained in the body) + offlineImService_->sendMessage( lastContact_, message.body() ); + // The message has been sent as an OIM, remove it to avoid it + // being sent twice + pendingMessages_.removeAll( message ); + + // sent offline IM. + return; + } + debug() << "Connection is closed, requesting a new chat from the notification server..."; - KMESS_ASSERT( connectionState_ == SB_DISCONNECTED ); // Request a new switchboard session startConnecting(); @@ -1289,6 +1225,8 @@ participants_.clear(); } + connectionState_ = SB_DISCONNECTED; + emit disconnected(); } @@ -1508,7 +1446,7 @@ } } -#warning todo: +#warning TODO-P2P: MsnObject download of contacts who've joined chat. // TODO how and where do we do this (probably not automatically?): /* // Check whether the contact picture is outdated. @@ -1560,8 +1498,7 @@ // so startChat() needs to reconnect. // close the switchboard connection. - delete switchboard_; - switchboard_ = 0; + switchboard_->closeConnection(); } } @@ -1574,6 +1511,8 @@ { KMESS_ASSERT( switchboard_ != 0 ); + connectionState_ = SB_CHAT_STARTED; + // Send all pending messages sendPendingMessages(); @@ -1598,8 +1537,12 @@ // The requested chat session is available, connect to it void MsnChat::initiateSession( const QString &server, const quint16 &port, const QString &authorization ) { - createSwitchboardConnection(); - + // don't recreate it if it already exists + if ( switchboard_ == 0 ) + { + createSwitchboardConnection(); + } + if( switchboard_ == 0 ) { warning() << "Switchboard creation failed: unable to start the session!"; @@ -1607,7 +1550,10 @@ } // Initialize the switchboard as a user-requested chat + switchboard_->start( server, port, authorization ); + + connectionState_ = SB_CONNECTING; emit switchboardCreated(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |