Ticket #193: webcam-firststeps.patch
| File webcam-firststeps.patch, 56.4 kB (added by diederik, 4 months ago) |
|---|
-
network/applications/filetransferp2p.cpp
473 473 << ( usePreview ? "with thumbnail." : "without thumbnail." ); 474 474 #endif 475 475 476 // Create the short name477 uint shortNameLength = fileName_.length();478 479 476 // Get the file data (preview 480 477 ulong filesize = fileData->size(); 481 478 int flags = (hasPreview ? 0 : 1); … … 493 490 P2PMessage::insertBytes( context, flags, 16 ); // Field 4: 1 if NO preview data 494 491 495 492 // Field 5: the file name 496 const unsigned short * utf16Name = fileName_.utf16(); 497 int offset = 20; 498 for(uint i = 0; i < shortNameLength; ++i) 499 { 500 P2PMessage::insertShortBytes(context, utf16Name[i], offset); 501 offset += 2; 502 } 503 493 P2PMessage::insertUtf16String( context, fileName_, 20 ); 504 494 P2PMessage::insertBytes(context, 0xFFFFFFFF, 570); // Field 6: some splitter field. 505 495 506 496 // Insert preview data … … 836 826 } 837 827 838 828 829 839 830 /** 840 831 * @brief Called when the thumbnail is generated. 841 832 */ … … 843 834 { 844 835 bool hasPreview = thumbnailProvider_->isSuccessful(); 845 836 846 // Create the session id and context field847 QString context = createContextField( file_, hasPreview );848 uint sessionID = (uint)KMessShared::generateID();849 850 837 // Send the invitation 851 sendSlpSessionInvitation(sessionID, getAppId(), 2, context); 838 QString context = createContextField( file_, hasPreview ); 839 sendSlpSessionInvitation( KMessShared::generateID(), getAppId(), 2, context ); 852 840 853 854 841 // Generate the HTML to cancel the transfer 855 842 QString html = i18n( "Sending file "%1" (%2).", 856 843 "<span class=\"filename invitationFilename\">" + fileName_ + "</span>", -
network/applications/p2papplicationbase.cpp
286 286 } 287 287 288 288 // Also attempt to match on the messageID alone if: 289 // - it's a 0x80 message. In this case sendP2PMessage () has overwritten the previous uniqueID.289 // - it's a 0x80 message. In this case sendP2PMessageImpl() has overwritten the previous uniqueID. 290 290 // - the UniqueID is not set. (also happens with normal ack messages in GAIM 1.5). 291 291 // 292 292 // This happens with 0x01 control messages: … … 863 863 shouldSendAck_ = true; 864 864 gotDataPreparation(p2pMessage); 865 865 } 866 // Check for data messages867 else if( p2pMessage.isMsnObjectData()868 || p2pMessage.isFileData())866 // Check for normal data messages 867 else if( p2pMessage.isMsnObjectData() 868 || p2pMessage.isFileData()) 869 869 { 870 870 gotDataFragment(p2pMessage); 871 871 } 872 else if( waitingState_ == P2P_WAIT_FOR_FILE_DATA873 && p2pMessage.getFlags() == 0874 && p2pMessage.isFragment())872 else if( waitingState_ == P2P_WAIT_FOR_FILE_DATA 873 && p2pMessage.getFlags() == 0 874 && p2pMessage.isFragment()) 875 875 { 876 876 // HACK: added for Kopete 0.9.2 code (has no flag set with data messages). 877 877 kWarning() << "Expecting data message, " … … 882 882 " class=" << metaObject()->className() << ")!"; 883 883 gotDataFragment(p2pMessage); 884 884 } 885 else if( p2pMessage.getFlags() == 0 886 && p2pMessage.getDataSize() >= 18 887 && (quint8) ( p2pMessage.getData()[0] ) == 0x80 ) 888 { 889 // Webcam setup. Even WLM sends then without flags. 890 // At the switchboard the "footercode" is set to 4. 891 // Pass it to the WebcamTransferP2P class to deal with it. 892 // Not using gotDataFragment() here because it will check if everything is received. 893 gotData( p2pMessage ); 894 } 885 895 else 886 896 { 887 897 // Unknown p2p message … … 1187 1197 // Reserve the next message ID. 1188 1198 nextMessageID_++; 1189 1199 1190 // Set the total size field, this causes sendP2PMessage ()1200 // Set the total size field, this causes sendP2PMessageImpl() 1191 1201 // to handle fragmented messages correctly. 1192 1202 // The 'fragmentMessageID_' is set so KMess sends all fragments with the same message ID. 1193 1203 // It could happen the client receives a SLP ACK meanwhile, and ACKs it with a new message ID. … … 1220 1230 1221 1231 // TODO: Check the various footer codes send for certain transfers. 1222 1232 QByteArray p2pMessage( 4, 0x00 ); 1223 sendP2PMessage (p2pMessage, 0, 1, P2P_MSG_DATA_PREPARATION);1233 sendP2PMessageImpl( p2pMessage, 0, P2P_TYPE_PICTURE, P2P_MSG_DATA_PREPARATION ); 1224 1234 1225 1235 // TODO: after the data preparation is sent, WLM8 starts a direct connection setup: 1226 1236 // - it does not send an ACK yet … … 1373 1383 << " buffer=" << bytesRead; 1374 1384 #endif 1375 1385 1376 // Determine the progress value now because mesageOffset_ it reset by the last sendP2PMessage () call.1386 // Determine the progress value now because mesageOffset_ it reset by the last sendP2PMessageImpl() call. 1377 1387 unsigned long nextProgressValue = ( fragmentOffset_ + bytesRead ); 1378 1388 1379 1389 // Determine the flags: 1380 1390 // Funny, MSN6 doesn't seam to care which flag was set 1381 1391 // while transferring the file. KMess however, does. 1382 bool writeSuccess = false;1392 uint flag = 0; 1383 1393 switch( dataType_ ) 1384 1394 { 1385 case P2P_TYPE_PICTURE: 1386 writeSuccess = sendP2PMessage( data, P2PMessage::MSN_FLAG_OBJECT_DATA, 1, P2P_MSG_DATA, fragmentMessageID_ ); 1387 break; 1388 1389 case P2P_TYPE_FILE: 1390 writeSuccess = sendP2PMessage( data, P2PMessage::MSN_FLAG_FILE_DATA, 2, P2P_MSG_DATA, fragmentMessageID_ ); 1391 break; 1392 1395 case P2P_TYPE_PICTURE: flag = P2PMessage::MSN_FLAG_OBJECT_DATA; break; 1396 case P2P_TYPE_FILE: flag = P2PMessage::MSN_FLAG_FILE_DATA; break; 1393 1397 default: 1394 1398 // Display error message for the first message only. 1395 1399 if( fragmentOffset_ == 0 ) … … 1401 1405 " class=" << metaObject()->className() << 1402 1406 " action=tryflag)."; 1403 1407 } 1404 1405 writeSuccess = sendP2PMessage( data, 0, 1, P2P_MSG_DATA, fragmentMessageID_ ); // The best solution in this situation1406 1408 } 1407 1409 1410 // Send the message 1411 bool writeSuccess = sendP2PMessageImpl( data, flag, dataType_, P2P_MSG_DATA, fragmentMessageID_ ); 1412 1408 1413 // Avoid next round if write was blocked already. 1409 1414 // This could happen if a direct connection can't write all data. 1410 1415 // The DirectConnectionBase class will automatically send the remaining parts, so don't worry about that here. … … 1524 1529 1525 1530 1526 1531 /** 1527 * @brief Send a P2P ACK message.1532 * @brief Internal function to send a P2P ACK message. 1528 1533 * 1529 1534 * This method is the internal implementation for sendP2PAck() and others. 1530 1535 * … … 1693 1698 1694 1699 1695 1700 /** 1696 * @brief Sends a P2P Message.1701 * @brief Sends a complete P2P message payload. 1697 1702 * 1703 * It splits the data message into chunks which fit in the individual P2P messages. 1704 * 1705 * If you need to send data, use sendData() instead. 1706 * This method is stream based, and also takes care of state changes. 1707 * 1708 * @param messageData The message payload to send. 1709 * @param flagField The value for the flag field in the P2P header. 1710 * @param footerCode The message footer, which is appended when the message is sent over the switchboard. 1711 * @param messageType The type of the message. This value is returned with gotAck(). 1712 */ 1713 void P2PApplicationBase::sendP2PMessage(const QByteArray &messageData, int flagField, P2PDataType footerCode, P2PMessageType messageType) 1714 { 1715 // Make sure the message gets sent in chunks of 1202 bytes. 1716 // Only set fragmentTotalSize_ if there are chunks, for useless debug messages. 1717 int remainingBytes = messageData.size(); 1718 fragmentOffset_ = 0; 1719 fragmentTotalSize_ = ( remainingBytes <= 1202 ? 0 : remainingBytes ); 1720 1721 do 1722 { 1723 // Let another QByteArray encapsulate a part of the utf8Message 1724 const char *dataPointer = messageData.data() + fragmentOffset_; 1725 uint dataSize = qMin( remainingBytes, 1202 ); 1726 QByteArray messagePart = QByteArray::fromRawData( dataPointer, dataSize ); 1727 1728 // Send the message with the generic sendP2PMessageImpl() method 1729 // fragmentOffset_ is updated automatically 1730 sendP2PMessageImpl( messagePart, flagField, footerCode, messageType ); 1731 remainingBytes -= dataSize; 1732 1733 #ifdef KMESSTEST 1734 KMESS_ASSERT( (uint) remainingBytes == fragmentTotalSize_ - fragmentOffset_ ); 1735 #endif 1736 } 1737 while( remainingBytes > 0 ); 1738 1739 // Reset for normal operations 1740 fragmentOffset_ = 0; 1741 fragmentTotalSize_ = 0; 1742 } 1743 1744 1745 1746 /** 1747 * @brief Internal function to send a single P2P message. 1748 * 1698 1749 * This method constructs the P2P binary header fields. 1699 1750 * The constructed message is delivered to ApplicationList::sendMessage(). 1700 1751 * … … 1705 1756 * - outgoingMessages_ is updated to trace ACKs back later. 1706 1757 * 1707 1758 * The fragmentTotalSize_ should be set to the total size before sending message fragments. 1708 * This is done automatically by send SlpMessage().1759 * This is done automatically by sendP2PMessage() function, which is part of the public API. 1709 1760 * 1710 1761 * @param messageData The message payload to send. This can be binary file data or a SLP MIME data. 1711 1762 * @param flagField The value for the flag field in the P2P header. 1712 1763 * @param footerCode The message footer, which is appended when the message is sent over the switchboard. 1713 1764 * @param messageType The type of the message. This value is stored with in the unacked message queue. 1714 1765 * This value is used later to respond to ACKs of certain special messages. 1715 * @param messageID Optional message ID to enforce. If nothing is selected, the next available message ID will be used automatically. 1766 * @param messageID Optional message ID to enforce. If nothing is selected, 1767 * the next available message ID will be used automatically. 1768 * This parameter is used to send file data with a specific message ID. 1716 1769 * @return Whether the message can be sent. If the socket would block, false is returned. 1717 1770 * This only occurs for direct connections connections. 1718 1771 */ 1719 bool P2PApplicationBase::sendP2PMessage (const QByteArray &messageData, int flagField, uintfooterCode, P2PMessageType messageType, unsigned long messageID)1772 bool P2PApplicationBase::sendP2PMessageImpl(const QByteArray &messageData, int flagField, P2PDataType footerCode, P2PMessageType messageType, unsigned long messageID) 1720 1773 { 1721 1774 #ifdef KMESSTEST 1722 1775 KMESS_ASSERT( messageData.size() <= 1202 ); … … 1762 1815 1763 1816 1764 1817 // Determine the message size: 1818 // Internal trick: fragmentTotalSize_ is set by the caller if this is a splitted message. 1765 1819 uint messageSize = messageData.size(); 1766 1820 ulong totalSize; 1767 1821 ulong offsetField; … … 1786 1840 // Set session ID to zero when SLP messages are sent. 1787 1841 unsigned long sessionID = getSessionID(); 1788 1842 if( flagField == 0 1789 && messageType != P2P_MSG_DATA_PREPARATION ) 1843 && messageType != P2P_MSG_DATA_PREPARATION 1844 && messageType != P2P_MSG_WEBCAM_SETUP ) // HACK! to fix this we need to pass messages as 'P2PMessage'. 1790 1845 { 1791 1846 sessionID = 0; 1792 1847 } … … 1804 1859 1805 1860 1806 1861 // Deliver the message over the correct link (switchboard or direct connection) 1807 bool writeSuccess = applicationList_->sendMessage( this, header, messageData, footerCode );1862 bool writeSuccess = applicationList_->sendMessage( this, header, messageData, (uint) footerCode ); 1808 1863 if( ! writeSuccess ) 1809 1864 { 1810 1865 // This only happens when a direct connection transfer is congested. … … 1896 1951 */ 1897 1952 void P2PApplicationBase::sendP2PWaitingError() 1898 1953 { 1899 sendP2PMessage (0, P2PMessage::MSN_FLAG_WAITING, 0);1954 sendP2PMessageImpl( 0, P2PMessage::MSN_FLAG_WAITING ); 1900 1955 shouldSendAck_ = false; 1901 1956 } 1902 1957 … … 1905 1960 /** 1906 1961 * @brief Send a complete SLP message in multiple P2P packets. 1907 1962 * 1908 * It splits the SLP message into chunks which fit in the P2P payload.1909 * Each part will be sent with sendP2PMessage().1910 * The messages always have a Session ID of zero.1911 *1912 1963 * This is a low-level function which is primary used by 1913 1964 * P2PApplication::sendSlpInvitation(), P2PApplication::sendSlpBye(), etc.. 1914 1965 * 1966 * It converts the SLP string to the payload data, 1967 * which could be splitted across multiple P2P messages. 1968 * 1915 1969 * @param slpMessage The whole SLP message to send, including SLP headers. 1916 * @param messageType The type of the message , used to trace ACK messages back later.1970 * @param messageType The type of the message. This value is returned with gotAck(). 1917 1971 */ 1918 1972 void P2PApplicationBase::sendSlpMessage(const QString &slpMessage, P2PMessageType messageType) 1919 1973 { … … 1928 1982 // Make sure the extra padded '\0' character is there. MSN 6-WLM rely on this. 1929 1983 utf8Message.append('\0'); 1930 1984 1931 // Make sure the message gets sent in chunks of 1202 bytes. 1932 // Only set fragmentTotalSize_ if there are chunks, for useless debug messages. 1933 int remainingBytes = utf8Message.size(); 1934 fragmentOffset_ = 0; 1935 fragmentTotalSize_ = ( remainingBytes <= 1202 ? 0 : remainingBytes ); 1936 1937 do 1938 { 1939 // Let another QByteArray encapsulate a part of the utf8Message 1940 char *dataPointer = utf8Message.data() + fragmentOffset_; 1941 uint dataSize = qMin(remainingBytes, 1202); 1942 messagePart = QByteArray::fromRawData( dataPointer, dataSize ); 1943 1944 // Send the message with the generic sendP2PMessage() method 1945 // fragmentOffset_ is updated automatically 1946 sendP2PMessage(messagePart, 0, 0, messageType); 1947 remainingBytes -= dataSize; 1948 1949 #ifdef KMESSTEST 1950 KMESS_ASSERT( (uint) remainingBytes == fragmentTotalSize_ - fragmentOffset_ ); 1951 #endif 1952 } 1953 while(remainingBytes > 0); 1954 1955 // Reset for normal operations 1956 fragmentOffset_ = 0; 1957 fragmentTotalSize_ = 0; 1985 sendP2PMessage( utf8Message, 0, P2P_TYPE_NEGOTIATION, messageType ); // will split the message. 1958 1986 } 1959 1987 1960 1988 … … 2137 2165 } 2138 2166 2139 2167 // Send the message 2140 sendP2PMessage (0, waitFlag, 0); // TODO: pass the original message which is unacked!!2168 sendP2PMessageImpl(0, waitFlag, 0); // TODO: pass the original message which is unacked!! 2141 2169 */ 2142 2170 testUnAckedMessages( true ); // TODO: argument is not used, and replaces sendP2PWaitingError(). 2143 2171 -
network/applications/webapplicationp2p.cpp
82 82 // int realAppID = appID.mid(4, 4).toInt(); 83 83 84 84 // Parse the context 85 context += "===="; // Make sure the base64 encoded string is null padded to avoid problems with QString::fromUtf16().85 // Contents is something like '10331021;1;Tic Tac Toe' 86 86 QByteArray decodedContext = QByteArray::fromBase64( context.toLatin1() ); 87 QString contextString = QString::fromUtf16( reinterpret_cast<const ushort*>( decodedContext.data() ), decodedContext.size() / 2 ); 87 88 88 // Contents is something like '10331021;1;Tic Tac Toe'89 QString contextString = QString::fromUtf16( reinterpret_cast<const ushort*>( decodedContext.data() ), decodedContext.size() / 2 );90 91 89 // Get the fields 92 90 QString unknown = contextString.section(';', 1, 1); 93 91 QString appName = contextString.section(';', 2, 2); -
network/applications/p2papplication.cpp
2787 2787 2788 2788 #ifdef KMESSTEST 2789 2789 // Test, as other invocations likely result in undefined client behavour 2790 // (2791 2790 KMESS_ASSERT( gotSlpMessage_ ); 2792 KMESS_ASSERT( isWaitingState( P2P_WAIT_DEFAULT ) );2791 KMESS_ASSERT( isWaitingState( P2P_WAIT_DEFAULT ) || isWaitingState( P2P_WAIT_USER_ACCEPT ) ); 2793 2792 KMESS_ASSERT( ! callID_.isEmpty() ); 2794 2793 KMESS_ASSERT( ! branch_.isEmpty() ); 2795 2794 #endif -
network/applications/p2papplicationbase.h
228 228 P2P_MSG_DATA = 5, ///< The actual data message. 229 229 P2P_MSG_SESSION_BYE = 6, ///< The SLP BYE message. 230 230 P2P_MSG_TRANSFER_DECLINE = 7, ///< The SLP 603 Decline message. 231 P2P_MSG_SLP_ERROR = 8 ///< One of the possible SLP error messages. 231 P2P_MSG_SLP_ERROR = 8, ///< One of the possible SLP error messages. 232 P2P_MSG_WEBCAM_SETUP = 8 ///< One of the possible webcam setup messages. 232 233 }; 233 234 234 235 /** … … 242 243 , P2P_TYPE_PICTURE = 1 ///< Packet contains MsnObject data. 243 244 , P2P_TYPE_FILE = 2 ///< Packet contains file data. 244 245 , P2P_TYPE_INK = 3 ///< Packet contains an Ink message. 246 , P2P_TYPE_WEBCAM = 4 ///< Packet contains a webcam setup message. 245 247 }; 246 248 247 249 /** … … 260 262 P2P_WAIT_DEFAULT = 0, ///< Not waiting at all. 261 263 P2P_WAIT_FOR_SLP_OK_ACK = 1, ///< Waiting for remote client to ack the the SLP OK message. 262 264 P2P_WAIT_FOR_FILE_DATA = 2, ///< Waiting for remote client to send file data. 265 P2P_WAIT_FOR_WEBCAM_DATA = 19, ///< Waiting for remote client to send webcam invite data. 263 266 P2P_WAIT_FOR_PREPARE = 3, ///< Waiting for remote client to send some prepare message. 264 267 P2P_WAIT_FOR_PREPARE_ACK = 4, ///< Waiting for remote client to ack the data preparation. 265 268 P2P_WAIT_FOR_SLP_BYE = 5, ///< Waiting for remote client to send the SLP BYE. … … 332 335 void sendP2PAbort(); 333 336 // Send an low-level ACK message for a received message if this is needed. 334 337 bool sendP2PAck(); 338 // Send a low-level P2P data message 339 void sendP2PMessage(const QByteArray &messageData, int flagField = 0, P2PDataType footerCode = P2P_TYPE_NEGOTIATION, P2PMessageType messageType = P2P_MSG_UNKNOWN); 335 340 // Send a low-level error message that the application is waiting for a certain message. 336 341 void sendP2PWaitingError(); 337 342 // Send a given string using sendP2PMessage() … … 384 389 // Send a P2P ACK message 385 390 void sendP2PAckImpl(int ackType = P2PMessage::MSN_FLAG_ACK, UnAckedMessage *originalMessageData = 0); 386 391 // Send a P2P message 387 bool sendP2PMessage (const QByteArray &messageData, int flagField = 0, uint footerCode = 0, P2PMessageType messageType = P2P_MSG_UNKNOWN, unsigned long messageID = 0);392 bool sendP2PMessageImpl(const QByteArray &messageData, int flagField = 0, P2PDataType footerCode = P2P_TYPE_NEGOTIATION, P2PMessageType messageType = P2P_MSG_UNKNOWN, unsigned long messageID = 0); 388 393 // Test if there are still unacked messages. 389 394 void testUnAckedMessages(bool sendError); 390 395 -
network/applications/webcamtransferp2p.cpp
18 18 #include "webcamtransferp2p.h" 19 19 20 20 #include "../../kmessdebug.h" 21 #include "../../utils/kmessshared.h" 21 22 #include "../mimemessage.h" 22 23 23 24 #include <KLocale> 25 #include <stdlib.h> // rand() 24 26 25 27 28 // 29 // I'd like to have many thanks to the Kopete developers here, 30 // without them writing this code would have been a lot harder. 31 // Especially since all webcam online docs seam to be gone. 32 // 26 33 34 35 36 27 37 /** 28 38 * Constructor 29 39 * … … 31 41 */ 32 42 WebcamTransferP2P::WebcamTransferP2P(ApplicationList *applicationList) 33 43 : P2PApplication(applicationList) 44 , isUserSender_(false) 34 45 { 35 46 setApplicationType( ChatMessage::TYPE_APPLICATION_WEBCAM ); 36 47 } … … 63 74 * 64 75 * @param message The invitation message 65 76 */ 66 void WebcamTransferP2P::contactStarted1_ContactInvitesUser(const MimeMessage & /*message*/)77 void WebcamTransferP2P::contactStarted1_ContactInvitesUser(const MimeMessage & message) 67 78 { 68 #ifdef KMESSDEBUG_WEB APPLICATION_P2P79 #ifdef KMESSDEBUG_WEBCAMTRANSFER_P2P 69 80 kDebug(); 70 81 #endif 71 82 72 #if 0 73 QString appID = message.getValue("AppID");74 QString eufGuid = message.getValue("EUF-GUID");75 QString context = message.getValue("Context");83 // Read the values from the message 84 uint appID = message.getValue("AppID").toUInt(); 85 QString eufGuid = message.getValue("EUF-GUID"); 86 QString context = message.getValue("Context"); 76 87 77 // Parse the context 78 context += "===="; // Make sure the base64 encoded string is null padded to avoid problems with QString::fromUtf16(). 79 QByteArray decodedContext; 80 KCodecs::base64Decode(context.utf8(), decodedContext); 88 if(appID != 4) 89 { 90 kWarning() << "Received unexpected AppID: " << appID << "."; 81 91 82 // Contents is another GUID 83 QString contextString = QString::fromUtf16( reinterpret_cast<const unsigned short*>(decodedContext.data()) ); 92 // Wouldn't know what to do if the AppID is not 2, so send an 500 Internal Error back. 93 showEventMessage( i18n("The webcam invitation was cancelled. Bad data was received."), ChatMessage::CONTENT_APP_CANCELED, true ); 94 sendCancelMessage( CANCEL_ABORT ); 95 return; 96 } 97 98 // Contact can request a webcam from us, or share it's own webcam. 99 isUserSender_ = ( eufGuid == getPullAppId() ); 100 101 // Parse the context, it contains another GUI 102 QByteArray decodedContext = QByteArray::fromBase64( context.toLatin1() ); 103 webcamGuid_ = P2PMessage::extractUtf16String( decodedContext.data(), 0, decodedContext.size() ); 104 105 // Display the accept message. 106 #ifdef KMESSDEBUG_WEBCAMTRANSFER_P2P 107 kDebug() << "Webcam invitation received, GUID=" << webcamGuid_ << endl; 108 kDebug() << "waiting for user to accept..." << endl; 84 109 #endif 85 110 86 // KMess does not support the webapplication invitations yet, 87 // this class is currently a STUB to produce a proper error message 88 showSystemMessage( i18n( "The contact is inviting you for '%1', but this is not implemented yet.", 89 i18n("webcam") ), 90 ChatMessage::CONTENT_SYSTEM_NOTICE, true ); 111 offerAcceptOrReject( i18n("You are invited to view this person's webcam.") ); 112 } 91 113 92 // Tell the contact we don't support this.93 sendCancelMessage(CANCEL_NOT_INSTALLED);94 114 95 // // Everything seams OK, accept this message: 96 // contactStarted2_UserAccepts(); 115 116 /** 117 * Step two of a contact-started chat: the user accepts 118 */ 119 void WebcamTransferP2P::contactStarted2_UserAccepts() 120 { 121 #ifdef KMESSDEBUG_FILETRANSFER_P2P 122 kDebug() << "sending accept message"; 123 #endif 124 125 // Create the message 126 MimeMessage message; 127 message.addField( "SessionID", QString::number( getInvitationSessionID() ) ); 128 129 // Send the message 130 sendSlpOkMessage(message); 131 setWaitingState( P2P_WAIT_FOR_WEBCAM_DATA, 120000 ); // 120 seconds 97 132 } 98 133 99 134 100 135 136 101 137 /** 138 * Step three of a contact-started chat: the contact confirms the accept 139 */ 140 void WebcamTransferP2P::contactStarted3_ContactConfirmsAccept(const MimeMessage& /*message*/) 141 { 142 #ifdef KMESSDEBUG_WEBCAMTRANSFER_P2P 143 kDebug(); 144 #endif 145 146 // The invitation continues with the gotData() call. 147 } 148 149 150 151 /** 152 * Create the producer or viewer XML tag. 153 */ 154 QString WebcamTransferP2P::createSipXml( uint session, uint rid ) 155 { 156 QString rootNode = ( isUserSender_ ? "producer" : "viewer" ); 157 158 QString ipTags = "<tcpipaddress1>10.0.0.1</tcpipaddress1>"; 159 160 /* 161 uint ip_number=1; 162 QStringList::iterator it; 163 QStringList ips=m_dispatcher->localIp(); 164 for ( it = ips.begin(); it != ips.end(); ++it ) 165 { 166 ip+=QString("<tcpipaddress%1>%2</tcpipaddress%3>").arg(ip_number).arg(*it).arg(ip_number); 167 ++ip_number; 168 } 169 170 //QString port = QString::number(getAvailablePort()); 171 //m_listener = new KServerSocket(port, this) ; 172 */ 173 174 int port = 0; 175 176 return "<" + rootNode + ">" 177 "<version>2.0</version>" 178 "<rid>" + QString::number( rid ) + "</rid>" 179 "<udprid>" + QString::number( rid + 1 ) + "</udprid>" 180 "<session>" + QString::number( session ) + "</session>" 181 "<ctypes>0</ctypes>" 182 "<cpu>2931</cpu>" 183 "<tcp>" 184 "<tcpport>7786</tcpport>" // "\t\t\t\t\t\t\t\t " 185 "<tcplocalport>7786</tcplocalport>" // "\t\t\t\t\t\t\t\t " 186 "<tcpexternalport>7786</tcpexternalport>" + ipTags + 187 "</tcp>" 188 "<udp>" 189 "<udplocalport>7786</udplocalport>" 190 "<udpexternalport>31863</udpexternalport>" 191 "<udpexternalip>" + ipTags + "</udpexternalip>" 192 "<a1_port>31859</a1_port>" 193 "<b1_port>31860</b1_port>" 194 "<b2_port>31861</b2_port>" 195 "<b3_port>31862</b3_port>" 196 "<symmetricallocation>1</symmetricallocation>" 197 "<symmetricallocationincrement>1</symmetricallocationincrement>" 198 "<udpversion>1</udpversion>" 199 "<udpinternalipaddress1>127.0.0.1</udpinternalipaddress1>" 200 "</udp>" 201 "<codec></codec>" 202 "<channelmode>1</channelmode>" 203 "</" + rootNode + ">\r\n\r\n"; 204 } 205 206 207 208 /** 209 * Return the application's GUID for "video conference" invitations. 210 */ 211 QString WebcamTransferP2P::getConferenceAppId() 212 { 213 return "{4BD96FC0-AB17-4425-A14A-439185962DC8}"; 214 } 215 216 217 218 /** 102 219 * Return the application's GUID for "user push" invitations. 103 220 */ 104 221 QString WebcamTransferP2P::getPushAppId() … … 117 234 } 118 235 119 236 237 238 /** 239 * Called when SIP data is received. 240 * This is the second stage of the webcam invitation. 241 * 242 * @param message P2P message with the data. 243 */ 244 void WebcamTransferP2P::gotData(const P2PMessage &message) 245 { 246 bool contactStarted = ( ! isUserStartedApp() ); 247 QString contents = P2PMessage::extractUtf16String( message.getData(), 10, message.getDataSize() - 10 ); 248 249 #ifdef KMESSDEBUG_FILETRANSFER_P2P 250 kDebug() << "received setup data:" << contents; 251 #endif 252 253 sendP2PAck(); 254 255 // Find out what to do. 256 if( contents == "syn" ) 257 { 258 if( contactStarted ) 259 { 260 sendSipMessage("syn", 0x17,0x2a,0x01); 261 } 262 else 263 { 264 sendSipMessage("ack", 0xea,0x00,0x00); 265 } 266 } 267 else if( contents == "ack" ) 268 { 269 if( contactStarted ) 270 { 271 sendSipMessage("ack", 0xea,0x00,0x00); 272 } 273 274 // Send the <producer> message 275 if( isUserSender_ ) 276 { 277 uint session = rand() % 1000 + 5000; 278 uint rid = rand() % 100 + 50; 279 authentication_ = "recipientid=" + QString::number( rid ) + "&sessionid=" + QString::number( session ) + "\r\n\r\n"; 280 QString producerXml = createSipXml( session, rid ); 281 sendSipMessage( producerXml, 0, 0, 0 ); 282 } 283 } 284 else if( contents.startsWith("<") ) 285 { 286 // XML. 287 } 288 else 289 { 290 sendP2PAbort(); 291 } 292 } 293 294 295 296 /** 297 * Send a webcam negotiation message
