summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/AdHoc/OutgoingAdHocCommandSession.cpp102
-rw-r--r--Swiften/AdHoc/OutgoingAdHocCommandSession.h88
-rw-r--r--Swiften/AdHoc/SConscript6
-rw-r--r--Swiften/Avatars/AvatarFileStorage.cpp104
-rw-r--r--Swiften/Avatars/AvatarFileStorage.h41
-rw-r--r--Swiften/Avatars/AvatarManager.h2
-rw-r--r--Swiften/Avatars/AvatarProvider.h3
-rw-r--r--Swiften/Avatars/AvatarStorage.h2
-rw-r--r--Swiften/Avatars/SConscript1
-rw-r--r--Swiften/Avatars/VCardAvatarManager.h3
-rw-r--r--Swiften/Base/ByteArray.cpp45
-rw-r--r--Swiften/Base/ByteArray.h34
-rw-r--r--Swiften/Base/IDGenerator.h5
-rw-r--r--Swiften/Base/Paths.cpp6
-rw-r--r--Swiften/Base/Paths.h2
-rw-r--r--Swiften/Base/Platform.h9
-rw-r--r--Swiften/Base/String.h1
-rw-r--r--Swiften/Base/UnitTest/ByteArrayTest.cpp29
-rw-r--r--Swiften/Base/foreach.h5
-rw-r--r--Swiften/Base/format.h1
-rw-r--r--Swiften/Base/sleep.h5
-rw-r--r--Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp1
-rw-r--r--Swiften/Client/Client.cpp8
-rw-r--r--Swiften/Client/Client.h8
-rw-r--r--Swiften/Client/ClientOptions.h39
-rw-r--r--Swiften/Client/ClientSession.cpp2
-rw-r--r--Swiften/Client/ClientSession.h5
-rw-r--r--Swiften/Client/ClientSessionStanzaChannel.cpp1
-rw-r--r--Swiften/Client/ClientXMLTracer.cpp31
-rw-r--r--Swiften/Client/ClientXMLTracer.h20
-rw-r--r--Swiften/Client/CoreClient.cpp58
-rw-r--r--Swiften/Client/CoreClient.h93
-rw-r--r--Swiften/Client/DummyStanzaChannel.h16
-rw-r--r--Swiften/Client/FileStorages.cpp39
-rw-r--r--Swiften/Client/FileStorages.h50
-rw-r--r--Swiften/Client/MemoryStorages.cpp8
-rw-r--r--Swiften/Client/MemoryStorages.h2
-rw-r--r--Swiften/Client/NickResolver.h2
-rw-r--r--Swiften/Client/Storages.cpp12
-rw-r--r--Swiften/Client/Storages.h4
-rw-r--r--Swiften/Component/ComponentSessionStanzaChannel.cpp1
-rw-r--r--Swiften/Component/ComponentXMLTracer.cpp31
-rw-r--r--Swiften/Component/ComponentXMLTracer.h20
-rw-r--r--Swiften/Component/CoreComponent.cpp1
-rw-r--r--Swiften/Component/SConscript1
-rw-r--r--Swiften/Compress/ZLibCompressor.cpp2
-rw-r--r--Swiften/Compress/ZLibCompressor.h2
-rw-r--r--Swiften/Compress/ZLibDecompressor.cpp2
-rw-r--r--Swiften/Compress/ZLibDecompressor.h2
-rw-r--r--Swiften/Config/swiften-config.cpp1
-rw-r--r--Swiften/Disco/CapsFileStorage.cpp61
-rw-r--r--Swiften/Disco/CapsFileStorage.h28
-rw-r--r--Swiften/Disco/CapsManager.cpp1
-rw-r--r--Swiften/Disco/DummyEntityCapsProvider.cpp21
-rw-r--r--Swiften/Disco/DummyEntityCapsProvider.h10
-rw-r--r--Swiften/Disco/GetDiscoItemsRequest.h9
-rw-r--r--Swiften/Disco/SConscript2
-rw-r--r--Swiften/Elements/Body.h5
-rw-r--r--Swiften/Elements/Bytestreams.h2
-rw-r--r--Swiften/Elements/CapsInfo.h2
-rw-r--r--Swiften/Elements/ChatState.h1
-rw-r--r--Swiften/Elements/Command.h2
-rw-r--r--Swiften/Elements/ComponentHandshake.h2
-rw-r--r--Swiften/Elements/Delay.h2
-rw-r--r--Swiften/Elements/DiscoInfo.cpp7
-rw-r--r--Swiften/Elements/DiscoInfo.h9
-rw-r--r--Swiften/Elements/DiscoItems.h3
-rw-r--r--Swiften/Elements/Element.h5
-rw-r--r--Swiften/Elements/ErrorPayload.h2
-rw-r--r--Swiften/Elements/Form.h3
-rw-r--r--Swiften/Elements/FormField.h3
-rw-r--r--Swiften/Elements/IBB.h14
-rw-r--r--Swiften/Elements/InBandRegistrationPayload.h2
-rw-r--r--Swiften/Elements/JingleContentPayload.h (renamed from Swiften/Elements/JingleContent.h)31
-rw-r--r--Swiften/Elements/JingleIBBTransportPayload.h (renamed from Swiften/Elements/JingleIBBTransport.h)8
-rw-r--r--Swiften/Elements/JinglePayload.h8
-rw-r--r--Swiften/Elements/JingleS5BTransportPayload.h (renamed from Swiften/Elements/JingleS5BTransport.h)6
-rw-r--r--Swiften/Elements/JingleTransportPayload.h18
-rw-r--r--Swiften/Elements/MUCPayload.h2
-rw-r--r--Swiften/Elements/Payload.h4
-rw-r--r--Swiften/Elements/Presence.cpp46
-rw-r--r--Swiften/Elements/Presence.h37
-rw-r--r--Swiften/Elements/Priority.h4
-rw-r--r--Swiften/Elements/RosterItemExchangePayload.cpp18
-rw-r--r--Swiften/Elements/RosterItemExchangePayload.h83
-rw-r--r--Swiften/Elements/RosterItemPayload.h14
-rw-r--r--Swiften/Elements/RosterPayload.h9
-rw-r--r--Swiften/Elements/SecurityLabelsCatalog.h8
-rw-r--r--Swiften/Elements/SoftwareVersion.h4
-rw-r--r--Swiften/Elements/Stanza.cpp5
-rw-r--r--Swiften/Elements/Stanza.h27
-rw-r--r--Swiften/Elements/Status.h5
-rw-r--r--Swiften/Elements/StatusShow.cpp12
-rw-r--r--Swiften/Elements/StatusShow.h25
-rw-r--r--Swiften/Elements/StreamFeatures.cpp21
-rw-r--r--Swiften/Elements/StreamFeatures.h23
-rw-r--r--Swiften/Elements/StreamManagementEnabled.cpp15
-rw-r--r--Swiften/Elements/StreamManagementEnabled.h28
-rw-r--r--Swiften/Elements/StreamResume.cpp15
-rw-r--r--Swiften/Elements/StreamResume.h40
-rw-r--r--Swiften/Elements/StreamResumed.cpp15
-rw-r--r--Swiften/Elements/StreamResumed.h40
-rw-r--r--Swiften/Elements/UnitTest/StanzaTest.cpp1
-rw-r--r--Swiften/Entity/Entity.cpp27
-rw-r--r--Swiften/Entity/Entity.h24
-rw-r--r--Swiften/Entity/GenericPayloadPersister.h36
-rw-r--r--Swiften/Entity/PayloadPersister.cpp53
-rw-r--r--Swiften/Entity/PayloadPersister.h30
-rw-r--r--Swiften/EventLoop/DummyEventLoop.cpp24
-rw-r--r--Swiften/EventLoop/DummyEventLoop.h14
-rw-r--r--Swiften/EventLoop/EventLoop.cpp2
-rw-r--r--Swiften/EventLoop/SConscript1
-rw-r--r--Swiften/Examples/BenchTool/BenchTool.cpp1
-rw-r--r--Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp1
-rw-r--r--Swiften/Examples/SendFile/ReceiveFile.cpp3
-rw-r--r--Swiften/Examples/SendFile/SendFile.cpp8
-rw-r--r--Swiften/Examples/SendMessage/SendMessage.cpp2
-rw-r--r--Swiften/FileTransfer/ByteArrayReadBytestream.h19
-rw-r--r--Swiften/FileTransfer/ByteArrayWriteBytestream.h28
-rw-r--r--Swiften/FileTransfer/FileReadBytestream.cpp6
-rw-r--r--Swiften/FileTransfer/FileReadBytestream.h4
-rw-r--r--Swiften/FileTransfer/FileWriteBytestream.cpp4
-rw-r--r--Swiften/FileTransfer/FileWriteBytestream.h6
-rw-r--r--Swiften/FileTransfer/IBBReceiveSession.cpp111
-rw-r--r--Swiften/FileTransfer/IBBReceiveSession.h20
-rw-r--r--Swiften/FileTransfer/IBBSendSession.cpp4
-rw-r--r--Swiften/FileTransfer/IncomingFileTransfer.cpp11
-rw-r--r--Swiften/FileTransfer/IncomingFileTransferManager.cpp16
-rw-r--r--Swiften/FileTransfer/IncomingFileTransferManager.h4
-rw-r--r--Swiften/FileTransfer/IncomingJingleFileTransfer.cpp152
-rw-r--r--Swiften/FileTransfer/IncomingJingleFileTransfer.h57
-rw-r--r--Swiften/FileTransfer/JingleIncomingIBBTransport.cpp23
-rw-r--r--Swiften/FileTransfer/JingleIncomingIBBTransport.h27
-rw-r--r--Swiften/FileTransfer/JingleTransport.cpp (renamed from Swiften/Elements/JingleTransport.h)11
-rw-r--r--Swiften/FileTransfer/JingleTransport.h25
-rw-r--r--Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp14
-rw-r--r--Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h27
-rw-r--r--Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.cpp14
-rw-r--r--Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h18
-rw-r--r--Swiften/FileTransfer/OutgoingFileTransfer.cpp68
-rw-r--r--Swiften/FileTransfer/OutgoingFileTransfer.h41
-rw-r--r--Swiften/FileTransfer/OutgoingSIFileTransfer.cpp78
-rw-r--r--Swiften/FileTransfer/OutgoingSIFileTransfer.h53
-rw-r--r--Swiften/FileTransfer/ReadBytestream.h5
-rw-r--r--Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp14
-rw-r--r--Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h29
-rw-r--r--Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.cpp14
-rw-r--r--Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h18
-rw-r--r--Swiften/FileTransfer/SConscript17
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp3
-rw-r--r--Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp188
-rw-r--r--Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp9
-rw-r--r--Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp36
-rw-r--r--Swiften/FileTransfer/WriteBytestream.h5
-rw-r--r--Swiften/JID/JID.cpp82
-rw-r--r--Swiften/JID/JID.h14
-rw-r--r--Swiften/JID/UnitTest/JIDTest.cpp55
-rw-r--r--Swiften/Jingle/IncomingJingleSession.cpp15
-rw-r--r--Swiften/Jingle/IncomingJingleSession.h20
-rw-r--r--Swiften/Jingle/IncomingJingleSessionHandler.h4
-rw-r--r--Swiften/Jingle/Jingle.h25
-rw-r--r--Swiften/Jingle/JingleContentID.h23
-rw-r--r--Swiften/Jingle/JingleResponder.cpp8
-rw-r--r--Swiften/Jingle/JingleSession.cpp12
-rw-r--r--Swiften/Jingle/JingleSession.h42
-rw-r--r--Swiften/Jingle/JingleSessionImpl.cpp42
-rw-r--r--Swiften/Jingle/JingleSessionImpl.h30
-rw-r--r--Swiften/Jingle/JingleSessionManager.cpp9
-rw-r--r--Swiften/Jingle/JingleSessionManager.h8
-rw-r--r--Swiften/Jingle/SConscript4
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp60
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h47
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp101
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h86
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp22
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h8
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp65
-rw-r--r--Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h52
-rw-r--r--Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h2
-rw-r--r--Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp2
-rw-r--r--Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h14
-rw-r--r--Swiften/LinkLocal/OutgoingLinkLocalSession.cpp1
-rw-r--r--Swiften/LinkLocal/SConscript6
-rw-r--r--Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp2
-rw-r--r--Swiften/MUC/MUC.cpp1
-rw-r--r--Swiften/MUC/MUCBookmarkManager.cpp1
-rw-r--r--Swiften/Network/BoostConnection.cpp2
-rw-r--r--Swiften/Network/BoostConnection.h3
-rw-r--r--Swiften/Network/BoostConnectionFactory.h2
-rw-r--r--Swiften/Network/BoostConnectionServer.cpp1
-rw-r--r--Swiften/Network/BoostConnectionServer.h3
-rw-r--r--Swiften/Network/BoostIOServiceThread.h4
-rw-r--r--Swiften/Network/BoostTimer.cpp1
-rw-r--r--Swiften/Network/BoostTimer.h4
-rw-r--r--Swiften/Network/BoostTimerFactory.h2
-rw-r--r--Swiften/Network/CAresDomainNameResolver.h2
-rw-r--r--Swiften/Network/ChainedConnector.cpp82
-rw-r--r--Swiften/Network/ChainedConnector.h47
-rw-r--r--Swiften/Network/Connection.cpp15
-rw-r--r--Swiften/Network/Connection.h12
-rw-r--r--Swiften/Network/DummyConnection.cpp30
-rw-r--r--Swiften/Network/DummyConnection.h18
-rw-r--r--Swiften/Network/EnvironmentProxyProvider.cpp48
-rw-r--r--Swiften/Network/EnvironmentProxyProvider.h24
-rw-r--r--Swiften/Network/FakeConnection.cpp64
-rw-r--r--Swiften/Network/FakeConnection.h52
-rw-r--r--Swiften/Network/GConfProxyProvider.cpp51
-rw-r--r--Swiften/Network/GConfProxyProvider.h24
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnection.cpp100
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnection.h54
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp20
-rw-r--r--Swiften/Network/HTTPConnectProxiedConnectionFactory.h23
-rw-r--r--Swiften/Network/HostAddress.cpp6
-rw-r--r--Swiften/Network/HostAddress.h7
-rw-r--r--Swiften/Network/HostAddressPort.cpp23
-rw-r--r--Swiften/Network/HostAddressPort.h14
-rw-r--r--Swiften/Network/MacOSXProxyProvider.cpp97
-rw-r--r--Swiften/Network/MacOSXProxyProvider.h18
-rw-r--r--Swiften/Network/NullProxyProvider.cpp20
-rw-r--r--Swiften/Network/NullProxyProvider.h19
-rw-r--r--Swiften/Network/PlatformDomainNameAddressQuery.cpp2
-rw-r--r--Swiften/Network/PlatformDomainNameAddressQuery.h2
-rw-r--r--Swiften/Network/PlatformDomainNameResolver.h2
-rw-r--r--Swiften/Network/PlatformProxyProvider.h26
-rw-r--r--Swiften/Network/ProxyProvider.cpp19
-rw-r--r--Swiften/Network/ProxyProvider.h23
-rw-r--r--Swiften/Network/SConscript27
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnection.cpp174
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnection.h59
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp20
-rw-r--r--Swiften/Network/SOCKS5ProxiedConnectionFactory.h23
-rw-r--r--Swiften/Network/UnitTest/ChainedConnectorTest.cpp161
-rw-r--r--Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp244
-rw-r--r--Swiften/Network/UnixProxyProvider.cpp55
-rw-r--r--Swiften/Network/UnixProxyProvider.h25
-rw-r--r--Swiften/Network/WindowsProxyProvider.cpp113
-rw-r--r--Swiften/Network/WindowsProxyProvider.h22
-rw-r--r--Swiften/Parser/Attribute.h33
-rw-r--r--Swiften/Parser/AttributeMap.cpp62
-rw-r--r--Swiften/Parser/AttributeMap.h62
-rw-r--r--Swiften/Parser/ExpatParser.cpp2
-rw-r--r--Swiften/Parser/IQParser.cpp17
-rw-r--r--Swiften/Parser/IQParser.h5
-rw-r--r--Swiften/Parser/LibXMLParser.cpp12
-rw-r--r--Swiften/Parser/MessageParser.cpp16
-rw-r--r--Swiften/Parser/PayloadParser.h2
-rw-r--r--Swiften/Parser/PayloadParsers/BytestreamsParser.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/DelayParser.cpp1
-rw-r--r--Swiften/Parser/PayloadParsers/DelayParserFactory.cpp1
-rw-r--r--Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/FormParser.cpp5
-rw-r--r--Swiften/Parser/PayloadParsers/FormParser.h1
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/IBBParser.cpp6
-rw-r--r--Swiften/Parser/PayloadParsers/PriorityParser.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp68
-rw-r--r--Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h34
-rw-r--r--Swiften/Parser/PayloadParsers/RosterParser.cpp11
-rw-r--r--Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp4
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp4
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp52
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp22
-rw-r--r--Swiften/Parser/PresenceParser.cpp21
-rw-r--r--Swiften/Parser/SConscript4
-rw-r--r--Swiften/Parser/SerializingParser.cpp6
-rw-r--r--Swiften/Parser/StanzaParser.cpp19
-rw-r--r--Swiften/Parser/StreamFeaturesParser.cpp3
-rw-r--r--Swiften/Parser/StreamManagementEnabledParser.cpp29
-rw-r--r--Swiften/Parser/StreamManagementEnabledParser.h18
-rw-r--r--Swiften/Parser/StreamResumeParser.cpp36
-rw-r--r--Swiften/Parser/StreamResumeParser.h27
-rw-r--r--Swiften/Parser/UnitTest/AttributeMapTest.cpp20
-rw-r--r--Swiften/Parser/UnitTest/StanzaParserTest.cpp10
-rw-r--r--Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp2
-rw-r--r--Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp34
-rw-r--r--Swiften/Parser/UnitTest/XMLParserTest.cpp32
-rw-r--r--Swiften/Parser/XMPPParser.cpp7
-rw-r--r--Swiften/Presence/PayloadAddingPresenceSender.cpp2
-rw-r--r--Swiften/Presence/PayloadAddingPresenceSender.h8
-rw-r--r--Swiften/QA/ClientTest/ClientTest.cpp1
-rw-r--r--Swiften/QA/ProxyProviderTest/.gitignore1
-rw-r--r--Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp35
-rw-r--r--Swiften/QA/ProxyProviderTest/SConscript11
-rw-r--r--Swiften/QA/SConscript3
-rw-r--r--Swiften/QA/StorageTest/FileReadBytestreamTest.cpp7
-rw-r--r--Swiften/Queries/RawRequest.h2
-rw-r--r--Swiften/Queries/Request.h11
-rw-r--r--Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h4
-rw-r--r--Swiften/Roster/GetRosterRequest.h6
-rw-r--r--Swiften/Roster/RosterMemoryStorage.cpp23
-rw-r--r--Swiften/Roster/RosterMemoryStorage.h25
-rw-r--r--Swiften/Roster/RosterStorage.cpp14
-rw-r--r--Swiften/Roster/RosterStorage.h21
-rw-r--r--Swiften/Roster/SetRosterRequest.h8
-rw-r--r--Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp173
-rw-r--r--Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp28
-rw-r--r--Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h39
-rw-r--r--Swiften/Roster/XMPPRosterController.cpp48
-rw-r--r--Swiften/Roster/XMPPRosterController.h12
-rw-r--r--Swiften/SASL/SConscript1
-rw-r--r--Swiften/SConscript36
-rw-r--r--Swiften/Serializer/IQSerializer.h2
-rw-r--r--Swiften/Serializer/PayloadSerializer.h11
-rw-r--r--Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp2
-rw-r--r--Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp1
-rw-r--r--Swiften/Serializer/PayloadSerializers/FormSerializer.cpp8
-rw-r--r--Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp2
-rw-r--r--Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp3
-rw-r--r--Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp46
-rw-r--r--Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h19
-rw-r--r--Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp3
-rw-r--r--Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp2
-rw-r--r--Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp11
-rw-r--r--Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp54
-rw-r--r--Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp27
-rw-r--r--Swiften/Serializer/PresenceSerializer.h2
-rw-r--r--Swiften/Serializer/StanzaSerializer.cpp1
-rw-r--r--Swiften/Serializer/StreamFeaturesSerializer.cpp5
-rw-r--r--Swiften/Serializer/StreamManagementEnabledSerializer.cpp29
-rw-r--r--Swiften/Serializer/StreamManagementEnabledSerializer.h8
-rw-r--r--Swiften/Serializer/StreamResumeSerializer.cpp28
-rw-r--r--Swiften/Serializer/StreamResumeSerializer.h21
-rw-r--r--Swiften/Serializer/StreamResumedSerializer.cpp28
-rw-r--r--Swiften/Serializer/StreamResumedSerializer.h21
-rw-r--r--Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp2
-rw-r--r--Swiften/Serializer/XMPPSerializer.cpp52
-rw-r--r--Swiften/Session/SessionTracer.cpp28
-rw-r--r--Swiften/Session/SessionTracer.h17
-rw-r--r--Swiften/StreamManagement/StanzaAckRequester.cpp1
-rw-r--r--Swiften/StreamStack/CompressionLayer.h4
-rw-r--r--Swiften/StreamStack/ConnectionLayer.cpp21
-rw-r--r--Swiften/StreamStack/ConnectionLayer.h11
-rw-r--r--Swiften/StreamStack/SConscript1
-rw-r--r--Swiften/StreamStack/StreamStack.h5
-rw-r--r--Swiften/StringCodecs/SHA1.cpp69
-rw-r--r--Swiften/StringCodecs/SHA1.h27
-rw-r--r--Swiften/StringCodecs/UnitTest/SHA1Test.cpp53
-rw-r--r--Swiften/VCards/SConscript1
-rw-r--r--Swiften/VCards/VCardFileStorage.cpp129
-rw-r--r--Swiften/VCards/VCardFileStorage.h38
342 files changed, 6165 insertions, 1728 deletions
diff --git a/Swiften/AdHoc/OutgoingAdHocCommandSession.cpp b/Swiften/AdHoc/OutgoingAdHocCommandSession.cpp
new file mode 100644
index 0000000..da7f042
--- /dev/null
+++ b/Swiften/AdHoc/OutgoingAdHocCommandSession.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010-2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/AdHoc/OutgoingAdHocCommandSession.h>
+
+#include <boost/bind.hpp>
+
+#include <Swiften/Queries/GenericRequest.h>
+
+namespace Swift {
+OutgoingAdHocCommandSession::OutgoingAdHocCommandSession(const DiscoItems::Item& command, AdHocCommandWindowFactory* /*factory*/, IQRouter* iqRouter) : command_(command), iqRouter_(iqRouter), isMultiStage_(false) {
+
+}
+
+void OutgoingAdHocCommandSession::handleResponse(boost::shared_ptr<Command> payload, ErrorPayload::ref error) {
+ if (error) {
+ onError(error);
+ } else {
+ const std::vector<Command::Action> actions = payload->getAvailableActions();
+ actionStates_.clear();
+ if (payload->getStatus() == Command::Executing ) {
+ actionStates_[Command::Cancel] = EnabledAndPresent;
+ actionStates_[Command::Complete] = Present;
+ if (std::find(actions.begin(), actions.end(), Command::Complete) != actions.end()) {
+ actionStates_[Command::Complete] = EnabledAndPresent;
+ }
+
+ if (getIsMultiStage()) {
+ actionStates_[Command::Next] = Present;
+ actionStates_[Command::Prev] = Present;
+ }
+
+ if (std::find(actions.begin(), actions.end(), Command::Next) != actions.end()) {
+ actionStates_[Command::Next] = EnabledAndPresent;
+ }
+ if (std::find(actions.begin(), actions.end(), Command::Prev) != actions.end()) {
+ actionStates_[Command::Prev] = EnabledAndPresent;
+ }
+ }
+
+ sessionID_ = payload->getSessionID();
+ if (std::find(actions.begin(), actions.end(), Command::Next) != actions.end()
+ || std::find(actions.begin(), actions.end(), Command::Prev) != actions.end()) {
+ isMultiStage_ = true;
+ }
+ onNextStageReceived(payload);
+ }
+}
+
+bool OutgoingAdHocCommandSession::getIsMultiStage() {
+ return isMultiStage_;
+}
+
+void OutgoingAdHocCommandSession::start() {
+ boost::shared_ptr<Payload> commandPayload(new Command(command_.getNode()));
+ boost::shared_ptr<GenericRequest<Command> > commandRequest(new GenericRequest<Command>(IQ::Set, command_.getJID(), commandPayload, iqRouter_));
+ commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2));
+ commandRequest->send();
+}
+
+void OutgoingAdHocCommandSession::cancel() {
+ if (!sessionID_.empty()) {
+ boost::shared_ptr<Payload> commandPayload(new Command(command_.getNode(), sessionID_, Command::Cancel));
+ boost::shared_ptr<GenericRequest<Command> > commandRequest(new GenericRequest<Command>(IQ::Set, command_.getJID(), commandPayload, iqRouter_));
+ commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2));
+ commandRequest->send();
+ }
+}
+
+void OutgoingAdHocCommandSession::goBack() {
+ boost::shared_ptr<Payload> commandPayload(new Command(command_.getNode(), sessionID_, Command::Prev));
+ boost::shared_ptr<GenericRequest<Command> > commandRequest(new GenericRequest<Command>(IQ::Set, command_.getJID(), commandPayload, iqRouter_));
+ commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2));
+ commandRequest->send();
+}
+
+void OutgoingAdHocCommandSession::complete(Form::ref form) {
+ Command* command = new Command(command_.getNode(), sessionID_, Command::Complete);
+ boost::shared_ptr<Payload> commandPayload(command);
+ command->setForm(form);
+ boost::shared_ptr<GenericRequest<Command> > commandRequest(new GenericRequest<Command>(IQ::Set, command_.getJID(), commandPayload, iqRouter_));
+ commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2));
+ commandRequest->send();
+}
+
+void OutgoingAdHocCommandSession::goNext(Form::ref form) {
+ Command* command = new Command(command_.getNode(), sessionID_, Command::Next);
+ boost::shared_ptr<Payload> commandPayload(command);
+ command->setForm(form);
+ boost::shared_ptr<GenericRequest<Command> > commandRequest(new GenericRequest<Command>(IQ::Set, command_.getJID(), commandPayload, iqRouter_));
+ commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2));
+ commandRequest->send();
+}
+
+OutgoingAdHocCommandSession::ActionState OutgoingAdHocCommandSession::getActionState(Command::Action action) {
+ return actionStates_[action];
+}
+
+}
diff --git a/Swiften/AdHoc/OutgoingAdHocCommandSession.h b/Swiften/AdHoc/OutgoingAdHocCommandSession.h
new file mode 100644
index 0000000..f4b5242
--- /dev/null
+++ b/Swiften/AdHoc/OutgoingAdHocCommandSession.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010-2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <boost/shared_ptr.hpp>
+#include <Swiften/Elements/DiscoItems.h>
+#include <Swiften/Elements/Command.h>
+#include <Swiften/Elements/ErrorPayload.h>
+
+namespace Swift {
+ class IQRouter;
+ class MainWindow;
+ class UIEventStream;
+ class AdHocCommandWindowFactory;
+ class OutgoingAdHocCommandSession {
+ public:
+
+ /**
+ * Availability of action.
+ */
+ enum ActionState {
+ Absent /** Action isn't applicable to this command. */ = 0,
+ Present /** Action is applicable to this command */= 1,
+ Enabled /** Action is applicable and currently available */ = 2,
+ EnabledAndPresent = 3};
+
+ OutgoingAdHocCommandSession(const DiscoItems::Item& command, AdHocCommandWindowFactory* factory, IQRouter* iqRouter);
+ /**
+ * Send initial request to the target.
+ */
+ void start();
+ /**
+ * Cancel command session with the target.
+ */
+ void cancel();
+ /**
+ * Return to the previous stage.
+ */
+ void goBack();
+ /**
+ * Send the form to complete the command.
+ * \param form Form for submission - if missing the command will be submitted with no form.
+ */
+ void complete(Form::ref form);
+ /**
+ * Send the form to advance to the next stage of the command.
+ * \param form Form for submission - if missing the command will be submitted with no form.
+ */
+ void goNext(Form::ref form);
+
+ /**
+ * Is the form multi-stage?
+ */
+ bool getIsMultiStage();
+
+ /**
+ * Emitted when the form for the next stage is available.
+ */
+ boost::signal<void (Command::ref)> onNextStageReceived;
+
+ /**
+ * Emitted on error.
+ */
+ boost::signal<void (ErrorPayload::ref)> onError;
+
+ /**
+ * Get the state of a given action.
+ * This is useful for a UI to determine which buttons should be visible,
+ * and which enabled.
+ * Use for Next, Prev, Cancel and Complete only.
+ * If no actions are available, the command has completed.
+ */
+ ActionState getActionState(Command::Action action);
+ private:
+ void handleResponse(boost::shared_ptr<Command> payload, ErrorPayload::ref error);
+ private:
+ DiscoItems::Item command_;
+ IQRouter* iqRouter_;
+ bool isMultiStage_;
+ std::string sessionID_;
+ std::map<Command::Action, ActionState> actionStates_;
+ };
+}
diff --git a/Swiften/AdHoc/SConscript b/Swiften/AdHoc/SConscript
new file mode 100644
index 0000000..69c9083
--- /dev/null
+++ b/Swiften/AdHoc/SConscript
@@ -0,0 +1,6 @@
+Import("swiften_env")
+
+objects = swiften_env.SwiftenObject([
+ "OutgoingAdHocCommandSession.cpp",
+ ])
+swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Avatars/AvatarFileStorage.cpp b/Swiften/Avatars/AvatarFileStorage.cpp
deleted file mode 100644
index 4f76c80..0000000
--- a/Swiften/Avatars/AvatarFileStorage.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/Avatars/AvatarFileStorage.h>
-
-#include <iostream>
-#include <boost/filesystem/fstream.hpp>
-
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Base/String.h>
-#include <Swiften/StringCodecs/SHA1.h>
-#include <Swiften/StringCodecs/Hexify.h>
-
-namespace Swift {
-
-AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile) : avatarsDir(avatarsDir), avatarsFile(avatarsFile) {
- if (boost::filesystem::exists(avatarsFile)) {
- try {
- boost::filesystem::ifstream file(avatarsFile);
- std::string line;
- if (file.is_open()) {
- while (!file.eof()) {
- getline(file, line);
- std::pair<std::string, std::string> r = String::getSplittedAtFirst(line, ' ');
- JID jid(r.second);
- if (jid.isValid()) {
- jidAvatars.insert(std::make_pair(jid, r.first));
- }
- else if (!r.first.empty() || !r.second.empty()) {
- std::cerr << "Invalid entry in avatars file: " << r.second << std::endl;
- }
- }
- }
- }
- catch (...) {
- std::cerr << "Error reading avatars file" << std::endl;
- }
- }
-}
-
-bool AvatarFileStorage::hasAvatar(const std::string& hash) const {
- return boost::filesystem::exists(getAvatarPath(hash));
-}
-
-void AvatarFileStorage::addAvatar(const std::string& hash, const ByteArray& avatar) {
- assert(Hexify::hexify(SHA1::getHash(avatar)) == hash);
-
- boost::filesystem::path avatarPath = getAvatarPath(hash);
- if (!boost::filesystem::exists(avatarPath.parent_path())) {
- try {
- boost::filesystem::create_directories(avatarPath.parent_path());
- }
- catch (const boost::filesystem::filesystem_error& e) {
- std::cerr << "ERROR: " << e.what() << std::endl;
- }
- }
- boost::filesystem::ofstream file(avatarPath, boost::filesystem::ofstream::binary|boost::filesystem::ofstream::out);
- file.write(reinterpret_cast<const char*>(avatar.getData()), avatar.getSize());
- file.close();
-}
-
-boost::filesystem::path AvatarFileStorage::getAvatarPath(const std::string& hash) const {
- return avatarsDir / hash;
-}
-
-ByteArray AvatarFileStorage::getAvatar(const std::string& hash) const {
- ByteArray data;
- data.readFromFile(getAvatarPath(hash).string());
- return data;
-}
-
-void AvatarFileStorage::setAvatarForJID(const JID& jid, const std::string& hash) {
- std::pair<JIDAvatarMap::iterator, bool> r = jidAvatars.insert(std::make_pair(jid, hash));
- if (r.second) {
- saveJIDAvatars();
- }
- else if (r.first->second != hash) {
- r.first->second = hash;
- saveJIDAvatars();
- }
-}
-
-std::string AvatarFileStorage::getAvatarForJID(const JID& jid) const {
- JIDAvatarMap::const_iterator i = jidAvatars.find(jid);
- return i == jidAvatars.end() ? "" : i->second;
-}
-
-void AvatarFileStorage::saveJIDAvatars() {
- try {
- boost::filesystem::ofstream file(avatarsFile);
- for (JIDAvatarMap::const_iterator i = jidAvatars.begin(); i != jidAvatars.end(); ++i) {
- file << i->second << " " << i->first.toString() << std::endl;
- }
- file.close();
- }
- catch (...) {
- std::cerr << "Error writing avatars file" << std::endl;
- }
-}
-
-}
diff --git a/Swiften/Avatars/AvatarFileStorage.h b/Swiften/Avatars/AvatarFileStorage.h
deleted file mode 100644
index e736230..0000000
--- a/Swiften/Avatars/AvatarFileStorage.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <map>
-#include <string>
-#include <boost/filesystem.hpp>
-
-#include <Swiften/JID/JID.h>
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/Avatars/AvatarStorage.h"
-
-namespace Swift {
- class AvatarFileStorage : public AvatarStorage {
- public:
- AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile);
-
- virtual bool hasAvatar(const std::string& hash) const;
- virtual void addAvatar(const std::string& hash, const ByteArray& avatar);
- virtual ByteArray getAvatar(const std::string& hash) const;
-
- virtual boost::filesystem::path getAvatarPath(const std::string& hash) const;
-
- virtual void setAvatarForJID(const JID& jid, const std::string& hash);
- virtual std::string getAvatarForJID(const JID& jid) const;
-
- private:
- void saveJIDAvatars();
-
- private:
- boost::filesystem::path avatarsDir;
- boost::filesystem::path avatarsFile;
- typedef std::map<JID, std::string> JIDAvatarMap;
- JIDAvatarMap jidAvatars;
- };
-
-}
diff --git a/Swiften/Avatars/AvatarManager.h b/Swiften/Avatars/AvatarManager.h
index e1af451..3461973 100644
--- a/Swiften/Avatars/AvatarManager.h
+++ b/Swiften/Avatars/AvatarManager.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Base/ByteArray.h>
diff --git a/Swiften/Avatars/AvatarProvider.h b/Swiften/Avatars/AvatarProvider.h
index 0f66904..d2d408e 100644
--- a/Swiften/Avatars/AvatarProvider.h
+++ b/Swiften/Avatars/AvatarProvider.h
@@ -6,9 +6,10 @@
#pragma once
-#include "Swiften/Base/boost_bsignals.h"
#include <string>
+#include <Swiften/Base/boost_bsignals.h>
+
namespace Swift {
class JID;
diff --git a/Swiften/Avatars/AvatarStorage.h b/Swiften/Avatars/AvatarStorage.h
index 48fc885..d1aff39 100644
--- a/Swiften/Avatars/AvatarStorage.h
+++ b/Swiften/Avatars/AvatarStorage.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
#include <string>
namespace Swift {
diff --git a/Swiften/Avatars/SConscript b/Swiften/Avatars/SConscript
index 46ae897..9c219a4 100644
--- a/Swiften/Avatars/SConscript
+++ b/Swiften/Avatars/SConscript
@@ -1,7 +1,6 @@
Import("swiften_env")
objects = swiften_env.SwiftenObject([
- "AvatarFileStorage.cpp",
"VCardUpdateAvatarManager.cpp",
"VCardAvatarManager.cpp",
"OfflineAvatarManager.cpp",
diff --git a/Swiften/Avatars/VCardAvatarManager.h b/Swiften/Avatars/VCardAvatarManager.h
index 3f99dad..6c02ace 100644
--- a/Swiften/Avatars/VCardAvatarManager.h
+++ b/Swiften/Avatars/VCardAvatarManager.h
@@ -6,11 +6,8 @@
#pragma once
-#include <map>
-
#include "Swiften/Avatars/AvatarProvider.h"
#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/VCard.h"
namespace Swift {
class MUCRegistry;
diff --git a/Swiften/Base/ByteArray.cpp b/Swiften/Base/ByteArray.cpp
index 928e145..323c866 100644
--- a/Swiften/Base/ByteArray.cpp
+++ b/Swiften/Base/ByteArray.cpp
@@ -9,6 +9,10 @@
#include <fstream>
std::ostream& operator<<(std::ostream& os, const Swift::ByteArray& s) {
+ return operator<<(os, s.getDataVector());
+}
+
+std::ostream& operator<<(std::ostream& os, const std::vector<unsigned char>& s) {
std::ios::fmtflags oldFlags = os.flags();
os << std::hex;
for (Swift::ByteArray::const_iterator i = s.begin(); i != s.end(); ++i) {
@@ -37,4 +41,45 @@ void ByteArray::readFromFile(const std::string& file) {
input.close();
}
+std::vector<unsigned char> ByteArray::create(const std::string& s) {
+ return std::vector<unsigned char>(s.begin(), s.end());
+}
+
+std::vector<unsigned char> ByteArray::create(const char* c) {
+ std::vector<unsigned char> data;
+ while (*c) {
+ data.push_back(static_cast<unsigned char>(*c));
+ ++c;
+ }
+ return data;
+}
+
+std::vector<unsigned char> ByteArray::create(const char* c, size_t n) {
+ std::vector<unsigned char> data;
+ if (n > 0) {
+ data.resize(n);
+ memcpy(&data[0], c, n);
+ }
+ return data;
+}
+
+std::vector<unsigned char> ByteArray::create(const unsigned char* c, size_t n) {
+ std::vector<unsigned char> data;
+ if (n > 0) {
+ data.resize(n);
+ memcpy(&data[0], c, n);
+ }
+ return data;
+}
+
+std::string ByteArray::toString() const {
+ size_t i;
+ for (i = data_.size(); i > 0; --i) {
+ if (data_[i - 1] != 0) {
+ break;
+ }
+ }
+ return i > 0 ? std::string(reinterpret_cast<const char*>(getData()), i) : "";
+}
+
}
diff --git a/Swiften/Base/ByteArray.h b/Swiften/Base/ByteArray.h
index ad2c1e5..ebc22d8 100644
--- a/Swiften/Base/ByteArray.h
+++ b/Swiften/Base/ByteArray.h
@@ -6,11 +6,9 @@
#pragma once
-#include <cstring>
#include <vector>
-#include <iostream>
-
#include <string>
+#include <cstring> // for memcpy
namespace Swift {
class ByteArray
@@ -24,7 +22,7 @@ namespace Swift {
ByteArray(const char* c) {
while (*c) {
- data_.push_back(*c);
+ data_.push_back(static_cast<unsigned char>(*c));
++c;
}
}
@@ -75,7 +73,7 @@ namespace Swift {
}
void resize(size_t size, char c) {
- return data_.resize(size, c);
+ return data_.resize(size, static_cast<unsigned char>(c));
}
friend ByteArray operator+(const ByteArray& a, const ByteArray&b) {
@@ -87,7 +85,7 @@ namespace Swift {
friend ByteArray operator+(const ByteArray& a, char b) {
ByteArray x;
x.resize(1);
- x[0] = b;
+ x[0] = static_cast<unsigned char>(b);
return a + x;
}
@@ -97,7 +95,7 @@ namespace Swift {
}
ByteArray& operator+=(char c) {
- data_.push_back(c);
+ data_.push_back(static_cast<unsigned char>(c));
return *this;
}
@@ -122,9 +120,7 @@ namespace Swift {
return data_.end();
}
- std::string toString() const {
- return std::string(reinterpret_cast<const char*>(getData()), getSize());
- }
+ std::string toString() const;
void readFromFile(const std::string& file);
@@ -132,9 +128,27 @@ namespace Swift {
data_.clear();
}
+ const std::vector<unsigned char>& getDataVector() const {
+ return data_;
+ }
+
+ static std::vector<unsigned char> create(const std::string& s);
+ static std::vector<unsigned char> create(const char* c);
+ static std::vector<unsigned char> create(const unsigned char* c, size_t n);
+ static std::vector<unsigned char> create(const char* c, size_t n);
+
+ static const unsigned char* data(const std::vector<unsigned char>& v) {
+ return v.empty() ? NULL : &v[0];
+ }
+
+ static const char* charData(const std::vector<unsigned char>& v) {
+ return v.empty() ? NULL : reinterpret_cast<const char*>(&v[0]);
+ }
+
private:
std::vector<unsigned char> data_;
};
}
std::ostream& operator<<(std::ostream& os, const Swift::ByteArray& s);
+std::ostream& operator<<(std::ostream& os, const std::vector<unsigned char>& s);
diff --git a/Swiften/Base/IDGenerator.h b/Swiften/Base/IDGenerator.h
index 4b6289b..d536dcc 100644
--- a/Swiften/Base/IDGenerator.h
+++ b/Swiften/Base/IDGenerator.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_IDGenerator_H
-#define SWIFTEN_IDGenerator_H
+#pragma once
#include <string>
@@ -20,5 +19,3 @@ namespace Swift {
std::string currentID_;
};
}
-
-#endif
diff --git a/Swiften/Base/Paths.cpp b/Swiften/Base/Paths.cpp
index 43eee57..d901ff9 100644
--- a/Swiften/Base/Paths.cpp
+++ b/Swiften/Base/Paths.cpp
@@ -25,7 +25,7 @@ boost::filesystem::path Paths::getExecutablePath() {
uint32_t size = 4096;
path.resize(size);
if (_NSGetExecutablePath(reinterpret_cast<char*>(path.getData()), &size) == 0) {
- return boost::filesystem::path(path.toString().c_str()).parent_path();
+ return boost::filesystem::path(std::string(reinterpret_cast<const char*>(path.getData()), path.getSize()).c_str()).parent_path();
}
#elif defined(SWIFTEN_PLATFORM_LINUX)
ByteArray path;
@@ -33,13 +33,13 @@ boost::filesystem::path Paths::getExecutablePath() {
size_t size = readlink("/proc/self/exe", reinterpret_cast<char*>(path.getData()), path.getSize());
if (size > 0) {
path.resize(size);
- return boost::filesystem::path(path.toString().c_str()).parent_path();
+ return boost::filesystem::path(std::string(reinterpret_cast<const char*>(path.getData()), path.getSize()).c_str()).parent_path();
}
#elif defined(SWIFTEN_PLATFORM_WINDOWS)
ByteArray data;
data.resize(2048);
GetModuleFileName(NULL, reinterpret_cast<char*>(data.getData()), data.getSize());
- return boost::filesystem::path(data.toString().c_str()).parent_path();
+ return boost::filesystem::path(std::string(reinterpret_cast<const char*>(data.getData()), data.getSize()).c_str()).parent_path();
#endif
return boost::filesystem::path();
}
diff --git a/Swiften/Base/Paths.h b/Swiften/Base/Paths.h
index 06c6aeb..8ac4640 100644
--- a/Swiften/Base/Paths.h
+++ b/Swiften/Base/Paths.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
namespace Swift {
class Paths {
diff --git a/Swiften/Base/Platform.h b/Swiften/Base/Platform.h
index 32e2671..395747c 100644
--- a/Swiften/Base/Platform.h
+++ b/Swiften/Base/Platform.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_Platform_H
-#define SWIFTEN_Platform_H
+#pragma once
// Base platforms
#if defined(linux) || defined(__linux) || defined(__linux__)
@@ -26,6 +25,10 @@
#define SWIFTEN_PLATFORM_BEOS
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#define SWIFTEN_PLATFORM_MACOSX
+#include <TargetConditionals.h>
+# if defined(TARGET_OS_IPHONE)
+# define SWIFTEN_PLATFORM_IPHONE
+# endif
#elif defined(__IBMCPP__) || defined(_AIX)
#define SWIFTEN_PLATFORM_AIX
#elif defined(__amigaos__)
@@ -46,5 +49,3 @@
#elif defined(BOOST_BIG_ENDIAN)
#define SWIFTEN_BIG_ENDIAN
#endif
-
-#endif
diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h
index 192d53b..0de6cac 100644
--- a/Swiften/Base/String.h
+++ b/Swiften/Base/String.h
@@ -6,7 +6,6 @@
#pragma once
-#include <map>
#include <string>
#include <vector>
diff --git a/Swiften/Base/UnitTest/ByteArrayTest.cpp b/Swiften/Base/UnitTest/ByteArrayTest.cpp
index cb10dd4..069e68e 100644
--- a/Swiften/Base/UnitTest/ByteArrayTest.cpp
+++ b/Swiften/Base/UnitTest/ByteArrayTest.cpp
@@ -8,12 +8,17 @@
#include <cppunit/extensions/TestFactoryRegistry.h>
#include "Swiften/Base/ByteArray.h"
+#include <boost/lexical_cast.hpp>
using namespace Swift;
class ByteArrayTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ByteArrayTest);
CPPUNIT_TEST(testGetData_NoData);
+ CPPUNIT_TEST(testToString);
+ CPPUNIT_TEST(testToString_NullTerminated);
+ CPPUNIT_TEST(testToString_TwoNullTerminated);
+ CPPUNIT_TEST(testToString_AllNull);
CPPUNIT_TEST_SUITE_END();
public:
@@ -22,6 +27,30 @@ class ByteArrayTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(reinterpret_cast<const char*>(NULL), reinterpret_cast<const char*>(testling.getData()));
}
+
+ void testToString() {
+ ByteArray testling(ByteArray::create("abcde"));
+
+ CPPUNIT_ASSERT_EQUAL(std::string("abcde"), testling.toString());
+ }
+
+ void testToString_NullTerminated() {
+ ByteArray testling(ByteArray::create("abcde\0", 6));
+
+ CPPUNIT_ASSERT_EQUAL(std::string("abcde"), testling.toString());
+ }
+
+ void testToString_TwoNullTerminated() {
+ ByteArray testling(ByteArray::create("abcde\0\0", 7));
+
+ CPPUNIT_ASSERT_EQUAL(std::string("abcde"), testling.toString());
+ }
+
+ void testToString_AllNull() {
+ ByteArray testling(ByteArray::create("\0\0", 2));
+
+ CPPUNIT_ASSERT_EQUAL(std::string(""), testling.toString());
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(ByteArrayTest);
diff --git a/Swiften/Base/foreach.h b/Swiften/Base/foreach.h
index 05366d6..87f6147 100644
--- a/Swiften/Base/foreach.h
+++ b/Swiften/Base/foreach.h
@@ -4,12 +4,9 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_FOREACH_H
-#define SWIFTEN_FOREACH_H
+#pragma once
#include <boost/foreach.hpp>
#undef foreach
#define foreach BOOST_FOREACH
-
-#endif
diff --git a/Swiften/Base/format.h b/Swiften/Base/format.h
index 4591827..0e49eaa 100644
--- a/Swiften/Base/format.h
+++ b/Swiften/Base/format.h
@@ -7,6 +7,7 @@
#pragma once
#include <boost/format.hpp>
+#include <iostream>
namespace Swift {
inline boost::format format(const std::string& s) {
diff --git a/Swiften/Base/sleep.h b/Swiften/Base/sleep.h
index c2bc601..a95e907 100644
--- a/Swiften/Base/sleep.h
+++ b/Swiften/Base/sleep.h
@@ -4,11 +4,8 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_sleep_H
-#define SWIFTEN_sleep_H
+#pragma once
namespace Swift {
void sleep(unsigned int msecs);
}
-
-#endif
diff --git a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
index 5d7961b..aa16892 100644
--- a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
+++ b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
@@ -8,6 +8,7 @@
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <boost/bind.hpp>
+#include <Swiften/Base/foreach.h>
#include "Swiften/Chat/ChatStateNotifier.h"
#include "Swiften/Client/DummyStanzaChannel.h"
#include "Swiften/Disco/DummyEntityCapsProvider.h"
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 7918c46..5a3450c 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -25,6 +25,7 @@
#include "Swiften/Presence/SubscriptionManager.h"
#include "Swiften/TLS/BlindCertificateTrustChecker.h"
#include <Swiften/Client/NickManagerImpl.h>
+#include <Swiften/Client/ClientSession.h>
namespace Swift {
@@ -35,7 +36,7 @@ Client::Client(const JID& jid, const std::string& password, NetworkFactories* ne
softwareVersionResponder->start();
roster = new XMPPRosterImpl();
- rosterController = new XMPPRosterController(getIQRouter(), roster);
+ rosterController = new XMPPRosterController(getIQRouter(), roster, getStorages()->getRosterStorage());
subscriptionManager = new SubscriptionManager(getStanzaChannel());
@@ -98,6 +99,11 @@ void Client::setSoftwareVersion(const std::string& name, const std::string& vers
}
void Client::requestRoster() {
+ // FIXME: We should set this once when the session is finished, but there
+ // is currently no callback for this
+ if (getSession()) {
+ rosterController->setUseVersioning(getSession()->getRosterVersioningSupported());
+ }
rosterController->requestRoster();
}
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 083b8a0..05c1e6e 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -6,7 +6,7 @@
#pragma once
-#include "Swiften/Client/CoreClient.h"
+#include <Swiften/Client/CoreClient.h>
namespace Swift {
class SoftwareVersionResponder;
@@ -85,12 +85,12 @@ namespace Swift {
/**
* Returns the last received presence for the given (full) JID.
*/
- Presence::ref getLastPresence(const JID& jid) const;
+ boost::shared_ptr<Presence> getLastPresence(const JID& jid) const;
/**
* Returns the presence with the highest priority received for the given JID.
*/
- Presence::ref getHighestPriorityPresence(const JID& bareJID) const;
+ boost::shared_ptr<Presence> getHighestPriorityPresence(const JID& bareJID) const;
PresenceOracle* getPresenceOracle() const {
return presenceOracle;
@@ -142,7 +142,7 @@ namespace Swift {
/**
* This signal is emitted when a JID changes presence.
*/
- boost::signal<void (Presence::ref)> onPresenceChange;
+ boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChange;
private:
Storages* getStorages() const;
diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h
new file mode 100644
index 0000000..1155b46
--- /dev/null
+++ b/Swiften/Client/ClientOptions.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+struct ClientOptions {
+ enum UseTLS {
+ NeverUseTLS,
+ UseTLSWhenAvailable
+ };
+
+ ClientOptions() : useStreamCompression(true), useTLS(UseTLSWhenAvailable), useStreamResumption(false) {
+ }
+
+ /**
+ * Whether ZLib stream compression should be used when available.
+ *
+ * Default: true
+ */
+ bool useStreamCompression;
+
+ /**
+ * Sets whether TLS encryption should be used.
+ *
+ * Default: UseTLSWhenAvailable
+ */
+ UseTLS useTLS;
+
+ /**
+ * Use XEP-196 stream resumption when available.
+ *
+ * Default: false
+ */
+ bool useStreamResumption;
+};
+
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index e1c1d8e..cadc9a4 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -54,6 +54,7 @@ ClientSession::ClientSession(
needSessionStart(false),
needResourceBind(false),
needAcking(false),
+ rosterVersioningSupported(false),
authenticator(NULL),
certificateTrustChecker(NULL) {
}
@@ -223,6 +224,7 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
}
else {
// Start the session
+ rosterVersioningSupported = streamFeatures->hasRosterVersioning();
stream->setWhitespacePingEnabled(true);
needSessionStart = streamFeatures->hasSession();
needResourceBind = streamFeatures->hasResourceBind();
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index 25ee694..4447f57 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -89,6 +89,10 @@ namespace Swift {
return stanzaAckRequester_;
}
+ bool getRosterVersioningSupported() const {
+ return rosterVersioningSupported;
+ }
+
const JID& getLocalJID() const {
return localJID;
}
@@ -153,6 +157,7 @@ namespace Swift {
bool needSessionStart;
bool needResourceBind;
bool needAcking;
+ bool rosterVersioningSupported;
ClientAuthenticator* authenticator;
boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_;
boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_;
diff --git a/Swiften/Client/ClientSessionStanzaChannel.cpp b/Swiften/Client/ClientSessionStanzaChannel.cpp
index 6b32b3d..85d9dec 100644
--- a/Swiften/Client/ClientSessionStanzaChannel.cpp
+++ b/Swiften/Client/ClientSessionStanzaChannel.cpp
@@ -7,6 +7,7 @@
#include "Swiften/Client/ClientSessionStanzaChannel.h"
#include <boost/bind.hpp>
+#include <iostream>
namespace Swift {
diff --git a/Swiften/Client/ClientXMLTracer.cpp b/Swiften/Client/ClientXMLTracer.cpp
new file mode 100644
index 0000000..a26ce66
--- /dev/null
+++ b/Swiften/Client/ClientXMLTracer.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Client/ClientXMLTracer.h>
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+ClientXMLTracer::ClientXMLTracer(CoreClient* client) {
+ client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, '<', _1));
+ client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, '>', _1));
+}
+
+void ClientXMLTracer::printData(char direction, const std::string& data) {
+ printLine(direction);
+ std::cerr << data << std::endl;
+}
+
+void ClientXMLTracer::printLine(char c) {
+ for (unsigned int i = 0; i < 80; ++i) {
+ std::cerr << c;
+ }
+ std::cerr << std::endl;
+}
+
+}
diff --git a/Swiften/Client/ClientXMLTracer.h b/Swiften/Client/ClientXMLTracer.h
index bca2a54..617c53f 100644
--- a/Swiften/Client/ClientXMLTracer.h
+++ b/Swiften/Client/ClientXMLTracer.h
@@ -6,29 +6,15 @@
#pragma once
-#include <boost/bind.hpp>
-
#include <Swiften/Client/CoreClient.h>
namespace Swift {
class ClientXMLTracer {
public:
- ClientXMLTracer(CoreClient* client) {
- client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, '<', _1));
- client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, '>', _1));
- }
+ ClientXMLTracer(CoreClient* client);
private:
- static void printData(char direction, const std::string& data) {
- printLine(direction);
- std::cerr << data << std::endl;
- }
-
- static void printLine(char c) {
- for (unsigned int i = 0; i < 80; ++i) {
- std::cerr << c;
- }
- std::cerr << std::endl;
- }
+ static void printData(char direction, const std::string& data);
+ static void printLine(char c);
};
}
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index f0c5333..de40517 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -7,11 +7,12 @@
#include "Swiften/Client/CoreClient.h"
#include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
#include "Swiften/Client/ClientSession.h"
#include "Swiften/TLS/PlatformTLSFactories.h"
#include "Swiften/TLS/CertificateVerificationError.h"
-#include "Swiften/Network/Connector.h"
+#include <Swiften/Network/ChainedConnector.h>
#include "Swiften/Network/NetworkFactories.h"
#include "Swiften/TLS/PKCS12Certificate.h"
#include "Swiften/Session/BasicSessionStream.h"
@@ -19,10 +20,14 @@
#include "Swiften/Base/IDGenerator.h"
#include "Swiften/Client/ClientSessionStanzaChannel.h"
#include <Swiften/Base/Log.h>
+#include <Swiften/Base/foreach.h>
+#include "Swiften/Network/PlatformProxyProvider.h"
+#include "Swiften/Network/SOCKS5ProxiedConnectionFactory.h"
+#include "Swiften/Network/HTTPConnectProxiedConnectionFactory.h"
namespace Swift {
-CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), disconnectRequested_(false), certificateTrustChecker(NULL) {
+CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), disconnectRequested_(false), certificateTrustChecker(NULL) {
stanzaChannel_ = new ClientSessionStanzaChannel();
stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1));
stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1));
@@ -47,8 +52,9 @@ CoreClient::~CoreClient() {
delete stanzaChannel_;
}
-void CoreClient::connect() {
+void CoreClient::connect(const ClientOptions& o) {
SWIFT_LOG(debug) << "Connecting" << std::endl;
+ options = o;
connect(jid_.getDomain());
}
@@ -56,7 +62,19 @@ void CoreClient::connect(const std::string& host) {
SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
disconnectRequested_ = false;
assert(!connector_);
- connector_ = Connector::create(host, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory());
+
+ assert(proxyConnectionFactories.empty());
+ PlatformProxyProvider proxyProvider;
+ if(proxyProvider.getSOCKS5Proxy().isValid()) {
+ proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getSOCKS5Proxy()));
+ }
+ if(proxyProvider.getHTTPConnectProxy().isValid()) {
+ proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getHTTPConnectProxy()));
+ }
+ std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories);
+ connectionFactories.push_back(networkFactories->getConnectionFactory());
+
+ connector_ = boost::make_shared<ChainedConnector>(host, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory());
connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
connector_->setTimeoutMilliseconds(60*1000);
connector_->start();
@@ -65,6 +83,10 @@ void CoreClient::connect(const std::string& host) {
void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
connector_.reset();
+ foreach(ConnectionFactory* f, proxyConnectionFactories) {
+ delete f;
+ }
+
if (!connection) {
onDisconnected(disconnectRequested_ ? boost::optional<ClientError>() : boost::optional<ClientError>(ClientError::ConnectionError));
}
@@ -82,12 +104,12 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio
session_ = ClientSession::create(jid_, sessionStream_);
session_->setCertificateTrustChecker(certificateTrustChecker);
- session_->setUseStreamCompression(useStreamCompression);
- switch(useTLS) {
- case UseTLSWhenAvailable:
+ session_->setUseStreamCompression(options.useStreamCompression);
+ switch(options.useTLS) {
+ case ClientOptions::UseTLSWhenAvailable:
session_->setUseTLS(ClientSession::UseTLSWhenAvailable);
break;
- case NeverUseTLS:
+ case ClientOptions::NeverUseTLS:
session_->setUseTLS(ClientSession::NeverUseTLS);
break;
}
@@ -275,13 +297,25 @@ void CoreClient::handleStanzaAcked(Stanza::ref stanza) {
onStanzaAcked(stanza);
}
-void CoreClient::setUseStreamCompression(bool b) {
- useStreamCompression = b;
+bool CoreClient::isAvailable() const {
+ return stanzaChannel_->isAvailable();
}
-void CoreClient::setUseTLS(UseTLS b) {
- useTLS = b;
+bool CoreClient::getStreamManagementEnabled() const {
+ return stanzaChannel_->getStreamManagementEnabled();
}
+StanzaChannel* CoreClient::getStanzaChannel() const {
+ return stanzaChannel_;
+}
+
+const JID& CoreClient::getJID() const {
+ if (session_) {
+ return session_->getLocalJID();
+ }
+ else {
+ return jid_;
+ }
+}
}
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index eb9c42c..7c46fe7 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -6,35 +6,33 @@
#pragma once
-#include "Swiften/Base/boost_bsignals.h"
+#include <string>
#include <boost/shared_ptr.hpp>
+#include <Swiften/Base/boost_bsignals.h>
-#include "Swiften/Network/PlatformDomainNameResolver.h"
-#include "Swiften/Network/Connector.h"
-#include "Swiften/Base/Error.h"
-#include "Swiften/Client/ClientSession.h"
-#include "Swiften/Client/ClientError.h"
-#include "Swiften/Elements/Presence.h"
-#include "Swiften/Elements/Message.h"
-#include "Swiften/JID/JID.h"
-#include <string>
-#include "Swiften/Client/StanzaChannel.h"
-#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
-#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
#include <Swiften/Entity/Entity.h>
-
-#include "Swiften/Client/ClientSessionStanzaChannel.h"
+#include <Swiften/JID/JID.h>
+#include <Swiften/Client/ClientError.h>
+#include <Swiften/Client/ClientOptions.h>
namespace Swift {
+ class ChainedConnector;
+ class Message;
+ class Presence;
+ class Error;
class IQRouter;
class TLSContextFactory;
class ConnectionFactory;
+ class Connection;
class TimerFactory;
class ClientSession;
+ class StanzaChannel;
+ class Stanza;
class BasicSessionStream;
class PlatformTLSFactories;
class CertificateTrustChecker;
class NetworkFactories;
+ class ClientSessionStanzaChannel;
/**
* The central class for communicating with an XMPP server.
@@ -48,11 +46,6 @@ namespace Swift {
*/
class CoreClient : public Entity {
public:
- enum UseTLS {
- NeverUseTLS,
- UseTLSWhenAvailable
- };
-
/**
* Constructs a client for the given JID with the given password.
* The given eventLoop will be used to post events to.
@@ -68,7 +61,7 @@ namespace Swift {
* After the connection is established, the client will set
* initialize the stream and authenticate.
*/
- void connect();
+ void connect(const ClientOptions& = ClientOptions());
/**
* Disconnects the client from the server.
@@ -80,12 +73,12 @@ namespace Swift {
/**
* Sends a message.
*/
- void sendMessage(Message::ref);
+ void sendMessage(boost::shared_ptr<Message>);
/**
* Sends a presence stanza.
*/
- void sendPresence(Presence::ref);
+ void sendPresence(boost::shared_ptr<Presence>);
/**
* Sends raw, unchecked data.
@@ -103,9 +96,7 @@ namespace Swift {
* Checks whether the client is connected to the server,
* and stanzas can be sent.
*/
- bool isAvailable() const {
- return stanzaChannel_->isAvailable();
- }
+ bool isAvailable() const;
/**
* Checks whether the client is active.
@@ -118,14 +109,7 @@ namespace Swift {
* Returns the JID of the client.
* After the session was initialized, this returns the bound JID.
*/
- const JID& getJID() const {
- if (session_) {
- return session_->getLocalJID();
- }
- else {
- return jid_;
- }
- }
+ const JID& getJID() const;
/**
* Checks whether stream management is enabled.
@@ -135,13 +119,9 @@ namespace Swift {
*
* \see onStanzaAcked
*/
- bool getStreamManagementEnabled() const {
- return stanzaChannel_->getStreamManagementEnabled();
- }
+ bool getStreamManagementEnabled() const;
- StanzaChannel* getStanzaChannel() const {
- return stanzaChannel_;
- }
+ StanzaChannel* getStanzaChannel() const;
/**
* Sets the certificate trust checker.
@@ -153,16 +133,6 @@ namespace Swift {
*/
void setCertificateTrustChecker(CertificateTrustChecker*);
- /**
- * Sets whether ZLib stream compression should be used when available.
- */
- void setUseStreamCompression(bool b);
-
- /**
- * Sets whether TLS encryption should be used.
- */
- void setUseTLS(UseTLS useTLS);
-
public:
/**
* Emitted when the client was disconnected from the network.
@@ -197,12 +167,12 @@ namespace Swift {
/**
* Emitted when a message is received.
*/
- boost::signal<void (Message::ref)> onMessageReceived;
+ boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived;
/**
* Emitted when a presence stanza is received.
*/
- boost::signal<void (Presence::ref) > onPresenceReceived;
+ boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived;
/**
* Emitted when the server acknowledges receipt of a
@@ -210,7 +180,12 @@ namespace Swift {
*
* \see getStreamManagementEnabled()
*/
- boost::signal<void (Stanza::ref)> onStanzaAcked;
+ boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked;
+
+ protected:
+ boost::shared_ptr<ClientSession> getSession() const {
+ return session_;
+ }
private:
void handleConnectorFinished(boost::shared_ptr<Connection>);
@@ -219,19 +194,19 @@ namespace Swift {
void handleNeedCredentials();
void handleDataRead(const std::string&);
void handleDataWritten(const std::string&);
- void handlePresenceReceived(Presence::ref);
- void handleMessageReceived(Message::ref);
- void handleStanzaAcked(Stanza::ref);
+ void handlePresenceReceived(boost::shared_ptr<Presence>);
+ void handleMessageReceived(boost::shared_ptr<Message>);
+ void handleStanzaAcked(boost::shared_ptr<Stanza>);
private:
JID jid_;
std::string password_;
NetworkFactories* networkFactories;
- bool useStreamCompression;
- UseTLS useTLS;
ClientSessionStanzaChannel* stanzaChannel_;
IQRouter* iqRouter_;
- Connector::ref connector_;
+ ClientOptions options;
+ boost::shared_ptr<ChainedConnector> connector_;
+ std::vector<ConnectionFactory*> proxyConnectionFactories;
PlatformTLSFactories* tlsFactories;
boost::shared_ptr<Connection> connection_;
boost::shared_ptr<BasicSessionStream> sessionStream_;
diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h
index b9f05c3..306e2b4 100644
--- a/Swiften/Client/DummyStanzaChannel.h
+++ b/Swiften/Client/DummyStanzaChannel.h
@@ -56,6 +56,22 @@ namespace Swift {
return iqStanza && iqStanza->getType() == type && iqStanza->getTo() == jid && iqStanza->getPayload<T>();
}
+ bool isResultAtIndex(size_t index, const std::string& id) {
+ if (index >= sentStanzas.size()) {
+ return false;
+ }
+ boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]);
+ return iqStanza && iqStanza->getType() == IQ::Result && iqStanza->getID() == id;
+ }
+
+ bool isErrorAtIndex(size_t index, const std::string& id) {
+ if (index >= sentStanzas.size()) {
+ return false;
+ }
+ boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]);
+ return iqStanza && iqStanza->getType() == IQ::Error && iqStanza->getID() == id;
+ }
+
template<typename T> boost::shared_ptr<T> getStanzaAtIndex(size_t index) {
if (sentStanzas.size() <= index) {
return boost::shared_ptr<T>();
diff --git a/Swiften/Client/FileStorages.cpp b/Swiften/Client/FileStorages.cpp
deleted file mode 100644
index 3c76c46..0000000
--- a/Swiften/Client/FileStorages.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include "Swiften/Client/FileStorages.h"
-#include "Swiften/VCards/VCardFileStorage.h"
-#include "Swiften/Avatars/AvatarFileStorage.h"
-#include "Swiften/Disco/CapsFileStorage.h"
-
-namespace Swift {
-
-FileStorages::FileStorages(const boost::filesystem::path& baseDir, const JID& jid) {
- std::string profile = jid.toBare();
- vcardStorage = new VCardFileStorage(baseDir / profile / "vcards");
- capsStorage = new CapsFileStorage(baseDir / "caps");
- avatarStorage = new AvatarFileStorage(baseDir / "avatars", baseDir / profile / "avatars");
-}
-
-FileStorages::~FileStorages() {
- delete avatarStorage;
- delete capsStorage;
- delete vcardStorage;
-}
-
-VCardStorage* FileStorages::getVCardStorage() const {
- return vcardStorage;
-}
-
-CapsStorage* FileStorages::getCapsStorage() const {
- return capsStorage;
-}
-
-AvatarStorage* FileStorages::getAvatarStorage() const {
- return avatarStorage;
-}
-
-}
diff --git a/Swiften/Client/FileStorages.h b/Swiften/Client/FileStorages.h
deleted file mode 100644
index 451105f..0000000
--- a/Swiften/Client/FileStorages.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <boost/filesystem.hpp>
-
-#include "Swiften/Client/Storages.h"
-
-namespace Swift {
- class VCardFileStorage;
- class AvatarFileStorage;
- class CapsFileStorage;
- class JID;
-
- /**
- * A storages implementation that stores all controller data on disk.
- */
- class FileStorages : public Storages {
- public:
- /**
- * Creates the storages interface.
- *
- * All data will be stored relative to a base directory, and
- * for some controllers, in a subdirectory for the given profile.
- * The data is stored in the following places:
- * - Avatars: <basedir>/avatars
- * - VCards: <basedir>/<profile>/vcards
- * - Entity capabilities: <basedir>/caps
- *
- * \param baseDir the base dir to store data relative to
- * \param jid the subdir in which profile-specific data will be stored.
- * The bare JID will be used as the subdir name.
- */
- FileStorages(const boost::filesystem::path& baseDir, const JID& jid);
- ~FileStorages();
-
- virtual VCardStorage* getVCardStorage() const;
- virtual AvatarStorage* getAvatarStorage() const;
- virtual CapsStorage* getCapsStorage() const;
-
- private:
- VCardFileStorage* vcardStorage;
- AvatarFileStorage* avatarStorage;
- CapsFileStorage* capsStorage;
- };
-}
diff --git a/Swiften/Client/MemoryStorages.cpp b/Swiften/Client/MemoryStorages.cpp
index 5f6371b..6941add 100644
--- a/Swiften/Client/MemoryStorages.cpp
+++ b/Swiften/Client/MemoryStorages.cpp
@@ -8,6 +8,7 @@
#include "Swiften/VCards/VCardMemoryStorage.h"
#include "Swiften/Avatars/AvatarMemoryStorage.h"
#include "Swiften/Disco/CapsMemoryStorage.h"
+#include "Swiften/Roster/RosterMemoryStorage.h"
namespace Swift {
@@ -15,9 +16,11 @@ MemoryStorages::MemoryStorages() {
vcardStorage = new VCardMemoryStorage();
capsStorage = new CapsMemoryStorage();
avatarStorage = new AvatarMemoryStorage();
+ rosterStorage = new RosterMemoryStorage();
}
MemoryStorages::~MemoryStorages() {
+ delete rosterStorage;
delete avatarStorage;
delete capsStorage;
delete vcardStorage;
@@ -35,4 +38,9 @@ AvatarStorage* MemoryStorages::getAvatarStorage() const {
return avatarStorage;
}
+RosterStorage* MemoryStorages::getRosterStorage() const {
+ return rosterStorage;
+}
+
+
}
diff --git a/Swiften/Client/MemoryStorages.h b/Swiften/Client/MemoryStorages.h
index 67025cd..1e1a596 100644
--- a/Swiften/Client/MemoryStorages.h
+++ b/Swiften/Client/MemoryStorages.h
@@ -23,10 +23,12 @@ namespace Swift {
virtual VCardStorage* getVCardStorage() const;
virtual AvatarStorage* getAvatarStorage() const;
virtual CapsStorage* getCapsStorage() const;
+ virtual RosterStorage* getRosterStorage() const;
private:
VCardMemoryStorage* vcardStorage;
AvatarStorage* avatarStorage;
CapsStorage* capsStorage;
+ RosterStorage* rosterStorage;
};
}
diff --git a/Swiften/Client/NickResolver.h b/Swiften/Client/NickResolver.h
index 881362a..bf373fa 100644
--- a/Swiften/Client/NickResolver.h
+++ b/Swiften/Client/NickResolver.h
@@ -5,9 +5,9 @@
*/
#include <map>
-#include <boost/signals.hpp>
#include <boost/shared_ptr.hpp>
+#include <Swiften/Base/boost_bsignals.h>
#include <string>
#include "Swiften/JID/JID.h"
#include "Swiften/Elements/VCard.h"
diff --git a/Swiften/Client/Storages.cpp b/Swiften/Client/Storages.cpp
new file mode 100644
index 0000000..3c2dbc5
--- /dev/null
+++ b/Swiften/Client/Storages.cpp
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Client/Storages.h>
+
+using namespace Swift;
+
+Storages::~Storages() {
+}
diff --git a/Swiften/Client/Storages.h b/Swiften/Client/Storages.h
index e62f0a9..1c5bbe9 100644
--- a/Swiften/Client/Storages.h
+++ b/Swiften/Client/Storages.h
@@ -10,6 +10,7 @@ namespace Swift {
class VCardStorage;
class AvatarStorage;
class CapsStorage;
+ class RosterStorage;
/**
* An interface to hold storage classes for different
@@ -17,10 +18,11 @@ namespace Swift {
*/
class Storages {
public:
- virtual ~Storages() {}
+ virtual ~Storages();
virtual VCardStorage* getVCardStorage() const = 0;
virtual AvatarStorage* getAvatarStorage() const = 0;
virtual CapsStorage* getCapsStorage() const = 0;
+ virtual RosterStorage* getRosterStorage() const = 0;
};
}
diff --git a/Swiften/Component/ComponentSessionStanzaChannel.cpp b/Swiften/Component/ComponentSessionStanzaChannel.cpp
index b9fecb2..b342714 100644
--- a/Swiften/Component/ComponentSessionStanzaChannel.cpp
+++ b/Swiften/Component/ComponentSessionStanzaChannel.cpp
@@ -7,6 +7,7 @@
#include "Swiften/Component/ComponentSessionStanzaChannel.h"
#include <boost/bind.hpp>
+#include <iostream>
namespace Swift {
diff --git a/Swiften/Component/ComponentXMLTracer.cpp b/Swiften/Component/ComponentXMLTracer.cpp
new file mode 100644
index 0000000..b952c29
--- /dev/null
+++ b/Swiften/Component/ComponentXMLTracer.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Component/ComponentXMLTracer.h>
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+ComponentXMLTracer::ComponentXMLTracer(CoreComponent* client) {
+ client->onDataRead.connect(boost::bind(&ComponentXMLTracer::printData, '<', _1));
+ client->onDataWritten.connect(boost::bind(&ComponentXMLTracer::printData, '>', _1));
+}
+
+void ComponentXMLTracer::printData(char direction, const std::string& data) {
+ printLine(direction);
+ std::cerr << data << std::endl;
+}
+
+void ComponentXMLTracer::printLine(char c) {
+ for (unsigned int i = 0; i < 80; ++i) {
+ std::cerr << c;
+ }
+ std::cerr << std::endl;
+}
+
+}
diff --git a/Swiften/Component/ComponentXMLTracer.h b/Swiften/Component/ComponentXMLTracer.h
index 70a617b..d7e2b46 100644
--- a/Swiften/Component/ComponentXMLTracer.h
+++ b/Swiften/Component/ComponentXMLTracer.h
@@ -6,29 +6,15 @@
#pragma once
-#include <boost/bind.hpp>
-
#include "Swiften/Component/Component.h"
namespace Swift {
class ComponentXMLTracer {
public:
- ComponentXMLTracer(Component* component) {
- component->onDataRead.connect(boost::bind(&ComponentXMLTracer::printData, '<', _1));
- component->onDataWritten.connect(boost::bind(&ComponentXMLTracer::printData, '>', _1));
- }
+ ComponentXMLTracer(CoreComponent* component);
private:
- static void printData(char direction, const std::string& data) {
- printLine(direction);
- std::cerr << data << std::endl;
- }
-
- static void printLine(char c) {
- for (unsigned int i = 0; i < 80; ++i) {
- std::cerr << c;
- }
- std::cerr << std::endl;
- }
+ static void printData(char direction, const std::string& data);
+ static void printLine(char c);
};
}
diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp
index e79d735..f995ab0 100644
--- a/Swiften/Component/CoreComponent.cpp
+++ b/Swiften/Component/CoreComponent.cpp
@@ -7,6 +7,7 @@
#include "Swiften/Component/CoreComponent.h"
#include <boost/bind.hpp>
+#include <iostream>
#include "Swiften/Component/ComponentSession.h"
#include "Swiften/Network/Connector.h"
diff --git a/Swiften/Component/SConscript b/Swiften/Component/SConscript
index 0a9f250..ef5700c 100644
--- a/Swiften/Component/SConscript
+++ b/Swiften/Component/SConscript
@@ -7,6 +7,7 @@ sources = [
"ComponentSessionStanzaChannel.cpp",
"CoreComponent.cpp",
"Component.cpp",
+ "ComponentXMLTracer.cpp",
]
swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources))
diff --git a/Swiften/Compress/ZLibCompressor.cpp b/Swiften/Compress/ZLibCompressor.cpp
index 7e3116e..b740c68 100644
--- a/Swiften/Compress/ZLibCompressor.cpp
+++ b/Swiften/Compress/ZLibCompressor.cpp
@@ -6,6 +6,8 @@
#include "Swiften/Compress/ZLibCompressor.h"
+#include <cassert>
+
#pragma GCC diagnostic ignored "-Wold-style-cast"
namespace Swift {
diff --git a/Swiften/Compress/ZLibCompressor.h b/Swiften/Compress/ZLibCompressor.h
index 7fe5387..e0b4759 100644
--- a/Swiften/Compress/ZLibCompressor.h
+++ b/Swiften/Compress/ZLibCompressor.h
@@ -6,8 +6,6 @@
#pragma once
-#include <cassert>
-
#include "Swiften/Compress/ZLibCodecompressor.h"
#include "Swiften/Base/ByteArray.h"
diff --git a/Swiften/Compress/ZLibDecompressor.cpp b/Swiften/Compress/ZLibDecompressor.cpp
index af7349b..78e9846 100644
--- a/Swiften/Compress/ZLibDecompressor.cpp
+++ b/Swiften/Compress/ZLibDecompressor.cpp
@@ -6,6 +6,8 @@
#include "Swiften/Compress/ZLibDecompressor.h"
+#include <cassert>
+
#pragma GCC diagnostic ignored "-Wold-style-cast"
namespace Swift {
diff --git a/Swiften/Compress/ZLibDecompressor.h b/Swiften/Compress/ZLibDecompressor.h
index ec08a4f..917e1b7 100644
--- a/Swiften/Compress/ZLibDecompressor.h
+++ b/Swiften/Compress/ZLibDecompressor.h
@@ -6,8 +6,6 @@
#pragma once
-#include <cassert>
-
#include "Swiften/Compress/ZLibCodecompressor.h"
#include "Swiften/Base/ByteArray.h"
diff --git a/Swiften/Config/swiften-config.cpp b/Swiften/Config/swiften-config.cpp
index b3875cb..0c46cf0 100644
--- a/Swiften/Config/swiften-config.cpp
+++ b/Swiften/Config/swiften-config.cpp
@@ -11,6 +11,7 @@
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options.hpp>
#include <boost/version.hpp>
+#include <boost/filesystem.hpp>
#include <string>
#include <Swiften/Base/Platform.h>
diff --git a/Swiften/Disco/CapsFileStorage.cpp b/Swiften/Disco/CapsFileStorage.cpp
deleted file mode 100644
index 1e53854..0000000
--- a/Swiften/Disco/CapsFileStorage.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include "Swiften/Disco/CapsFileStorage.h"
-
-#include <iostream>
-#include <boost/filesystem/fstream.hpp>
-
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h"
-#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h"
-#include "Swiften/Parser/PayloadParsers/DiscoInfoParser.h"
-#include "Swiften/StringCodecs/Hexify.h"
-#include "Swiften/StringCodecs/Base64.h"
-
-namespace Swift {
-
-CapsFileStorage::CapsFileStorage(const boost::filesystem::path& path) : path(path) {
-}
-
-DiscoInfo::ref CapsFileStorage::getDiscoInfo(const std::string& hash) const {
- boost::filesystem::path capsPath(getCapsPath(hash));
- if (boost::filesystem::exists(capsPath)) {
- ByteArray data;
- data.readFromFile(capsPath.string());
-
- DiscoInfoParser parser;
- PayloadParserTester tester(&parser);
- tester.parse(data.toString());
- return boost::dynamic_pointer_cast<DiscoInfo>(parser.getPayload());
- }
- else {
- return DiscoInfo::ref();
- }
-}
-
-void CapsFileStorage::setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo) {
- boost::filesystem::path capsPath(getCapsPath(hash));
- if (!boost::filesystem::exists(capsPath.parent_path())) {
- try {
- boost::filesystem::create_directories(capsPath.parent_path());
- }
- catch (const boost::filesystem::filesystem_error& e) {
- std::cerr << "ERROR: " << e.what() << std::endl;
- }
- }
- DiscoInfo::ref bareDiscoInfo(new DiscoInfo(*discoInfo.get()));
- bareDiscoInfo->setNode("");
- boost::filesystem::ofstream file(capsPath);
- file << DiscoInfoSerializer().serializePayload(bareDiscoInfo);
- file.close();
-}
-
-boost::filesystem::path CapsFileStorage::getCapsPath(const std::string& hash) const {
- return path / (Hexify::hexify(Base64::decode(hash)) + ".xml");
-}
-
-}
diff --git a/Swiften/Disco/CapsFileStorage.h b/Swiften/Disco/CapsFileStorage.h
deleted file mode 100644
index 5faf08b..0000000
--- a/Swiften/Disco/CapsFileStorage.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <boost/filesystem.hpp>
-
-#include "Swiften/Disco/CapsStorage.h"
-#include <string>
-
-namespace Swift {
- class CapsFileStorage : public CapsStorage {
- public:
- CapsFileStorage(const boost::filesystem::path& path);
-
- virtual DiscoInfo::ref getDiscoInfo(const std::string& hash) const;
- virtual void setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo);
-
- private:
- boost::filesystem::path getCapsPath(const std::string& hash) const;
-
- private:
- boost::filesystem::path path;
- };
-}
diff --git a/Swiften/Disco/CapsManager.cpp b/Swiften/Disco/CapsManager.cpp
index 63166e6..6eb7c17 100644
--- a/Swiften/Disco/CapsManager.cpp
+++ b/Swiften/Disco/CapsManager.cpp
@@ -7,6 +7,7 @@
#include "Swiften/Disco/CapsManager.h"
#include <boost/bind.hpp>
+#include <iostream>
#include "Swiften/Client/StanzaChannel.h"
#include "Swiften/Disco/CapsStorage.h"
diff --git a/Swiften/Disco/DummyEntityCapsProvider.cpp b/Swiften/Disco/DummyEntityCapsProvider.cpp
new file mode 100644
index 0000000..a906652
--- /dev/null
+++ b/Swiften/Disco/DummyEntityCapsProvider.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Disco/DummyEntityCapsProvider.h>
+
+#include <iostream>
+
+namespace Swift {
+
+DiscoInfo::ref DummyEntityCapsProvider::getCaps(const JID& jid) const {
+ std::map<JID, DiscoInfo::ref>::const_iterator i = caps.find(jid);
+ if (i != caps.end()) {
+ return i->second;
+ }
+ return DiscoInfo::ref();
+}
+
+}
diff --git a/Swiften/Disco/DummyEntityCapsProvider.h b/Swiften/Disco/DummyEntityCapsProvider.h
index 68cef2f..1bd4bb9 100644
--- a/Swiften/Disco/DummyEntityCapsProvider.h
+++ b/Swiften/Disco/DummyEntityCapsProvider.h
@@ -7,7 +7,7 @@
#pragma once
#include <map>
-#include <iostream>
+
#include "Swiften/Disco/EntityCapsProvider.h"
namespace Swift {
@@ -16,13 +16,7 @@ namespace Swift {
DummyEntityCapsProvider() {
}
- DiscoInfo::ref getCaps(const JID& jid) const {
- std::map<JID, DiscoInfo::ref>::const_iterator i = caps.find(jid);
- if (i != caps.end()) {
- return i->second;
- }
- return DiscoInfo::ref();
- }
+ DiscoInfo::ref getCaps(const JID& jid) const;
std::map<JID, DiscoInfo::ref> caps;
};
diff --git a/Swiften/Disco/GetDiscoItemsRequest.h b/Swiften/Disco/GetDiscoItemsRequest.h
index 0a94402..46735ef 100644
--- a/Swiften/Disco/GetDiscoItemsRequest.h
+++ b/Swiften/Disco/GetDiscoItemsRequest.h
@@ -18,9 +18,18 @@ namespace Swift {
return ref(new GetDiscoItemsRequest(jid, router));
}
+ static ref create(const JID& jid, const std::string& node, IQRouter* router) {
+ return ref(new GetDiscoItemsRequest(jid, node, router));
+ }
+
private:
GetDiscoItemsRequest(const JID& jid, IQRouter* router) :
GenericRequest<DiscoItems>(IQ::Get, jid, boost::shared_ptr<DiscoItems>(new DiscoItems()), router) {
}
+
+ GetDiscoItemsRequest(const JID& jid, const std::string& node, IQRouter* router) :
+ GenericRequest<DiscoItems>(IQ::Get, jid, boost::shared_ptr<DiscoItems>(new DiscoItems()), router) {
+ getPayloadGeneric()->setNode(node);
+ }
};
}
diff --git a/Swiften/Disco/SConscript b/Swiften/Disco/SConscript
index 9982192..434018a 100644
--- a/Swiften/Disco/SConscript
+++ b/Swiften/Disco/SConscript
@@ -5,8 +5,8 @@ objects = swiften_env.SwiftenObject([
"CapsManager.cpp",
"EntityCapsManager.cpp",
"EntityCapsProvider.cpp",
+ "DummyEntityCapsProvider.cpp",
"CapsStorage.cpp",
- "CapsFileStorage.cpp",
"ClientDiscoManager.cpp",
"DiscoInfoResponder.cpp",
"JIDDiscoInfoResponder.cpp",
diff --git a/Swiften/Elements/Body.h b/Swiften/Elements/Body.h
index 2887390..a2497f7 100644
--- a/Swiften/Elements/Body.h
+++ b/Swiften/Elements/Body.h
@@ -6,14 +6,13 @@
#pragma once
-#include "Swiften/Elements/Payload.h"
#include <string>
+#include <Swiften/Elements/Payload.h>
+
namespace Swift {
class Body : public Payload {
public:
- typedef boost::shared_ptr<Body> ref;
-
Body(const std::string& text = "") : text_(text) {
}
diff --git a/Swiften/Elements/Bytestreams.h b/Swiften/Elements/Bytestreams.h
index b493375..211396b 100644
--- a/Swiften/Elements/Bytestreams.h
+++ b/Swiften/Elements/Bytestreams.h
@@ -9,9 +9,9 @@
#include <vector>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
+#include <string>
#include "Swiften/JID/JID.h"
-#include <string>
#include "Swiften/Elements/Payload.h"
namespace Swift {
diff --git a/Swiften/Elements/CapsInfo.h b/Swiften/Elements/CapsInfo.h
index ccad278..f1e2c37 100644
--- a/Swiften/Elements/CapsInfo.h
+++ b/Swiften/Elements/CapsInfo.h
@@ -7,8 +7,8 @@
#pragma once
#include <boost/shared_ptr.hpp>
-
#include <string>
+
#include "Swiften/Elements/Payload.h"
namespace Swift {
diff --git a/Swiften/Elements/ChatState.h b/Swiften/Elements/ChatState.h
index 2896877..ddeed79 100644
--- a/Swiften/Elements/ChatState.h
+++ b/Swiften/Elements/ChatState.h
@@ -7,6 +7,7 @@
#pragma once
#include <string>
+
#include "Swiften/Elements/Payload.h"
namespace Swift {
diff --git a/Swiften/Elements/Command.h b/Swiften/Elements/Command.h
index f4059a8..4a9c2a3 100644
--- a/Swiften/Elements/Command.h
+++ b/Swiften/Elements/Command.h
@@ -7,8 +7,8 @@
#pragma once
#include <boost/shared_ptr.hpp>
-
#include <string>
+
#include "Swiften/Elements/Payload.h"
#include "Swiften/Elements/Form.h"
diff --git a/Swiften/Elements/ComponentHandshake.h b/Swiften/Elements/ComponentHandshake.h
index 6047eab..3fe0457 100644
--- a/Swiften/Elements/ComponentHandshake.h
+++ b/Swiften/Elements/ComponentHandshake.h
@@ -7,9 +7,9 @@
#pragma once
#include <boost/shared_ptr.hpp>
+#include <string>
#include "Swiften/Elements/Element.h"
-#include <string>
namespace Swift {
class ComponentHandshake : public Element {
diff --git a/Swiften/Elements/Delay.h b/Swiften/Elements/Delay.h
index 3213037..85d167b 100644
--- a/Swiften/Elements/Delay.h
+++ b/Swiften/Elements/Delay.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/optional.hpp>
#include "Swiften/Elements/Payload.h"
diff --git a/Swiften/Elements/DiscoInfo.cpp b/Swiften/Elements/DiscoInfo.cpp
index f0e728e..5b2bb04 100644
--- a/Swiften/Elements/DiscoInfo.cpp
+++ b/Swiften/Elements/DiscoInfo.cpp
@@ -6,12 +6,15 @@
#include "Swiften/Elements/DiscoInfo.h"
+#include <algorithm>
+
namespace Swift {
const std::string DiscoInfo::ChatStatesFeature = std::string("http://jabber.org/protocol/chatstates");
const std::string DiscoInfo::SecurityLabelsFeature = std::string("urn:xmpp:sec-label:0");
const std::string DiscoInfo::SecurityLabelsCatalogFeature = std::string("urn:xmpp:sec-label:catalog:2");
const std::string DiscoInfo::JabberSearchFeature = std::string("jabber:iq:search");
+const std::string DiscoInfo::CommandsFeature = std::string("http://jabber.org/protocol/commands");
bool DiscoInfo::Identity::operator<(const Identity& other) const {
@@ -33,4 +36,8 @@ bool DiscoInfo::Identity::operator<(const Identity& other) const {
}
}
+bool DiscoInfo::hasFeature(const std::string& feature) const {
+ return std::find(features_.begin(), features_.end(), feature) != features_.end();
+}
+
}
diff --git a/Swiften/Elements/DiscoInfo.h b/Swiften/Elements/DiscoInfo.h
index d5bf64a..cd650b9 100644
--- a/Swiften/Elements/DiscoInfo.h
+++ b/Swiften/Elements/DiscoInfo.h
@@ -7,11 +7,9 @@
#pragma once
#include <vector>
-#include <algorithm>
-
-#include "Swiften/Elements/Payload.h"
#include <string>
+#include "Swiften/Elements/Payload.h"
#include "Swiften/Elements/Form.h"
namespace Swift {
@@ -23,6 +21,7 @@ namespace Swift {
static const std::string SecurityLabelsFeature;
static const std::string SecurityLabelsCatalogFeature;
static const std::string JabberSearchFeature;
+ static const std::string CommandsFeature;
class Identity {
public:
@@ -82,9 +81,7 @@ namespace Swift {
features_.push_back(feature);
}
- bool hasFeature(const std::string& feature) const {
- return std::find(features_.begin(), features_.end(), feature) != features_.end();
- }
+ bool hasFeature(const std::string& feature) const;
void addExtension(Form::ref form) {
extensions_.push_back(form);
diff --git a/Swiften/Elements/DiscoItems.h b/Swiften/Elements/DiscoItems.h
index cc5a583..1b7063b 100644
--- a/Swiften/Elements/DiscoItems.h
+++ b/Swiften/Elements/DiscoItems.h
@@ -7,10 +7,9 @@
#pragma once
#include <vector>
-#include <algorithm>
+#include <string>
#include "Swiften/Elements/Payload.h"
-#include <string>
#include "Swiften/JID/JID.h"
namespace Swift {
diff --git a/Swiften/Elements/Element.h b/Swiften/Elements/Element.h
index aded528..1e6a9d0 100644
--- a/Swiften/Elements/Element.h
+++ b/Swiften/Elements/Element.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_ELEMENT_H
-#define SWIFTEN_ELEMENT_H
+#pragma once
namespace Swift {
class Element {
@@ -13,5 +12,3 @@ namespace Swift {
virtual ~Element();
};
}
-
-#endif
diff --git a/Swiften/Elements/ErrorPayload.h b/Swiften/Elements/ErrorPayload.h
index 12ad574..cece81f 100644
--- a/Swiften/Elements/ErrorPayload.h
+++ b/Swiften/Elements/ErrorPayload.h
@@ -7,9 +7,9 @@
#pragma once
#include <boost/shared_ptr.hpp>
+#include <string>
#include "Swiften/Elements/Payload.h"
-#include <string>
namespace Swift {
class ErrorPayload : public Payload {
diff --git a/Swiften/Elements/Form.h b/Swiften/Elements/Form.h
index 1c50f0c..4e6e9f1 100644
--- a/Swiften/Elements/Form.h
+++ b/Swiften/Elements/Form.h
@@ -7,11 +7,10 @@
#pragma once
#include <vector>
+#include <string>
#include "Swiften/Elements/Payload.h"
#include "Swiften/Elements/FormField.h"
-#include <string>
-
#include "Swiften/JID/JID.h"
namespace Swift {
diff --git a/Swiften/Elements/FormField.h b/Swiften/Elements/FormField.h
index f455303..2438bb3 100644
--- a/Swiften/Elements/FormField.h
+++ b/Swiften/Elements/FormField.h
@@ -11,8 +11,8 @@
#include <vector>
#include <boost/shared_ptr.hpp>
-
#include <string>
+
#include "Swiften/JID/JID.h"
namespace Swift {
@@ -111,5 +111,4 @@ namespace Swift {
SWIFTEN_DECLARE_FORM_FIELD(JIDSingle, JID);
SWIFTEN_DECLARE_FORM_FIELD(JIDMulti, std::vector<JID>);
SWIFTEN_DECLARE_FORM_FIELD(ListMulti, std::vector<std::string>);
- SWIFTEN_DECLARE_FORM_FIELD(Untyped, std::vector<std::string>);
}
diff --git a/Swiften/Elements/IBB.h b/Swiften/Elements/IBB.h
index 55f2c4f..8138e83 100644
--- a/Swiften/Elements/IBB.h
+++ b/Swiften/Elements/IBB.h
@@ -6,11 +6,11 @@
#pragma once
+#include <string>
+#include <vector>
#include <boost/shared_ptr.hpp>
-#include <string>
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/Elements/Payload.h"
+#include <Swiften/Elements/Payload.h>
namespace Swift {
class IBB : public Payload {
@@ -36,7 +36,7 @@ namespace Swift {
return result;
}
- static IBB::ref createIBBData(const std::string& streamID, int sequenceNumber, const ByteArray& data) {
+ static IBB::ref createIBBData(const std::string& streamID, int sequenceNumber, const std::vector<unsigned char>& data) {
IBB::ref result(new IBB(Data, streamID));
result->setSequenceNumber(sequenceNumber);
result->setData(data);
@@ -71,11 +71,11 @@ namespace Swift {
return streamID;
}
- const ByteArray& getData() const {
+ const std::vector<unsigned char>& getData() const {
return data;
}
- void setData(const ByteArray& data) {
+ void setData(const std::vector<unsigned char>& data) {
this->data = data;
}
@@ -98,7 +98,7 @@ namespace Swift {
private:
Action action;
std::string streamID;
- ByteArray data;
+ std::vector<unsigned char> data;
StanzaType stanzaType;
int blockSize;
int sequenceNumber;
diff --git a/Swiften/Elements/InBandRegistrationPayload.h b/Swiften/Elements/InBandRegistrationPayload.h
index e4e1e6f..6e0f741 100644
--- a/Swiften/Elements/InBandRegistrationPayload.h
+++ b/Swiften/Elements/InBandRegistrationPayload.h
@@ -8,10 +8,10 @@
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
+#include <string>
#include "Swiften/Elements/Payload.h"
#include "Swiften/Elements/Form.h"
-#include <string>
namespace Swift {
class InBandRegistrationPayload : public Payload {
diff --git a/Swiften/Elements/JingleContent.h b/Swiften/Elements/JingleContentPayload.h
index 4ae908b..c44a806 100644
--- a/Swiften/Elements/JingleContent.h
+++ b/Swiften/Elements/JingleContentPayload.h
@@ -8,18 +8,17 @@
#include <vector>
#include <boost/optional.hpp>
-
#include <string>
+
#include <Swiften/JID/JID.h>
#include <Swiften/Elements/Payload.h>
#include <Swiften/Elements/JingleDescription.h>
-#include <Swiften/Elements/JingleTransport.h>
-#include <Swiften/Base/foreach.h>
+#include <Swiften/Elements/JingleTransportPayload.h>
namespace Swift {
- class JingleContent : public Payload {
+ class JingleContentPayload : public Payload {
public:
- typedef boost::shared_ptr<JingleContent> ref;
+ typedef boost::shared_ptr<JingleContentPayload> ref;
enum Creator {
InitiatorCreator,
@@ -33,10 +32,18 @@ namespace Swift {
BothSenders,
};*/
+ Creator getCreator() const {
+ return creator;
+ }
+
void setCreator(Creator creator) {
this->creator = creator;
}
+ const std::string& getName() const {
+ return name;
+ }
+
void setName(const std::string& name) {
this->name = name;
}
@@ -49,18 +56,18 @@ namespace Swift {
descriptions.push_back(description);
}
- const std::vector<JingleTransport::ref>& getTransports() const {
+ const std::vector<boost::shared_ptr<JingleTransportPayload> >& getTransports() const {
return transports;
}
- void addTransport(JingleTransport::ref transport) {
+ void addTransport(boost::shared_ptr<JingleTransportPayload> transport) {
transports.push_back(transport);
}
template<typename T>
boost::shared_ptr<T> getDescription() const {
- foreach (JingleDescription::ref i, descriptions) {
- boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i));
+ for (size_t i = 0; i < descriptions.size(); ++i) {
+ boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(descriptions[i]));
if (result) {
return result;
}
@@ -70,8 +77,8 @@ namespace Swift {
template<typename T>
boost::shared_ptr<T> getTransport() const {
- foreach (JingleTransport::ref i, transports) {
- boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i));
+ for (size_t i = 0; i < transports.size(); ++i) {
+ boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(transports[i]));
if (result) {
return result;
}
@@ -84,6 +91,6 @@ namespace Swift {
std::string name;
//Senders senders;
std::vector<JingleDescription::ref> descriptions;
- std::vector<JingleTransport::ref> transports;
+ std::vector<boost::shared_ptr<JingleTransportPayload> > transports;
};
}
diff --git a/Swiften/Elements/JingleIBBTransport.h b/Swiften/Elements/JingleIBBTransportPayload.h
index faa5af3..67aab09 100644
--- a/Swiften/Elements/JingleIBBTransport.h
+++ b/Swiften/Elements/JingleIBBTransportPayload.h
@@ -6,12 +6,16 @@
#pragma once
+#include <boost/shared_ptr.hpp>
#include <string>
-#include <Swiften/Elements/JingleTransport.h>
+
+#include <Swiften/Elements/JingleTransportPayload.h>
namespace Swift {
- class JingleIBBTransport : public JingleTransport {
+ class JingleIBBTransportPayload : public JingleTransportPayload {
public:
+ typedef boost::shared_ptr<JingleIBBTransportPayload> ref;
+
enum StanzaType {
IQStanza,
MessageStanza,
diff --git a/Swiften/Elements/JinglePayload.h b/Swiften/Elements/JinglePayload.h
index 59d3c99..be02543 100644
--- a/Swiften/Elements/JinglePayload.h
+++ b/Swiften/Elements/JinglePayload.h
@@ -12,7 +12,7 @@
#include <string>
#include <Swiften/JID/JID.h>
#include <Swiften/Elements/Payload.h>
-#include <Swiften/Elements/JingleContent.h>
+#include <Swiften/Elements/JingleContentPayload.h>
namespace Swift {
@@ -98,11 +98,11 @@ namespace Swift {
return sessionID;
}
- void addContent(JingleContent::ref content) {
+ void addContent(JingleContentPayload::ref content) {
this->contents.push_back(content);
}
- const std::vector<JingleContent::ref> getContents() const {
+ const std::vector<JingleContentPayload::ref> getContents() const {
return contents;
}
@@ -119,7 +119,7 @@ namespace Swift {
JID initiator;
JID responder;
std::string sessionID;
- std::vector<JingleContent::ref> contents;
+ std::vector<JingleContentPayload::ref> contents;
boost::optional<Reason> reason;
};
}
diff --git a/Swiften/Elements/JingleS5BTransport.h b/Swiften/Elements/JingleS5BTransportPayload.h
index 4522417..7b3089f 100644
--- a/Swiften/Elements/JingleS5BTransport.h
+++ b/Swiften/Elements/JingleS5BTransportPayload.h
@@ -6,11 +6,13 @@
#pragma once
-#include <Swiften/Elements/JingleTransport.h>
+#include <Swiften/Elements/JingleTransportPayload.h>
#include <Swiften/Elements/Bytestreams.h>
+// FIXME: Remove Bytestreams, and replace by our own candidate
+
namespace Swift {
- class JingleS5BTransport : public JingleTransport {
+ class JingleS5BTransportPayload : public JingleTransportPayload {
public:
const Bytestreams& getInfo() const {
return info;
diff --git a/Swiften/Elements/JingleTransportPayload.h b/Swiften/Elements/JingleTransportPayload.h
new file mode 100644
index 0000000..7a9ea29
--- /dev/null
+++ b/Swiften/Elements/JingleTransportPayload.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Elements/Payload.h>
+
+namespace Swift {
+ class JingleTransportPayload : public Payload {
+ public:
+ typedef boost::shared_ptr<JingleTransportPayload> ref;
+ };
+}
diff --git a/Swiften/Elements/MUCPayload.h b/Swiften/Elements/MUCPayload.h
index c372360..eb3baeb 100644
--- a/Swiften/Elements/MUCPayload.h
+++ b/Swiften/Elements/MUCPayload.h
@@ -7,7 +7,7 @@
#pragma once
#include <boost/optional.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "Swiften/JID/JID.h"
#include <string>
diff --git a/Swiften/Elements/Payload.h b/Swiften/Elements/Payload.h
index c87b899..8b6d44a 100644
--- a/Swiften/Elements/Payload.h
+++ b/Swiften/Elements/Payload.h
@@ -6,13 +6,9 @@
#pragma once
-#include <boost/shared_ptr.hpp>
-
namespace Swift {
class Payload {
public:
- typedef boost::shared_ptr<Payload> ref;
-
virtual ~Payload();
};
}
diff --git a/Swiften/Elements/Presence.cpp b/Swiften/Elements/Presence.cpp
new file mode 100644
index 0000000..6cde567
--- /dev/null
+++ b/Swiften/Elements/Presence.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Elements/Presence.h>
+
+#include <Swiften/Elements/Priority.h>
+#include <Swiften/Elements/Status.h>
+
+namespace Swift {
+
+Presence::Presence() : type_(Available) /*, showType_(Online)*/ {
+}
+
+Presence::Presence(const std::string& status) : type_(Available) {
+ setStatus(status);
+}
+
+Presence::~Presence() {
+}
+
+int Presence::getPriority() const {
+ boost::shared_ptr<Priority> priority(getPayload<Priority>());
+ return (priority ? priority->getPriority() : 0);
+}
+
+void Presence::setPriority(int priority) {
+ updatePayload(boost::shared_ptr<Priority>(new Priority(priority)));
+}
+
+std::string Presence::getStatus() const {
+ boost::shared_ptr<Status> status(getPayload<Status>());
+ if (status) {
+ return status->getText();
+ }
+ return "";
+}
+
+void Presence::setStatus(const std::string& status) {
+ updatePayload(boost::shared_ptr<Status>(new Status(status)));
+}
+
+
+}
diff --git a/Swiften/Elements/Presence.h b/Swiften/Elements/Presence.h
index 7f957ba..5ae482b 100644
--- a/Swiften/Elements/Presence.h
+++ b/Swiften/Elements/Presence.h
@@ -6,11 +6,8 @@
#pragma once
-
-#include "Swiften/Elements/Stanza.h"
-#include "Swiften/Elements/Status.h"
-#include "Swiften/Elements/StatusShow.h"
-#include "Swiften/Elements/Priority.h"
+#include <Swiften/Elements/Stanza.h>
+#include <Swiften/Elements/StatusShow.h>
namespace Swift {
class Presence : public Stanza {
@@ -19,10 +16,9 @@ namespace Swift {
enum Type { Available, Error, Probe, Subscribe, Subscribed, Unavailable, Unsubscribe, Unsubscribed };
- Presence() : type_(Available) /*, showType_(Online)*/ {}
- Presence(const std::string& status) : type_(Available) {
- setStatus(status);
- }
+ Presence();
+ Presence(const std::string& status);
+ virtual ~Presence();
static ref create() {
return ref(new Presence());
@@ -51,26 +47,11 @@ namespace Swift {
updatePayload(boost::shared_ptr<StatusShow>(new StatusShow(show)));
}
- std::string getStatus() const {
- boost::shared_ptr<Status> status(getPayload<Status>());
- if (status) {
- return status->getText();
- }
- return "";
- }
+ std::string getStatus() const;
+ void setStatus(const std::string& status);
- void setStatus(const std::string& status) {
- updatePayload(boost::shared_ptr<Status>(new Status(status)));
- }
-
- int getPriority() const {
- boost::shared_ptr<Priority> priority(getPayload<Priority>());
- return (priority ? priority->getPriority() : 0);
- }
-
- void setPriority(int priority) {
- updatePayload(boost::shared_ptr<Priority>(new Priority(priority)));
- }
+ int getPriority() const;
+ void setPriority(int priority);
boost::shared_ptr<Presence> clone() const {
return boost::shared_ptr<Presence>(new Presence(*this));
diff --git a/Swiften/Elements/Priority.h b/Swiften/Elements/Priority.h
index 12181d4..2c0cb9b 100644
--- a/Swiften/Elements/Priority.h
+++ b/Swiften/Elements/Priority.h
@@ -6,13 +6,11 @@
#pragma once
-#include "Swiften/Elements/Payload.h"
+#include <Swiften/Elements/Payload.h>
namespace Swift {
class Priority : public Payload {
public:
- typedef boost::shared_ptr<Priority> ref;
-
Priority(int priority = 0) : priority_(priority) {
}
diff --git a/Swiften/Elements/RosterItemExchangePayload.cpp b/Swiften/Elements/RosterItemExchangePayload.cpp
new file mode 100644
index 0000000..f4f3a57
--- /dev/null
+++ b/Swiften/Elements/RosterItemExchangePayload.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Elements/RosterItemExchangePayload.h"
+#include "Swiften/Base/foreach.h"
+
+namespace Swift {
+
+RosterItemExchangePayload::Item::Item() {
+}
+
+RosterItemExchangePayload::RosterItemExchangePayload() {
+}
+
+}
diff --git a/Swiften/Elements/RosterItemExchangePayload.h b/Swiften/Elements/RosterItemExchangePayload.h
new file mode 100644
index 0000000..d9e2912
--- /dev/null
+++ b/Swiften/Elements/RosterItemExchangePayload.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+#include <string>
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Elements/Payload.h"
+#include "Swiften/JID/JID.h"
+
+
+namespace Swift {
+ class RosterItemExchangePayload : public Payload {
+ public:
+ typedef boost::shared_ptr<RosterItemExchangePayload> ref;
+
+ class Item {
+ public:
+ enum Action { Add, Modify, Delete };
+
+ Item();
+
+ Action getAction() const {
+ return action;
+ }
+
+ void setAction(Action action) {
+ this->action = action;
+ }
+
+ const JID& getJID() const {
+ return jid;
+ }
+
+ void setJID(const JID& jid) {
+ this->jid = jid;
+ }
+
+ const std::string& getName() const {
+ return name;
+ }
+
+ void setName(const std::string& name) {
+ this->name = name;
+ }
+
+ const std::vector<std::string>& getGroups() const {
+ return groups;
+ }
+
+ void addGroup(const std::string& group) {
+ groups.push_back(group);
+ }
+
+ private:
+ Action action;
+ JID jid;
+ std::string name;
+ std::vector<std::string> groups;
+ };
+
+ typedef std::vector<RosterItemExchangePayload::Item> RosterItemExchangePayloadItems;
+
+ public:
+ RosterItemExchangePayload();
+
+ void addItem(const RosterItemExchangePayload::Item& item) {
+ items_.push_back(item);
+ }
+
+ const RosterItemExchangePayloadItems& getItems() const {
+ return items_;
+ }
+
+ private:
+ RosterItemExchangePayloadItems items_;
+ };
+}
diff --git a/Swiften/Elements/RosterItemPayload.h b/Swiften/Elements/RosterItemPayload.h
index b8a1b10..915ae31 100644
--- a/Swiften/Elements/RosterItemPayload.h
+++ b/Swiften/Elements/RosterItemPayload.h
@@ -4,22 +4,20 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_RosterItemPayloadPayload_H
-#define SWIFTEN_RosterItemPayloadPayload_H
+#pragma once
#include <vector>
-
-#include "Swiften/JID/JID.h"
#include <string>
+#include <Swiften/JID/JID.h>
+
namespace Swift {
- class RosterItemPayload
- {
+ class RosterItemPayload {
public:
enum Subscription { None, To, From, Both, Remove };
RosterItemPayload() : subscription_(None), ask_(false) {}
- RosterItemPayload(const JID& jid, const std::string& name, Subscription subscription) : jid_(jid), name_(name), subscription_(subscription), ask_(false) { }
+ RosterItemPayload(const JID& jid, const std::string& name, Subscription subscription, const std::vector<std::string>& groups = std::vector<std::string>()) : jid_(jid), name_(name), subscription_(subscription), groups_(groups), ask_(false) { }
void setJID(const JID& jid) { jid_ = jid; }
const JID& getJID() const { return jid_; }
@@ -51,5 +49,3 @@ namespace Swift {
std::string unknownContent_;
};
}
-
-#endif
diff --git a/Swiften/Elements/RosterPayload.h b/Swiften/Elements/RosterPayload.h
index b46b384..3102f0e 100644
--- a/Swiften/Elements/RosterPayload.h
+++ b/Swiften/Elements/RosterPayload.h
@@ -33,7 +33,16 @@ namespace Swift {
return items_;
}
+ const boost::optional<std::string>& getVersion() const {
+ return version_;
+ }
+
+ void setVersion(const std::string& version) {
+ version_ = version;
+ }
+
private:
RosterItemPayloads items_;
+ boost::optional<std::string> version_;
};
}
diff --git a/Swiften/Elements/SecurityLabelsCatalog.h b/Swiften/Elements/SecurityLabelsCatalog.h
index 10ef459..cd84b0b 100644
--- a/Swiften/Elements/SecurityLabelsCatalog.h
+++ b/Swiften/Elements/SecurityLabelsCatalog.h
@@ -4,13 +4,13 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_SecurityLabelsCatalog_H
-#define SWIFTEN_SecurityLabelsCatalog_H
+#pragma once
#include <vector>
+#include <string>
+#include <boost/shared_ptr.hpp>
#include "Swiften/JID/JID.h"
-#include <string>
#include "Swiften/Elements/Payload.h"
#include "Swiften/Elements/SecurityLabel.h"
@@ -85,5 +85,3 @@ namespace Swift {
std::vector<Item> items_;
};
}
-
-#endif
diff --git a/Swiften/Elements/SoftwareVersion.h b/Swiften/Elements/SoftwareVersion.h
index 5863b38..887c6e9 100644
--- a/Swiften/Elements/SoftwareVersion.h
+++ b/Swiften/Elements/SoftwareVersion.h
@@ -6,8 +6,10 @@
#pragma once
-#include "Swiften/Elements/Payload.h"
#include <string>
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Elements/Payload.h"
namespace Swift {
class SoftwareVersion : public Payload {
diff --git a/Swiften/Elements/Stanza.cpp b/Swiften/Elements/Stanza.cpp
index d15d778..607dfd1 100644
--- a/Swiften/Elements/Stanza.cpp
+++ b/Swiften/Elements/Stanza.cpp
@@ -9,8 +9,13 @@
#include <typeinfo>
+#include <Swiften/Base/foreach.h>
+
namespace Swift {
+Stanza::Stanza() {
+}
+
Stanza::~Stanza() {
payloads_.clear();
}
diff --git a/Swiften/Elements/Stanza.h b/Swiften/Elements/Stanza.h
index 9b934e4..9e082cc 100644
--- a/Swiften/Elements/Stanza.h
+++ b/Swiften/Elements/Stanza.h
@@ -7,27 +7,28 @@
#pragma once
#include <vector>
+#include <string>
#include <boost/shared_ptr.hpp>
-#include <boost/optional.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/optional/optional_fwd.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
-#include "Swiften/Elements/Element.h"
-#include "Swiften/Elements/Payload.h"
-#include <string>
-#include "Swiften/Base/foreach.h"
-#include "Swiften/JID/JID.h"
+#include <Swiften/Elements/Element.h>
+#include <Swiften/JID/JID.h>
namespace Swift {
+ class Payload;
+
class Stanza : public Element {
public:
typedef boost::shared_ptr<Stanza> ref;
+ Stanza();
virtual ~Stanza();
template<typename T>
boost::shared_ptr<T> getPayload() const {
- foreach (const boost::shared_ptr<Payload>& i, payloads_) {
- boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i));
+ for (size_t i = 0; i < payloads_.size(); ++i) {
+ boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(payloads_[i]));
if (result) {
return result;
}
@@ -38,8 +39,8 @@ namespace Swift {
template<typename T>
std::vector< boost::shared_ptr<T> > getPayloads() const {
std::vector< boost::shared_ptr<T> > results;
- foreach (const boost::shared_ptr<Payload>& i, payloads_) {
- boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i));
+ for (size_t i = 0; i < payloads_.size(); ++i) {
+ boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(payloads_[i]));
if (result) {
results.push_back(result);
}
@@ -78,8 +79,6 @@ namespace Swift {
std::string id_;
JID from_;
JID to_;
-
- typedef std::vector< boost::shared_ptr<Payload> > Payloads;
- Payloads payloads_;
+ std::vector< boost::shared_ptr<Payload> > payloads_;
};
}
diff --git a/Swiften/Elements/Status.h b/Swiften/Elements/Status.h
index 3ef6401..bb9b6e9 100644
--- a/Swiften/Elements/Status.h
+++ b/Swiften/Elements/Status.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_Status_H
-#define SWIFTEN_Status_H
+#pragma once
#include "Swiften/Elements/Payload.h"
#include <string>
@@ -28,5 +27,3 @@ namespace Swift {
std::string text_;
};
}
-
-#endif
diff --git a/Swiften/Elements/StatusShow.cpp b/Swiften/Elements/StatusShow.cpp
new file mode 100644
index 0000000..656e5c4
--- /dev/null
+++ b/Swiften/Elements/StatusShow.cpp
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Elements/StatusShow.h>
+
+using namespace Swift;
+
+StatusShow::StatusShow(const Type& type) : type_(type) {
+}
diff --git a/Swiften/Elements/StatusShow.h b/Swiften/Elements/StatusShow.h
index a158239..cd3477e 100644
--- a/Swiften/Elements/StatusShow.h
+++ b/Swiften/Elements/StatusShow.h
@@ -4,19 +4,16 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_StatusShow_H
-#define SWIFTEN_StatusShow_H
+#pragma once
-#include "Swiften/Elements/Payload.h"
-#include <string>
+#include <Swiften/Elements/Payload.h>
namespace Swift {
class StatusShow : public Payload {
public:
enum Type { Online, Away, FFC, XA, DND, None };
- StatusShow(const Type& type = Online) : type_(type) {
- }
+ StatusShow(const Type& type = Online);
void setType(const Type& type) {
type_ = type;
@@ -32,19 +29,17 @@ namespace Swift {
*/
static int typeToAvailabilityOrdering(Type type) {
switch (type) {
- case Online: return 4;
- case FFC: return 5;
- case Away: return 2;
- case XA: return 1;
- case DND: return 3;
- case None: return 0;
+ case Online: return 4;
+ case FFC: return 5;
+ case Away: return 2;
+ case XA: return 1;
+ case DND: return 3;
+ case None: return 0;
}
- return -1;
+ return 0;
}
private:
Type type_;
};
}
-
-#endif
diff --git a/Swiften/Elements/StreamFeatures.cpp b/Swiften/Elements/StreamFeatures.cpp
new file mode 100644
index 0000000..c6f6c04
--- /dev/null
+++ b/Swiften/Elements/StreamFeatures.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Elements/StreamFeatures.h>
+
+#include <algorithm>
+
+namespace Swift {
+
+bool StreamFeatures::hasCompressionMethod(const std::string& mechanism) const {
+ return std::find(compressionMethods_.begin(), compressionMethods_.end(), mechanism) != compressionMethods_.end();
+}
+
+bool StreamFeatures::hasAuthenticationMechanism(const std::string& mechanism) const {
+ return std::find(authenticationMechanisms_.begin(), authenticationMechanisms_.end(), mechanism) != authenticationMechanisms_.end();
+}
+
+}
diff --git a/Swiften/Elements/StreamFeatures.h b/Swiften/Elements/StreamFeatures.h
index fbc0bb8..5dc5a26 100644
--- a/Swiften/Elements/StreamFeatures.h
+++ b/Swiften/Elements/StreamFeatures.h
@@ -7,9 +7,9 @@
#pragma once
#include <vector>
-#include <algorithm>
-
#include <string>
+#include <boost/shared_ptr.hpp>
+
#include "Swiften/Elements/Element.h"
namespace Swift {
@@ -17,7 +17,7 @@ namespace Swift {
public:
typedef boost::shared_ptr<StreamFeatures> ref;
- StreamFeatures() : hasStartTLS_(false), hasResourceBind_(false), hasSession_(false), hasStreamManagement_(false) {}
+ StreamFeatures() : hasStartTLS_(false), hasResourceBind_(false), hasSession_(false), hasStreamManagement_(false), hasRosterVersioning_(false) {}
void setHasStartTLS() {
hasStartTLS_ = true;
@@ -51,9 +51,7 @@ namespace Swift {
compressionMethods_.push_back(mechanism);
}
- bool hasCompressionMethod(const std::string& mechanism) const {
- return std::find(compressionMethods_.begin(), compressionMethods_.end(), mechanism) != compressionMethods_.end();
- }
+ bool hasCompressionMethod(const std::string& mechanism) const;
const std::vector<std::string>& getAuthenticationMechanisms() const {
return authenticationMechanisms_;
@@ -63,9 +61,7 @@ namespace Swift {
authenticationMechanisms_.push_back(mechanism);
}
- bool hasAuthenticationMechanism(const std::string& mechanism) const {
- return std::find(authenticationMechanisms_.begin(), authenticationMechanisms_.end(), mechanism) != authenticationMechanisms_.end();
- }
+ bool hasAuthenticationMechanism(const std::string& mechanism) const;
bool hasAuthenticationMechanisms() const {
return !authenticationMechanisms_.empty();
@@ -79,6 +75,14 @@ namespace Swift {
hasStreamManagement_ = true;
}
+ bool hasRosterVersioning() const {
+ return hasRosterVersioning_;
+ }
+
+ void setHasRosterVersioning() {
+ hasRosterVersioning_ = true;
+ }
+
private:
bool hasStartTLS_;
std::vector<std::string> compressionMethods_;
@@ -86,5 +90,6 @@ namespace Swift {
bool hasResourceBind_;
bool hasSession_;
bool hasStreamManagement_;
+ bool hasRosterVersioning_;
};
}
diff --git a/Swiften/Elements/StreamManagementEnabled.cpp b/Swiften/Elements/StreamManagementEnabled.cpp
new file mode 100644
index 0000000..bab7516
--- /dev/null
+++ b/Swiften/Elements/StreamManagementEnabled.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Elements/StreamManagementEnabled.h>
+
+using namespace Swift;
+
+StreamManagementEnabled::StreamManagementEnabled() {
+}
+
+StreamManagementEnabled::~StreamManagementEnabled() {
+}
diff --git a/Swiften/Elements/StreamManagementEnabled.h b/Swiften/Elements/StreamManagementEnabled.h
index 0c72b84..02e77f3 100644
--- a/Swiften/Elements/StreamManagementEnabled.h
+++ b/Swiften/Elements/StreamManagementEnabled.h
@@ -1,17 +1,39 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2011 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
-#include "Swiften/Elements/Element.h"
+#include <string>
+#include <Swiften/Elements/Element.h>
namespace Swift {
class StreamManagementEnabled : public Element {
public:
- StreamManagementEnabled() {}
+ StreamManagementEnabled();
+ ~StreamManagementEnabled();
+
+ void setResumeSupported() {
+ resumeSupported = true;
+ }
+
+ bool getResumeSupported() const {
+ return resumeSupported;
+ }
+
+ void setResumeID(const std::string& id) {
+ resumeID = id;
+ }
+
+ const std::string& getResumeID() const {
+ return resumeID;
+ }
+
+ private:
+ bool resumeSupported;
+ std::string resumeID;
};
}
diff --git a/Swiften/Elements/StreamResume.cpp b/Swiften/Elements/StreamResume.cpp
new file mode 100644
index 0000000..d55ef78
--- /dev/null
+++ b/Swiften/Elements/StreamResume.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Elements/StreamResume.h>
+
+using namespace Swift;
+
+StreamResume::StreamResume() {
+}
+
+StreamResume::~StreamResume() {
+}
diff --git a/Swiften/Elements/StreamResume.h b/Swiften/Elements/StreamResume.h
new file mode 100644
index 0000000..652182a
--- /dev/null
+++ b/Swiften/Elements/StreamResume.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <boost/optional.hpp>
+
+#include <Swiften/Elements/Element.h>
+
+namespace Swift {
+ class StreamResume : public Element {
+ public:
+ StreamResume();
+ ~StreamResume();
+
+ void setResumeID(const std::string& id) {
+ resumeID = id;
+ }
+
+ const std::string& getResumeID() const {
+ return resumeID;
+ }
+
+ const boost::optional<int> getHandledStanzasCount() const {
+ return handledStanzasCount;
+ }
+
+ void setHandledStanzasCount(int i) {
+ handledStanzasCount = i;
+ }
+
+ private:
+ std::string resumeID;
+ boost::optional<int> handledStanzasCount;
+ };
+}
diff --git a/Swiften/Elements/StreamResumed.cpp b/Swiften/Elements/StreamResumed.cpp
new file mode 100644
index 0000000..552e654
--- /dev/null
+++ b/Swiften/Elements/StreamResumed.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Elements/StreamResumed.h>
+
+using namespace Swift;
+
+StreamResumed::StreamResumed() {
+}
+
+StreamResumed::~StreamResumed() {
+}
diff --git a/Swiften/Elements/StreamResumed.h b/Swiften/Elements/StreamResumed.h
new file mode 100644
index 0000000..cc42895
--- /dev/null
+++ b/Swiften/Elements/StreamResumed.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <boost/optional.hpp>
+
+#include <Swiften/Elements/Element.h>
+
+namespace Swift {
+ class StreamResumed : public Element {
+ public:
+ StreamResumed();
+ ~StreamResumed();
+
+ void setResumeID(const std::string& id) {
+ resumeID = id;
+ }
+
+ const std::string& getResumeID() const {
+ return resumeID;
+ }
+
+ const boost::optional<int> getHandledStanzasCount() const {
+ return handledStanzasCount;
+ }
+
+ void setHandledStanzasCount(int i) {
+ handledStanzasCount = i;
+ }
+
+ private:
+ std::string resumeID;
+ boost::optional<int> handledStanzasCount;
+ };
+}
diff --git a/Swiften/Elements/UnitTest/StanzaTest.cpp b/Swiften/Elements/UnitTest/StanzaTest.cpp
index 4020f8b..4669f16 100644
--- a/Swiften/Elements/UnitTest/StanzaTest.cpp
+++ b/Swiften/Elements/UnitTest/StanzaTest.cpp
@@ -7,6 +7,7 @@
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
#include "Swiften/Elements/Stanza.h"
#include "Swiften/Elements/Payload.h"
diff --git a/Swiften/Entity/Entity.cpp b/Swiften/Entity/Entity.cpp
index da2ecaf..dea47b0 100644
--- a/Swiften/Entity/Entity.cpp
+++ b/Swiften/Entity/Entity.cpp
@@ -6,26 +6,45 @@
#include "Swiften/Entity/Entity.h"
+#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
+#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
+
+
namespace Swift {
+Entity::Entity() {
+ payloadParserFactories = new FullPayloadParserFactoryCollection();
+ payloadSerializers = new FullPayloadSerializerCollection();
+}
+
Entity::~Entity() {
+ delete payloadSerializers;
+ delete payloadParserFactories;
}
void Entity::addPayloadParserFactory(PayloadParserFactory* payloadParserFactory) {
- payloadParserFactories.addFactory(payloadParserFactory);
+ payloadParserFactories->addFactory(payloadParserFactory);
}
void Entity::removePayloadParserFactory(PayloadParserFactory* payloadParserFactory) {
- payloadParserFactories.removeFactory(payloadParserFactory);
+ payloadParserFactories->removeFactory(payloadParserFactory);
}
void Entity::addPayloadSerializer(PayloadSerializer* payloadSerializer) {
- payloadSerializers.addSerializer(payloadSerializer);
+ payloadSerializers->addSerializer(payloadSerializer);
}
void Entity::removePayloadSerializer(PayloadSerializer* payloadSerializer) {
- payloadSerializers.removeSerializer(payloadSerializer);
+ payloadSerializers->removeSerializer(payloadSerializer);
+}
+
+PayloadParserFactoryCollection* Entity::getPayloadParserFactories() {
+ return payloadParserFactories;
+}
+
+PayloadSerializerCollection* Entity::getPayloadSerializers() {
+ return payloadSerializers;
}
}
diff --git a/Swiften/Entity/Entity.h b/Swiften/Entity/Entity.h
index 20d02ba..65480d0 100644
--- a/Swiften/Entity/Entity.h
+++ b/Swiften/Entity/Entity.h
@@ -6,21 +6,20 @@
#pragma once
-#include <Swiften/Base/boost_bsignals.h>
-#include <boost/shared_ptr.hpp>
-
-#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
-#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
-
namespace Swift {
class PayloadParserFactory;
class PayloadSerializer;
+ class FullPayloadParserFactoryCollection;
+ class FullPayloadSerializerCollection;
+ class PayloadParserFactoryCollection;
+ class PayloadSerializerCollection;
/**
* The base class for XMPP entities (Clients, Components).
*/
class Entity {
public:
+ Entity();
virtual ~Entity();
void addPayloadParserFactory(PayloadParserFactory* payloadParserFactory);
@@ -30,16 +29,11 @@ namespace Swift {
void removePayloadSerializer(PayloadSerializer* payloadSerializer);
protected:
- PayloadParserFactoryCollection* getPayloadParserFactories() {
- return &payloadParserFactories;
- }
-
- PayloadSerializerCollection* getPayloadSerializers() {
- return &payloadSerializers;
- }
+ PayloadParserFactoryCollection* getPayloadParserFactories();
+ PayloadSerializerCollection* getPayloadSerializers();
private:
- FullPayloadParserFactoryCollection payloadParserFactories;
- FullPayloadSerializerCollection payloadSerializers;
+ FullPayloadParserFactoryCollection* payloadParserFactories;
+ FullPayloadSerializerCollection* payloadSerializers;
};
}
diff --git a/Swiften/Entity/GenericPayloadPersister.h b/Swiften/Entity/GenericPayloadPersister.h
new file mode 100644
index 0000000..63553de
--- /dev/null
+++ b/Swiften/Entity/GenericPayloadPersister.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Entity/PayloadPersister.h>
+#include <Swiften/Parser/GenericPayloadParserFactory.h>
+
+namespace Swift {
+ template<typename PAYLOAD, typename PARSER, typename SERIALIZER>
+ class GenericPayloadPersister : public PayloadPersister {
+ public:
+ GenericPayloadPersister() {
+ }
+
+ public:
+ boost::shared_ptr<PAYLOAD> loadPayloadGeneric(const boost::filesystem::path& path) {
+ return boost::dynamic_pointer_cast<PAYLOAD>(loadPayload(path));
+ }
+
+ protected:
+ virtual const PayloadSerializer* getSerializer() const {
+ return &serializer;
+ }
+
+ virtual PayloadParser* createParser() const {
+ return new PARSER();
+ }
+
+ private:
+ SERIALIZER serializer;
+ };
+}
diff --git a/Swiften/Entity/PayloadPersister.cpp b/Swiften/Entity/PayloadPersister.cpp
new file mode 100644
index 0000000..f7278cc
--- /dev/null
+++ b/Swiften/Entity/PayloadPersister.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Entity/PayloadPersister.h>
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/filesystem.hpp>
+#include <iostream>
+
+#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h>
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Parser/PayloadParser.h>
+#include <Swiften/Parser/PayloadParserFactory.h>
+#include <Swiften/Serializer/PayloadSerializer.h>
+
+using namespace Swift;
+
+PayloadPersister::PayloadPersister() {
+}
+
+PayloadPersister::~PayloadPersister() {
+}
+
+void PayloadPersister::savePayload(boost::shared_ptr<Payload> payload, const boost::filesystem::path& path) {
+ if (!boost::filesystem::exists(path.parent_path())) {
+ try {
+ boost::filesystem::create_directories(path.parent_path());
+ }
+ catch (const boost::filesystem::filesystem_error& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ }
+ }
+ boost::filesystem::ofstream file(path);
+ file << getSerializer()->serialize(payload);
+ file.close();
+}
+
+boost::shared_ptr<Payload> PayloadPersister::loadPayload(const boost::filesystem::path& path) {
+ if (boost::filesystem::exists(path)) {
+ ByteArray data;
+ data.readFromFile(path.string());
+ std::auto_ptr<PayloadParser> parser(createParser());
+ PayloadParserTester tester(parser.get());
+ tester.parse(data.toString());
+ return parser->getPayload();
+ }
+ else {
+ return boost::shared_ptr<Payload>();
+ }
+}
diff --git a/Swiften/Entity/PayloadPersister.h b/Swiften/Entity/PayloadPersister.h
new file mode 100644
index 0000000..ea7c74c
--- /dev/null
+++ b/Swiften/Entity/PayloadPersister.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem/path.hpp>
+
+namespace Swift {
+ class Payload;
+ class PayloadSerializer;
+ class PayloadParser;
+
+ class PayloadPersister {
+ public:
+ PayloadPersister();
+ virtual ~PayloadPersister();
+
+ void savePayload(boost::shared_ptr<Payload>, const boost::filesystem::path&);
+ boost::shared_ptr<Payload> loadPayload(const boost::filesystem::path&);
+
+ protected:
+
+ virtual const PayloadSerializer* getSerializer() const = 0;
+ virtual PayloadParser* createParser() const = 0;
+ };
+}
diff --git a/Swiften/EventLoop/DummyEventLoop.cpp b/Swiften/EventLoop/DummyEventLoop.cpp
new file mode 100644
index 0000000..3741eec
--- /dev/null
+++ b/Swiften/EventLoop/DummyEventLoop.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/EventLoop/DummyEventLoop.h>
+
+#include <iostream>
+
+namespace Swift {
+
+DummyEventLoop::DummyEventLoop() {
+}
+
+DummyEventLoop::~DummyEventLoop() {
+ if (!events_.empty()) {
+ std::cerr << "DummyEventLoop: Unhandled events at destruction time" << std::endl;
+ }
+ events_.clear();
+}
+
+
+}
diff --git a/Swiften/EventLoop/DummyEventLoop.h b/Swiften/EventLoop/DummyEventLoop.h
index b7ef516..68f9b85 100644
--- a/Swiften/EventLoop/DummyEventLoop.h
+++ b/Swiften/EventLoop/DummyEventLoop.h
@@ -7,24 +7,14 @@
#pragma once
#include <deque>
-#include <iostream>
-#include <boost/function.hpp>
#include "Swiften/EventLoop/EventLoop.h"
-#include "Swiften/Base/foreach.h"
namespace Swift {
class DummyEventLoop : public EventLoop {
public:
- DummyEventLoop() {
- }
-
- ~DummyEventLoop() {
- if (!events_.empty()) {
- std::cerr << "DummyEventLoop: Unhandled events at destruction time" << std::endl;
- }
- events_.clear();
- }
+ DummyEventLoop();
+ ~DummyEventLoop();
void processEvents() {
while (!events_.empty()) {
diff --git a/Swiften/EventLoop/EventLoop.cpp b/Swiften/EventLoop/EventLoop.cpp
index 56bb6ac..510ed63 100644
--- a/Swiften/EventLoop/EventLoop.cpp
+++ b/Swiften/EventLoop/EventLoop.cpp
@@ -9,6 +9,7 @@
#include <algorithm>
#include <boost/bind.hpp>
#include <iostream>
+#include <cassert>
#include <Swiften/Base/Log.h>
@@ -17,6 +18,7 @@ namespace Swift {
inline void invokeCallback(const Event& event) {
try {
+ assert(!event.callback.empty());
event.callback();
}
catch (const std::exception& e) {
diff --git a/Swiften/EventLoop/SConscript b/Swiften/EventLoop/SConscript
index 21ae8b9..e448f43 100644
--- a/Swiften/EventLoop/SConscript
+++ b/Swiften/EventLoop/SConscript
@@ -5,6 +5,7 @@ sources = [
"EventOwner.cpp",
"Event.cpp",
"SimpleEventLoop.cpp",
+ "DummyEventLoop.cpp",
]
objects = swiften_env.SwiftenObject(sources)
diff --git a/Swiften/Examples/BenchTool/BenchTool.cpp b/Swiften/Examples/BenchTool/BenchTool.cpp
index 9e54ed9..1fb6601 100644
--- a/Swiften/Examples/BenchTool/BenchTool.cpp
+++ b/Swiften/Examples/BenchTool/BenchTool.cpp
@@ -6,6 +6,7 @@
#include <boost/bind.hpp>
#include <boost/thread.hpp>
+#include <iostream>
#include "Swiften/Client/Client.h"
#include "Swiften/Network/TimerFactory.h"
diff --git a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
index fda203a..3b66d96 100644
--- a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
+++ b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
@@ -6,6 +6,7 @@
#include <boost/bind.hpp>
#include <boost/thread.hpp>
+#include <iostream>
#include "Swiften/Client/Client.h"
#include "Swiften/Network/Timer.h"
diff --git a/Swiften/Examples/SendFile/ReceiveFile.cpp b/Swiften/Examples/SendFile/ReceiveFile.cpp
index b46d790..effa1b7 100644
--- a/Swiften/Examples/SendFile/ReceiveFile.cpp
+++ b/Swiften/Examples/SendFile/ReceiveFile.cpp
@@ -7,7 +7,10 @@
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/smart_ptr/make_shared.hpp>
+#include <iostream>
+#include <Swiften/Elements/Presence.h>
+#include <Swiften/Base/foreach.h>
#include <Swiften/Client/Client.h>
#include <Swiften/Network/BoostNetworkFactories.h>
#include <Swiften/EventLoop/SimpleEventLoop.h>
diff --git a/Swiften/Examples/SendFile/SendFile.cpp b/Swiften/Examples/SendFile/SendFile.cpp
index 5ec00a9..d8300be 100644
--- a/Swiften/Examples/SendFile/SendFile.cpp
+++ b/Swiften/Examples/SendFile/SendFile.cpp
@@ -6,15 +6,17 @@
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
+#include <iostream>
#include "Swiften/Client/Client.h"
+#include <Swiften/Elements/Presence.h>
#include "Swiften/Network/BoostTimer.h"
#include "Swiften/Network/TimerFactory.h"
#include "Swiften/Network/BoostNetworkFactories.h"
#include "Swiften/EventLoop/EventLoop.h"
#include "Swiften/Client/ClientXMLTracer.h"
#include "Swiften/EventLoop/SimpleEventLoop.h"
-#include "Swiften/FileTransfer/OutgoingFileTransfer.h"
+#include "Swiften/FileTransfer/OutgoingSIFileTransfer.h"
#include "Swiften/FileTransfer/FileReadBytestream.h"
#include "Swiften/FileTransfer/SOCKS5BytestreamServer.h"
#include "Swiften/Network/BoostConnectionServer.h"
@@ -64,7 +66,7 @@ class FileSender {
private:
void handleConnected() {
client->sendPresence(Presence::create());
- transfer = new OutgoingFileTransfer("myid", client->getJID(), recipient, file.filename(), boost::filesystem::file_size(file), "A file", boost::shared_ptr<FileReadBytestream>(new FileReadBytestream(file)), client->getIQRouter(), socksBytestreamServer);
+ transfer = new OutgoingSIFileTransfer("myid", client->getJID(), recipient, file.filename(), boost::filesystem::file_size(file), "A file", boost::shared_ptr<FileReadBytestream>(new FileReadBytestream(file)), client->getIQRouter(), socksBytestreamServer);
transfer->onFinished.connect(boost::bind(&FileSender::handleFileTransferFinished, this, _1));
transfer->start();
}
@@ -99,7 +101,7 @@ class FileSender {
boost::filesystem::path file;
Client* client;
ClientXMLTracer* tracer;
- OutgoingFileTransfer* transfer;
+ OutgoingSIFileTransfer* transfer;
};
diff --git a/Swiften/Examples/SendMessage/SendMessage.cpp b/Swiften/Examples/SendMessage/SendMessage.cpp
index d7f7333..ad75318 100644
--- a/Swiften/Examples/SendMessage/SendMessage.cpp
+++ b/Swiften/Examples/SendMessage/SendMessage.cpp
@@ -6,8 +6,10 @@
#include <boost/bind.hpp>
#include <boost/thread.hpp>
+#include <iostream>
#include "Swiften/Client/Client.h"
+#include "Swiften/Elements/Message.h"
#include "Swiften/Network/BoostNetworkFactories.h"
#include "Swiften/Network/TimerFactory.h"
#include "Swiften/EventLoop/EventLoop.h"
diff --git a/Swiften/FileTransfer/ByteArrayReadBytestream.h b/Swiften/FileTransfer/ByteArrayReadBytestream.h
index d459658..4704db6 100644
--- a/Swiften/FileTransfer/ByteArrayReadBytestream.h
+++ b/Swiften/FileTransfer/ByteArrayReadBytestream.h
@@ -6,31 +6,32 @@
#pragma once
-#include "Swiften/FileTransfer/ReadBytestream.h"
-#include "Swiften/Base/ByteArray.h"
+#include <vector>
+
+#include <Swiften/FileTransfer/ReadBytestream.h>
namespace Swift {
class ByteArrayReadBytestream : public ReadBytestream {
public:
- ByteArrayReadBytestream(const ByteArray& data) : data(data), position(0) {
+ ByteArrayReadBytestream(const std::vector<unsigned char>& data) : data(data), position(0) {
}
- virtual ByteArray read(size_t size) {
+ virtual std::vector<unsigned char> read(size_t size) {
size_t readSize = size;
- if (position + readSize > data.getSize()) {
- readSize = data.getSize() - position;
+ if (position + readSize > data.size()) {
+ readSize = data.size() - position;
}
- ByteArray result(data.getData() + position, readSize);
+ std::vector<unsigned char> result(data.begin() + position, data.begin() + position + readSize);
position += readSize;
return result;
}
virtual bool isFinished() const {
- return position >= data.getSize();
+ return position >= data.size();
}
private:
- ByteArray data;
+ std::vector<unsigned char> data;
size_t position;
};
}
diff --git a/Swiften/FileTransfer/ByteArrayWriteBytestream.h b/Swiften/FileTransfer/ByteArrayWriteBytestream.h
new file mode 100644
index 0000000..6c360e6
--- /dev/null
+++ b/Swiften/FileTransfer/ByteArrayWriteBytestream.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/FileTransfer/WriteBytestream.h>
+
+namespace Swift {
+ class ByteArrayWriteBytestream : public WriteBytestream {
+ public:
+ ByteArrayWriteBytestream() {
+ }
+
+ virtual void write(const std::vector<unsigned char>& bytes) {
+ data.insert(data.end(), bytes.begin(), bytes.end());
+ }
+
+ const std::vector<unsigned char>& getData() const {
+ return data;
+ }
+
+ private:
+ std::vector<unsigned char> data;
+ };
+}
diff --git a/Swiften/FileTransfer/FileReadBytestream.cpp b/Swiften/FileTransfer/FileReadBytestream.cpp
index c08747b..e997366 100644
--- a/Swiften/FileTransfer/FileReadBytestream.cpp
+++ b/Swiften/FileTransfer/FileReadBytestream.cpp
@@ -21,14 +21,14 @@ FileReadBytestream::~FileReadBytestream() {
}
}
-ByteArray FileReadBytestream::read(size_t size) {
+std::vector<unsigned char> FileReadBytestream::read(size_t size) {
if (!stream) {
stream = new boost::filesystem::ifstream(file, std::ios_base::in|std::ios_base::binary);
}
- ByteArray result;
+ std::vector<unsigned char> result;
result.resize(size);
assert(stream->good());
- stream->read(reinterpret_cast<char*>(result.getData()), size);
+ stream->read(reinterpret_cast<char*>(&result[0]), size);
result.resize(stream->gcount());
return result;
}
diff --git a/Swiften/FileTransfer/FileReadBytestream.h b/Swiften/FileTransfer/FileReadBytestream.h
index 055e194..f136a68 100644
--- a/Swiften/FileTransfer/FileReadBytestream.h
+++ b/Swiften/FileTransfer/FileReadBytestream.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
#include "Swiften/FileTransfer/ReadBytestream.h"
@@ -17,7 +17,7 @@ namespace Swift {
FileReadBytestream(const boost::filesystem::path& file);
~FileReadBytestream();
- virtual ByteArray read(size_t size) ;
+ virtual std::vector<unsigned char> read(size_t size);
virtual bool isFinished() const;
private:
diff --git a/Swiften/FileTransfer/FileWriteBytestream.cpp b/Swiften/FileTransfer/FileWriteBytestream.cpp
index 4d29bd1..803a10b 100644
--- a/Swiften/FileTransfer/FileWriteBytestream.cpp
+++ b/Swiften/FileTransfer/FileWriteBytestream.cpp
@@ -21,12 +21,12 @@ FileWriteBytestream::~FileWriteBytestream() {
}
}
-void FileWriteBytestream::write(const ByteArray& data) {
+void FileWriteBytestream::write(const std::vector<unsigned char>& data) {
if (!stream) {
stream = new boost::filesystem::ofstream(file, std::ios_base::out|std::ios_base::binary);
}
assert(stream->good());
- stream->write(reinterpret_cast<const char*>(data.getData()), data.getSize());
+ stream->write(reinterpret_cast<const char*>(&data[0]), data.size());
}
}
diff --git a/Swiften/FileTransfer/FileWriteBytestream.h b/Swiften/FileTransfer/FileWriteBytestream.h
index c6f7b39..8cfa718 100644
--- a/Swiften/FileTransfer/FileWriteBytestream.h
+++ b/Swiften/FileTransfer/FileWriteBytestream.h
@@ -6,10 +6,10 @@
#pragma once
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
-#include "Swiften/FileTransfer/WriteBytestream.h"
+#include <Swiften/FileTransfer/WriteBytestream.h>
namespace Swift {
class FileWriteBytestream : public WriteBytestream {
@@ -17,7 +17,7 @@ namespace Swift {
FileWriteBytestream(const boost::filesystem::path& file);
~FileWriteBytestream();
- virtual void write(const ByteArray&);
+ virtual void write(const std::vector<unsigned char>&);
private:
boost::filesystem::path file;
diff --git a/Swiften/FileTransfer/IBBReceiveSession.cpp b/Swiften/FileTransfer/IBBReceiveSession.cpp
index 5c90757..566dcca 100644
--- a/Swiften/FileTransfer/IBBReceiveSession.cpp
+++ b/Swiften/FileTransfer/IBBReceiveSession.cpp
@@ -4,31 +4,96 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/FileTransfer/IBBReceiveSession.h"
+#include <Swiften/FileTransfer/IBBReceiveSession.h>
#include <boost/bind.hpp>
-#include "Swiften/Queries/IQRouter.h"
-#include "Swiften/FileTransfer/IBBRequest.h"
-#include "Swiften/FileTransfer/BytestreamException.h"
+#include <Swiften/Base/Log.h>
+#include <Swiften/Queries/IQRouter.h>
+#include <Swiften/FileTransfer/IBBRequest.h>
+#include <Swiften/FileTransfer/BytestreamException.h>
+#include <Swiften/Queries/SetResponder.h>
namespace Swift {
-IBBReceiveSession::IBBReceiveSession(const std::string& id, const JID& from, size_t size, WriteBytestream::ref bytestream, IQRouter* router) : SetResponder<IBB>(router), id(id), from(from), size(size), bytestream(bytestream), router(router), sequenceNumber(0), active(false), receivedSize(0) {
+class IBBReceiveSession::IBBResponder : public SetResponder<IBB> {
+ public:
+ IBBResponder(IBBReceiveSession* session, IQRouter* router) : SetResponder<IBB>(router), session(session), sequenceNumber(0), receivedSize(0) {
+ }
+
+ virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, IBB::ref ibb) {
+ if (from == session->from && ibb->getStreamID() == session->id) {
+ if (ibb->getAction() == IBB::Data) {
+ if (sequenceNumber == ibb->getSequenceNumber()) {
+ session->onDataReceived(ibb->getData());
+ receivedSize += ibb->getData().size();
+ sequenceNumber++;
+ sendResponse(from, id, IBB::ref());
+ if (receivedSize >= session->size) {
+ if (receivedSize > session->size) {
+ std::cerr << "Warning: Received more data than expected" << std::endl;
+ }
+ session->finish(boost::optional<FileTransferError>());
+ }
+ }
+ else {
+ SWIFT_LOG(warning) << "Received data out of order" << std::endl;
+ sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel);
+ session->finish(FileTransferError(FileTransferError::ClosedError));
+ }
+ }
+ else if (ibb->getAction() == IBB::Open) {
+ sendResponse(from, id, IBB::ref());
+ }
+ else if (ibb->getAction() == IBB::Close) {
+ sendResponse(from, id, IBB::ref());
+ session->finish(FileTransferError(FileTransferError::ClosedError));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ IBBReceiveSession* session;
+ int sequenceNumber;
+ size_t receivedSize;
+};
+
+
+IBBReceiveSession::IBBReceiveSession(
+ const std::string& id,
+ const JID& from,
+ size_t size,
+ IQRouter* router) :
+ id(id),
+ from(from),
+ size(size),
+ router(router),
+ active(false) {
+ responder = new IBBResponder(this, router);
}
IBBReceiveSession::~IBBReceiveSession() {
+ if (active) {
+ SWIFT_LOG(warning) << "Session still active" << std::endl;
+ }
+ delete responder;
}
void IBBReceiveSession::start() {
active = true;
+ responder->start();
}
void IBBReceiveSession::stop() {
- if (active && router->isAvailable()) {
- IBBRequest::create(from, IBB::createIBBClose(id), router)->send();
+ responder->stop();
+ if (active) {
+ if (router->isAvailable()) {
+ IBBRequest::create(from, IBB::createIBBClose(id), router)->send();
+ }
+ finish(boost::optional<FileTransferError>());
}
- finish(boost::optional<FileTransferError>());
}
void IBBReceiveSession::finish(boost::optional<FileTransferError> error) {
@@ -36,34 +101,4 @@ void IBBReceiveSession::finish(boost::optional<FileTransferError> error) {
onFinished(error);
}
-bool IBBReceiveSession::handleSetRequest(const JID& from, const JID&, const std::string& id, IBB::ref ibb) {
- if (from == this->from && ibb->getStreamID() == id) {
- if (ibb->getAction() == IBB::Data) {
- if (sequenceNumber == ibb->getSequenceNumber()) {
- bytestream->write(ibb->getData());
- receivedSize += ibb->getData().getSize();
- if (receivedSize >= size) {
- if (receivedSize > size) {
- std::cerr << "Warning: Received more data than expected" << std::endl;
- }
- finish(boost::optional<FileTransferError>());
- }
- }
- else {
- sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel);
- finish(FileTransferError(FileTransferError::ClosedError));
- }
- }
- else if (ibb->getAction() == IBB::Open) {
- sendResponse(from, id, IBB::ref());
- }
- else if (ibb->getAction() == IBB::Close) {
- sendResponse(from, id, IBB::ref());
- finish(FileTransferError(FileTransferError::ClosedError));
- }
- return true;
- }
- return false;
-}
-
}
diff --git a/Swiften/FileTransfer/IBBReceiveSession.h b/Swiften/FileTransfer/IBBReceiveSession.h
index 6d936de..d512025 100644
--- a/Swiften/FileTransfer/IBBReceiveSession.h
+++ b/Swiften/FileTransfer/IBBReceiveSession.h
@@ -7,27 +7,30 @@
#pragma once
#include <boost/shared_ptr.hpp>
-#include <boost/optional.hpp>
+#include <boost/optional/optional_fwd.hpp>
#include "Swiften/Base/boost_bsignals.h"
#include "Swiften/FileTransfer/WriteBytestream.h"
#include "Swiften/JID/JID.h"
#include "Swiften/Elements/IBB.h"
-#include "Swiften/Elements/ErrorPayload.h"
#include "Swiften/FileTransfer/FileTransferError.h"
-#include "Swiften/Queries/SetResponder.h"
namespace Swift {
class IQRouter;
- class IBBReceiveSession : public SetResponder<IBB> {
+ class IBBReceiveSession {
public:
- IBBReceiveSession(const std::string& id, const JID& from, size_t size, WriteBytestream::ref bytestream, IQRouter* router);
+ IBBReceiveSession(
+ const std::string& id,
+ const JID& from,
+ size_t size,
+ IQRouter* router);
~IBBReceiveSession();
void start();
void stop();
+ boost::signal<void (const std::vector<unsigned char>&)> onDataReceived;
boost::signal<void (boost::optional<FileTransferError>)> onFinished;
private:
@@ -35,13 +38,14 @@ namespace Swift {
void finish(boost::optional<FileTransferError>);
private:
+ class IBBResponder;
+ friend class IBBResponder;
+
std::string id;
JID from;
size_t size;
- WriteBytestream::ref bytestream;
IQRouter* router;
- int sequenceNumber;
+ IBBResponder* responder;
bool active;
- size_t receivedSize;
};
}
diff --git a/Swiften/FileTransfer/IBBSendSession.cpp b/Swiften/FileTransfer/IBBSendSession.cpp
index 0fb47d3..c31fe4a 100644
--- a/Swiften/FileTransfer/IBBSendSession.cpp
+++ b/Swiften/FileTransfer/IBBSendSession.cpp
@@ -38,13 +38,13 @@ void IBBSendSession::handleIBBResponse(IBB::ref, ErrorPayload::ref error) {
if (!error) {
if (!bytestream->isFinished()) {
try {
- ByteArray data = bytestream->read(blockSize);
+ std::vector<unsigned char> data = bytestream->read(blockSize);
IBBRequest::ref request = IBBRequest::create(to, IBB::createIBBData(id, sequenceNumber, data), router);
sequenceNumber++;
request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2));
request->send();
}
- catch (const BytestreamException& e) {
+ catch (const BytestreamException&) {
finish(FileTransferError(FileTransferError::ReadError));
}
}
diff --git a/Swiften/FileTransfer/IncomingFileTransfer.cpp b/Swiften/FileTransfer/IncomingFileTransfer.cpp
index 238ccce..7c97e4d 100644
--- a/Swiften/FileTransfer/IncomingFileTransfer.cpp
+++ b/Swiften/FileTransfer/IncomingFileTransfer.cpp
@@ -4,20 +4,11 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/FileTransfer/IncomingFileTransfer.h"
+#include <Swiften/FileTransfer/IncomingFileTransfer.h>
namespace Swift {
IncomingFileTransfer::~IncomingFileTransfer() {
-
-}
-
-/*void IncomingFileTransfer::accept(WriteBytestream::ref) {
-
}
-void IncomingFileTransfer::stop() {
-
-}*/
-
}
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
index 5535840..79d2391 100644
--- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
@@ -10,8 +10,10 @@
#include <Swiften/Elements/JingleDescription.h>
#include <Swiften/Elements/JingleFileTransferDescription.h>
-#include <Swiften/Elements/JingleIBBTransport.h>
+#include <Swiften/Elements/JingleIBBTransportPayload.h>
+#include <Swiften/Elements/JingleS5BTransportPayload.h>
#include <Swiften/Jingle/JingleSessionManager.h>
+#include <Swiften/Jingle/Jingle.h>
#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
namespace Swift {
@@ -24,12 +26,12 @@ IncomingFileTransferManager::~IncomingFileTransferManager() {
jingleSessionManager->removeIncomingSessionHandler(this);
}
-bool IncomingFileTransferManager::handleIncomingJingleSession(IncomingJingleSession::ref session) {
- JingleContent::ref content = session->getContentWithDescription<JingleFileTransferDescription>();
- if (content) {
- // Check for supported transports
- if (content->getTransport<JingleIBBTransport>()) {
- IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>(session);
+bool IncomingFileTransferManager::handleIncomingJingleSession(JingleSession::ref session, const std::vector<JingleContentPayload::ref>& contents) {
+ if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) {
+ if (content->getTransport<JingleIBBTransportPayload>() || content->getTransport<JingleS5BTransportPayload>()) {
+ RemoteJingleTransportCandidateSelectorFactory* a;
+ LocalJingleTransportCandidateGeneratorFactory* b;
+ IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>(session, content, a, b, router);
onIncomingFileTransfer(transfer);
}
else {
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h
index a54b5cd..428a838 100644
--- a/Swiften/FileTransfer/IncomingFileTransferManager.h
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.h
@@ -15,6 +15,8 @@
namespace Swift {
class IQRouter;
class JingleSessionManager;
+ class RemoteJingleTransportCandidateSelectorFactory;
+ class LocalJingleTransportCandidateGeneratorFactory;
class IncomingFileTransferManager : public IncomingJingleSessionHandler {
public:
@@ -24,7 +26,7 @@ namespace Swift {
boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer;
private:
- bool handleIncomingJingleSession(IncomingJingleSession::ref session);
+ bool handleIncomingJingleSession(JingleSession::ref session, const std::vector<JingleContentPayload::ref>& contents);
private:
JingleSessionManager* jingleSessionManager;
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
index cb2f65c..904b53e 100644
--- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
@@ -6,14 +6,164 @@
#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
+#include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h>
+#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h>
+#include <Swiften/FileTransfer/JingleIncomingIBBTransport.h>
+#include <Swiften/Elements/JingleIBBTransportPayload.h>
+#include <Swiften/Elements/JingleS5BTransportPayload.h>
+#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h>
+#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h>
+
namespace Swift {
-IncomingJingleFileTransfer::IncomingJingleFileTransfer(IncomingJingleSession::ref session) : session(session) {
+IncomingJingleFileTransfer::IncomingJingleFileTransfer(
+ JingleSession::ref session,
+ JingleContentPayload::ref content,
+ RemoteJingleTransportCandidateSelectorFactory* candidateSelectorFactory,
+ LocalJingleTransportCandidateGeneratorFactory* candidateGeneratorFactory,
+ IQRouter* router) :
+ session(session),
+ router(router),
+ initialContent(content),
+ contentID(content->getName(), content->getCreator()),
+ state(Initial),
+ remoteTransportCandidateSelectFinished(false),
+ localTransportCandidateSelectFinished(false) {
+
+ candidateSelector = candidateSelectorFactory->createCandidateSelector();
+ candidateSelector->onRemoteTransportCandidateSelectFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1));
+
+ candidateGenerator = candidateGeneratorFactory->createCandidateGenerator();
+ candidateGenerator->onLocalTransportCandidatesGenerated.connect(boost::bind(&IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1));
+
+ session->onTransportInfoReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2));
+ session->onTransportReplaceReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportReplaceReceived, this, _1, _2));
+ session->onSessionTerminateReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleSessionTerminateReceived, this));
+
+ description = initialContent->getDescription<JingleFileTransferDescription>();
+ assert(description);
+}
+
+IncomingJingleFileTransfer::~IncomingJingleFileTransfer() {
+ session->onSessionTerminateReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleSessionTerminateReceived, this));
+ session->onTransportReplaceReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportReplaceReceived, this, _1, _2));
+ session->onTransportInfoReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2));
+
+ candidateGenerator->onLocalTransportCandidatesGenerated.disconnect(boost::bind(&IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1));
+ delete candidateGenerator;
+ candidateSelector->onRemoteTransportCandidateSelectFinished.disconnect(boost::bind(&IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1));
+ delete candidateSelector;
}
void IncomingJingleFileTransfer::accept(WriteBytestream::ref stream) {
+ assert(!stream);
this->stream = stream;
+
+ if (JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>()) {
+ setActiveTransport(createIBBTransport(ibbTransport));
+ session->accept();
+ }
+ else if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) {
+ state = CreatingInitialTransports;
+ candidateSelector->addRemoteTransportCandidates(s5bTransport);
+ candidateGenerator->generateLocalTransportCandidates();
+ }
+ else {
+ assert(false);
+ }
+}
+
+
+void IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated(JingleTransportPayload::ref candidates) {
+ if (state == CreatingInitialTransports) {
+ if (!candidates) {
+ localTransportCandidateSelectFinished = true;
+ }
+ session->accept(candidates);
+ state = NegotiatingTransport;
+ candidateSelector->selectCandidate();
+ }
+}
+
+
+void IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished(JingleTransportPayload::ref transport) {
+ remoteTransportCandidateSelectFinished = true;
+ selectedRemoteTransportCandidate = transport;
+ session->sendTransportInfo(contentID, transport);
+ checkCandidateSelected();
+}
+
+void IncomingJingleFileTransfer::checkCandidateSelected() {
+ if (localTransportCandidateSelectFinished && remoteTransportCandidateSelectFinished) {
+ if (candidateGenerator->isActualCandidate(selectedLocalTransportCandidate) && candidateSelector->isActualCandidate(selectedRemoteTransportCandidate)) {
+ if (candidateGenerator->getPriority(selectedLocalTransportCandidate) > candidateSelector->getPriority(selectedRemoteTransportCandidate)) {
+ setActiveTransport(candidateGenerator->selectTransport(selectedLocalTransportCandidate));
+ }
+ else {
+ setActiveTransport(candidateSelector->selectTransport(selectedRemoteTransportCandidate));
+ }
+ }
+ else if (candidateSelector->isActualCandidate(selectedRemoteTransportCandidate)) {
+ setActiveTransport(candidateSelector->selectTransport(selectedRemoteTransportCandidate));
+ }
+ else if (candidateGenerator->isActualCandidate(selectedLocalTransportCandidate)) {
+ setActiveTransport(candidateGenerator->selectTransport(selectedLocalTransportCandidate));
+ }
+ else {
+ state = WaitingForFallbackOrTerminate;
+ }
+ }
+}
+
+void IncomingJingleFileTransfer::setActiveTransport(JingleTransport::ref transport) {
+ state = Transferring;
+ activeTransport = transport;
+ activeTransport->onDataReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportDataReceived, this, _1));
+ activeTransport->start();
+}
+
+void IncomingJingleFileTransfer::handleSessionTerminateReceived() {
+ // TODO
+ state = Terminated;
+}
+
+void IncomingJingleFileTransfer::handleTransportDataReceived(const std::vector<unsigned char>& data) {
+ stream->write(data);
+}
+
+
+void IncomingJingleFileTransfer::handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref transport) {
+ localTransportCandidateSelectFinished = true;
+ selectedLocalTransportCandidate = transport;
+ if (candidateGenerator->isActualCandidate(transport)) {
+ candidateSelector->setMinimumPriority(candidateGenerator->getPriority(transport));
+ }
+ checkCandidateSelected();
+}
+
+void IncomingJingleFileTransfer::handleTransportReplaceReceived(const JingleContentID& content, JingleTransportPayload::ref transport) {
+ if (JingleIBBTransportPayload::ref ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) {
+ setActiveTransport(createIBBTransport(ibbTransport));
+ session->acceptTransport(content, transport);
+ }
+ else {
+ session->rejectTransport(content, transport);
+ }
+}
+
+void IncomingJingleFileTransfer::stopActiveTransport() {
+ if (activeTransport) {
+ activeTransport->stop();
+ activeTransport->onDataReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportDataReceived, this, _1));
+ }
+}
+
+JingleIncomingIBBTransport::ref IncomingJingleFileTransfer::createIBBTransport(JingleIBBTransportPayload::ref ibbTransport) {
+ return boost::make_shared<JingleIncomingIBBTransport>(session->getInitiator(), ibbTransport->getSessionID(), description->getOffer()->size, router);
}
}
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
index d69449e..164d868 100644
--- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
@@ -8,20 +8,71 @@
#include <boost/shared_ptr.hpp>
-#include <Swiften/Jingle/IncomingJingleSession.h>
+#include <Swiften/Jingle/JingleSession.h>
+#include <Swiften/Jingle/JingleContentID.h>
#include <Swiften/FileTransfer/IncomingFileTransfer.h>
+#include <Swiften/FileTransfer/JingleTransport.h>
+#include <Swiften/FileTransfer/JingleIncomingIBBTransport.h>
+#include <Swiften/Elements/JingleContentPayload.h>
+#include <Swiften/Elements/JingleFileTransferDescription.h>
+#include <Swiften/Elements/JingleIBBTransportPayload.h>
namespace Swift {
+ class IQRouter;
+ class RemoteJingleTransportCandidateSelectorFactory;
+ class LocalJingleTransportCandidateGeneratorFactory;
+ class RemoteJingleTransportCandidateSelector;
+ class LocalJingleTransportCandidateGenerator;
+
class IncomingJingleFileTransfer : public IncomingFileTransfer {
public:
typedef boost::shared_ptr<IncomingJingleFileTransfer> ref;
+ enum State {
+ Initial,
+ CreatingInitialTransports,
+ NegotiatingTransport,
+ Transferring,
+ WaitingForFallbackOrTerminate,
+ Terminated
+ };
- IncomingJingleFileTransfer(IncomingJingleSession::ref session);
+ IncomingJingleFileTransfer(
+ JingleSession::ref,
+ JingleContentPayload::ref content,
+ RemoteJingleTransportCandidateSelectorFactory*,
+ LocalJingleTransportCandidateGeneratorFactory*,
+ IQRouter* router);
+ ~IncomingJingleFileTransfer();
virtual void accept(WriteBytestream::ref);
private:
- IncomingJingleSession::ref session;
+ void handleSessionTerminateReceived();
+ void handleTransportReplaceReceived(const JingleContentID&, JingleTransportPayload::ref);
+ void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref);
+ void handleLocalTransportCandidatesGenerated(JingleTransportPayload::ref candidates);
+ void handleRemoteTransportCandidateSelectFinished(JingleTransportPayload::ref candidate);
+ void setActiveTransport(JingleTransport::ref transport);
+ void handleTransportDataReceived(const std::vector<unsigned char>& data);
+ void stopActiveTransport();
+ void checkCandidateSelected();
+ JingleIncomingIBBTransport::ref createIBBTransport(JingleIBBTransportPayload::ref ibbTransport);
+
+ private:
+ JingleSession::ref session;
+ IQRouter* router;
+ JingleContentPayload::ref initialContent;
+ JingleContentID contentID;
+ State state;
+ JingleFileTransferDescription::ref description;
WriteBytestream::ref stream;
+ RemoteJingleTransportCandidateSelector* candidateSelector;
+ LocalJingleTransportCandidateGenerator* candidateGenerator;
+ bool remoteTransportCandidateSelectFinished;
+ JingleTransportPayload::ref selectedRemoteTransportCandidate;
+ bool localTransportCandidateSelectFinished;
+ JingleTransportPayload::ref selectedLocalTransportCandidate;
+
+ JingleTransport::ref activeTransport;
};
}
diff --git a/Swiften/FileTransfer/JingleIncomingIBBTransport.cpp b/Swiften/FileTransfer/JingleIncomingIBBTransport.cpp
new file mode 100644
index 0000000..0ca899f
--- /dev/null
+++ b/Swiften/FileTransfer/JingleIncomingIBBTransport.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/FileTransfer/JingleIncomingIBBTransport.h>
+
+namespace Swift {
+
+JingleIncomingIBBTransport::JingleIncomingIBBTransport(const JID& from, const std::string& id, size_t size, IQRouter* router) : ibbSession(from, id, size, router) {
+ ibbSession.onDataReceived.connect(boost::ref(onDataReceived));
+}
+
+void JingleIncomingIBBTransport::start() {
+ ibbSession.start();
+}
+
+void JingleIncomingIBBTransport::stop() {
+ ibbSession.stop();
+}
+
+}
diff --git a/Swiften/FileTransfer/JingleIncomingIBBTransport.h b/Swiften/FileTransfer/JingleIncomingIBBTransport.h
new file mode 100644
index 0000000..e2fa485
--- /dev/null
+++ b/Swiften/FileTransfer/JingleIncomingIBBTransport.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/FileTransfer/JingleTransport.h>
+#include <Swiften/FileTransfer/IBBReceiveSession.h>
+
+namespace Swift {
+ class JingleIncomingIBBTransport : public JingleTransport {
+ public:
+ typedef boost::shared_ptr<JingleIncomingIBBTransport> ref;
+
+ JingleIncomingIBBTransport(const JID& from, const std::string& id, size_t size, IQRouter* router);
+
+ virtual void start();
+ virtual void stop();
+
+ private:
+ IBBReceiveSession ibbSession;
+ };
+}
diff --git a/Swiften/Elements/JingleTransport.h b/Swiften/FileTransfer/JingleTransport.cpp
index ecd2a34..c507922 100644
--- a/Swiften/Elements/JingleTransport.h
+++ b/Swiften/FileTransfer/JingleTransport.cpp
@@ -4,11 +4,12 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#pragma once
-
-#include <Swiften/Elements/Payload.h>
+#include <Swiften/FileTransfer/JingleTransport.h>
namespace Swift {
- class JingleTransport : public Payload {
- };
+
+JingleTransport::~JingleTransport() {
+
+}
+
}
diff --git a/Swiften/FileTransfer/JingleTransport.h b/Swiften/FileTransfer/JingleTransport.h
new file mode 100644
index 0000000..1d163d0
--- /dev/null
+++ b/Swiften/FileTransfer/JingleTransport.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Base/boost_bsignals.h>
+
+namespace Swift {
+ class JingleTransport {
+ public:
+ typedef boost::shared_ptr<JingleTransport> ref;
+
+ virtual ~JingleTransport();
+
+ virtual void start() = 0;
+ virtual void stop() = 0;
+
+ boost::signal<void (const std::vector<unsigned char>&)> onDataReceived;
+ };
+}
diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp
new file mode 100644
index 0000000..852902b
--- /dev/null
+++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h>
+
+namespace Swift {
+
+LocalJingleTransportCandidateGenerator::~LocalJingleTransportCandidateGenerator() {
+}
+
+}
diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h
new file mode 100644
index 0000000..c111005
--- /dev/null
+++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+
+#include <Swiften/Elements/JingleTransportPayload.h>
+#include <Swiften/FileTransfer/JingleTransport.h>
+
+namespace Swift {
+ class LocalJingleTransportCandidateGenerator {
+ public:
+ virtual ~LocalJingleTransportCandidateGenerator();
+
+ virtual void generateLocalTransportCandidates() = 0;
+
+ virtual bool isActualCandidate(JingleTransportPayload::ref) = 0;
+ virtual int getPriority(JingleTransportPayload::ref) = 0;
+ virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref) = 0;
+
+ boost::signal<void (JingleTransportPayload::ref)> onLocalTransportCandidatesGenerated;
+ };
+}
diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.cpp b/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.cpp
new file mode 100644
index 0000000..a1e3874
--- /dev/null
+++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h>
+
+namespace Swift {
+
+LocalJingleTransportCandidateGeneratorFactory::~LocalJingleTransportCandidateGeneratorFactory() {
+}
+
+}
diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h b/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h
new file mode 100644
index 0000000..c969fc7
--- /dev/null
+++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+namespace Swift {
+ class LocalJingleTransportCandidateGenerator;
+
+ class LocalJingleTransportCandidateGeneratorFactory {
+ public:
+ virtual ~LocalJingleTransportCandidateGeneratorFactory();
+
+ virtual LocalJingleTransportCandidateGenerator* createCandidateGenerator() = 0;
+ };
+}
diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.cpp b/Swiften/FileTransfer/OutgoingFileTransfer.cpp
index 32f7e17..94d4348 100644
--- a/Swiften/FileTransfer/OutgoingFileTransfer.cpp
+++ b/Swiften/FileTransfer/OutgoingFileTransfer.cpp
@@ -4,75 +4,11 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/FileTransfer/OutgoingFileTransfer.h"
-
-#include <boost/bind.hpp>
-
-#include "Swiften/FileTransfer/StreamInitiationRequest.h"
-#include "Swiften/FileTransfer/BytestreamsRequest.h"
-#include "Swiften/FileTransfer/SOCKS5BytestreamServer.h"
-#include "Swiften/FileTransfer/IBBSendSession.h"
+#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
namespace Swift {
-OutgoingFileTransfer::OutgoingFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer) : id(id), from(from), to(to), name(name), size(size), description(description), bytestream(bytestream), iqRouter(iqRouter), socksServer(socksServer) {
-}
-
-void OutgoingFileTransfer::start() {
- StreamInitiation::ref streamInitiation(new StreamInitiation());
- streamInitiation->setID(id);
- streamInitiation->setFileInfo(StreamInitiationFileInfo(name, description, size));
- //streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams");
- streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb");
- StreamInitiationRequest::ref request = StreamInitiationRequest::create(to, streamInitiation, iqRouter);
- request->onResponse.connect(boost::bind(&OutgoingFileTransfer::handleStreamInitiationRequestResponse, this, _1, _2));
- request->send();
-}
-
-void OutgoingFileTransfer::stop() {
-}
-
-void OutgoingFileTransfer::handleStreamInitiationRequestResponse(StreamInitiation::ref response, ErrorPayload::ref error) {
- if (error) {
- finish(FileTransferError());
- }
- else {
- if (response->getRequestedMethod() == "http://jabber.org/protocol/bytestreams") {
- socksServer->addBytestream(id, from, to, bytestream);
- Bytestreams::ref bytestreams(new Bytestreams());
- bytestreams->setStreamID(id);
- HostAddressPort addressPort = socksServer->getAddressPort();
- bytestreams->addStreamHost(Bytestreams::StreamHost(addressPort.getAddress().toString(), from, addressPort.getPort()));
- BytestreamsRequest::ref request = BytestreamsRequest::create(to, bytestreams, iqRouter);
- request->onResponse.connect(boost::bind(&OutgoingFileTransfer::handleBytestreamsRequestResponse, this, _1, _2));
- request->send();
- }
- else if (response->getRequestedMethod() == "http://jabber.org/protocol/ibb") {
- ibbSession = boost::shared_ptr<IBBSendSession>(new IBBSendSession(id, to, bytestream, iqRouter));
- ibbSession->onFinished.connect(boost::bind(&OutgoingFileTransfer::handleIBBSessionFinished, this, _1));
- ibbSession->start();
- }
- }
-}
-
-void OutgoingFileTransfer::handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref error) {
- if (error) {
- finish(FileTransferError());
- }
- //socksServer->onTransferFinished.connect();
-}
-
-void OutgoingFileTransfer::finish(boost::optional<FileTransferError> error) {
- if (ibbSession) {
- ibbSession->onFinished.disconnect(boost::bind(&OutgoingFileTransfer::handleIBBSessionFinished, this, _1));
- ibbSession.reset();
- }
- socksServer->removeBytestream(id, from, to);
- onFinished(error);
-}
-
-void OutgoingFileTransfer::handleIBBSessionFinished(boost::optional<FileTransferError> error) {
- finish(error);
+OutgoingFileTransfer::~OutgoingFileTransfer() {
}
}
diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.h b/Swiften/FileTransfer/OutgoingFileTransfer.h
index a694c13..a8c1e81 100644
--- a/Swiften/FileTransfer/OutgoingFileTransfer.h
+++ b/Swiften/FileTransfer/OutgoingFileTransfer.h
@@ -6,47 +6,12 @@
#pragma once
-#include <boost/shared_ptr.hpp>
-
-#include "Swiften/FileTransfer/ReadBytestream.h"
-#include "Swiften/Base/boost_bsignals.h"
-#include "Swiften/FileTransfer/FileTransferError.h"
-#include "Swiften/FileTransfer/SOCKS5BytestreamServer.h"
-#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/StreamInitiation.h"
-#include "Swiften/Elements/Bytestreams.h"
-#include "Swiften/Elements/ErrorPayload.h"
-#include "Swiften/FileTransfer/IBBSendSession.h"
-
namespace Swift {
- class IQRouter;
- class SOCKS5BytestreamServer;
-
class OutgoingFileTransfer {
public:
- OutgoingFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer);
-
- void start();
- void stop();
-
- boost::signal<void (const boost::optional<FileTransferError>&)> onFinished;
-
- private:
- void handleStreamInitiationRequestResponse(StreamInitiation::ref, ErrorPayload::ref);
- void handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref);
- void finish(boost::optional<FileTransferError> error);
- void handleIBBSessionFinished(boost::optional<FileTransferError> error);
+ virtual ~OutgoingFileTransfer();
- private:
- std::string id;
- JID from;
- JID to;
- std::string name;
- int size;
- std::string description;
- boost::shared_ptr<ReadBytestream> bytestream;
- IQRouter* iqRouter;
- SOCKS5BytestreamServer* socksServer;
- boost::shared_ptr<IBBSendSession> ibbSession;
+ virtual void start() = 0;
+ virtual void stop() = 0;
};
}
diff --git a/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp b/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp
new file mode 100644
index 0000000..2ed3a9d
--- /dev/null
+++ b/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/FileTransfer/OutgoingSIFileTransfer.h"
+
+#include <boost/bind.hpp>
+
+#include "Swiften/FileTransfer/StreamInitiationRequest.h"
+#include "Swiften/FileTransfer/BytestreamsRequest.h"
+#include "Swiften/FileTransfer/SOCKS5BytestreamServer.h"
+#include "Swiften/FileTransfer/IBBSendSession.h"
+
+namespace Swift {
+
+OutgoingSIFileTransfer::OutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer) : id(id), from(from), to(to), name(name), size(size), description(description), bytestream(bytestream), iqRouter(iqRouter), socksServer(socksServer) {
+}
+
+void OutgoingSIFileTransfer::start() {
+ StreamInitiation::ref streamInitiation(new StreamInitiation());
+ streamInitiation->setID(id);
+ streamInitiation->setFileInfo(StreamInitiationFileInfo(name, description, size));
+ //streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams");
+ streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb");
+ StreamInitiationRequest::ref request = StreamInitiationRequest::create(to, streamInitiation, iqRouter);
+ request->onResponse.connect(boost::bind(&OutgoingSIFileTransfer::handleStreamInitiationRequestResponse, this, _1, _2));
+ request->send();
+}
+
+void OutgoingSIFileTransfer::stop() {
+}
+
+void OutgoingSIFileTransfer::handleStreamInitiationRequestResponse(StreamInitiation::ref response, ErrorPayload::ref error) {
+ if (error) {
+ finish(FileTransferError());
+ }
+ else {
+ if (response->getRequestedMethod() == "http://jabber.org/protocol/bytestreams") {
+ socksServer->addBytestream(id, from, to, bytestream);
+ Bytestreams::ref bytestreams(new Bytestreams());
+ bytestreams->setStreamID(id);
+ HostAddressPort addressPort = socksServer->getAddressPort();
+ bytestreams->addStreamHost(Bytestreams::StreamHost(addressPort.getAddress().toString(), from, addressPort.getPort()));
+ BytestreamsRequest::ref request = BytestreamsRequest::create(to, bytestreams, iqRouter);
+ request->onResponse.connect(boost::bind(&OutgoingSIFileTransfer::handleBytestreamsRequestResponse, this, _1, _2));
+ request->send();
+ }
+ else if (response->getRequestedMethod() == "http://jabber.org/protocol/ibb") {
+ ibbSession = boost::shared_ptr<IBBSendSession>(new IBBSendSession(id, to, bytestream, iqRouter));
+ ibbSession->onFinished.connect(boost::bind(&OutgoingSIFileTransfer::handleIBBSessionFinished, this, _1));
+ ibbSession->start();
+ }
+ }
+}
+
+void OutgoingSIFileTransfer::handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref error) {
+ if (error) {
+ finish(FileTransferError());
+ }
+ //socksServer->onTransferFinished.connect();
+}
+
+void OutgoingSIFileTransfer::finish(boost::optional<FileTransferError> error) {
+ if (ibbSession) {
+ ibbSession->onFinished.disconnect(boost::bind(&OutgoingSIFileTransfer::handleIBBSessionFinished, this, _1));
+ ibbSession.reset();
+ }
+ socksServer->removeBytestream(id, from, to);
+ onFinished(error);
+}
+
+void OutgoingSIFileTransfer::handleIBBSessionFinished(boost::optional<FileTransferError> error) {
+ finish(error);
+}
+
+}
diff --git a/Swiften/FileTransfer/OutgoingSIFileTransfer.h b/Swiften/FileTransfer/OutgoingSIFileTransfer.h
new file mode 100644
index 0000000..cdf988f
--- /dev/null
+++ b/Swiften/FileTransfer/OutgoingSIFileTransfer.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
+#include "Swiften/FileTransfer/ReadBytestream.h"
+#include "Swiften/Base/boost_bsignals.h"
+#include "Swiften/FileTransfer/FileTransferError.h"
+#include "Swiften/FileTransfer/SOCKS5BytestreamServer.h"
+#include "Swiften/JID/JID.h"
+#include "Swiften/Elements/StreamInitiation.h"
+#include "Swiften/Elements/Bytestreams.h"
+#include "Swiften/Elements/ErrorPayload.h"
+#include "Swiften/FileTransfer/IBBSendSession.h"
+
+namespace Swift {
+ class IQRouter;
+ class SOCKS5BytestreamServer;
+
+ class OutgoingSIFileTransfer : public OutgoingFileTransfer {
+ public:
+ OutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer);
+
+ virtual void start();
+ virtual void stop();
+
+ boost::signal<void (const boost::optional<FileTransferError>&)> onFinished;
+
+ private:
+ void handleStreamInitiationRequestResponse(StreamInitiation::ref, ErrorPayload::ref);
+ void handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref);
+ void finish(boost::optional<FileTransferError> error);
+ void handleIBBSessionFinished(boost::optional<FileTransferError> error);
+
+ private:
+ std::string id;
+ JID from;
+ JID to;
+ std::string name;
+ int size;
+ std::string description;
+ boost::shared_ptr<ReadBytestream> bytestream;
+ IQRouter* iqRouter;
+ SOCKS5BytestreamServer* socksServer;
+ boost::shared_ptr<IBBSendSession> ibbSession;
+ };
+}
diff --git a/Swiften/FileTransfer/ReadBytestream.h b/Swiften/FileTransfer/ReadBytestream.h
index 4da2bc2..2601192 100644
--- a/Swiften/FileTransfer/ReadBytestream.h
+++ b/Swiften/FileTransfer/ReadBytestream.h
@@ -6,13 +6,14 @@
#pragma once
-#include "Swiften/Base/ByteArray.h"
+#include <vector>
+#include <cstring>
namespace Swift {
class ReadBytestream {
public:
virtual ~ReadBytestream();
- virtual ByteArray read(size_t size) = 0;
+ virtual std::vector<unsigned char> read(size_t size) = 0;
virtual bool isFinished() const = 0;
};
}
diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp
new file mode 100644
index 0000000..338f221
--- /dev/null
+++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h>
+
+namespace Swift {
+
+RemoteJingleTransportCandidateSelector::~RemoteJingleTransportCandidateSelector() {
+}
+
+}
diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h
new file mode 100644
index 0000000..b12b06b
--- /dev/null
+++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+
+#include <Swiften/Elements/JingleTransportPayload.h>
+#include <Swiften/FileTransfer/JingleTransport.h>
+
+namespace Swift {
+ class RemoteJingleTransportCandidateSelector {
+ public:
+ virtual ~RemoteJingleTransportCandidateSelector();
+
+ virtual void addRemoteTransportCandidates(JingleTransportPayload::ref) = 0;
+ virtual void selectCandidate() = 0;
+ virtual void setMinimumPriority(int) = 0;
+
+ virtual bool isActualCandidate(JingleTransportPayload::ref) = 0;
+ virtual int getPriority(JingleTransportPayload::ref) = 0;
+ virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref) = 0;
+
+ boost::signal<void (JingleTransportPayload::ref)> onRemoteTransportCandidateSelectFinished;
+ };
+}
diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.cpp b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.cpp
new file mode 100644
index 0000000..36b7cba
--- /dev/null
+++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h>
+
+namespace Swift {
+
+RemoteJingleTransportCandidateSelectorFactory::~RemoteJingleTransportCandidateSelectorFactory() {
+}
+
+}
diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h
new file mode 100644
index 0000000..caa3097
--- /dev/null
+++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+namespace Swift {
+ class RemoteJingleTransportCandidateSelector;
+
+ class RemoteJingleTransportCandidateSelectorFactory {
+ public:
+ virtual ~RemoteJingleTransportCandidateSelectorFactory();
+
+ virtual RemoteJingleTransportCandidateSelector* createCandidateSelector() = 0;
+ };
+}
diff --git a/Swiften/FileTransfer/SConscript b/Swiften/FileTransfer/SConscript
index ea9e7bb..24fc9e8 100644
--- a/Swiften/FileTransfer/SConscript
+++ b/Swiften/FileTransfer/SConscript
@@ -1,10 +1,17 @@
-Import("swiften_env")
+Import("swiften_env", "env")
sources = [
"OutgoingFileTransfer.cpp",
+ "OutgoingSIFileTransfer.cpp",
"IncomingFileTransfer.cpp",
"IncomingJingleFileTransfer.cpp",
- "IncomingFileTransferManager.cpp",
+ "IncomingFileTransferManager.cpp",
+ "RemoteJingleTransportCandidateSelector.cpp",
+ "RemoteJingleTransportCandidateSelectorFactory.cpp",
+ "LocalJingleTransportCandidateGenerator.cpp",
+ "LocalJingleTransportCandidateGeneratorFactory.cpp",
+ "JingleTransport.cpp",
+ "JingleIncomingIBBTransport.cpp",
"ReadBytestream.cpp",
"WriteBytestream.cpp",
"FileReadBytestream.cpp",
@@ -17,3 +24,9 @@ sources = [
]
swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources))
+
+env.Append(UNITTEST_SOURCES = [
+ File("UnitTest/SOCKS5BytestreamServerSessionTest.cpp"),
+ File("UnitTest/IBBSendSessionTest.cpp"),
+ File("UnitTest/IBBReceiveSessionTest.cpp"),
+ ])
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp
index 9951f7a..268ba4c 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp
+++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp
@@ -7,6 +7,7 @@
#include "Swiften/FileTransfer/SOCKS5BytestreamServerSession.h"
#include <boost/bind.hpp>
+#include <iostream>
#include "Swiften/Base/ByteArray.h"
#include "Swiften/FileTransfer/SOCKS5BytestreamRegistry.h"
@@ -98,7 +99,7 @@ void SOCKS5BytestreamServerSession::sendData() {
try {
connection->write(bytestream->read(chunkSize));
}
- catch (const BytestreamException& e) {
+ catch (const BytestreamException&) {
finish(true);
}
}
diff --git a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp
new file mode 100644
index 0000000..590443f
--- /dev/null
+++ b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <vector>
+#include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Base/ByteArray.h>
+#include "Swiften/FileTransfer/IBBReceiveSession.h"
+#include "Swiften/Queries/IQRouter.h"
+#include "Swiften/Client/DummyStanzaChannel.h"
+
+using namespace Swift;
+
+class IBBReceiveSessionTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(IBBReceiveSessionTest);
+ CPPUNIT_TEST(testOpen);
+ CPPUNIT_TEST(testReceiveData);
+ CPPUNIT_TEST(testReceiveMultipleData);
+ CPPUNIT_TEST(testReceiveDataForOtherSession);
+ CPPUNIT_TEST(testReceiveDataOutOfOrder);
+ CPPUNIT_TEST(testReceiveLastData);
+ CPPUNIT_TEST(testReceiveClose);
+ CPPUNIT_TEST(testStopWhileActive);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ stanzaChannel = new DummyStanzaChannel();
+ iqRouter = new IQRouter(stanzaChannel);
+ finished = false;
+ }
+
+ void tearDown() {
+ delete iqRouter;
+ delete stanzaChannel;
+ }
+
+ void testOpen() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession"));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(0, "id-open"));
+ CPPUNIT_ASSERT(!finished);
+
+ testling->stop();
+ }
+
+ void testReceiveData() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession"));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, ByteArray::create("abc")), "foo@bar.com/baz", "id-a"));
+
+ CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(1, "id-a"));
+ CPPUNIT_ASSERT(ByteArray::create("abc") == receivedData);
+ CPPUNIT_ASSERT(!finished);
+
+ testling->stop();
+ }
+
+ void testReceiveMultipleData() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession"));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, ByteArray::create("abc")), "foo@bar.com/baz", "id-a"));
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, ByteArray::create("def")), "foo@bar.com/baz", "id-b"));
+
+ CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b"));
+ CPPUNIT_ASSERT(ByteArray::create("abcdef") == receivedData);
+ CPPUNIT_ASSERT(!finished);
+
+ testling->stop();
+ }
+
+ void testReceiveDataForOtherSession() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession"));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("othersession", 0, ByteArray::create("abc")), "foo@bar.com/baz", "id-a"));
+
+ CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(1, "id-a"));
+
+ testling->stop();
+ }
+
+ void testReceiveDataOutOfOrder() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession"));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, ByteArray::create("abc")), "foo@bar.com/baz", "id-a"));
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, ByteArray::create("def")), "foo@bar.com/baz", "id-b"));
+
+ CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(2, "id-b"));
+ CPPUNIT_ASSERT(finished);
+ CPPUNIT_ASSERT(error);
+
+ testling->stop();
+ }
+
+ void testReceiveLastData() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession", 6));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, ByteArray::create("abc")), "foo@bar.com/baz", "id-a"));
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, ByteArray::create("def")), "foo@bar.com/baz", "id-b"));
+
+ CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b"));
+ CPPUNIT_ASSERT(ByteArray::create("abcdef") == receivedData);
+ CPPUNIT_ASSERT(finished);
+ CPPUNIT_ASSERT(!error);
+
+ testling->stop();
+ }
+
+ void testReceiveClose() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession"));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBClose("mysession"), "foo@bar.com/baz", "id-close"));
+
+ CPPUNIT_ASSERT(finished);
+ CPPUNIT_ASSERT(error);
+
+ testling->stop();
+ }
+
+ void testStopWhileActive() {
+ std::auto_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession"));
+ testling->start();
+ stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open"));
+
+ testling->stop();
+
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set));
+ IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>();
+ CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction());
+ CPPUNIT_ASSERT_EQUAL(std::string("mysession"), ibb->getStreamID());
+ CPPUNIT_ASSERT(finished);
+ CPPUNIT_ASSERT(!error);
+ }
+
+ private:
+ IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) {
+ IQ::ref request = IQ::createRequest(IQ::Set, JID("baz@fum.com/dum"), id, ibb);
+ request->setFrom(from);
+ return request;
+ }
+
+ IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) {
+ IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), size, iqRouter);
+ session->onDataReceived.connect(boost::bind(&IBBReceiveSessionTest::handleDataReceived, this, _1));
+ session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1));
+ return session;
+ }
+
+
+ void handleFinished(boost::optional<FileTransferError> error) {
+ finished = true;
+ this->error = error;
+ }
+
+ void handleDataReceived(const std::vector<unsigned char>& data) {
+ receivedData.insert(receivedData.end(), data.begin(), data.end());
+ }
+
+ private:
+ DummyStanzaChannel* stanzaChannel;
+ IQRouter* iqRouter;
+ bool finished;
+ boost::optional<FileTransferError> error;
+ std::vector<unsigned char> receivedData;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(IBBReceiveSessionTest);
diff --git a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp
index 0cd273a..32df34b 100644
--- a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp
@@ -4,13 +4,12 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Base/ByteArray.h"
-
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <vector>
#include <boost/bind.hpp>
+#include "Swiften/Base/ByteArray.h"
#include "Swiften/FileTransfer/IBBSendSession.h"
#include "Swiften/FileTransfer/ByteArrayReadBytestream.h"
#include "Swiften/Queries/IQRouter.h"
@@ -33,7 +32,7 @@ class IBBSendSessionTest : public CppUnit::TestFixture {
void setUp() {
stanzaChannel = new DummyStanzaChannel();
iqRouter = new IQRouter(stanzaChannel);
- bytestream = boost::shared_ptr<ByteArrayReadBytestream>(new ByteArrayReadBytestream(ByteArray("abcdefg")));
+ bytestream = boost::shared_ptr<ByteArrayReadBytestream>(new ByteArrayReadBytestream(ByteArray::create("abcdefg")));
}
void tearDown() {
@@ -66,7 +65,7 @@ class IBBSendSessionTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set));
IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>();
CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction());
- CPPUNIT_ASSERT_EQUAL(ByteArray("abc"), ibb->getData());
+ CPPUNIT_ASSERT(ByteArray::create("abc") == ibb->getData());
CPPUNIT_ASSERT_EQUAL(0, ibb->getSequenceNumber());
CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID());
}
@@ -82,7 +81,7 @@ class IBBSendSessionTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(2, JID("foo@bar.com/baz"), IQ::Set));
IBB::ref ibb = stanzaChannel->sentStanzas[2]->getPayload<IBB>();
CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction());
- CPPUNIT_ASSERT_EQUAL(ByteArray("def"), ibb->getData());
+ CPPUNIT_ASSERT(ByteArray::create("def") == ibb->getData());
CPPUNIT_ASSERT_EQUAL(1, ibb->getSequenceNumber());
CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID());
}
diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp
index c6d246d..1c1a246 100644
--- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp
@@ -35,7 +35,7 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
eventLoop = new DummyEventLoop();
connection = boost::shared_ptr<DummyConnection>(new DummyConnection(eventLoop));
connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1));
- stream1 = boost::shared_ptr<ByteArrayReadBytestream>(new ByteArrayReadBytestream(ByteArray("abcdefg")));
+ stream1 = boost::shared_ptr<ByteArrayReadBytestream>(new ByteArrayReadBytestream(ByteArray::create("abcdefg")));
}
void tearDown() {
@@ -47,20 +47,20 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
std::auto_ptr<SOCKS5BytestreamServerSession> testling(createSession());
StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get());
- receive(ByteArray("\x05\x02\x01\x02"));
+ receive(ByteArray::create("\x05\x02\x01\x02"));
- CPPUNIT_ASSERT_EQUAL(ByteArray("\x05\x00", 2), receivedData);
+ CPPUNIT_ASSERT(ByteArray::create("\x05\x00", 2) == receivedData);
}
void testAuthenticate_Chunked() {
std::auto_ptr<SOCKS5BytestreamServerSession> testling(createSession());
StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get());
- receive(ByteArray("\x05\x02\x01"));
+ receive(ByteArray::create("\x05\x02\x01"));
- CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.getSize()));
- receive(ByteArray("\x01"));
- CPPUNIT_ASSERT_EQUAL(ByteArray("\x05\x00", 2), receivedData);
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.size()));
+ receive(ByteArray::create("\x01"));
+ CPPUNIT_ASSERT(ByteArray::create("\x05\x00", 2) == receivedData);
}
void testRequest() {
@@ -70,8 +70,8 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
authenticate();
ByteArray hostname("abcdef");
- receive(ByteArray("\x05\x01\x00\x03", 4) + hostname.getSize() + hostname + ByteArray("\x00\x00", 2));
- CPPUNIT_ASSERT_EQUAL(ByteArray("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13), ByteArray(receivedData.getData(), 13));
+ receive(ByteArray(ByteArray::create("\x05\x01\x00\x03", 4)) + hostname.getSize() + hostname + ByteArray::create("\x00\x00", 2));
+ CPPUNIT_ASSERT(ByteArray::create("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == ByteArray::create(&receivedData[0], 13));
}
void testRequest_UnknownBytestream() {
@@ -80,8 +80,8 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
authenticate();
ByteArray hostname("abcdef");
- receive(ByteArray("\x05\x01\x00\x03", 4) + hostname.getSize() + hostname + ByteArray("\x00\x00", 2));
- CPPUNIT_ASSERT_EQUAL(ByteArray("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13), receivedData);
+ receive(ByteArray(ByteArray::create("\x05\x01\x00\x03", 4)) + hostname.getSize() + hostname + ByteArray::create("\x00\x00", 2));
+ CPPUNIT_ASSERT(ByteArray::create("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == receivedData);
}
void testReceiveData() {
@@ -93,7 +93,7 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
eventLoop->processEvents();
skipHeader("abcdef");
- CPPUNIT_ASSERT_EQUAL(ByteArray("abcdefg"), receivedData);
+ CPPUNIT_ASSERT(ByteArray::create("abcdefg") == receivedData);
CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks);
}
@@ -107,7 +107,7 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
eventLoop->processEvents();
skipHeader("abcdef");
- CPPUNIT_ASSERT_EQUAL(ByteArray("abcdefg"), receivedData);
+ CPPUNIT_ASSERT(ByteArray::create("abcdefg") == receivedData);
CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks);
}
@@ -118,23 +118,23 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
}
void authenticate() {
- receive(ByteArray("\x05\x02\x01\x02"));
+ receive(ByteArray::create("\x05\x02\x01\x02"));
receivedData.clear();
receivedDataChunks = 0;
}
void request(const std::string& hostname) {
- receive(ByteArray("\x05\x01\x00\x03", 4) + hostname.size() + hostname + ByteArray("\x00\x00", 2));
+ receive(ByteArray(ByteArray::create("\x05\x01\x00\x03", 4)) + hostname.size() + hostname + ByteArray::create("\x00\x00", 2));
}
void skipHeader(const std::string& hostname) {
int headerSize = 7 + hostname.size();
- receivedData = ByteArray(receivedData.getData() + headerSize, receivedData.getSize() - headerSize);
+ receivedData = ByteArray::create(&receivedData[headerSize], receivedData.size() - headerSize);
}
void handleDataWritten(const ByteArray& data) {
- receivedData += data;
+ receivedData.insert(receivedData.end(), data.begin(), data.end());
receivedDataChunks++;
}
@@ -148,7 +148,7 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture {
DummyEventLoop* eventLoop;
SOCKS5BytestreamRegistry bytestreams;
boost::shared_ptr<DummyConnection> connection;
- ByteArray receivedData;
+ std::vector<unsigned char> receivedData;
int receivedDataChunks;
boost::shared_ptr<ByteArrayReadBytestream> stream1;
};
diff --git a/Swiften/FileTransfer/WriteBytestream.h b/Swiften/FileTransfer/WriteBytestream.h
index 1dc791c..c27aeff 100644
--- a/Swiften/FileTransfer/WriteBytestream.h
+++ b/Swiften/FileTransfer/WriteBytestream.h
@@ -7,8 +7,7 @@
#pragma once
#include <boost/shared_ptr.hpp>
-
-#include "Swiften/Base/ByteArray.h"
+#include <vector>
namespace Swift {
class WriteBytestream {
@@ -17,6 +16,6 @@ namespace Swift {
virtual ~WriteBytestream();
- virtual void write(const ByteArray&) = 0;
+ virtual void write(const std::vector<unsigned char>&) = 0;
};
}
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp
index e4611b3..00adf34 100644
--- a/Swiften/JID/JID.cpp
+++ b/Swiften/JID/JID.cpp
@@ -7,12 +7,17 @@
#define SWIFTEN_CACHE_JID_PREP
#include <vector>
+#include <list>
#include <iostream>
#include <string>
#ifdef SWIFTEN_CACHE_JID_PREP
#include <boost/unordered_map.hpp>
#endif
+#include <boost/assign/list_of.hpp>
+#include <boost/algorithm/string/find_format.hpp>
+#include <boost/algorithm/string/finder.hpp>
+#include <sstream>
#include <stringprep.h>
#include <Swiften/Base/String.h>
@@ -27,6 +32,75 @@ static PrepCache domainPrepCache;
static PrepCache resourcePrepCache;
#endif
+static const std::list<char> escapedChars = boost::assign::list_of(' ')('"')('&')('\'')('/')('<')('>')('@')(':');
+
+bool getEscapeSequenceValue(const std::string& sequence, unsigned char& value) {
+ std::stringstream s;
+ unsigned int v;
+ s << std::hex << sequence;
+ s >> v;
+ value = static_cast<unsigned char>(v);
+ return (!s.fail() && !s.bad() && (value == 0x5C || std::find(escapedChars.begin(), escapedChars.end(), value) != escapedChars.end()));
+}
+
+struct UnescapedCharacterFinder {
+ template<typename Iterator> boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) {
+ for (; begin != end; ++begin) {
+ if (std::find(escapedChars.begin(), escapedChars.end(), *begin) != escapedChars.end()) {
+ return boost::iterator_range<Iterator>(begin, begin + 1);
+ }
+ else if (*begin == '\\') {
+ // Check if we have an escaped dissalowed character sequence
+ Iterator innerBegin = begin + 1;
+ if (innerBegin != end && innerBegin + 1 != end) {
+ Iterator innerEnd = innerBegin + 2;
+ unsigned char value;
+ if (getEscapeSequenceValue(std::string(innerBegin, innerEnd), value)) {
+ return boost::iterator_range<Iterator>(begin, begin + 1);
+ }
+ }
+ }
+ }
+ return boost::iterator_range<Iterator>(end, end);
+ }
+};
+
+struct UnescapedCharacterFormatter {
+ template<typename FindResult> std::string operator()(const FindResult& match) const {
+ std::ostringstream s;
+ s << '\\' << std::hex << static_cast<int>(*match.begin());
+ return s.str();
+ }
+};
+
+struct EscapedCharacterFinder {
+ template<typename Iterator> boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) {
+ for (; begin != end; ++begin) {
+ if (*begin == '\\') {
+ Iterator innerEnd = begin + 1;
+ for (size_t i = 0; i < 2 && innerEnd != end; ++i, ++innerEnd) {
+ }
+ unsigned char value;
+ if (getEscapeSequenceValue(std::string(begin + 1, innerEnd), value)) {
+ return boost::iterator_range<Iterator>(begin, innerEnd);
+ }
+ }
+ }
+ return boost::iterator_range<Iterator>(end, end);
+ }
+};
+
+struct EscapedCharacterFormatter {
+ template<typename FindResult> std::string operator()(const FindResult& match) const {
+ unsigned char value;
+ if (getEscapeSequenceValue(std::string(match.begin() + 1, match.end()), value)) {
+ return std::string(reinterpret_cast<const char*>(&value), 1);
+ }
+ return boost::copy_range<std::string>(match);
+ }
+};
+
+
namespace Swift {
JID::JID(const char* jid) {
@@ -126,5 +200,13 @@ int JID::compare(const Swift::JID& o, CompareType compareType) const {
return 0;
}
+std::string JID::getEscapedNode(const std::string& node) {
+ return boost::find_format_all_copy(node, UnescapedCharacterFinder(), UnescapedCharacterFormatter());
+}
+
+std::string JID::getUnescapedNode() const {
+ return boost::find_format_all_copy(node_, EscapedCharacterFinder(), EscapedCharacterFormatter());
+}
+
} // namespace Swift
diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h
index 63e063d..98b42da 100644
--- a/Swiften/JID/JID.h
+++ b/Swiften/JID/JID.h
@@ -7,7 +7,7 @@
#pragma once
#include <string>
-#include <ostream>
+#include <iosfwd>
namespace Swift {
class JID {
@@ -38,6 +38,18 @@ namespace Swift {
return !hasResource_;
}
+ /**
+ * Returns the given node, escaped according to XEP-0106.
+ * The resulting node is a valid node for a JID, whereas the input value can contain characters
+ * that are not allowed.
+ */
+ static std::string getEscapedNode(const std::string& node);
+
+ /**
+ * Returns the node of the current JID, unescaped according to XEP-0106.
+ */
+ std::string getUnescapedNode() const;
+
JID toBare() const {
JID result(*this);
result.hasResource_ = false;
diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp
index 0f22e15..5e79db2 100644
--- a/Swiften/JID/UnitTest/JIDTest.cpp
+++ b/Swiften/JID/UnitTest/JIDTest.cpp
@@ -51,6 +51,10 @@ class JIDTest : public CppUnit::TestFixture
CPPUNIT_TEST(testSmallerThan_Larger);
CPPUNIT_TEST(testHasResource);
CPPUNIT_TEST(testHasResource_NoResource);
+ CPPUNIT_TEST(testGetEscapedNode);
+ CPPUNIT_TEST(testGetEscapedNode_XEP106Examples);
+ CPPUNIT_TEST(testGetUnescapedNode);
+ CPPUNIT_TEST(testGetUnescapedNode_XEP106Examples);
CPPUNIT_TEST_SUITE_END();
public:
@@ -311,6 +315,57 @@ class JIDTest : public CppUnit::TestFixture
CPPUNIT_ASSERT(testling.isBare());
}
+
+ void testGetEscapedNode() {
+ std::string escaped = JID::getEscapedNode("alice@wonderland.lit");
+ CPPUNIT_ASSERT_EQUAL(std::string("alice\\40wonderland.lit"), escaped);
+
+ escaped = JID::getEscapedNode("\\& \" ' / <\\\\> @ :\\3a\\40");
+ CPPUNIT_ASSERT_EQUAL(std::string("\\\\26\\20\\22\\20\\27\\20\\2f\\20\\3c\\\\\\3e\\20\\40\\20\\3a\\5c3a\\5c40"), escaped);
+ }
+
+ void testGetEscapedNode_XEP106Examples() {
+ CPPUNIT_ASSERT_EQUAL(std::string("\\2plus\\2is\\4"), JID::getEscapedNode("\\2plus\\2is\\4"));
+ CPPUNIT_ASSERT_EQUAL(std::string("foo\\bar"), JID::getEscapedNode("foo\\bar"));
+ CPPUNIT_ASSERT_EQUAL(std::string("foob\\41r"), JID::getEscapedNode("foob\\41r"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("space cadet"), std::string("space\\20cadet"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("call me \"ishmael\""), std::string("call\\20me\\20\\22ishmael\\22"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("at&t guy"), std::string("at\\26t\\20guy"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("d'artagnan"), std::string("d\\27artagnan"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("/.fanboy"), std::string("\\2f.fanboy"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("::foo::"), std::string("\\3a\\3afoo\\3a\\3a"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("<foo>"), std::string("\\3cfoo\\3e"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("user@host"), std::string("user\\40host"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\net"), std::string("c\\3a\\net"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\\\net"), std::string("c\\3a\\\\net"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\cool stuff"), std::string("c\\3a\\cool\\20stuff"));
+ CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\5commas"), std::string("c\\3a\\5c5commas"));
+ }
+
+ void testGetUnescapedNode() {
+ std::string input = "\\& \" ' / <\\\\> @ : \\5c\\40";
+ JID testling(JID::getEscapedNode(input) + "@y");
+ CPPUNIT_ASSERT(testling.isValid());
+ CPPUNIT_ASSERT_EQUAL(input, testling.getUnescapedNode());
+ }
+
+ void testGetUnescapedNode_XEP106Examples() {
+ CPPUNIT_ASSERT_EQUAL(std::string("\\2plus\\2is\\4"), JID("\\2plus\\2is\\4@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("foo\\bar"), JID("foo\\bar@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("foob\\41r"), JID("foob\\41r@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("space cadet"), JID("space\\20cadet@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("call me \"ishmael\""), JID("call\\20me\\20\\22ishmael\\22@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("at&t guy"), JID("at\\26t\\20guy@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("d'artagnan"), JID("d\\27artagnan@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("/.fanboy"), JID("\\2f.fanboy@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("::foo::"), JID("\\3a\\3afoo\\3a\\3a@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("<foo>"), JID("\\3cfoo\\3e@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("user@host"), JID("user\\40host@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("c:\\net"), JID("c\\3a\\net@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("c:\\\\net"), JID("c\\3a\\\\net@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("c:\\cool stuff"), JID("c\\3a\\cool\\20stuff@example.com").getUnescapedNode());
+ CPPUNIT_ASSERT_EQUAL(std::string("c:\\5commas"), JID("c\\3a\\5c5commas@example.com").getUnescapedNode());
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(JIDTest);
diff --git a/Swiften/Jingle/IncomingJingleSession.cpp b/Swiften/Jingle/IncomingJingleSession.cpp
deleted file mode 100644
index b18d9d3..0000000
--- a/Swiften/Jingle/IncomingJingleSession.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/Jingle/IncomingJingleSession.h>
-
-namespace Swift {
-
-IncomingJingleSession::IncomingJingleSession(const std::string& id, const std::vector<JingleContent::ref>& contents) : JingleSession(id, contents) {
-
-}
-
-}
diff --git a/Swiften/Jingle/IncomingJingleSession.h b/Swiften/Jingle/IncomingJingleSession.h
deleted file mode 100644
index 64816f6..0000000
--- a/Swiften/Jingle/IncomingJingleSession.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2011 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-
-#include <Swiften/Jingle/JingleSession.h>
-
-namespace Swift {
- class IncomingJingleSession : public JingleSession {
- public:
- IncomingJingleSession(const std::string& id, const std::vector<JingleContent::ref>& contents);
-
- typedef boost::shared_ptr<IncomingJingleSession> ref;
- };
-}
diff --git a/Swiften/Jingle/IncomingJingleSessionHandler.h b/Swiften/Jingle/IncomingJingleSessionHandler.h
index 5bf9237..4d22a4e 100644
--- a/Swiften/Jingle/IncomingJingleSessionHandler.h
+++ b/Swiften/Jingle/IncomingJingleSessionHandler.h
@@ -6,13 +6,13 @@
#pragma once
-#include <Swiften/Jingle/IncomingJingleSession.h>
+#include <Swiften/Jingle/JingleSession.h>
namespace Swift {
class IncomingJingleSessionHandler {
public:
virtual ~IncomingJingleSessionHandler();
- virtual bool handleIncomingJingleSession(IncomingJingleSession::ref) = 0;
+ virtual bool handleIncomingJingleSession(JingleSession::ref, const std::vector<JingleContentPayload::ref>& contents) = 0;
};
}
diff --git a/Swiften/Jingle/Jingle.h b/Swiften/Jingle/Jingle.h
new file mode 100644
index 0000000..ba4dfe3
--- /dev/null
+++ b/Swiften/Jingle/Jingle.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <Swiften/Elements/JingleContentPayload.h>
+
+namespace Swift {
+ namespace Jingle {
+ template<typename T>
+ JingleContentPayload::ref getContentWithDescription(const std::vector<JingleContentPayload::ref>& contents) {
+ for (size_t i = 0; i < contents.size(); ++i) {
+ if (contents[i]->getDescription<T>()) {
+ return contents[i];
+ }
+ }
+ return JingleContentPayload::ref();
+ }
+ }
+}
diff --git a/Swiften/Jingle/JingleContentID.h b/Swiften/Jingle/JingleContentID.h
new file mode 100644
index 0000000..8d75581
--- /dev/null
+++ b/Swiften/Jingle/JingleContentID.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <Swiften/Elements/JingleContentPayload.h>
+
+namespace Swift {
+ class JingleContentID {
+ public:
+ JingleContentID(const std::string& name, JingleContentPayload::Creator creator) : name(name), creator(creator) {
+ }
+
+ private:
+ std::string name;
+ JingleContentPayload::Creator creator;
+ };
+}
diff --git a/Swiften/Jingle/JingleResponder.cpp b/Swiften/Jingle/JingleResponder.cpp
index 2397e63..198f9a2 100644
--- a/Swiften/Jingle/JingleResponder.cpp
+++ b/Swiften/Jingle/JingleResponder.cpp
@@ -9,7 +9,7 @@
#include <boost/smart_ptr/make_shared.hpp>
#include <Swiften/Jingle/JingleSessionManager.h>
-#include <Swiften/Jingle/IncomingJingleSession.h>
+#include <Swiften/Jingle/JingleSessionImpl.h>
namespace Swift {
@@ -24,12 +24,12 @@ bool JingleResponder::handleSetRequest(const JID& from, const JID&, const std::s
}
else {
sendResponse(from, id, boost::shared_ptr<JinglePayload>());
- IncomingJingleSession::ref session = boost::make_shared<IncomingJingleSession>(id, payload->getContents());
- sessionManager->handleIncomingSession(from, session);
+ JingleSessionImpl::ref session = boost::make_shared<JingleSessionImpl>(payload->getInitiator(), payload->getSessionID());
+ sessionManager->handleIncomingSession(from, session, payload->getContents());
}
}
else {
- JingleSession::ref session = sessionManager->getSession(from, payload->getSessionID());
+ JingleSessionImpl::ref session = sessionManager->getSession(from, payload->getSessionID());
if (session) {
session->handleIncomingAction(payload);
sendResponse(from, id, boost::shared_ptr<JinglePayload>());
diff --git a/Swiften/Jingle/JingleSession.cpp b/Swiften/Jingle/JingleSession.cpp
index d255abd..1366191 100644
--- a/Swiften/Jingle/JingleSession.cpp
+++ b/Swiften/Jingle/JingleSession.cpp
@@ -10,21 +10,11 @@
namespace Swift {
-JingleSession::JingleSession(const std::string& id, const std::vector<JingleContent::ref>& contents) : id(id), contents(contents) {
+JingleSession::JingleSession(const JID& initiator, const std::string& id) : initiator(initiator), id(id) {
}
JingleSession::~JingleSession() {
}
-void JingleSession::handleIncomingAction(JinglePayload::ref) {
-}
-
-void JingleSession::terminate(JinglePayload::Reason::Type reason) {
- JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionTerminate, id);
- payload->setReason(JinglePayload::Reason(reason));
- //onAction(payload)
-}
-
-
}
diff --git a/Swiften/Jingle/JingleSession.h b/Swiften/Jingle/JingleSession.h
index c00492d..fa7da7e 100644
--- a/Swiften/Jingle/JingleSession.h
+++ b/Swiften/Jingle/JingleSession.h
@@ -7,47 +7,43 @@
#pragma once
#include <boost/shared_ptr.hpp>
+#include <string>
#include <Swiften/Base/boost_bsignals.h>
-#include <string>
+#include <Swiften/JID/JID.h>
#include <Swiften/Elements/JinglePayload.h>
-#include <Swiften/Elements/JingleContent.h>
-#include <Swiften/Base/foreach.h>
namespace Swift {
+ class JingleContentID;
+
class JingleSession {
- friend class JingleResponder;
public:
typedef boost::shared_ptr<JingleSession> ref;
- JingleSession(const std::string& id, const std::vector<JingleContent::ref>& contents);
+ JingleSession(const JID& initiator, const std::string& id);
virtual ~JingleSession();
- std::string getID() const {
- return id;
+ const JID& getInitiator() const {
+ return initiator;
}
- template<typename T>
- JingleContent::ref getContentWithDescription() const {
- foreach (JingleContent::ref content, contents) {
- if (content->getDescription<T>()) {
- return content;
- }
- }
- return JingleContent::ref();
- }
-
- const std::vector<JingleContent::ref> getContents() const {
- return contents;
+ std::string getID() const {
+ return id;
}
- void terminate(JinglePayload::Reason::Type reason);
+ virtual void terminate(JinglePayload::Reason::Type reason) = 0;
+ virtual void accept(JingleTransportPayload::ref = JingleTransportPayload::ref()) = 0;
+ virtual void sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref) = 0;
+ virtual void acceptTransport(const JingleContentID&, JingleTransportPayload::ref) = 0;
+ virtual void rejectTransport(const JingleContentID&, JingleTransportPayload::ref) = 0;
- private:
- void handleIncomingAction(JinglePayload::ref);
+ public:
+ boost::signal<void ()> onSessionTerminateReceived;
+ boost::signal<void (const JingleContentID&, JingleTransportPayload::ref)> onTransportInfoReceived;
+ boost::signal<void (const JingleContentID&, JingleTransportPayload::ref)> onTransportReplaceReceived;
private:
+ JID initiator;
std::string id;
- std::vector<JingleContent::ref> contents;
};
}
diff --git a/Swiften/Jingle/JingleSessionImpl.cpp b/Swiften/Jingle/JingleSessionImpl.cpp
new file mode 100644
index 0000000..cbb2b42
--- /dev/null
+++ b/Swiften/Jingle/JingleSessionImpl.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Jingle/JingleSessionImpl.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace Swift {
+
+JingleSessionImpl::JingleSessionImpl(const JID& initiator, const std::string& id) : JingleSession(initiator, id) {
+}
+
+void JingleSessionImpl::handleIncomingAction(JinglePayload::ref) {
+}
+
+void JingleSessionImpl::terminate(JinglePayload::Reason::Type reason) {
+ JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionTerminate, getID());
+ payload->setReason(JinglePayload::Reason(reason));
+ //onAction(payload)
+}
+
+void JingleSessionImpl::acceptTransport(const JingleContentID&, JingleTransportPayload::ref) {
+
+}
+
+void JingleSessionImpl::rejectTransport(const JingleContentID&, JingleTransportPayload::ref) {
+
+}
+
+void JingleSessionImpl::accept(JingleTransportPayload::ref) {
+}
+
+void JingleSessionImpl::sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref) {
+
+}
+
+
+
+}
diff --git a/Swiften/Jingle/JingleSessionImpl.h b/Swiften/Jingle/JingleSessionImpl.h
new file mode 100644
index 0000000..a254ead
--- /dev/null
+++ b/Swiften/Jingle/JingleSessionImpl.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Jingle/JingleSession.h>
+
+namespace Swift {
+ class JingleSessionImpl : public JingleSession {
+ friend class JingleResponder;
+ public:
+ typedef boost::shared_ptr<JingleSessionImpl> ref;
+
+ JingleSessionImpl(const JID& initiator, const std::string& id);
+
+ virtual void terminate(JinglePayload::Reason::Type reason);
+ virtual void accept(JingleTransportPayload::ref);
+ virtual void sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref);
+ virtual void acceptTransport(const JingleContentID&, JingleTransportPayload::ref);
+ virtual void rejectTransport(const JingleContentID&, JingleTransportPayload::ref);
+
+ private:
+ void handleIncomingAction(JinglePayload::ref);
+ };
+}
diff --git a/Swiften/Jingle/JingleSessionManager.cpp b/Swiften/Jingle/JingleSessionManager.cpp
index e60449b..58e90c8 100644
--- a/Swiften/Jingle/JingleSessionManager.cpp
+++ b/Swiften/Jingle/JingleSessionManager.cpp
@@ -7,6 +7,7 @@
#include <Swiften/Jingle/JingleSessionManager.h>
#include <Swiften/Jingle/JingleResponder.h>
#include <Swiften/Jingle/IncomingJingleSessionHandler.h>
+#include <Swiften/Base/foreach.h>
namespace Swift {
@@ -18,9 +19,9 @@ JingleSessionManager::~JingleSessionManager() {
delete responder;
}
-JingleSession::ref JingleSessionManager::getSession(const JID& jid, const std::string& id) const {
+JingleSessionImpl::ref JingleSessionManager::getSession(const JID& jid, const std::string& id) const {
SessionMap::const_iterator i = incomingSessions.find(JIDSession(jid, id));
- return i != incomingSessions.end() ? i->second : JingleSession::ref();
+ return i != incomingSessions.end() ? i->second : JingleSessionImpl::ref();
}
void JingleSessionManager::addIncomingSessionHandler(IncomingJingleSessionHandler* handler) {
@@ -31,10 +32,10 @@ void JingleSessionManager::removeIncomingSessionHandler(IncomingJingleSessionHan
incomingSessionHandlers.erase(std::remove(incomingSessionHandlers.begin(), incomingSessionHandlers.end(), handler), incomingSessionHandlers.end());
}
-void JingleSessionManager::handleIncomingSession(const JID& from, IncomingJingleSession::ref session) {
+void JingleSessionManager::handleIncomingSession(const JID& from, JingleSessionImpl::ref session, const std::vector<JingleContentPayload::ref>& contents) {
incomingSessions.insert(std::make_pair(JIDSession(from, session->getID()), session));
foreach (IncomingJingleSessionHandler* handler, incomingSessionHandlers) {
- if (handler->handleIncomingJingleSession(session)) {
+ if (handler->handleIncomingJingleSession(session, contents)) {
return;
}
}
diff --git a/Swiften/Jingle/JingleSessionManager.h b/Swiften/Jingle/JingleSessionManager.h
index 3e99656..3b23fb0 100644
--- a/Swiften/Jingle/JingleSessionManager.h
+++ b/Swiften/Jingle/JingleSessionManager.h
@@ -10,7 +10,7 @@
#include <map>
#include <Swiften/Base/boost_bsignals.h>
-#include <Swiften/Jingle/IncomingJingleSession.h>
+#include <Swiften/Jingle/JingleSessionImpl.h>
namespace Swift {
class IQRouter;
@@ -23,13 +23,13 @@ namespace Swift {
JingleSessionManager(IQRouter* router);
~JingleSessionManager();
- JingleSession::ref getSession(const JID& jid, const std::string& id) const;
+ JingleSessionImpl::ref getSession(const JID& jid, const std::string& id) const;
void addIncomingSessionHandler(IncomingJingleSessionHandler* handler);
void removeIncomingSessionHandler(IncomingJingleSessionHandler* handler);
protected:
- void handleIncomingSession(const JID& from, IncomingJingleSession::ref);
+ void handleIncomingSession(const JID& from, JingleSessionImpl::ref, const std::vector<JingleContentPayload::ref>& contents);
private:
IQRouter* router;
@@ -43,7 +43,7 @@ namespace Swift {
JID jid;
std::string session;
};
- typedef std::map<JIDSession, JingleSession::ref> SessionMap;
+ typedef std::map<JIDSession, JingleSessionImpl::ref> SessionMap;
SessionMap incomingSessions;
};
}
diff --git a/Swiften/Jingle/SConscript b/Swiften/Jingle/SConscript
index a8890b7..6b3cfd3 100644
--- a/Swiften/Jingle/SConscript
+++ b/Swiften/Jingle/SConscript
@@ -1,11 +1,11 @@
Import("swiften_env")
sources = [
- "IncomingJingleSession.cpp",
+ "JingleSession.cpp",
+ "JingleSessionImpl.cpp",
"IncomingJingleSessionHandler.cpp",
"JingleSessionManager.cpp",
"JingleResponder.cpp",
- "JingleSession.cpp",
]
swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources))
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp
new file mode 100644
index 0000000..e31bf87
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h>
+
+#include <boost/bind.hpp>
+#include <iostream>
+
+#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h>
+
+namespace Swift {
+
+void AvahiBrowseQuery::startBrowsing() {
+ std::cout << "Start browsing" << std::endl;
+ assert(!browser);
+ avahi_threaded_poll_lock(querier->getThreadedPoll());
+ browser = avahi_service_browser_new(querier->getClient(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_presence._tcp", NULL, static_cast<AvahiLookupFlags>(0), &handleServiceDiscoveredStatic, this);
+ if (!browser) {
+ std::cout << "Error" << std::endl;
+ eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this());
+ }
+ avahi_threaded_poll_unlock(querier->getThreadedPoll());
+}
+
+void AvahiBrowseQuery::stopBrowsing() {
+ std::cout << "Stop browsing" << std::endl;
+ avahi_threaded_poll_lock(querier->getThreadedPoll());
+ avahi_service_browser_free(browser);
+ browser = NULL;
+ avahi_threaded_poll_unlock(querier->getThreadedPoll());
+}
+
+void AvahiBrowseQuery::handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags) {
+ switch (event) {
+ case AVAHI_BROWSER_FAILURE:
+ std::cout << "Service browse error" << std::endl;
+ eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this());
+ break;
+ case AVAHI_BROWSER_NEW: {
+ DNSSDServiceID service(name, domain, type, interfaceIndex);
+ std::cout << "Service discovered " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl;
+ eventLoop->postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
+ break;
+ }
+ case AVAHI_BROWSER_REMOVE: {
+ std::cout << "Service went away " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl;
+ DNSSDServiceID service(name, domain, type, interfaceIndex);
+ eventLoop->postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
+ break;
+ }
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ break;
+ }
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h
index 163a5f6..7641712 100644
--- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/bind.hpp>
+#include <avahi-client/lookup.h>
#include "Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h"
#include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h"
@@ -20,54 +20,15 @@ namespace Swift {
AvahiBrowseQuery(boost::shared_ptr<AvahiQuerier> q, EventLoop* eventLoop) : AvahiQuery(q, eventLoop), browser(NULL) {
}
- void startBrowsing() {
- std::cout << "Start browsing" << std::endl;
- assert(!browser);
- avahi_threaded_poll_lock(querier->getThreadedPoll());
- browser = avahi_service_browser_new(querier->getClient(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_presence._tcp", NULL, static_cast<AvahiLookupFlags>(0), &handleServiceDiscoveredStatic, this);
- if (!browser) {
- std::cout << "Error" << std::endl;
- eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this());
- }
- avahi_threaded_poll_unlock(querier->getThreadedPoll());
- }
-
- void stopBrowsing() {
- std::cout << "Stop browsing" << std::endl;
- avahi_threaded_poll_lock(querier->getThreadedPoll());
- avahi_service_browser_free(browser);
- browser = NULL;
- avahi_threaded_poll_unlock(querier->getThreadedPoll());
- }
+ void startBrowsing();
+ void stopBrowsing();
private:
static void handleServiceDiscoveredStatic(AvahiServiceBrowser *b, AvahiIfIndex interfaceIndex, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* context) {
static_cast<AvahiBrowseQuery*>(context)->handleServiceDiscovered(b, interfaceIndex, protocol, event, name, type, domain, flags);
}
- void handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags) {
- switch (event) {
- case AVAHI_BROWSER_FAILURE:
- std::cout << "Service browse error" << std::endl;
- eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this());
- break;
- case AVAHI_BROWSER_NEW: {
- DNSSDServiceID service(name, domain, type, interfaceIndex);
- std::cout << "Service discovered " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl;
- eventLoop->postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
- break;
- }
- case AVAHI_BROWSER_REMOVE: {
- std::cout << "Service went away " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl;
- DNSSDServiceID service(name, domain, type, interfaceIndex);
- eventLoop->postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
- break;
- }
- case AVAHI_BROWSER_ALL_FOR_NOW:
- case AVAHI_BROWSER_CACHE_EXHAUSTED:
- break;
- }
- }
+ void handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags);
private:
AvahiServiceBrowser* browser;
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp
new file mode 100644
index 0000000..7975e7b
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h>
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h>
+
+namespace Swift {
+
+void AvahiRegisterQuery::registerService() {
+ std::cout << "Registering service " << name << ":" << port << std::endl;
+ avahi_threaded_poll_lock(querier->getThreadedPoll());
+ if (!group) {
+ std::cout << "Creating entry group" << std::endl;
+ group = avahi_entry_group_new(querier->getClient(), handleEntryGroupChange, this);
+ if (!group) {
+ std::cout << "Error ceating entry group" << std::endl;
+ eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
+ }
+ }
+
+ doRegisterService();
+ avahi_threaded_poll_unlock(querier->getThreadedPoll());
+}
+
+void AvahiRegisterQuery::unregisterService() {
+ if (group) {
+ avahi_entry_group_free(group);
+ group = NULL;
+ }
+}
+
+void AvahiRegisterQuery::updateServiceInfo(const ByteArray& txtRecord) {
+ this->txtRecord = txtRecord;
+ avahi_threaded_poll_lock(querier->getThreadedPoll());
+ assert(group);
+ avahi_entry_group_reset(group);
+ doRegisterService();
+ avahi_threaded_poll_unlock(querier->getThreadedPoll());
+}
+
+void AvahiRegisterQuery::doRegisterService() {
+ AvahiStringList* txtList;
+ avahi_string_list_parse(txtRecord.getData(), txtRecord.getSize(), &txtList);
+
+ int result = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name.c_str(), "_presence._tcp", NULL, NULL, port, txtList);
+ if (result < 0) {
+ std::cout << "Error registering service: " << avahi_strerror(result) << std::endl;
+ eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
+ }
+ result = avahi_entry_group_commit(group);
+ if (result < 0) {
+ std::cout << "Error registering service: " << avahi_strerror(result) << std::endl;
+ }
+}
+
+void AvahiRegisterQuery::handleEntryGroupChange(AvahiEntryGroup* g, AvahiEntryGroupState state) {
+ std::cout << "ENtry group callback: " << state << std::endl;
+ switch (state) {
+ case AVAHI_ENTRY_GROUP_ESTABLISHED :
+ // Domain is a hack!
+ eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, "local", "_presence._tcp", 0))), shared_from_this());
+ std::cout << "Entry group established" << std::endl;
+ break;
+ case AVAHI_ENTRY_GROUP_COLLISION : {
+ std::cout << "Entry group collision" << std::endl;
+ /*char *n;
+ n = avahi_alternative_service_name(name);
+ avahi_free(name);
+ name = n;*/
+ break;
+ }
+
+ case AVAHI_ENTRY_GROUP_FAILURE :
+ std::cout << "Entry group failure " << avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))) << std::endl;
+ break;
+
+ case AVAHI_ENTRY_GROUP_UNCOMMITED:
+ case AVAHI_ENTRY_GROUP_REGISTERING:
+ ;
+
+ /*
+ DNSServiceErrorType result = DNSServiceRegister(
+ &sdRef, 0, 0, name.c_str(), "_presence._tcp", NULL, NULL, port,
+ txtRecord.getSize(), txtRecord.getData(),
+ &AvahiRegisterQuery::handleServiceRegisteredStatic, this);
+ if (result != kDNSServiceErr_NoError) {
+ sdRef = NULL;
+ }*/
+ //eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
+ }
+}
+
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h
index 07966af..3303f1b 100644
--- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h
@@ -21,94 +21,18 @@ namespace Swift {
AvahiRegisterQuery(const std::string& name, int port, const ByteArray& txtRecord, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), name(name), port(port), txtRecord(txtRecord), group(0) {
}
- void registerService() {
- std::cout << "Registering service " << name << ":" << port << std::endl;
- avahi_threaded_poll_lock(querier->getThreadedPoll());
- if (!group) {
- std::cout << "Creating entry group" << std::endl;
- group = avahi_entry_group_new(querier->getClient(), handleEntryGroupChange, this);
- if (!group) {
- std::cout << "Error ceating entry group" << std::endl;
- eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
- }
- }
-
- doRegisterService();
- avahi_threaded_poll_unlock(querier->getThreadedPoll());
- }
-
- void unregisterService() {
- if (group) {
- avahi_entry_group_free(group);
- group = NULL;
- }
- }
-
- void updateServiceInfo(const ByteArray& txtRecord) {
- this->txtRecord = txtRecord;
- avahi_threaded_poll_lock(querier->getThreadedPoll());
- assert(group);
- avahi_entry_group_reset(group);
- doRegisterService();
- avahi_threaded_poll_unlock(querier->getThreadedPoll());
- }
+ void registerService();
+ void unregisterService();
+ void updateServiceInfo(const ByteArray& txtRecord);
private:
- void doRegisterService() {
- AvahiStringList* txtList;
- avahi_string_list_parse(txtRecord.getData(), txtRecord.getSize(), &txtList);
-
- int result = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name.c_str(), "_presence._tcp", NULL, NULL, port, txtList);
- if (result < 0) {
- std::cout << "Error registering service: " << avahi_strerror(result) << std::endl;
- eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
- }
- result = avahi_entry_group_commit(group);
- if (result < 0) {
- std::cout << "Error registering service: " << avahi_strerror(result) << std::endl;
- }
- }
+ void doRegisterService();
static void handleEntryGroupChange(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
static_cast<AvahiRegisterQuery*>(userdata)->handleEntryGroupChange(g, state);
}
- void handleEntryGroupChange(AvahiEntryGroup* g, AvahiEntryGroupState state) {
- std::cout << "ENtry group callback: " << state << std::endl;
- switch (state) {
- case AVAHI_ENTRY_GROUP_ESTABLISHED :
- // Domain is a hack!
- eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, "local", "_presence._tcp", 0))), shared_from_this());
- std::cout << "Entry group established" << std::endl;
- break;
- case AVAHI_ENTRY_GROUP_COLLISION : {
- std::cout << "Entry group collision" << std::endl;
- /*char *n;
- n = avahi_alternative_service_name(name);
- avahi_free(name);
- name = n;*/
- break;
- }
-
- case AVAHI_ENTRY_GROUP_FAILURE :
- std::cout << "Entry group failure " << avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))) << std::endl;
- break;
-
- case AVAHI_ENTRY_GROUP_UNCOMMITED:
- case AVAHI_ENTRY_GROUP_REGISTERING:
- ;
-
- /*
- DNSServiceErrorType result = DNSServiceRegister(
- &sdRef, 0, 0, name.c_str(), "_presence._tcp", NULL, NULL, port,
- txtRecord.getSize(), txtRecord.getData(),
- &AvahiRegisterQuery::handleServiceRegisteredStatic, this);
- if (result != kDNSServiceErr_NoError) {
- sdRef = NULL;
- }*/
- //eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
- }
- }
+ void handleEntryGroupChange(AvahiEntryGroup* g, AvahiEntryGroupState state);
/*
static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp
new file mode 100644
index 0000000..d9a1c5c
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h>
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+AvahiResolveHostnameQuery::AvahiResolveHostnameQuery(const std::string& hostname, int, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), hostname(hostname) {
+ std::cout << "Resolving hostname " << hostname << std::endl;
+}
+
+void AvahiResolveHostnameQuery::run() {
+ eventLoop->postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>(HostAddress(hostname))), shared_from_this());
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h
index 00712f1..acc1897 100644
--- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h
@@ -19,13 +19,9 @@ namespace Swift {
class AvahiResolveHostnameQuery : public DNSSDResolveHostnameQuery, public AvahiQuery {
public:
- AvahiResolveHostnameQuery(const std::string& hostname, int, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), hostname(hostname) {
- std::cout << "Resolving hostname " << hostname << std::endl;
- }
+ AvahiResolveHostnameQuery(const std::string& hostname, int, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop);
- void run() {
- eventLoop->postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>(HostAddress(hostname))), shared_from_this());
- }
+ void run();
void finish() {
}
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp
new file mode 100644
index 0000000..24fe067
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h>
+
+#include <boost/bind.hpp>
+#include <iostream>
+
+#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h>
+
+namespace Swift {
+
+void AvahiResolveServiceQuery::start() {
+ std::cout << "Start resolving " << service.getName() << " " << service.getType() << " " << service.getDomain() << std::endl;
+ avahi_threaded_poll_lock(querier->getThreadedPoll());
+ assert(!resolver);
+ resolver = avahi_service_resolver_new(querier->getClient(), service.getNetworkInterfaceID(), AVAHI_PROTO_UNSPEC, service.getName().c_str(), service.getType().c_str(), service.getDomain().c_str(), AVAHI_PROTO_UNSPEC, static_cast<AvahiLookupFlags>(0), handleServiceResolvedStatic, this);
+ if (!resolver) {
+ std::cout << "Error starting resolver" << std::endl;
+ eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+ }
+ avahi_threaded_poll_unlock(querier->getThreadedPoll());
+}
+
+void AvahiResolveServiceQuery::stop() {
+ std::cout << "Stop resolving" << std::endl;
+ avahi_threaded_poll_lock(querier->getThreadedPoll());
+ avahi_service_resolver_free(resolver);
+ resolver = NULL;
+ avahi_threaded_poll_unlock(querier->getThreadedPoll());
+}
+
+void AvahiResolveServiceQuery::handleServiceResolved(AvahiServiceResolver* resolver, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent event, const char *name, const char * type, const char* domain, const char * /*host_name*/, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags) {
+ std::cout << "Resolve finished" << std::endl;
+ switch(event) {
+ case AVAHI_RESOLVER_FAILURE:
+ std::cout << "Resolve error " << avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(resolver))) << std::endl;
+ eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+ break;
+ case AVAHI_RESOLVER_FOUND: {
+ std::cout << "Success" << std::endl;
+ char a[AVAHI_ADDRESS_STR_MAX];
+ avahi_address_snprint(a, sizeof(a), address);
+
+ ByteArray txtRecord;
+ txtRecord.resize(1024);
+ avahi_string_list_serialize(txt, txtRecord.getData(), txtRecord.getSize());
+
+ // FIXME: Probably not accurate
+ std::string fullname = std::string(name) + "." + std::string(type) + "." + std::string(domain) + ".";
+ std::cout << "Result: " << fullname << "->" << std::string(a) << ":" << port << std::endl;
+ eventLoop->postEvent(
+ boost::bind(
+ boost::ref(onServiceResolved),
+ Result(fullname, std::string(a), port, txtRecord)),
+ shared_from_this());
+ break;
+ }
+ }
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h
index e9c4db1..be48409 100644
--- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h
@@ -6,6 +6,8 @@
#pragma once
+#include <avahi-client/lookup.h>
+
#include "Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h"
#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
@@ -20,59 +22,15 @@ namespace Swift {
AvahiResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), service(service), resolver(NULL) {
}
- void start() {
- std::cout << "Start resolving " << service.getName() << " " << service.getType() << " " << service.getDomain() << std::endl;
- avahi_threaded_poll_lock(querier->getThreadedPoll());
- assert(!resolver);
- resolver = avahi_service_resolver_new(querier->getClient(), service.getNetworkInterfaceID(), AVAHI_PROTO_UNSPEC, service.getName().c_str(), service.getType().c_str(), service.getDomain().c_str(), AVAHI_PROTO_UNSPEC, static_cast<AvahiLookupFlags>(0), handleServiceResolvedStatic, this);
- if (!resolver) {
- std::cout << "Error starting resolver" << std::endl;
- eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
- }
- avahi_threaded_poll_unlock(querier->getThreadedPoll());
- }
-
- void stop() {
- std::cout << "Stop resolving" << std::endl;
- avahi_threaded_poll_lock(querier->getThreadedPoll());
- avahi_service_resolver_free(resolver);
- resolver = NULL;
- avahi_threaded_poll_unlock(querier->getThreadedPoll());
- }
+ void start();
+ void stop();
private:
static void handleServiceResolvedStatic(AvahiServiceResolver* resolver, AvahiIfIndex interfaceIndex, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void* context) {
static_cast<AvahiResolveServiceQuery*>(context)->handleServiceResolved(resolver, interfaceIndex, protocol, event, name, type, domain, host_name, address, port, txt, flags);
}
- void handleServiceResolved(AvahiServiceResolver* resolver, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent event, const char *name, const char * type, const char* domain, const char * /*host_name*/, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags) {
- std::cout << "Resolve finished" << std::endl;
- switch(event) {
- case AVAHI_RESOLVER_FAILURE:
- std::cout << "Resolve error " << avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(resolver))) << std::endl;
- eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
- break;
- case AVAHI_RESOLVER_FOUND: {
- std::cout << "Success" << std::endl;
- char a[AVAHI_ADDRESS_STR_MAX];
- avahi_address_snprint(a, sizeof(a), address);
-
- ByteArray txtRecord;
- txtRecord.resize(1024);
- avahi_string_list_serialize(txt, txtRecord.getData(), txtRecord.getSize());
-
- // FIXME: Probably not accurate
- std::string fullname = std::string(name) + "." + std::string(type) + "." + std::string(domain) + ".";
- std::cout << "Result: " << fullname << "->" << std::string(a) << ":" << port << std::endl;
- eventLoop->postEvent(
- boost::bind(
- boost::ref(onServiceResolved),
- Result(fullname, std::string(a), port, txtRecord)),
- shared_from_this());
- break;
- }
- }
- }
+ void handleServiceResolved(AvahiServiceResolver* resolver, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent event, const char *name, const char * type, const char* domain, const char * /*host_name*/, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags);
private:
DNSSDServiceID service;
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
index edd3056..c342247 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
@@ -9,7 +9,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <list>
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
index d7d0228..b13b0c4 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
@@ -7,7 +7,9 @@
#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h"
#include <boost/bind.hpp>
+#include <iostream>
+#include <Swiften/Base/foreach.h>
#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h"
#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h"
#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h"
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
index b2871c9..9aef6a5 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
@@ -11,7 +11,6 @@
#include <list>
#include <set>
-#include "Swiften/Base/foreach.h"
#include <string>
#include "Swiften/EventLoop/EventOwner.h"
#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
@@ -63,8 +62,8 @@ namespace Swift {
template<typename T>
std::vector< boost::shared_ptr<T> > getAllQueriesEverRun() const {
std::vector< boost::shared_ptr<T> > result;
- foreach(const boost::shared_ptr<FakeDNSSDQuery>& query, allQueriesEverRun) {
- if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(query)) {
+ for (QueryList::const_iterator i = allQueriesEverRun.begin(); i != allQueriesEverRun.end(); ++i) {
+ if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(*i)) {
result.push_back(resultQuery);
}
}
@@ -75,8 +74,8 @@ namespace Swift {
template<typename T>
std::vector< boost::shared_ptr<T> > getQueries() const {
std::vector< boost::shared_ptr<T> > result;
- foreach(const boost::shared_ptr<FakeDNSSDQuery>& query, runningQueries) {
- if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(query)) {
+ for (QueryList::const_iterator i = runningQueries.begin(); i != runningQueries.end(); ++i) {
+ if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(*i)) {
result.push_back(resultQuery);
}
}
@@ -86,8 +85,9 @@ namespace Swift {
private:
std::string domain;
EventLoop* eventLoop;
- std::list< boost::shared_ptr<FakeDNSSDQuery> > runningQueries;
- std::list< boost::shared_ptr<FakeDNSSDQuery> > allQueriesEverRun;
+ typedef std::list< boost::shared_ptr<FakeDNSSDQuery> > QueryList;
+ QueryList runningQueries;
+ QueryList allQueriesEverRun;
std::set<DNSSDServiceID> services;
typedef std::map<DNSSDServiceID,DNSSDResolveServiceQuery::Result> ServiceInfoMap;
ServiceInfoMap serviceInfo;
diff --git a/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp
index 65542d2..d13032d 100644
--- a/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp
+++ b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp
@@ -8,6 +8,7 @@
#include <boost/bind.hpp>
+#include <Swiften/Base/foreach.h>
#include "Swiften/StreamStack/XMPPLayer.h"
#include "Swiften/Elements/ProtocolHeader.h"
#include "Swiften/Elements/StreamFeatures.h"
diff --git a/Swiften/LinkLocal/SConscript b/Swiften/LinkLocal/SConscript
index 6edf993..29ea692 100644
--- a/Swiften/LinkLocal/SConscript
+++ b/Swiften/LinkLocal/SConscript
@@ -31,7 +31,11 @@ elif myenv.get("HAVE_AVAHI", 0) :
myenv.Append(CPPDEFINES = ["HAVE_AVAHI"])
sources += [
"DNSSD/Avahi/AvahiQuerier.cpp",
- "DNSSD/Avahi/AvahiQuery.cpp"
+ "DNSSD/Avahi/AvahiQuery.cpp",
+ "DNSSD/Avahi/AvahiResolveHostnameQuery.cpp",
+ "DNSSD/Avahi/AvahiResolveServiceQuery.cpp",
+ "DNSSD/Avahi/AvahiRegisterQuery.cpp",
+ "DNSSD/Avahi/AvahiBrowseQuery.cpp",
]
objects = myenv.SwiftenObject(sources)
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp
index 98deed1..a2e8280 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp
@@ -7,6 +7,8 @@
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <boost/bind.hpp>
+
#include "Swiften/LinkLocal/LinkLocalConnector.h"
#include "Swiften/LinkLocal/LinkLocalService.h"
#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index 68a5a86..553e49d 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -10,6 +10,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
+#include <Swiften/Base/foreach.h>
#include "Swiften/Presence/DirectedPresenceSender.h"
#include "Swiften/Client/StanzaChannel.h"
#include "Swiften/Queries/IQRouter.h"
diff --git a/Swiften/MUC/MUCBookmarkManager.cpp b/Swiften/MUC/MUCBookmarkManager.cpp
index d0855cd..65e15e3 100644
--- a/Swiften/MUC/MUCBookmarkManager.cpp
+++ b/Swiften/MUC/MUCBookmarkManager.cpp
@@ -9,6 +9,7 @@
#include <boost/bind.hpp>
#include <iostream>
+#include <Swiften/Base/foreach.h>
#include "Swiften/Queries/IQRouter.h"
#include "Swiften/Queries/Requests/GetPrivateStorageRequest.h"
#include "Swiften/Queries/Requests/SetPrivateStorageRequest.h"
diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp
index f7ff8c4..c0faad9 100644
--- a/Swiften/Network/BoostConnection.cpp
+++ b/Swiften/Network/BoostConnection.cpp
@@ -9,6 +9,8 @@
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
+#include <boost/asio/placeholders.hpp>
+#include <boost/asio/write.hpp>
#include <Swiften/Base/Log.h>
#include "Swiften/EventLoop/EventLoop.h"
diff --git a/Swiften/Network/BoostConnection.h b/Swiften/Network/BoostConnection.h
index 506eedf..16e587d 100644
--- a/Swiften/Network/BoostConnection.h
+++ b/Swiften/Network/BoostConnection.h
@@ -6,7 +6,8 @@
#pragma once
-#include <boost/asio.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/tcp.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/mutex.hpp>
diff --git a/Swiften/Network/BoostConnectionFactory.h b/Swiften/Network/BoostConnectionFactory.h
index ea9d656..bf1bc6c 100644
--- a/Swiften/Network/BoostConnectionFactory.h
+++ b/Swiften/Network/BoostConnectionFactory.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/asio.hpp>
+#include <boost/asio/io_service.hpp>
#include "Swiften/Network/ConnectionFactory.h"
#include "Swiften/Network/BoostConnection.h"
diff --git a/Swiften/Network/BoostConnectionServer.cpp b/Swiften/Network/BoostConnectionServer.cpp
index 4c6403c..e5fb8c0 100644
--- a/Swiften/Network/BoostConnectionServer.cpp
+++ b/Swiften/Network/BoostConnectionServer.cpp
@@ -8,6 +8,7 @@
#include <boost/bind.hpp>
#include <boost/system/system_error.hpp>
+#include <boost/asio/placeholders.hpp>
#include "Swiften/EventLoop/EventLoop.h"
diff --git a/Swiften/Network/BoostConnectionServer.h b/Swiften/Network/BoostConnectionServer.h
index a45e598..3424720 100644
--- a/Swiften/Network/BoostConnectionServer.h
+++ b/Swiften/Network/BoostConnectionServer.h
@@ -7,8 +7,9 @@
#pragma once
#include <boost/shared_ptr.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/tcp.hpp>
#include <boost/enable_shared_from_this.hpp>
-#include <boost/asio.hpp>
#include "Swiften/Base/boost_bsignals.h"
#include "Swiften/Network/BoostConnection.h"
diff --git a/Swiften/Network/BoostIOServiceThread.h b/Swiften/Network/BoostIOServiceThread.h
index 1f72049..ea04b02 100644
--- a/Swiften/Network/BoostIOServiceThread.h
+++ b/Swiften/Network/BoostIOServiceThread.h
@@ -6,8 +6,8 @@
#pragma once
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/thread/thread.hpp>
#include <boost/shared_ptr.hpp>
namespace Swift {
diff --git a/Swiften/Network/BoostTimer.cpp b/Swiften/Network/BoostTimer.cpp
index 12d06c1..27e4b34 100644
--- a/Swiften/Network/BoostTimer.cpp
+++ b/Swiften/Network/BoostTimer.cpp
@@ -8,6 +8,7 @@
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
+#include <boost/bind.hpp>
#include "Swiften/EventLoop/EventLoop.h"
diff --git a/Swiften/Network/BoostTimer.h b/Swiften/Network/BoostTimer.h
index 1139dcf..614698d 100644
--- a/Swiften/Network/BoostTimer.h
+++ b/Swiften/Network/BoostTimer.h
@@ -6,8 +6,8 @@
#pragma once
-#include <boost/asio.hpp>
-#include <boost/thread.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/deadline_timer.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "Swiften/EventLoop/EventOwner.h"
diff --git a/Swiften/Network/BoostTimerFactory.h b/Swiften/Network/BoostTimerFactory.h
index c0e9ef7..789ba24 100644
--- a/Swiften/Network/BoostTimerFactory.h
+++ b/Swiften/Network/BoostTimerFactory.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/asio.hpp>
+#include <boost/asio/io_service.hpp>
#include "Swiften/Network/TimerFactory.h"
#include "Swiften/Network/BoostTimer.h"
diff --git a/Swiften/Network/CAresDomainNameResolver.h b/Swiften/Network/CAresDomainNameResolver.h
index a630b61..f0973b9 100644
--- a/Swiften/Network/CAresDomainNameResolver.h
+++ b/Swiften/Network/CAresDomainNameResolver.h
@@ -7,7 +7,7 @@
#pragma once
#include <ares.h>
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <list>
diff --git a/Swiften/Network/ChainedConnector.cpp b/Swiften/Network/ChainedConnector.cpp
new file mode 100644
index 0000000..1a38e53
--- /dev/null
+++ b/Swiften/Network/ChainedConnector.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/ChainedConnector.h>
+
+#include <boost/bind.hpp>
+#include <typeinfo>
+
+#include <Swiften/Base/Log.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Network/Connector.h>
+#include <Swiften/Network/ConnectionFactory.h>
+
+using namespace Swift;
+
+ChainedConnector::ChainedConnector(
+ const std::string& hostname,
+ DomainNameResolver* resolver,
+ const std::vector<ConnectionFactory*>& connectionFactories,
+ TimerFactory* timerFactory) :
+ hostname(hostname),
+ resolver(resolver),
+ connectionFactories(connectionFactories),
+ timerFactory(timerFactory),
+ timeoutMilliseconds(0) {
+}
+
+void ChainedConnector::setTimeoutMilliseconds(int milliseconds) {
+ timeoutMilliseconds = milliseconds;
+}
+
+void ChainedConnector::start() {
+ SWIFT_LOG(debug) << "Starting queued connector for " << hostname << std::endl;
+
+ connectionFactoryQueue = std::deque<ConnectionFactory*>(connectionFactories.begin(), connectionFactories.end());
+ tryNextConnectionFactory();
+}
+
+void ChainedConnector::stop() {
+ if (currentConnector) {
+ currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1));
+ currentConnector->stop();
+ currentConnector.reset();
+ }
+ finish(boost::shared_ptr<Connection>());
+}
+
+void ChainedConnector::tryNextConnectionFactory() {
+ assert(!currentConnector);
+ if (connectionFactoryQueue.empty()) {
+ SWIFT_LOG(debug) << "No more connection factories" << std::endl;
+ finish(boost::shared_ptr<Connection>());
+ }
+ else {
+ ConnectionFactory* connectionFactory = connectionFactoryQueue.front();
+ SWIFT_LOG(debug) << "Trying next connection factory: " << typeid(*connectionFactory).name() << std::endl;
+ connectionFactoryQueue.pop_front();
+ currentConnector = Connector::create(hostname, resolver, connectionFactory, timerFactory);
+ currentConnector->setTimeoutMilliseconds(timeoutMilliseconds);
+ currentConnector->onConnectFinished.connect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1));
+ currentConnector->start();
+ }
+}
+
+void ChainedConnector::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
+ SWIFT_LOG(debug) << "Connector finished" << std::endl;
+ currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1));
+ currentConnector.reset();
+ if (connection) {
+ finish(connection);
+ }
+ else {
+ tryNextConnectionFactory();
+ }
+}
+
+void ChainedConnector::finish(boost::shared_ptr<Connection> connection) {
+ onConnectFinished(connection);
+}
diff --git a/Swiften/Network/ChainedConnector.h b/Swiften/Network/ChainedConnector.h
new file mode 100644
index 0000000..15b17f3
--- /dev/null
+++ b/Swiften/Network/ChainedConnector.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <deque>
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Base/boost_bsignals.h>
+
+namespace Swift {
+ class Connection;
+ class Connector;
+ class ConnectionFactory;
+ class TimerFactory;
+ class DomainNameResolver;
+
+ class ChainedConnector {
+ public:
+ ChainedConnector(const std::string& hostname, DomainNameResolver*, const std::vector<ConnectionFactory*>&, TimerFactory*);
+
+ void setTimeoutMilliseconds(int milliseconds);
+ void start();
+ void stop();
+
+ boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished;
+
+ private:
+ void finish(boost::shared_ptr<Connection> connection);
+ void tryNextConnectionFactory();
+ void handleConnectorFinished(boost::shared_ptr<Connection>);
+
+ private:
+ std::string hostname;
+ DomainNameResolver* resolver;
+ std::vector<ConnectionFactory*> connectionFactories;
+ TimerFactory* timerFactory;
+ int timeoutMilliseconds;
+ std::deque<ConnectionFactory*> connectionFactoryQueue;
+ boost::shared_ptr<Connector> currentConnector;
+ };
+};
diff --git a/Swiften/Network/Connection.cpp b/Swiften/Network/Connection.cpp
new file mode 100644
index 0000000..9bb29e1
--- /dev/null
+++ b/Swiften/Network/Connection.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/Connection.h>
+
+using namespace Swift;
+
+Connection::Connection() {
+}
+
+Connection::~Connection() {
+}
diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h
index 529dd82..74d25aa 100644
--- a/Swiften/Network/Connection.h
+++ b/Swiften/Network/Connection.h
@@ -7,13 +7,13 @@
#pragma once
#include <boost/shared_ptr.hpp>
+#include <Swiften/Base/boost_bsignals.h>
-#include "Swiften/Base/boost_bsignals.h"
-#include "Swiften/Base/ByteArray.h"
-#include <string>
-#include "Swiften/Network/HostAddressPort.h"
+#include <Swiften/Base/ByteArray.h>
namespace Swift {
+ class HostAddressPort;
+
class Connection {
public:
typedef boost::shared_ptr<Connection> ref;
@@ -23,8 +23,8 @@ namespace Swift {
WriteError
};
- Connection() {}
- virtual ~Connection() {}
+ Connection();
+ virtual ~Connection();
virtual void listen() = 0;
virtual void connect(const HostAddressPort& address) = 0;
diff --git a/Swiften/Network/DummyConnection.cpp b/Swiften/Network/DummyConnection.cpp
new file mode 100644
index 0000000..ffc6dc2
--- /dev/null
+++ b/Swiften/Network/DummyConnection.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/DummyConnection.h>
+
+#include <boost/bind.hpp>
+#include <cassert>
+
+namespace Swift {
+
+DummyConnection::DummyConnection(EventLoop* eventLoop) : eventLoop(eventLoop) {
+}
+
+void DummyConnection::receive(const ByteArray& data) {
+ eventLoop->postEvent(boost::bind(boost::ref(onDataRead), ByteArray(data)), shared_from_this());
+}
+
+void DummyConnection::listen() {
+ assert(false);
+}
+
+void DummyConnection::connect(const HostAddressPort&) {
+ assert(false);
+}
+
+
+}
diff --git a/Swiften/Network/DummyConnection.h b/Swiften/Network/DummyConnection.h
index 6b426b1..e8cc48b 100644
--- a/Swiften/Network/DummyConnection.h
+++ b/Swiften/Network/DummyConnection.h
@@ -6,26 +6,20 @@
#pragma once
-#include <cassert>
-#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/HostAddressPort.h"
#include "Swiften/EventLoop/EventLoop.h"
#include "Swiften/EventLoop/EventOwner.h"
namespace Swift {
class DummyConnection : public Connection, public EventOwner, public boost::enable_shared_from_this<DummyConnection> {
public:
- DummyConnection(EventLoop* eventLoop) : eventLoop(eventLoop) {}
+ DummyConnection(EventLoop* eventLoop);
- void listen() {
- assert(false);
- }
-
- void connect(const HostAddressPort&) {
- assert(false);
- }
+ void listen();
+ void connect(const HostAddressPort&);
void disconnect() {
//assert(false);
@@ -36,9 +30,7 @@ namespace Swift {
onDataSent(data);
}
- void receive(const ByteArray& data) {
- eventLoop->postEvent(boost::bind(boost::ref(onDataRead), ByteArray(data)), shared_from_this());
- }
+ void receive(const ByteArray& data);
HostAddressPort getLocalAddress() const {
return localAddress;
diff --git a/Swiften/Network/EnvironmentProxyProvider.cpp b/Swiften/Network/EnvironmentProxyProvider.cpp
new file mode 100644
index 0000000..b3bd0f6
--- /dev/null
+++ b/Swiften/Network/EnvironmentProxyProvider.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/EnvironmentProxyProvider.h"
+
+namespace Swift {
+
+EnvironmentProxyProvider::EnvironmentProxyProvider() {
+ socksProxy = getFromEnv("all_proxy", "socks");
+ httpProxy = getFromEnv("http_proxy", "http");
+ SWIFT_LOG(debug) << "Environment: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl;
+}
+
+HostAddressPort EnvironmentProxyProvider::getHTTPConnectProxy() const {
+ return httpProxy;
+}
+
+HostAddressPort EnvironmentProxyProvider::getSOCKS5Proxy() const {
+ return socksProxy;
+}
+
+HostAddressPort EnvironmentProxyProvider::getFromEnv(const char* envVarName, std::string proxyProtocol) {
+ char* envVar = NULL;
+ std::string address;
+ int port = 0;
+
+ envVar = getenv(envVarName);
+
+ proxyProtocol += "://";
+ address = envVar != NULL ? envVar : "0.0.0.0";
+ if(envVar != NULL && address.compare(0, proxyProtocol.length(), proxyProtocol) == 0) {
+ address = address.substr(proxyProtocol.length(), address.length());
+ port = atoi(address.substr(address.find(':') + 1, address.length()).c_str());
+ address = address.substr(0, address.find(':'));
+ }
+
+ return HostAddressPort(HostAddress(address), port);
+}
+
+}
diff --git a/Swiften/Network/EnvironmentProxyProvider.h b/Swiften/Network/EnvironmentProxyProvider.h
new file mode 100644
index 0000000..1743269
--- /dev/null
+++ b/Swiften/Network/EnvironmentProxyProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+ class EnvironmentProxyProvider : public ProxyProvider {
+ public:
+ EnvironmentProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+ HostAddressPort getFromEnv(const char* envVarName, std::string proxyProtocol);
+ HostAddressPort socksProxy;
+ HostAddressPort httpProxy;
+ };
+}
+
+
diff --git a/Swiften/Network/FakeConnection.cpp b/Swiften/Network/FakeConnection.cpp
new file mode 100644
index 0000000..be5555c
--- /dev/null
+++ b/Swiften/Network/FakeConnection.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/FakeConnection.h>
+
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+FakeConnection::FakeConnection(EventLoop* eventLoop) : eventLoop(eventLoop), state(Initial), delayConnect(false) {
+}
+
+FakeConnection::~FakeConnection() {
+}
+
+void FakeConnection::listen() {
+ assert(false);
+}
+
+void FakeConnection::setError(const Error& e) {
+ error = boost::optional<Error>(e);
+ state = DisconnectedWithError;
+ if (connectedTo) {
+ eventLoop->postEvent(
+ boost::bind(boost::ref(onDisconnected), error),
+ shared_from_this());
+ }
+}
+
+void FakeConnection::connect(const HostAddressPort& address) {
+ if (delayConnect) {
+ state = Connecting;
+ }
+ else {
+ if (!error) {
+ connectedTo = address;
+ state = Connected;
+ }
+ else {
+ state = DisconnectedWithError;
+ }
+ eventLoop->postEvent(
+ boost::bind(boost::ref(onConnectFinished), error),
+ shared_from_this());
+ }
+}
+
+void FakeConnection::disconnect() {
+ if (!error) {
+ state = Disconnected;
+ }
+ else {
+ state = DisconnectedWithError;
+ }
+ connectedTo.reset();
+ eventLoop->postEvent(
+ boost::bind(boost::ref(onDisconnected), error),
+ shared_from_this());
+}
+
+}
diff --git a/Swiften/Network/FakeConnection.h b/Swiften/Network/FakeConnection.h
index 4e2e960..693dabf 100644
--- a/Swiften/Network/FakeConnection.h
+++ b/Swiften/Network/FakeConnection.h
@@ -7,7 +7,6 @@
#pragma once
#include <boost/optional.hpp>
-#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <vector>
@@ -30,56 +29,17 @@ namespace Swift {
DisconnectedWithError
};
- FakeConnection(EventLoop* eventLoop) : eventLoop(eventLoop), state(Initial), delayConnect(false) {}
-
- virtual void listen() {
- assert(false);
- }
+ FakeConnection(EventLoop* eventLoop);
+ ~FakeConnection();
+ virtual void listen();
virtual HostAddressPort getLocalAddress() const {
return HostAddressPort();
}
- void setError(const Error& e) {
- error = boost::optional<Error>(e);
- state = DisconnectedWithError;
- if (connectedTo) {
- eventLoop->postEvent(
- boost::bind(boost::ref(onDisconnected), error),
- shared_from_this());
- }
- }
-
- virtual void connect(const HostAddressPort& address) {
- if (delayConnect) {
- state = Connecting;
- }
- else {
- if (!error) {
- connectedTo = address;
- state = Connected;
- }
- else {
- state = DisconnectedWithError;
- }
- eventLoop->postEvent(
- boost::bind(boost::ref(onConnectFinished), error),
- shared_from_this());
- }
- }
-
- virtual void disconnect() {
- if (!error) {
- state = Disconnected;
- }
- else {
- state = DisconnectedWithError;
- }
- connectedTo.reset();
- eventLoop->postEvent(
- boost::bind(boost::ref(onDisconnected), error),
- shared_from_this());
- }
+ void setError(const Error& e);
+ virtual void connect(const HostAddressPort& address);
+ virtual void disconnect();
virtual void write(const ByteArray& data) {
dataWritten.push_back(data);
diff --git a/Swiften/Network/GConfProxyProvider.cpp b/Swiften/Network/GConfProxyProvider.cpp
new file mode 100644
index 0000000..687bf77
--- /dev/null
+++ b/Swiften/Network/GConfProxyProvider.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <gconf/gconf-client.h>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/GConfProxyProvider.h"
+
+namespace Swift {
+
+GConfProxyProvider::GConfProxyProvider() {
+ socksProxy = getFromGConf("/system/proxy/socks_host", "/system/proxy/socks_port");
+ httpProxy = getFromGConf("/system/http_proxy/host", "/system/http_proxy/port");
+ SWIFT_LOG(debug) << "GConf: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl;
+}
+
+HostAddressPort GConfProxyProvider::getHTTPConnectProxy() const {
+ return httpProxy;
+}
+
+HostAddressPort GConfProxyProvider::getSOCKS5Proxy() const {
+ return socksProxy;
+}
+
+HostAddressPort GConfProxyProvider::getFromGConf(const char* gcHost, const char* gcPort) {
+ std::string address;
+ int port = 0;
+ gchar* str;
+
+ GConfClient* client = gconf_client_get_default();
+
+ str = gconf_client_get_string(client, gcHost, NULL);
+ port = static_cast<int> (gconf_client_get_int(client, gcPort, NULL));
+
+ if(str) {
+ address = static_cast<char*> (str);
+ g_free(str);
+ }
+
+ g_object_unref(client);
+ return HostAddressPort(HostAddress(address), port);
+}
+
+}
diff --git a/Swiften/Network/GConfProxyProvider.h b/Swiften/Network/GConfProxyProvider.h
new file mode 100644
index 0000000..15586ad
--- /dev/null
+++ b/Swiften/Network/GConfProxyProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+ class GConfProxyProvider : public ProxyProvider {
+ public:
+ GConfProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+ HostAddressPort getFromGConf(const char* gcHost, const char* gcPort);
+ HostAddressPort socksProxy;
+ HostAddressPort httpProxy;
+ };
+}
+
+
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.cpp b/Swiften/Network/HTTPConnectProxiedConnection.cpp
new file mode 100644
index 0000000..51130e5
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/Network/HostAddressPort.h"
+#include <Swiften/Network/ConnectionFactory.h>
+
+using namespace Swift;
+
+HTTPConnectProxiedConnection::HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy) : connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0)) {
+ connected_ = false;
+}
+
+HTTPConnectProxiedConnection::~HTTPConnectProxiedConnection() {
+ if (connection_) {
+ connection_->onDataRead.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ }
+
+ if (connected_) {
+ std::cerr << "Warning: Connection was still established." << std::endl;
+ }
+}
+
+void HTTPConnectProxiedConnection::connect(const HostAddressPort& server) {
+ server_ = server;
+ connection_ = connectionFactory_->createConnection();
+ connection_->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ connection_->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ connection_->connect(proxy_);
+}
+
+void HTTPConnectProxiedConnection::listen() {
+ assert(false);
+ connection_->listen();
+}
+
+void HTTPConnectProxiedConnection::disconnect() {
+ connected_ = false;
+ connection_->disconnect();
+}
+
+void HTTPConnectProxiedConnection::handleDisconnected(const boost::optional<Error>& error) {
+ onDisconnected(error);
+}
+
+void HTTPConnectProxiedConnection::write(const ByteArray& data) {
+ connection_->write(data);
+}
+
+void HTTPConnectProxiedConnection::handleConnectionConnectFinished(bool error) {
+ connection_->onConnectFinished.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ if (!error) {
+ std::stringstream connect;
+ connect << "CONNECT " << server_.getAddress().toString() << ":" << server_.getPort() << " HTTP/1.1\r\n\r\n";
+ connection_->write(ByteArray(connect.str()));
+ }
+ else {
+ onConnectFinished(true);
+ }
+}
+
+void HTTPConnectProxiedConnection::handleDataRead(const ByteArray& data) {
+ if (!connected_) {
+ SWIFT_LOG(debug) << data.toString() << std::endl;
+ std::vector<std::string> tmp = String::split(data.toString(), ' ');
+ if(tmp.size() > 1) {
+ int status = boost::lexical_cast<int> (tmp[1].c_str());
+ SWIFT_LOG(debug) << "Proxy Status: " << status << std::endl;
+ if (status / 100 == 2) { // all 2XX states are OK
+ connected_ = true;
+ onConnectFinished(false);
+ return;
+ }
+ SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << data.toString() << std::endl;
+ }
+ disconnect();
+ onConnectFinished(true);
+ }
+ else {
+ onDataRead(data);
+ }
+}
+
+HostAddressPort HTTPConnectProxiedConnection::getLocalAddress() const {
+ return connection_->getLocalAddress();
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h
new file mode 100644
index 0000000..930f5e1
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnection.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/enable_shared_from_this.hpp>
+
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace boost {
+ class thread;
+ namespace system {
+ class error_code;
+ }
+}
+
+namespace Swift {
+ class ConnectionFactory;
+
+ class HTTPConnectProxiedConnection : public Connection, public boost::enable_shared_from_this<HTTPConnectProxiedConnection> {
+ public:
+ typedef boost::shared_ptr<HTTPConnectProxiedConnection> ref;
+
+ ~HTTPConnectProxiedConnection();
+
+ static ref create(ConnectionFactory* connectionFactory, HostAddressPort proxy) {
+ return ref(new HTTPConnectProxiedConnection(connectionFactory, proxy));
+ }
+
+ virtual void listen();
+ virtual void connect(const HostAddressPort& address);
+ virtual void disconnect();
+ virtual void write(const ByteArray& data);
+
+ virtual HostAddressPort getLocalAddress() const;
+ private:
+ HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+ void handleConnectionConnectFinished(bool error);
+ void handleDataRead(const ByteArray& data);
+ void handleDisconnected(const boost::optional<Error>& error);
+
+ private:
+ bool connected_;
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ HostAddressPort server_;
+ boost::shared_ptr<Connection> connection_;
+ };
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
new file mode 100644
index 0000000..050b0c0
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/HTTPConnectProxiedConnectionFactory.h"
+
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+
+namespace Swift {
+
+HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy) {
+}
+
+boost::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() {
+ return HTTPConnectProxiedConnection::create(connectionFactory_, proxy_);
+}
+
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
new file mode 100644
index 0000000..2b0c8d5
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+ class HTTPConnectProxiedConnectionFactory : public ConnectionFactory {
+ public:
+ HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy);
+
+ virtual boost::shared_ptr<Connection> createConnection();
+
+ private:
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ };
+}
diff --git a/Swiften/Network/HostAddress.cpp b/Swiften/Network/HostAddress.cpp
index 7acd407..f734329 100644
--- a/Swiften/Network/HostAddress.cpp
+++ b/Swiften/Network/HostAddress.cpp
@@ -24,7 +24,7 @@ HostAddress::HostAddress(const std::string& address) {
try {
address_ = boost::asio::ip::address::from_string(address);
}
- catch (const std::exception& t) {
+ catch (const std::exception&) {
}
}
@@ -57,4 +57,8 @@ bool HostAddress::isValid() const {
return !(address_.is_v4() && address_.to_v4().to_ulong() == 0);
}
+boost::asio::ip::address HostAddress::getRawAddress() const {
+ return address_;
+}
+
}
diff --git a/Swiften/Network/HostAddress.h b/Swiften/Network/HostAddress.h
index 34ccd24..0b3bdda 100644
--- a/Swiften/Network/HostAddress.h
+++ b/Swiften/Network/HostAddress.h
@@ -3,16 +3,12 @@
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-
#pragma once
#include <string>
-#include <vector>
-#include <boost/asio.hpp>
+#include <boost/asio/ip/address.hpp>
namespace Swift {
-
-
class HostAddress {
public:
HostAddress();
@@ -21,6 +17,7 @@ namespace Swift {
HostAddress(const boost::asio::ip::address& address);
std::string toString() const;
+ boost::asio::ip::address getRawAddress() const;
bool operator==(const HostAddress& o) const {
return address_ == o.address_;
diff --git a/Swiften/Network/HostAddressPort.cpp b/Swiften/Network/HostAddressPort.cpp
new file mode 100644
index 0000000..e2e6012
--- /dev/null
+++ b/Swiften/Network/HostAddressPort.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Network/HostAddressPort.h>
+
+#include <boost/lexical_cast.hpp>
+
+using namespace Swift;
+
+HostAddressPort::HostAddressPort(const HostAddress& address, int port) : address_(address), port_(port) {
+}
+
+HostAddressPort::HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint) {
+ address_ = HostAddress(endpoint.address());
+ port_ = endpoint.port();
+}
+
+std::string HostAddressPort::toString() const {
+ return getAddress().toString() + ":" + boost::lexical_cast<std::string>(getPort());
+}
diff --git a/Swiften/Network/HostAddressPort.h b/Swiften/Network/HostAddressPort.h
index 6883380..23a81b8 100644
--- a/Swiften/Network/HostAddressPort.h
+++ b/Swiften/Network/HostAddressPort.h
@@ -6,21 +6,15 @@
#pragma once
-#include <boost/asio.hpp>
+#include <boost/asio/ip/tcp.hpp>
#include "Swiften/Network/HostAddress.h"
namespace Swift {
class HostAddressPort {
public:
- HostAddressPort(const HostAddress& address = HostAddress(), int port = -1) : address_(address), port_(port) {
- }
-
- HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint) {
- address_ = HostAddress(endpoint.address());
- port_ = endpoint.port();
- }
-
+ HostAddressPort(const HostAddress& address = HostAddress(), int port = -1);
+ HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint);
const HostAddress& getAddress() const {
return address_;
@@ -37,6 +31,8 @@ namespace Swift {
bool isValid() const {
return address_.isValid() && port_ > 0;
}
+
+ std::string toString() const;
private:
HostAddress address_;
diff --git a/Swiften/Network/MacOSXProxyProvider.cpp b/Swiften/Network/MacOSXProxyProvider.cpp
new file mode 100644
index 0000000..dd44eff
--- /dev/null
+++ b/Swiften/Network/MacOSXProxyProvider.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Base/Platform.h>
+#include <Swiften/Network/MacOSXProxyProvider.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <utility>
+
+#ifndef SWIFTEN_PLATFORM_IPHONE
+#include <SystemConfiguration/SystemConfiguration.h>
+#endif
+
+using namespace Swift;
+
+#ifndef SWIFTEN_PLATFORM_IPHONE
+static HostAddressPort getFromDictionary(CFDictionaryRef dict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey) {
+ CFNumberRef numberValue = NULL;
+ HostAddressPort ret = HostAddressPort(HostAddress(), 0);
+
+ if(CFDictionaryGetValueIfPresent(dict, reinterpret_cast<const void*> (enabledKey), reinterpret_cast<const void**> (&numberValue)) == true) {
+ const int i = 0;
+ CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i);
+ CFComparisonResult result = CFNumberCompare(numberValue, zero, NULL);
+ CFRelease(numberValue);
+
+ if(result != kCFCompareEqualTo) {
+ int port = 0;
+ std::string host = "";
+
+ try {
+ CFNumberRef numberValue = reinterpret_cast<CFNumberRef> (CFDictionaryGetValue(dict, portKey));
+ if(numberValue != NULL) {
+ CFNumberGetValue(numberValue, kCFNumberIntType, &port);
+ CFRelease(numberValue);
+ }
+
+ CFStringRef stringValue = reinterpret_cast<CFStringRef> (CFDictionaryGetValue(dict, hostKey));
+ if(stringValue != NULL) {
+ std::vector<char> buffer;
+ // length must be +1 for the ending zero; and the Docu of CFStringGetCString tells it like
+ // if the string is toby the length must be at least 5.
+ CFIndex length = CFStringGetLength(stringValue) + 1;
+ buffer.resize(length);
+ if(CFStringGetCString(stringValue, &buffer[0], length, kCFStringEncodingMacRoman)) {
+ for(std::vector<char>::iterator iter = buffer.begin(); iter != buffer.end(); iter++) {
+ host += *iter;
+ }
+ }
+ CFRelease(stringValue);
+ }
+ }
+ catch(...) {
+ std::cerr << "Exception caught ... " << std::endl;
+ }
+
+ if(host != "" && port != 0) {
+ ret = HostAddressPort(HostAddress(host), port);
+ }
+ }
+ }
+ return ret;
+}
+#endif
+namespace Swift {
+
+MacOSXProxyProvider::MacOSXProxyProvider() {
+}
+
+HostAddressPort MacOSXProxyProvider::getHTTPConnectProxy() const {
+ HostAddressPort result;
+#ifndef SWIFTEN_PLATFORM_IPHONE
+ CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL);
+ if(proxies != NULL) {
+ result = getFromDictionary(proxies, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort);
+ }
+#endif
+ return result;
+}
+
+HostAddressPort MacOSXProxyProvider::getSOCKS5Proxy() const {
+ HostAddressPort result;
+#ifndef SWIFTEN_PLATFORM_IPHONE
+ CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL);
+ if(proxies != NULL) {
+ result = getFromDictionary(proxies, kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort);
+ }
+#endif
+ return result;
+}
+
+}
diff --git a/Swiften/Network/MacOSXProxyProvider.h b/Swiften/Network/MacOSXProxyProvider.h
new file mode 100644
index 0000000..5e7ff8a
--- /dev/null
+++ b/Swiften/Network/MacOSXProxyProvider.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include "Swiften/Network/ProxyProvider.h"
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace Swift {
+ class MacOSXProxyProvider : public ProxyProvider {
+ public:
+ MacOSXProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ };
+}
diff --git a/Swiften/Network/NullProxyProvider.cpp b/Swiften/Network/NullProxyProvider.cpp
new file mode 100644
index 0000000..3b9d94d
--- /dev/null
+++ b/Swiften/Network/NullProxyProvider.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/NullProxyProvider.h>
+
+using namespace Swift;
+
+NullProxyProvider::NullProxyProvider() {
+}
+
+HostAddressPort NullProxyProvider::getHTTPConnectProxy() const {
+ return HostAddressPort();
+}
+
+HostAddressPort NullProxyProvider::getSOCKS5Proxy() const {
+ return HostAddressPort();
+}
diff --git a/Swiften/Network/NullProxyProvider.h b/Swiften/Network/NullProxyProvider.h
new file mode 100644
index 0000000..544bea2
--- /dev/null
+++ b/Swiften/Network/NullProxyProvider.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Network/ProxyProvider.h>
+
+namespace Swift {
+ class NullProxyProvider : public ProxyProvider {
+ public:
+ NullProxyProvider();
+
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ };
+}
diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.cpp b/Swiften/Network/PlatformDomainNameAddressQuery.cpp
index 1832255..ec7e663 100644
--- a/Swiften/Network/PlatformDomainNameAddressQuery.cpp
+++ b/Swiften/Network/PlatformDomainNameAddressQuery.cpp
@@ -6,6 +6,8 @@
#include <Swiften/Network/PlatformDomainNameAddressQuery.h>
+#include <boost/asio/ip/tcp.hpp>
+
#include <Swiften/Network/PlatformDomainNameResolver.h>
#include <Swiften/EventLoop/EventLoop.h>
diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.h b/Swiften/Network/PlatformDomainNameAddressQuery.h
index c2854ac..e1dc05f 100644
--- a/Swiften/Network/PlatformDomainNameAddressQuery.h
+++ b/Swiften/Network/PlatformDomainNameAddressQuery.h
@@ -6,7 +6,7 @@
#pragma once
-#include <boost/asio.hpp>
+#include <boost/asio/io_service.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <Swiften/Network/DomainNameAddressQuery.h>
diff --git a/Swiften/Network/PlatformDomainNameResolver.h b/Swiften/Network/PlatformDomainNameResolver.h
index e681331..295ecc5 100644
--- a/Swiften/Network/PlatformDomainNameResolver.h
+++ b/Swiften/Network/PlatformDomainNameResolver.h
@@ -7,7 +7,7 @@
#pragma once
#include <deque>
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
diff --git a/Swiften/Network/PlatformProxyProvider.h b/Swiften/Network/PlatformProxyProvider.h
new file mode 100644
index 0000000..13b15d2
--- /dev/null
+++ b/Swiften/Network/PlatformProxyProvider.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Base/Platform.h"
+
+#if defined(SWIFTEN_PLATFORM_MACOSX)
+#include "Swiften/Network/MacOSXProxyProvider.h"
+namespace Swift {
+ typedef MacOSXProxyProvider PlatformProxyProvider;
+}
+#elif defined(SWIFTEN_PLATFORM_WIN32)
+#include "Swiften/Network/WindowsProxyProvider.h"
+namespace Swift {
+ typedef WindowsProxyProvider PlatformProxyProvider;
+}
+#else
+#include "Swiften/Network/UnixProxyProvider.h"
+namespace Swift {
+ typedef UnixProxyProvider PlatformProxyProvider;
+}
+#endif
diff --git a/Swiften/Network/ProxyProvider.cpp b/Swiften/Network/ProxyProvider.cpp
new file mode 100644
index 0000000..fe235b1
--- /dev/null
+++ b/Swiften/Network/ProxyProvider.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "ProxyProvider.h"
+
+namespace Swift {
+
+ProxyProvider::ProxyProvider()
+{
+}
+
+ProxyProvider::~ProxyProvider()
+{
+}
+
+}
diff --git a/Swiften/Network/ProxyProvider.h b/Swiften/Network/ProxyProvider.h
new file mode 100644
index 0000000..05bb5a7
--- /dev/null
+++ b/Swiften/Network/ProxyProvider.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include <map>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/HostAddressPort.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+ class ProxyProvider {
+ public:
+ ProxyProvider();
+ virtual ~ProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const = 0;
+ virtual HostAddressPort getSOCKS5Proxy() const = 0;
+ };
+}
+
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index fa186fa..183d09c 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -6,13 +6,21 @@ if myenv.get("HAVE_CARES", False) :
myenv.MergeFlags(myenv.get("CARES_FLAGS", {}))
sourceList = [
+ "HTTPConnectProxiedConnection.cpp",
+ "HTTPConnectProxiedConnectionFactory.cpp",
+ "SOCKS5ProxiedConnection.cpp",
+ "SOCKS5ProxiedConnectionFactory.cpp",
"BoostConnection.cpp",
"BoostConnectionFactory.cpp",
"BoostConnectionServer.cpp",
"BoostIOServiceThread.cpp",
"ConnectionFactory.cpp",
"ConnectionServer.cpp",
+ "DummyConnection.cpp",
+ "FakeConnection.cpp",
+ "ChainedConnector.cpp",
"Connector.cpp",
+ "Connection.cpp",
"TimerFactory.cpp",
"DummyTimerFactory.cpp",
"BoostTimerFactory.cpp",
@@ -24,13 +32,30 @@ sourceList = [
"PlatformDomainNameAddressQuery.cpp",
"StaticDomainNameResolver.cpp",
"HostAddress.cpp",
+ "HostAddressPort.cpp",
"NetworkFactories.cpp",
"BoostNetworkFactories.cpp",
"Timer.cpp",
- "BoostTimer.cpp"]
+ "BoostTimer.cpp",
+ "ProxyProvider.cpp",
+ "NullProxyProvider.cpp"
+ ]
+
if myenv.get("HAVE_CARES", False) :
sourceList.append("CAresDomainNameResolver.cpp")
+if myenv["PLATFORM"] == "darwin" :
+ myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"])
+ sourceList += [ "MacOSXProxyProvider.cpp" ]
+elif myenv["PLATFORM"] == "win32" :
+ sourceList += [ "WindowsProxyProvider.cpp" ]
+else :
+ sourceList += [ "UnixProxyProvider.cpp" ]
+ sourceList += [ "EnvironmentProxyProvider.cpp" ]
+ if myenv.get("HAVE_GCONF", 0) :
+ myenv.Append(CPPDEFINES = "HAVE_GCONF")
+ myenv.MergeFlags(myenv["GCONF_FLAGS"])
+ sourceList += [ "GConfProxyProvider.cpp" ]
objects = myenv.SwiftenObject(sourceList)
swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.cpp b/Swiften/Network/SOCKS5ProxiedConnection.cpp
new file mode 100644
index 0000000..0232ede
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnection.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+
+#include <Swiften/Network/ConnectionFactory.h>
+#include "Swiften/Base/Log.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+using namespace Swift;
+
+SOCKS5ProxiedConnection::SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0)) {
+ connected_ = false;
+}
+
+SOCKS5ProxiedConnection::~SOCKS5ProxiedConnection() {
+ if (connection_) {
+ connection_->onDataRead.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ }
+
+ if (connected_) {
+ std::cerr << "Warning: Connection was still established." << std::endl;
+ }
+}
+
+void SOCKS5ProxiedConnection::connect(const HostAddressPort& server) {
+ server_ = server;
+ connection_ = connectionFactory_->createConnection();
+ connection_->onConnectFinished.connect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ connection_->onDataRead.connect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1));
+ connection_->onDisconnected.connect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+ SWIFT_LOG(debug) << "Trying to connect via proxy " << proxy_.getAddress().toString() << ":" << proxy_.getPort() << std::endl;
+ SWIFT_LOG(debug) << "to server " << server.getAddress().toString() << ":" << server.getPort() << std::endl;
+ connection_->connect(proxy_);
+}
+
+void SOCKS5ProxiedConnection::listen() {
+ assert(false);
+ connection_->listen();
+}
+
+void SOCKS5ProxiedConnection::disconnect() {
+ connected_ = false;
+ if (connection_) {
+ connection_->disconnect();
+ }
+}
+
+void SOCKS5ProxiedConnection::handleDisconnected(const boost::optional<Error>& error) {
+ onDisconnected(error);
+}
+
+void SOCKS5ProxiedConnection::write(const ByteArray& data) {
+ if (connection_) {
+ connection_->write(data);
+ }
+}
+
+void SOCKS5ProxiedConnection::handleConnectionConnectFinished(bool error) {
+ connection_->onConnectFinished.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+ if (!error) {
+ SWIFT_LOG(debug) << "Connection to proxy established, now connect to the server via it." << std::endl;
+
+ proxyState_ = ProxyAuthenticating;
+ ByteArray socksConnect;
+ socksConnect += 0x05; // VER = SOCKS5 = 0x05
+ socksConnect += 0x01; // Number of authentication methods after this byte.
+ socksConnect += 0x00; // 0x00 == no authentication
+ // buffer.push_back(0x01); // 0x01 == GSSAPI
+ // buffer.push_back(0x02); // 0x02 == Username/Password
+ // rest see RFC 1928 (http://tools.ietf.org/html/rfc1928)
+ connection_->write(socksConnect);
+ }
+ else {
+ onConnectFinished(true);
+ }
+}
+
+void SOCKS5ProxiedConnection::handleDataRead(const ByteArray& data) {
+ ByteArray socksConnect;
+ boost::asio::ip::address rawAddress = server_.getAddress().getRawAddress();
+ assert(rawAddress.is_v4() || rawAddress.is_v6());
+ if (!connected_) {
+ if (proxyState_ == ProxyAuthenticating) {
+ SWIFT_LOG(debug) << "ProxyAuthenticating response received, reply with the connect BYTEs" << std::endl;
+ unsigned char choosenMethod = static_cast<unsigned char> (data[1]);
+ if (data[0] == 0x05 && choosenMethod != 0xFF) {
+ switch(choosenMethod) { // use the correct Method
+ case 0x00:
+ try {
+ proxyState_ = ProxyConnecting;
+ socksConnect += 0x05; // VER = SOCKS5 = 0x05
+ socksConnect += 0x01; // Construct a TCP connection. (CMD)
+ socksConnect += 0x00; // reserved.
+ socksConnect += rawAddress.is_v4() ? 0x01 : 0x04; // IPv4 == 0x01, Hostname == 0x02, IPv6 == 0x04. (ATYP)
+ size_t size = rawAddress.is_v4() ? rawAddress.to_v4().to_bytes().size() : rawAddress.to_v6().to_bytes().size();
+ for (size_t s = 0; s < size; s++) {
+ unsigned char uc;
+ if(rawAddress.is_v4()) {
+ uc = rawAddress.to_v4().to_bytes()[s]; // the address.
+ }
+ else {
+ uc = rawAddress.to_v6().to_bytes()[s]; // the address.
+ }
+ socksConnect += static_cast<char> (uc);
+
+ }
+ socksConnect += static_cast<unsigned char> ((server_.getPort() >> 8) & 0xFF); // highbyte of the port.
+ socksConnect += static_cast<unsigned char> (server_.getPort() & 0xFF); // lowbyte of the port.
+ connection_->write(socksConnect);
+ return;
+ }
+ catch(...) {
+ std::cerr << "exception caught" << std::endl;
+ }
+ connection_->write(socksConnect);
+ break;
+ default:
+ onConnectFinished(true);
+ break;
+ }
+ return;
+ }
+ }
+ else if (proxyState_ == ProxyConnecting) {
+ SWIFT_LOG(debug) << "Connect response received, check if successfully." << std::endl;
+ SWIFT_LOG(debug) << "Errorbyte: 0x" << std::hex << static_cast<int> (data[1]) << std::dec << std::endl;
+ /*
+
+ data.at(1) can be one of the following:
+ 0x00 succeeded
+ 0x01 general SOCKS server failure
+ 0x02 connection not allowed by ruleset
+ 0x03 Network unreachable
+ 0x04 Host unreachable
+ 0x05 Connection refused
+ 0x06 TTL expired
+ 0x07 Command not supported (CMD)
+ 0x08 Address type not supported (ATYP)
+ 0x09 bis 0xFF unassigned
+ */
+ if (data[0] == 0x05 && data[1] == 0x0) {
+ SWIFT_LOG(debug) << "Successfully connected the server via the proxy." << std::endl;
+ connected_ = true;
+ onConnectFinished(false);
+ return;
+ }
+ else {
+ std::cerr << "SOCKS Proxy returned an error: " << std::hex << data[1] << std::endl;
+ }
+ return;
+ }
+ }
+ else {
+ onDataRead(data);
+ return;
+ }
+ disconnect();
+ onConnectFinished(true);
+}
+
+HostAddressPort SOCKS5ProxiedConnection::getLocalAddress() const {
+ return connection_->getLocalAddress();
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.h b/Swiften/Network/SOCKS5ProxiedConnection.h
new file mode 100644
index 0000000..779bfa1
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnection.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/enable_shared_from_this.hpp>
+
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace boost {
+ class thread;
+ namespace system {
+ class error_code;
+ }
+}
+
+namespace Swift {
+ class ConnectionFactory;
+
+ class SOCKS5ProxiedConnection : public Connection, public boost::enable_shared_from_this<SOCKS5ProxiedConnection> {
+ public:
+ typedef boost::shared_ptr<SOCKS5ProxiedConnection> ref;
+
+ ~SOCKS5ProxiedConnection();
+
+ static ref create(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) {
+ return ref(new SOCKS5ProxiedConnection(connectionFactory, proxy));
+ }
+
+ virtual void listen();
+ virtual void connect(const HostAddressPort& address);
+ virtual void disconnect();
+ virtual void write(const ByteArray& data);
+
+ virtual HostAddressPort getLocalAddress() const;
+
+ private:
+ SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, const HostAddressPort& proxy);
+
+ void handleConnectionConnectFinished(bool error);
+ void handleDataRead(const ByteArray& data);
+ void handleDisconnected(const boost::optional<Error>& error);
+
+ private:
+ enum {
+ ProxyAuthenticating = 0,
+ ProxyConnecting,
+ } proxyState_;
+ bool connected_;
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ HostAddressPort server_;
+ boost::shared_ptr<Connection> connection_;
+ };
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
new file mode 100644
index 0000000..ab75644
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/SOCKS5ProxiedConnectionFactory.h"
+
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+
+namespace Swift {
+
+SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy) : connectionFactory_(connectionFactory), proxy_(proxy) {
+}
+
+boost::shared_ptr<Connection> SOCKS5ProxiedConnectionFactory::createConnection() {
+ return SOCKS5ProxiedConnection::create(connectionFactory_, proxy_);
+}
+
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
new file mode 100644
index 0000000..8f310c5
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+ class SOCKS5ProxiedConnectionFactory : public ConnectionFactory {
+ public:
+ SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, const HostAddressPort& proxy);
+
+ virtual boost::shared_ptr<Connection> createConnection();
+
+ private:
+ ConnectionFactory* connectionFactory_;
+ HostAddressPort proxy_;
+ };
+}
diff --git a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
new file mode 100644
index 0000000..9c4c99d
--- /dev/null
+++ b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Network/ChainedConnector.h>
+#include <Swiften/Network/Connection.h>
+#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Network/StaticDomainNameResolver.h>
+#include <Swiften/Network/DummyTimerFactory.h>
+#include <Swiften/EventLoop/DummyEventLoop.h>
+
+using namespace Swift;
+
+class ChainedConnectorTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(ChainedConnectorTest);
+ CPPUNIT_TEST(testConnect_FirstConnectorSucceeds);
+ CPPUNIT_TEST(testConnect_SecondConnectorSucceeds);
+ CPPUNIT_TEST(testConnect_NoConnectorSucceeds);
+ CPPUNIT_TEST(testStop);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ host = HostAddressPort(HostAddress("1.1.1.1"), 1234);
+ eventLoop = new DummyEventLoop();
+ resolver = new StaticDomainNameResolver(eventLoop);
+ resolver->addXMPPClientService("foo.com", host);
+ connectionFactory1 = new MockConnectionFactory(eventLoop, 1);
+ connectionFactory2 = new MockConnectionFactory(eventLoop, 2);
+ timerFactory = new DummyTimerFactory();
+ }
+
+ void tearDown() {
+ delete timerFactory;
+ delete connectionFactory2;
+ delete connectionFactory1;
+ delete resolver;
+ delete eventLoop;
+ }
+
+ void testConnect_FirstConnectorSucceeds() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = true;
+ connectionFactory2->connects = false;
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT_EQUAL(1, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id);
+ }
+
+ void testConnect_SecondConnectorSucceeds() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = false;
+ connectionFactory2->connects = true;
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(connections[0]);
+ CPPUNIT_ASSERT_EQUAL(2, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id);
+ }
+
+ void testConnect_NoConnectorSucceeds() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = false;
+ connectionFactory2->connects = false;
+
+ testling->start();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ }
+
+ void testStop() {
+ boost::shared_ptr<ChainedConnector> testling(createConnector());
+ connectionFactory1->connects = true;
+ connectionFactory2->connects = false;
+
+ testling->start();
+ testling->stop();
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+ CPPUNIT_ASSERT(!connections[0]);
+ }
+
+ private:
+ boost::shared_ptr<ChainedConnector> createConnector() {
+ std::vector<ConnectionFactory*> factories;
+ factories.push_back(connectionFactory1);
+ factories.push_back(connectionFactory2);
+ boost::shared_ptr<ChainedConnector> connector = boost::make_shared<ChainedConnector>("foo.com", resolver, factories, timerFactory);
+ connector->onConnectFinished.connect(boost::bind(&ChainedConnectorTest::handleConnectorFinished, this, _1));
+ return connector;
+ }
+
+ void handleConnectorFinished(boost::shared_ptr<Connection> connection) {
+ boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection));
+ if (connection) {
+ assert(c);
+ }
+ connections.push_back(c);
+ }
+
+ struct MockConnection : public Connection {
+ public:
+ MockConnection(bool connects, int id, EventLoop* eventLoop) : connects(connects), id(id), eventLoop(eventLoop) {
+ }
+
+ void listen() { assert(false); }
+ void connect(const HostAddressPort&) {
+ eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), !connects));
+ }
+
+ HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+ void disconnect() { assert(false); }
+ void write(const ByteArray&) { assert(false); }
+
+ bool connects;
+ int id;
+ EventLoop* eventLoop;
+ };
+
+ struct MockConnectionFactory : public ConnectionFactory {
+ MockConnectionFactory(EventLoop* eventLoop, int id) : eventLoop(eventLoop), connects(true), id(id) {
+ }
+
+ boost::shared_ptr<Connection> createConnection() {
+ return boost::make_shared<MockConnection>(connects, id, eventLoop);
+ }
+
+ EventLoop* eventLoop;
+ bool connects;
+ int id;
+ };
+
+ private:
+ HostAddressPort host;
+ DummyEventLoop* eventLoop;
+ StaticDomainNameResolver* resolver;
+ MockConnectionFactory* connectionFactory1;
+ MockConnectionFactory* connectionFactory2;
+ DummyTimerFactory* timerFactory;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ChainedConnectorTest);
diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
new file mode 100644
index 0000000..6c4c89c
--- /dev/null
+++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <boost/optional.hpp>
+#include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Network/Connection.h>
+#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/HTTPConnectProxiedConnection.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/EventLoop/DummyEventLoop.h>
+
+using namespace Swift;
+
+class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest);
+ CPPUNIT_TEST(testConnect_CreatesConnectionToProxy);
+ CPPUNIT_TEST(testConnect_SendsConnectRequest);
+ CPPUNIT_TEST(testConnect_ReceiveConnectResponse);
+ CPPUNIT_TEST(testConnect_ReceiveMalformedConnectResponse);
+ CPPUNIT_TEST(testConnect_ReceiveErrorConnectResponse);
+ CPPUNIT_TEST(testConnect_ReceiveDataAfterConnect);
+ CPPUNIT_TEST(testWrite_AfterConnect);
+ CPPUNIT_TEST(testDisconnect_AfterConnectRequest);
+ CPPUNIT_TEST(testDisconnect_AfterConnect);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void setUp() {
+ proxyHost = HostAddressPort(HostAddress("1.1.1.1"), 1234);
+ host = HostAddressPort(HostAddress("2.2.2.2"), 2345);
+ eventLoop = new DummyEventLoop();
+ connectionFactory = new MockConnectionFactory(eventLoop);
+ connectFinished = false;
+ disconnected = false;
+ }
+
+ void tearDown() {
+ delete connectionFactory;
+ delete eventLoop;
+ }
+
+ void testConnect_CreatesConnectionToProxy() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+
+ testling->connect(host);
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size()));
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort);
+ CPPUNIT_ASSERT(proxyHost == *connectionFactory->connections[0]->hostAddressPort);
+ CPPUNIT_ASSERT(!connectFinished);
+ }
+
+ void testConnect_SendsConnectRequest() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n\r\n"), connectionFactory->connections[0]->dataWritten);
+ }
+
+ void testConnect_ReceiveConnectResponse() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+
+ connectionFactory->connections[0]->onDataRead(ByteArray("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT(connectFinished);
+ CPPUNIT_ASSERT(!connectFinishedWithError);
+ CPPUNIT_ASSERT(dataRead.isEmpty());
+ }
+
+ void testConnect_ReceiveMalformedConnectResponse() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+
+ connectionFactory->connections[0]->onDataRead(ByteArray("FLOOP"));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT(connectFinished);
+ CPPUNIT_ASSERT(connectFinishedWithError);
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ }
+
+ void testConnect_ReceiveErrorConnectResponse() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+
+ connectionFactory->connections[0]->onDataRead(ByteArray("HTTP/1.0 401 Unauthorized\r\n\r\n"));
+ eventLoop->processEvents();
+
+ CPPUNIT_ASSERT(connectFinished);
+ CPPUNIT_ASSERT(connectFinishedWithError);
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ }
+
+ void testConnect_ReceiveDataAfterConnect() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+ connectionFactory->connections[0]->onDataRead(ByteArray("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+
+ connectionFactory->connections[0]->onDataRead(ByteArray("abcdef"));
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray("abcdef"), dataRead);
+ }
+
+ void testWrite_AfterConnect() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+ connectionFactory->connections[0]->onDataRead(ByteArray("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+ connectionFactory->connections[0]->dataWritten.clear();
+
+ testling->write(ByteArray("abcdef"));
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray("abcdef"), connectionFactory->connections[0]->dataWritten);
+ }
+
+ void testDisconnect_AfterConnectRequest() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+
+ testling->disconnect();
+
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ CPPUNIT_ASSERT(disconnected);
+ CPPUNIT_ASSERT(!disconnectedError);
+ }
+
+ void testDisconnect_AfterConnect() {
+ HTTPConnectProxiedConnection::ref testling(createTestling());
+ testling->connect(HostAddressPort(HostAddress("2.2.2.2"), 2345));
+ eventLoop->processEvents();
+ connectionFactory->connections[0]->onDataRead(ByteArray("HTTP/1.0 200 Connection established\r\n\r\n"));
+ eventLoop->processEvents();
+
+ testling->disconnect();
+
+ CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected);
+ CPPUNIT_ASSERT(disconnected);
+ CPPUNIT_ASSERT(!disconnectedError);
+ }
+
+ private:
+ HTTPConnectProxiedConnection::ref createTestling() {
+ boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(connectionFactory, proxyHost);
+ c->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleConnectFinished, this, _1));
+ c->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDisconnected, this, _1));
+ c->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDataRead, this, _1));
+ return c;
+ }
+
+ void handleConnectFinished(bool error) {
+ connectFinished = true;
+ connectFinishedWithError = error;
+ }
+
+ void handleDisconnected(const boost::optional<Connection::Error>& e) {
+ disconnected = true;
+ disconnectedError = e;
+ }
+
+ void handleDataRead(const ByteArray& d) {
+ dataRead += d;
+ }
+
+ struct MockConnection : public Connection {
+ public:
+ MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) {
+ }
+
+ void listen() { assert(false); }
+
+ void connect(const HostAddressPort& address) {
+ hostAddressPort = address;
+ bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end();
+ eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail));
+ }
+
+ HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+
+ void disconnect() {
+ disconnected = true;
+ onDisconnected(boost::optional<Connection::Error>());
+ }
+
+ void write(const ByteArray& d) {
+ dataWritten += d;
+ }
+
+ EventLoop* eventLoop;
+ boost::optional<HostAddressPort> hostAddressPort;
+ std::vector<HostAddressPort> failingPorts;
+ ByteArray dataWritten;
+ bool disconnected;
+ };
+
+ struct MockConnectionFactory : public ConnectionFactory {
+ MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {
+ }
+
+ boost::shared_ptr<Connection> createConnection() {
+ boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop);
+ connections.push_back(connection);
+ return connection;
+ }
+
+ EventLoop* eventLoop;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+ std::vector<HostAddressPort> failingPorts;
+ };
+
+ private:
+ HostAddressPort proxyHost;
+ HostAddressPort host;
+ DummyEventLoop* eventLoop;
+ MockConnectionFactory* connectionFactory;
+ std::vector< boost::shared_ptr<MockConnection> > connections;
+ bool connectFinished;
+ bool connectFinishedWithError;
+ bool disconnected;
+ boost::optional<Connection::Error> disconnectedError;
+ ByteArray dataRead;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HTTPConnectProxiedConnectionTest);
diff --git a/Swiften/Network/UnixProxyProvider.cpp b/Swiften/Network/UnixProxyProvider.cpp
new file mode 100644
index 0000000..e21b310
--- /dev/null
+++ b/Swiften/Network/UnixProxyProvider.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Network/UnixProxyProvider.h"
+
+namespace Swift {
+
+UnixProxyProvider::UnixProxyProvider() :
+#if defined(HAVE_GCONF)
+ gconfProxyProvider(),
+#endif
+ environmentProxyProvider()
+{
+}
+
+HostAddressPort UnixProxyProvider::getSOCKS5Proxy() const {
+ HostAddressPort proxy;
+#if defined(HAVE_GCONF)
+ proxy = gconfProxyProvider.getSOCKS5Proxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+#endif
+ proxy = environmentProxyProvider.getSOCKS5Proxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+ return HostAddressPort(HostAddress(), 0);
+}
+
+HostAddressPort UnixProxyProvider::getHTTPConnectProxy() const {
+ HostAddressPort proxy;
+#if defined(HAVE_GCONF)
+ proxy = gconfProxyProvider.getHTTPConnectProxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+#endif
+ proxy = environmentProxyProvider.getHTTPConnectProxy();
+ if(proxy.isValid()) {
+ return proxy;
+ }
+ return HostAddressPort(HostAddress(), 0);
+}
+
+
+}
diff --git a/Swiften/Network/UnixProxyProvider.h b/Swiften/Network/UnixProxyProvider.h
new file mode 100644
index 0000000..509cf4b
--- /dev/null
+++ b/Swiften/Network/UnixProxyProvider.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#if defined(HAVE_GCONF)
+# include "Swiften/Network/GConfProxyProvider.h"
+#endif
+#include "Swiften/Network/EnvironmentProxyProvider.h"
+
+namespace Swift {
+ class UnixProxyProvider : public ProxyProvider {
+ public:
+ UnixProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+#if defined(HAVE_GCONF)
+ GConfProxyProvider gconfProxyProvider;
+#endif
+ EnvironmentProxyProvider environmentProxyProvider;
+ };
+}
diff --git a/Swiften/Network/WindowsProxyProvider.cpp b/Swiften/Network/WindowsProxyProvider.cpp
new file mode 100644
index 0000000..5f6f5d2
--- /dev/null
+++ b/Swiften/Network/WindowsProxyProvider.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include <boost/lexical_cast.hpp>
+
+#include "Swiften/Base/log.h"
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Network/WindowsProxyProvider.h"
+#include "Swiften/Base/ByteArray.h"
+
+#include <windows.h>
+
+namespace Swift {
+
+WindowsProxyProvider::WindowsProxyProvider()
+: ProxyProvider()
+{
+ HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
+ long result;
+
+ result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_READ, &hKey);
+ if (result == ERROR_SUCCESS && hKey != INVALID_HANDLE_VALUE && proxyEnabled(hKey)) {
+ DWORD dataType = REG_SZ;
+ DWORD dataSize = 0;
+ ByteArray dataBuffer;
+
+ result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, NULL, &dataSize);
+ if(result != ERROR_SUCCESS) {
+ return;
+ }
+ dataBuffer.resize(dataSize);
+ result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, reinterpret_cast<BYTE*>(dataBuffer.getData()), &dataSize);
+ if(result == ERROR_SUCCESS) {
+ std::vector<std::string> proxies = String::split(dataBuffer.toString(), ';');
+ std::pair<std::string, std::string> protocolAndProxy;
+ foreach(std::string proxy, proxies) {
+ if(proxy.find('=') != std::string::npos) {
+ protocolAndProxy = String::getSplittedAtFirst(proxy, '=');
+ SWIFT_LOG(debug) << "Found proxy: " << protocolAndProxy.first << " => " << protocolAndProxy.second << std::endl;
+ if(protocolAndProxy.first.compare("socks") == 0) {
+ socksProxy = getAsHostAddressPort(protocolAndProxy.second);
+ }
+ else if (protocolAndProxy.first.compare("http") == 0) {
+ httpProxy = getAsHostAddressPort(protocolAndProxy.second);
+ }
+ }
+ }
+ }
+ }
+}
+
+HostAddressPort WindowsProxyProvider::getHTTPConnectProxy() const {
+ return httpProxy;
+}
+
+HostAddressPort WindowsProxyProvider::getSOCKS5Proxy() const {
+ return socksProxy;
+}
+
+HostAddressPort WindowsProxyProvider::getAsHostAddressPort(std::string proxy) {
+ HostAddressPort ret(HostAddress(), 0);
+
+ try {
+ std::pair<std::string, std::string> tmp;
+ int port = 0;
+ tmp = String::getSplittedAtFirst(proxy, ':');
+ // .c_str() is needed as tmp.second can include a \0 char which will end in an exception of the lexical cast.
+ // with .c_str() the \0 will not be part of the string which is to be casted
+ port = boost::lexical_cast<int> (tmp.second.c_str());
+ ret = HostAddressPort(HostAddress(tmp.first), port);
+ }
+ catch(...) {
+ std::cerr << "Exception occured while parsing windows proxy \"getHostAddressPort\"." << std::endl;
+ }
+
+ return ret;
+}
+
+
+bool WindowsProxyProvider::proxyEnabled(HKEY hKey) const {
+ bool ret = false;
+ long result;
+ DWORD dataType = REG_DWORD;
+ DWORD dataSize = 0;
+ DWORD data = 0;
+ ByteArray dataBuffer;
+
+ if(hKey == INVALID_HANDLE_VALUE)
+ return ret;
+
+ result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, NULL, &dataSize);
+ if(result != ERROR_SUCCESS)
+ return ret;
+
+ dataBuffer.resize(dataSize);
+ result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, reinterpret_cast<BYTE*>(dataBuffer.getData()), &dataSize);
+ if(result != ERROR_SUCCESS)
+ return ret;
+
+ for(size_t t = 0; t < dataBuffer.getSize(); t++) {
+ data += static_cast<int> (dataBuffer[t]) * pow(256, static_cast<double>(t));
+ }
+ return (data == 1);
+}
+
+}
diff --git a/Swiften/Network/WindowsProxyProvider.h b/Swiften/Network/WindowsProxyProvider.h
new file mode 100644
index 0000000..d8d08f0
--- /dev/null
+++ b/Swiften/Network/WindowsProxyProvider.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+ class WindowsProxyProvider : public ProxyProvider {
+ public:
+ WindowsProxyProvider();
+ virtual HostAddressPort getHTTPConnectProxy() const;
+ virtual HostAddressPort getSOCKS5Proxy() const;
+ private:
+ HostAddressPort getAsHostAddressPort(std::string proxy);
+ bool proxyEnabled(HKEY hKey) const;
+ HostAddressPort socksProxy;
+ HostAddressPort httpProxy;
+ };
+}
diff --git a/Swiften/Parser/Attribute.h b/Swiften/Parser/Attribute.h
new file mode 100644
index 0000000..f1f9a83
--- /dev/null
+++ b/Swiften/Parser/Attribute.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace Swift {
+ class Attribute {
+ public:
+ Attribute(const std::string& name, const std::string& ns) : name(name), ns(ns) {
+ }
+
+ const std::string& getName() const {
+ return name;
+ }
+
+ const std::string& getNamespace() const {
+ return ns;
+ }
+
+ bool operator==(const Attribute& o) const {
+ return o.name == name && o.ns == ns;
+ }
+
+ private:
+ std::string name;
+ std::string ns;
+ };
+}
diff --git a/Swiften/Parser/AttributeMap.cpp b/Swiften/Parser/AttributeMap.cpp
new file mode 100644
index 0000000..1aeaf99
--- /dev/null
+++ b/Swiften/Parser/AttributeMap.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Parser/AttributeMap.h>
+
+#include <algorithm>
+#include <boost/optional.hpp>
+
+using namespace Swift;
+
+namespace {
+ struct AttributeIs {
+ AttributeIs(const Attribute& attribute) : attribute(attribute) {
+ }
+
+ bool operator()(const AttributeMap::Entry& o) const {
+ return o.getAttribute() == attribute;
+ }
+
+ Attribute attribute;
+ };
+}
+
+AttributeMap::AttributeMap() {
+}
+
+std::string AttributeMap::getAttribute(const std::string& attribute, const std::string& ns) const {
+ AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ns)));
+ if (i == attributes.end()) {
+ return "";
+ }
+ else {
+ return i->getValue();
+ }
+}
+
+bool AttributeMap::getBoolAttribute(const std::string& attribute, bool defaultValue) const {
+ AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, "")));
+ if (i == attributes.end()) {
+ return defaultValue;
+ }
+ else {
+ return i->getValue() == "true" || i->getValue() == "1";
+ }
+}
+
+boost::optional<std::string> AttributeMap::getAttributeValue(const std::string& attribute) const {
+ AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, "")));
+ if (i == attributes.end()) {
+ return boost::optional<std::string>();
+ }
+ else {
+ return i->getValue();
+ }
+}
+
+void AttributeMap::addAttribute(const std::string& name, const std::string& ns, const std::string& value) {
+ attributes.push_back(Entry(Attribute(name, ns), value));
+}
diff --git a/Swiften/Parser/AttributeMap.h b/Swiften/Parser/AttributeMap.h
index c8b287b..31df606 100644
--- a/Swiften/Parser/AttributeMap.h
+++ b/Swiften/Parser/AttributeMap.h
@@ -4,38 +4,50 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef ATTRIBUTEMAP_H
-#define ATTRIBUTEMAP_H
+#pragma once
+#include <vector>
+#include <string>
#include <map>
+#include <boost/optional/optional_fwd.hpp>
-#include <string>
+#include <Swiften/Parser/Attribute.h>
namespace Swift {
- class AttributeMap : public std::map<std::string,std::string> {
+ class AttributeMap {
public:
- AttributeMap() {}
-
- std::string getAttribute(const std::string& attribute) const {
- AttributeMap::const_iterator i = find(attribute);
- if (i == end()) {
- return "";
- }
- else {
- return i->second;
- }
- }
+ class Entry {
+ public:
+ Entry(const Attribute& attribute, const std::string& value) : attribute(attribute), value(value) {
+ }
+
+ const Attribute& getAttribute() const {
+ return attribute;
+ }
+
+ const std::string& getValue() const {
+ return value;
+ }
+
+ private:
+ Attribute attribute;
+ std::string value;
+ };
- bool getBoolAttribute(const std::string& attribute, bool defaultValue = false) const {
- AttributeMap::const_iterator i = find(attribute);
- if (i == end()) {
- return defaultValue;
- }
- else {
- return i->second == "true" || i->second == "1";
- }
+ AttributeMap();
+
+ std::string getAttribute(const std::string& attribute, const std::string& ns = "") const;
+ bool getBoolAttribute(const std::string& attribute, bool defaultValue = false) const;
+ boost::optional<std::string> getAttributeValue(const std::string&) const;
+
+ void addAttribute(const std::string& name, const std::string& ns, const std::string& value);
+
+ const std::vector<Entry>& getEntries() const {
+ return attributes;
}
+
+ private:
+ typedef std::vector<Entry> AttributeValueMap;
+ AttributeValueMap attributes;
};
}
-
-#endif
diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp
index 88be752..448b199 100644
--- a/Swiften/Parser/ExpatParser.cpp
+++ b/Swiften/Parser/ExpatParser.cpp
@@ -30,7 +30,7 @@ static void handleStartElement(void* client, const XML_Char* name, const XML_Cha
nsAttributePair.second = nsAttributePair.first;
nsAttributePair.first = "";
}
- attributeValues[nsAttributePair.second] = std::string(*(currentAttribute+1));
+ attributeValues.addAttribute(nsAttributePair.second, nsAttributePair.first, std::string(*(currentAttribute+1)));
currentAttribute += 2;
}
diff --git a/Swiften/Parser/IQParser.cpp b/Swiften/Parser/IQParser.cpp
index e0883f2..62d775f 100644
--- a/Swiften/Parser/IQParser.cpp
+++ b/Swiften/Parser/IQParser.cpp
@@ -5,8 +5,9 @@
*/
#include <iostream>
+#include <boost/optional.hpp>
-#include "Swiften/Parser/IQParser.h"
+#include <Swiften/Parser/IQParser.h>
namespace Swift {
@@ -15,22 +16,22 @@ IQParser::IQParser(PayloadParserFactoryCollection* factories) :
}
void IQParser::handleStanzaAttributes(const AttributeMap& attributes) {
- AttributeMap::const_iterator type = attributes.find("type");
- if (type != attributes.end()) {
- if (type->second == "set") {
+ boost::optional<std::string> type = attributes.getAttributeValue("type");
+ if (type) {
+ if (*type == "set") {
getStanzaGeneric()->setType(IQ::Set);
}
- else if (type->second == "get") {
+ else if (*type == "get") {
getStanzaGeneric()->setType(IQ::Get);
}
- else if (type->second == "result") {
+ else if (*type == "result") {
getStanzaGeneric()->setType(IQ::Result);
}
- else if (type->second == "error") {
+ else if (*type == "error") {
getStanzaGeneric()->setType(IQ::Error);
}
else {
- std::cerr << "Unknown IQ type: " << type->second << std::endl;
+ std::cerr << "Unknown IQ type: " << *type << std::endl;
getStanzaGeneric()->setType(IQ::Get);
}
}
diff --git a/Swiften/Parser/IQParser.h b/Swiften/Parser/IQParser.h
index e104dc4..35ab132 100644
--- a/Swiften/Parser/IQParser.h
+++ b/Swiften/Parser/IQParser.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_IQParser_H
-#define SWIFTEN_IQParser_H
+#pragma once
#include "Swiften/Parser/GenericStanzaParser.h"
#include "Swiften/Elements/IQ.h"
@@ -19,5 +18,3 @@ namespace Swift {
virtual void handleStanzaAttributes(const AttributeMap&);
};
}
-
-#endif
diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp
index 34db4ca..0b15848 100644
--- a/Swiften/Parser/LibXMLParser.cpp
+++ b/Swiften/Parser/LibXMLParser.cpp
@@ -15,10 +15,18 @@
namespace Swift {
-static void handleStartElement(void *client, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int, const xmlChar ** attributes) {
+static void handleStartElement(void *client, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) {
AttributeMap attributeValues;
+ if (nbDefaulted != 0) {
+ // Just because i don't understand what this means yet :-)
+ std::cerr << "Unexpected nbDefaulted on XML element" << std::endl;
+ }
for (int i = 0; i < nbAttributes*5; i += 5) {
- attributeValues[std::string(reinterpret_cast<const char*>(attributes[i]))] = std::string(reinterpret_cast<const char*>(attributes[i+3]), attributes[i+4]-attributes[i+3]);
+ std::string attributeNS = "";
+ if (attributes[i+2]) {
+ attributeNS = std::string(reinterpret_cast<const char*>(attributes[i+2]));
+ }
+ attributeValues.addAttribute(std::string(reinterpret_cast<const char*>(attributes[i])), attributeNS, std::string(reinterpret_cast<const char*>(attributes[i+3]), attributes[i+4]-attributes[i+3]));
}
static_cast<XMLParserClient*>(client)->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string()), attributeValues);
}
diff --git a/Swiften/Parser/MessageParser.cpp b/Swiften/Parser/MessageParser.cpp
index 5f4d59c..7f5e6d4 100644
--- a/Swiften/Parser/MessageParser.cpp
+++ b/Swiften/Parser/MessageParser.cpp
@@ -4,9 +4,9 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include <iostream>
+#include <boost/optional.hpp>
-#include "Swiften/Parser/MessageParser.h"
+#include <Swiften/Parser/MessageParser.h>
namespace Swift {
@@ -16,18 +16,18 @@ MessageParser::MessageParser(PayloadParserFactoryCollection* factories) :
}
void MessageParser::handleStanzaAttributes(const AttributeMap& attributes) {
- AttributeMap::const_iterator type = attributes.find("type");
- if (type != attributes.end()) {
- if (type->second == "chat") {
+ boost::optional<std::string> type = attributes.getAttributeValue("type");
+ if (type) {
+ if (*type == "chat") {
getStanzaGeneric()->setType(Message::Chat);
}
- else if (type->second == "error") {
+ else if (*type == "error") {
getStanzaGeneric()->setType(Message::Error);
}
- else if (type->second == "groupchat") {
+ else if (*type == "groupchat") {
getStanzaGeneric()->setType(Message::Groupchat);
}
- else if (type->second == "headline") {
+ else if (*type == "headline") {
getStanzaGeneric()->setType(Message::Headline);
}
else {
diff --git a/Swiften/Parser/PayloadParser.h b/Swiften/Parser/PayloadParser.h
index 423a2bb..3dc04df 100644
--- a/Swiften/Parser/PayloadParser.h
+++ b/Swiften/Parser/PayloadParser.h
@@ -44,6 +44,6 @@ namespace Swift {
/**
* Retrieve a pointer to the payload.
*/
- virtual Payload::ref getPayload() const = 0;
+ virtual boost::shared_ptr<Payload> getPayload() const = 0;
};
}
diff --git a/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp b/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp
index 35db9ec..3de11ac 100644
--- a/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp
+++ b/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp
@@ -27,7 +27,7 @@ void BytestreamsParser::handleStartElement(const std::string& element, const std
try {
getPayloadInternal()->addStreamHost(Bytestreams::StreamHost(attributes.getAttribute("host"), JID(attributes.getAttribute("jid")), boost::lexical_cast<int>(attributes.getAttribute("port"))));
}
- catch (boost::bad_lexical_cast& e) {
+ catch (boost::bad_lexical_cast&) {
}
}
else if (element == "streamhost-used") {
diff --git a/Swiften/Parser/PayloadParsers/DelayParser.cpp b/Swiften/Parser/PayloadParsers/DelayParser.cpp
index 3425b84..0ab2d7b 100644
--- a/Swiften/Parser/PayloadParsers/DelayParser.cpp
+++ b/Swiften/Parser/PayloadParsers/DelayParser.cpp
@@ -9,6 +9,7 @@
#include <locale>
#include <boost/date_time/time_facet.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
namespace Swift {
diff --git a/Swiften/Parser/PayloadParsers/DelayParserFactory.cpp b/Swiften/Parser/PayloadParsers/DelayParserFactory.cpp
index 19d0530..48841d2 100644
--- a/Swiften/Parser/PayloadParsers/DelayParserFactory.cpp
+++ b/Swiften/Parser/PayloadParsers/DelayParserFactory.cpp
@@ -6,6 +6,7 @@
#include <Swiften/Parser/PayloadParsers/DelayParserFactory.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/time_facet.hpp>
namespace Swift {
diff --git a/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp
index e1fcb20..2e9e87a 100644
--- a/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp
+++ b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp
@@ -15,7 +15,7 @@ DiscoInfoParser::DiscoInfoParser() : level_(TopLevel), formParser_(NULL) {
void DiscoInfoParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
if (level_ == PayloadLevel) {
if (element == "identity") {
- getPayloadInternal()->addIdentity(DiscoInfo::Identity(attributes.getAttribute("name"), attributes.getAttribute("category"), attributes.getAttribute("type"), attributes.getAttribute("lang")));
+ getPayloadInternal()->addIdentity(DiscoInfo::Identity(attributes.getAttribute("name"), attributes.getAttribute("category"), attributes.getAttribute("type"), attributes.getAttribute("lang", "http://www.w3.org/XML/1998/namespace")));
}
else if (element == "feature") {
getPayloadInternal()->addFeature(attributes.getAttribute("var"));
diff --git a/Swiften/Parser/PayloadParsers/FormParser.cpp b/Swiften/Parser/PayloadParsers/FormParser.cpp
index f8e02a4..72449b8 100644
--- a/Swiften/Parser/PayloadParsers/FormParser.cpp
+++ b/Swiften/Parser/PayloadParsers/FormParser.cpp
@@ -63,12 +63,9 @@ void FormParser::handleStartElement(const std::string& element, const std::strin
else if (type == "text-private") {
currentFieldParseHelper_ = TextPrivateFormFieldParseHelper::create();
}
- else if (type == "text-single") {
+ else /*if (type == "text-single") || undefined */ {
currentFieldParseHelper_ = TextSingleFormFieldParseHelper::create();
}
- else {
- currentFieldParseHelper_ = UntypedFormFieldParseHelper::create();
- }
if (currentFieldParseHelper_) {
currentFieldParseHelper_->getField()->setName(attributes.getAttribute("var"));
currentFieldParseHelper_->getField()->setLabel(attributes.getAttribute("label"));
diff --git a/Swiften/Parser/PayloadParsers/FormParser.h b/Swiften/Parser/PayloadParsers/FormParser.h
index 90a3550..e6e6ec0 100644
--- a/Swiften/Parser/PayloadParsers/FormParser.h
+++ b/Swiften/Parser/PayloadParsers/FormParser.h
@@ -96,7 +96,6 @@ namespace Swift {
SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDSingle, JID);
SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDMulti, JIDList);
SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(ListMulti, StringList);
- SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Untyped, StringList);
enum Level {
TopLevel = 0,
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index e20c06d..5052e67 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -17,6 +17,7 @@
#include "Swiften/Parser/PayloadParsers/StartSessionParser.h"
#include "Swiften/Parser/PayloadParsers/StatusParser.h"
#include "Swiften/Parser/PayloadParsers/StatusShowParser.h"
+#include "Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h"
#include "Swiften/Parser/PayloadParsers/RosterParser.h"
#include "Swiften/Parser/PayloadParsers/SoftwareVersionParser.h"
#include "Swiften/Parser/PayloadParsers/StorageParser.h"
@@ -54,6 +55,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<ErrorParser>("error")));
factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<SoftwareVersionParser>("query", "jabber:iq:version")));
factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<StorageParser>("storage", "storage:bookmarks")));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<RosterItemExchangeParser>("x", "http://jabber.org/protocol/rosterx")));
factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<RosterParser>("query", "jabber:iq:roster")));
factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<DiscoInfoParser>("query", "http://jabber.org/protocol/disco#info")));
factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<DiscoItemsParser>("query", "http://jabber.org/protocol/disco#items")));
diff --git a/Swiften/Parser/PayloadParsers/IBBParser.cpp b/Swiften/Parser/PayloadParsers/IBBParser.cpp
index f36dc43..8196295 100644
--- a/Swiften/Parser/PayloadParsers/IBBParser.cpp
+++ b/Swiften/Parser/PayloadParsers/IBBParser.cpp
@@ -27,7 +27,7 @@ void IBBParser::handleStartElement(const std::string& element, const std::string
try {
getPayloadInternal()->setSequenceNumber(boost::lexical_cast<int>(attributes.getAttribute("seq")));
}
- catch (boost::bad_lexical_cast& e) {
+ catch (boost::bad_lexical_cast&) {
}
}
else if (element == "open") {
@@ -42,7 +42,7 @@ void IBBParser::handleStartElement(const std::string& element, const std::string
try {
getPayloadInternal()->setBlockSize(boost::lexical_cast<int>(attributes.getAttribute("block-size")));
}
- catch (boost::bad_lexical_cast& e) {
+ catch (boost::bad_lexical_cast&) {
}
}
else if (element == "close") {
@@ -64,7 +64,7 @@ void IBBParser::handleEndElement(const std::string& element, const std::string&)
data.push_back(c);
}
}
- getPayloadInternal()->setData(Base64::decode(std::string(&data[0], data.size())));
+ getPayloadInternal()->setData(Base64::decode(std::string(&data[0], data.size())).getDataVector());
}
}
}
diff --git a/Swiften/Parser/PayloadParsers/PriorityParser.cpp b/Swiften/Parser/PayloadParsers/PriorityParser.cpp
index bcbf67f..553a2b1 100644
--- a/Swiften/Parser/PayloadParsers/PriorityParser.cpp
+++ b/Swiften/Parser/PayloadParsers/PriorityParser.cpp
@@ -24,7 +24,7 @@ void PriorityParser::handleEndElement(const std::string&, const std::string&) {
try {
priority = boost::lexical_cast<int>(text_);
}
- catch (boost::bad_lexical_cast& e) {
+ catch (boost::bad_lexical_cast&) {
}
getPayloadInternal()->setPriority(priority);
}
diff --git a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp
new file mode 100644
index 0000000..ff2a73b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h"
+#include "Swiften/Parser/SerializingParser.h"
+
+namespace Swift {
+
+RosterItemExchangeParser::RosterItemExchangeParser() : level_(TopLevel), inItem_(false) {
+}
+
+void RosterItemExchangeParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) {
+ if (level_ == PayloadLevel) {
+ if (element == "item") {
+ inItem_ = true;
+
+ currentItem_ = RosterItemExchangePayload::Item();
+
+ currentItem_.setJID(JID(attributes.getAttribute("jid")));
+ currentItem_.setName(attributes.getAttribute("name"));
+
+ std::string action = attributes.getAttribute("action");
+ if (action == "add") {
+ currentItem_.setAction(RosterItemExchangePayload::Item::Add);
+ }
+ else if (action == "modify") {
+ currentItem_.setAction(RosterItemExchangePayload::Item::Modify);
+ }
+ else if (action == "delete") {
+ currentItem_.setAction(RosterItemExchangePayload::Item::Delete);
+ }
+ else {
+ // Add is default action according to XEP
+ currentItem_.setAction(RosterItemExchangePayload::Item::Add);
+ }
+ }
+ }
+ else if (level_ == ItemLevel) {
+ if (element == "group") {
+ currentText_ = "";
+ }
+ }
+ ++level_;
+}
+
+void RosterItemExchangeParser::handleEndElement(const std::string& element, const std::string& /*ns*/) {
+ --level_;
+ if (level_ == PayloadLevel) {
+ if (inItem_) {
+ getPayloadInternal()->addItem(currentItem_);
+ inItem_ = false;
+ }
+ }
+ else if (level_ == ItemLevel) {
+ if (element == "group") {
+ currentItem_.addGroup(currentText_);
+ }
+ }
+}
+
+void RosterItemExchangeParser::handleCharacterData(const std::string& data) {
+ currentText_ += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h
new file mode 100644
index 0000000..3d6b8f4
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Elements/RosterItemExchangePayload.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+ class SerializingParser;
+
+ class RosterItemExchangeParser : public GenericPayloadParser<RosterItemExchangePayload> {
+ public:
+ RosterItemExchangeParser();
+
+ virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
+ virtual void handleEndElement(const std::string& element, const std::string&);
+ virtual void handleCharacterData(const std::string& data);
+
+ private:
+ enum Level {
+ TopLevel = 0,
+ PayloadLevel = 1,
+ ItemLevel = 2
+ };
+ int level_;
+ bool inItem_;
+ RosterItemExchangePayload::Item currentItem_;
+ std::string currentText_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/RosterParser.cpp b/Swiften/Parser/PayloadParsers/RosterParser.cpp
index ba19fbf..5fba30b 100644
--- a/Swiften/Parser/PayloadParsers/RosterParser.cpp
+++ b/Swiften/Parser/PayloadParsers/RosterParser.cpp
@@ -5,6 +5,9 @@
*/
#include "Swiften/Parser/PayloadParsers/RosterParser.h"
+
+#include <boost/optional.hpp>
+
#include "Swiften/Parser/SerializingParser.h"
namespace Swift {
@@ -13,7 +16,13 @@ RosterParser::RosterParser() : level_(TopLevel), inItem_(false), unknownContentP
}
void RosterParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
- if (level_ == PayloadLevel) {
+ if (level_ == TopLevel) {
+ boost::optional<std::string> ver = attributes.getAttributeValue("ver");
+ if (ver) {
+ getPayloadInternal()->setVersion(*ver);
+ }
+ }
+ else if (level_ == PayloadLevel) {
if (element == "item") {
inItem_ = true;
currentItem_ = RosterItemPayload();
diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
index 1cf7fcf..0d4a407 100644
--- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
+++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
@@ -42,7 +42,7 @@ void StreamInitiationParser::handleStartElement(const std::string& element, cons
try {
currentFile.size = boost::lexical_cast<int>(attributes.getAttribute("size"));
}
- catch (boost::bad_lexical_cast& e) {
+ catch (boost::bad_lexical_cast&) {
}
}
else if (element == "feature" && ns == FEATURE_NEG_NS) {
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp
index 6ec825b..7feada1 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp
@@ -77,7 +77,6 @@ class FormParserTest : public CppUnit::TestFixture {
"</field>"
"<field var=\"untyped\">"
"<value>foo</value>"
- "<value>baz</value>"
"</field>"
"</x>"));
@@ -114,8 +113,7 @@ class FormParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(JID("baz@fum.org"), boost::dynamic_pointer_cast<JIDMultiFormField>(payload->getFields()[8])->getValue()[1]);
CPPUNIT_ASSERT_EQUAL(std::string("Tell all your friends about your new bot!"), payload->getFields()[8]->getDescription());
- CPPUNIT_ASSERT_EQUAL(std::string("foo"), boost::dynamic_pointer_cast<UntypedFormField>(payload->getFields()[9])->getValue()[0]);
- CPPUNIT_ASSERT_EQUAL(std::string("baz"), boost::dynamic_pointer_cast<UntypedFormField>(payload->getFields()[9])->getValue()[1]);
+ CPPUNIT_ASSERT_EQUAL(std::string("foo"), boost::dynamic_pointer_cast<TextSingleFormField>(payload->getFields()[9])->getValue());
}
};
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp
index b4229f2..2fc3e79 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp
@@ -32,7 +32,7 @@ class IBBParserTest : public CppUnit::TestFixture {
IBB::ref ibb = parser.getPayload<IBB>();
CPPUNIT_ASSERT(ibb->getAction() == IBB::Data);
- CPPUNIT_ASSERT_EQUAL(ByteArray("abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\x0a"), ibb->getData());
+ CPPUNIT_ASSERT(ByteArray::create("abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\x0a") == ibb->getData());
CPPUNIT_ASSERT_EQUAL(4, ibb->getSequenceNumber());
}
};
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp
index 68a2e4f..e2b8be2 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp
@@ -24,7 +24,7 @@ class PriorityParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT(parser.parse("<priority>-120</priority>"));
- Priority::ref payload = boost::dynamic_pointer_cast<Priority>(parser.getPayload());
+ boost::shared_ptr<Priority> payload = boost::dynamic_pointer_cast<Priority>(parser.getPayload());
CPPUNIT_ASSERT_EQUAL(-120, payload->getPriority());
}
@@ -33,7 +33,7 @@ class PriorityParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT(parser.parse("<priority>invalid</priority>"));
- Priority::ref payload = boost::dynamic_pointer_cast<Priority>(parser.getPayload());
+ boost::shared_ptr<Priority> payload = boost::dynamic_pointer_cast<Priority>(parser.getPayload());
CPPUNIT_ASSERT_EQUAL(0, payload->getPriority());
}
};
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp
new file mode 100644
index 0000000..9533e15
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+
+using namespace Swift;
+
+class RosterItemExchangeParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RosterItemExchangeParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testParse() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse(
+ "<x xmlns=\"http://jabber.org/protocol/rosterx\">"
+ "<item action=\"add\" jid=\"foo@bar.com\" name=\"Foo @ Bar\">"
+ "<group>Group 1</group>"
+ "<group>Group 2</group>"
+ "</item>"
+ "<item action=\"modify\" jid=\"baz@blo.com\" name=\"Baz\"/>"
+ "</x>"));
+
+ RosterItemExchangePayload* payload = dynamic_cast<RosterItemExchangePayload*>(parser.getPayload().get());
+ const RosterItemExchangePayload::RosterItemExchangePayloadItems& items = payload->getItems();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size());
+
+ CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), items[0].getJID());
+ CPPUNIT_ASSERT_EQUAL(std::string("Foo @ Bar"), items[0].getName());
+ CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Item::Add, items[0].getAction());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items[0].getGroups().size());
+ CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].getGroups()[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].getGroups()[1]);
+
+ CPPUNIT_ASSERT_EQUAL(JID("baz@blo.com"), items[1].getJID());
+ CPPUNIT_ASSERT_EQUAL(std::string("Baz"), items[1].getName());
+ CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Item::Modify, items[1].getAction());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].getGroups().size());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RosterItemExchangeParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp
index 1bcea0e..3102b74 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp
@@ -17,6 +17,8 @@ class RosterParserTest : public CppUnit::TestFixture
CPPUNIT_TEST_SUITE(RosterParserTest);
CPPUNIT_TEST(testParse);
CPPUNIT_TEST(testParse_ItemWithUnknownContent);
+ CPPUNIT_TEST(testParse_WithVersion);
+ CPPUNIT_TEST(testParse_WithEmptyVersion);
CPPUNIT_TEST_SUITE_END();
public:
@@ -32,6 +34,8 @@ class RosterParserTest : public CppUnit::TestFixture
"</query>"));
RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get());
+
+ CPPUNIT_ASSERT(!payload->getVersion());
const RosterPayload::RosterItemPayloads& items = payload->getItems();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size());
@@ -74,6 +78,24 @@ class RosterParserTest : public CppUnit::TestFixture
"<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>"
), items[0].getUnknownContent());
}
+
+ void testParse_WithVersion() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:roster' ver='ver10'/>"));
+
+ RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get());
+ CPPUNIT_ASSERT(payload->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string("ver10"), *payload->getVersion());
+ }
+
+ void testParse_WithEmptyVersion() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:roster' ver=''/>"));
+
+ RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get());
+ CPPUNIT_ASSERT(payload->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string(""), *payload->getVersion());
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(RosterParserTest);
diff --git a/Swiften/Parser/PresenceParser.cpp b/Swiften/Parser/PresenceParser.cpp
index 845ccf0..867155f 100644
--- a/Swiften/Parser/PresenceParser.cpp
+++ b/Swiften/Parser/PresenceParser.cpp
@@ -5,6 +5,7 @@
*/
#include <iostream>
+#include <boost/optional.hpp>
#include "Swiften/Parser/PresenceParser.h"
@@ -15,31 +16,31 @@ PresenceParser::PresenceParser(PayloadParserFactoryCollection* factories) :
}
void PresenceParser::handleStanzaAttributes(const AttributeMap& attributes) {
- AttributeMap::const_iterator type = attributes.find("type");
- if (type != attributes.end()) {
- if (type->second == "unavailable") {
+ boost::optional<std::string> type = attributes.getAttributeValue("type");
+ if (type) {
+ if (*type == "unavailable") {
getStanzaGeneric()->setType(Presence::Unavailable);
}
- else if (type->second == "probe") {
+ else if (*type == "probe") {
getStanzaGeneric()->setType(Presence::Probe);
}
- else if (type->second == "subscribe") {
+ else if (*type == "subscribe") {
getStanzaGeneric()->setType(Presence::Subscribe);
}
- else if (type->second == "subscribed") {
+ else if (*type == "subscribed") {
getStanzaGeneric()->setType(Presence::Subscribed);
}
- else if (type->second == "unsubscribe") {
+ else if (*type == "unsubscribe") {
getStanzaGeneric()->setType(Presence::Unsubscribe);
}
- else if (type->second == "unsubscribed") {
+ else if (*type == "unsubscribed") {
getStanzaGeneric()->setType(Presence::Unsubscribed);
}
- else if (type->second == "error") {
+ else if (*type == "error") {
getStanzaGeneric()->setType(Presence::Error);
}
else {
- std::cerr << "Unknown Presence type: " << type->second << std::endl;
+ std::cerr << "Unknown Presence type: " << *type << std::endl;
getStanzaGeneric()->setType(Presence::Available);
}
}
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index cbb2190..e7e8991 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -6,6 +6,7 @@ myenv.MergeFlags(swiften_env.get("LIBXML_FLAGS", ""))
myenv.MergeFlags(swiften_env.get("EXPAT_FLAGS", ""))
sources = [
+ "AttributeMap.cpp",
"AuthRequestParser.cpp",
"AuthChallengeParser.cpp",
"AuthSuccessParser.cpp",
@@ -37,6 +38,7 @@ sources = [
"PayloadParsers/PrivateStorageParser.cpp",
"PayloadParsers/RawXMLPayloadParser.cpp",
"PayloadParsers/ResourceBindParser.cpp",
+ "PayloadParsers/RosterItemExchangeParser.cpp",
"PayloadParsers/RosterParser.cpp",
"PayloadParsers/SecurityLabelParser.cpp",
"PayloadParsers/SecurityLabelsCatalogParser.cpp",
@@ -57,6 +59,8 @@ sources = [
"StanzaParser.cpp",
"StreamErrorParser.cpp",
"StreamFeaturesParser.cpp",
+ "StreamManagementEnabledParser.cpp",
+ "StreamResumeParser.cpp",
"XMLParser.cpp",
"XMLParserClient.cpp",
"XMLParserFactory.cpp",
diff --git a/Swiften/Parser/SerializingParser.cpp b/Swiften/Parser/SerializingParser.cpp
index 43dfc51..03b9575 100644
--- a/Swiften/Parser/SerializingParser.cpp
+++ b/Swiften/Parser/SerializingParser.cpp
@@ -7,7 +7,6 @@
#include "Swiften/Parser/SerializingParser.h"
#include "Swiften/Serializer/XML/XMLTextNode.h"
#include "Swiften/Base/foreach.h"
-#include <iostream>
namespace Swift {
@@ -16,8 +15,9 @@ SerializingParser::SerializingParser() {
void SerializingParser::handleStartElement(const std::string& tag, const std::string& ns, const AttributeMap& attributes) {
boost::shared_ptr<XMLElement> element(new XMLElement(tag, ns));
- for (AttributeMap::const_iterator i = attributes.begin(); i != attributes.end(); ++i) {
- element->setAttribute((*i).first, (*i).second);
+ // FIXME: Ignoring attribute namespace
+ foreach (const AttributeMap::Entry& e, attributes.getEntries()) {
+ element->setAttribute(e.getAttribute().getName(), e.getValue());
}
if (elementStack_.empty()) {
diff --git a/Swiften/Parser/StanzaParser.cpp b/Swiften/Parser/StanzaParser.cpp
index 64c4901..051f37e 100644
--- a/Swiften/Parser/StanzaParser.cpp
+++ b/Swiften/Parser/StanzaParser.cpp
@@ -7,6 +7,7 @@
#include "Swiften/Parser/StanzaParser.h"
#include <iostream>
+#include <boost/optional.hpp>
#include <cassert>
#include "Swiften/Parser/PayloadParser.h"
@@ -39,17 +40,17 @@ void StanzaParser::handleStartElement(const std::string& element, const std::str
currentPayloadParser_->handleStartElement(element, ns, attributes);
}
else {
- AttributeMap::const_iterator from = attributes.find("from");
- if (from != attributes.end()) {
- getStanza()->setFrom(JID(from->second));
+ boost::optional<std::string> from = attributes.getAttributeValue("from");
+ if (from) {
+ getStanza()->setFrom(JID(*from));
}
- AttributeMap::const_iterator to = attributes.find("to");
- if (to != attributes.end()) {
- getStanza()->setTo(JID(to->second));
+ boost::optional<std::string> to = attributes.getAttributeValue("to");
+ if (to) {
+ getStanza()->setTo(JID(*to));
}
- AttributeMap::const_iterator id = attributes.find("id");
- if (id != attributes.end()) {
- getStanza()->setID(id->second);
+ boost::optional<std::string> id = attributes.getAttributeValue("id");
+ if (id) {
+ getStanza()->setID(*id);
}
handleStanzaAttributes(attributes);
}
diff --git a/Swiften/Parser/StreamFeaturesParser.cpp b/Swiften/Parser/StreamFeaturesParser.cpp
index 377f215..1b3ad54 100644
--- a/Swiften/Parser/StreamFeaturesParser.cpp
+++ b/Swiften/Parser/StreamFeaturesParser.cpp
@@ -31,6 +31,9 @@ void StreamFeaturesParser::handleStartElement(const std::string& element, const
else if (element == "compression" && ns == "http://jabber.org/features/compress") {
inCompression_ = true;
}
+ else if (element == "ver" && ns == "urn:xmpp:features:rosterver") {
+ getElementGeneric()->setHasRosterVersioning();
+ }
}
else if (currentDepth_ == 2) {
if (inCompression_ && element == "method") {
diff --git a/Swiften/Parser/StreamManagementEnabledParser.cpp b/Swiften/Parser/StreamManagementEnabledParser.cpp
new file mode 100644
index 0000000..906e071
--- /dev/null
+++ b/Swiften/Parser/StreamManagementEnabledParser.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Parser/StreamManagementEnabledParser.h>
+
+using namespace Swift;
+
+StreamManagementEnabledParser::StreamManagementEnabledParser() : level(TopLevel) {
+}
+
+StreamManagementEnabledParser::~StreamManagementEnabledParser() {
+}
+
+void StreamManagementEnabledParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) {
+ if (level == TopLevel) {
+ if (attributes.getBoolAttribute("resume", false)) {
+ getElementGeneric()->setResumeSupported();
+ }
+ getElementGeneric()->setResumeID(attributes.getAttribute("id"));
+ }
+ ++level;
+}
+
+void StreamManagementEnabledParser::handleEndElement(const std::string&, const std::string&) {
+ --level;
+}
diff --git a/Swiften/Parser/StreamManagementEnabledParser.h b/Swiften/Parser/StreamManagementEnabledParser.h
index adc45ab..db616af 100644
--- a/Swiften/Parser/StreamManagementEnabledParser.h
+++ b/Swiften/Parser/StreamManagementEnabledParser.h
@@ -1,17 +1,27 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2011 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
-#include "Swiften/Parser/GenericElementParser.h"
-#include "Swiften/Elements/StreamManagementEnabled.h"
+#include <Swiften/Parser/GenericElementParser.h>
+#include <Swiften/Elements/StreamManagementEnabled.h>
namespace Swift {
class StreamManagementEnabledParser : public GenericElementParser<StreamManagementEnabled> {
public:
- StreamManagementEnabledParser() : GenericElementParser<StreamManagementEnabled>() {}
+ StreamManagementEnabledParser();
+ ~StreamManagementEnabledParser();
+
+ virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&);
+ virtual void handleEndElement(const std::string&, const std::string&);
+
+ private:
+ enum Level {
+ TopLevel = 0
+ };
+ int level;
};
}
diff --git a/Swiften/Parser/StreamResumeParser.cpp b/Swiften/Parser/StreamResumeParser.cpp
new file mode 100644
index 0000000..f54dcf0
--- /dev/null
+++ b/Swiften/Parser/StreamResumeParser.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Parser/StreamResumeParser.h>
+
+#include <boost/lexical_cast.hpp>
+
+using namespace Swift;
+
+StreamResumeParser::StreamResumeParser() : level(TopLevel) {
+}
+
+StreamResumeParser::~StreamResumeParser() {
+}
+
+void StreamResumeParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) {
+ if (level == TopLevel) {
+ boost::optional<std::string> handledStanzasCount = attributes.getAttributeValue("h");
+ if (handledStanzasCount) {
+ try {
+ getElementGeneric()->setHandledStanzasCount(boost::lexical_cast<int>(*handledStanzasCount));
+ }
+ catch (const boost::bad_lexical_cast &) {
+ }
+ }
+ getElementGeneric()->setResumeID(attributes.getAttribute("previd"));
+ }
+ ++level;
+}
+
+void StreamResumeParser::handleEndElement(const std::string&, const std::string&) {
+ --level;
+}
diff --git a/Swiften/Parser/StreamResumeParser.h b/Swiften/Parser/StreamResumeParser.h
new file mode 100644
index 0000000..0ccd24c
--- /dev/null
+++ b/Swiften/Parser/StreamResumeParser.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Parser/GenericElementParser.h>
+#include <Swiften/Elements/StreamResume.h>
+
+namespace Swift {
+ class StreamResumeParser : public GenericElementParser<StreamResume> {
+ public:
+ StreamResumeParser();
+ ~StreamResumeParser();
+
+ virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&);
+ virtual void handleEndElement(const std::string&, const std::string&);
+
+ private:
+ enum Level {
+ TopLevel = 0
+ };
+ int level;
+ };
+}
diff --git a/Swiften/Parser/UnitTest/AttributeMapTest.cpp b/Swiften/Parser/UnitTest/AttributeMapTest.cpp
index fb68f29..8e2ccff 100644
--- a/Swiften/Parser/UnitTest/AttributeMapTest.cpp
+++ b/Swiften/Parser/UnitTest/AttributeMapTest.cpp
@@ -14,6 +14,7 @@ using namespace Swift;
class AttributeMapTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(AttributeMapTest);
+ CPPUNIT_TEST(testGetAttribute_Namespaced);
CPPUNIT_TEST(testGetBoolAttribute_True);
CPPUNIT_TEST(testGetBoolAttribute_1);
CPPUNIT_TEST(testGetBoolAttribute_False);
@@ -24,39 +25,46 @@ class AttributeMapTest : public CppUnit::TestFixture
CPPUNIT_TEST_SUITE_END();
public:
- AttributeMapTest() {}
+ void testGetAttribute_Namespaced() {
+ AttributeMap testling;
+ testling.addAttribute("lang", "", "nl");
+ testling.addAttribute("lang", "http://www.w3.org/XML/1998/namespace", "en");
+ testling.addAttribute("lang", "", "fr");
+
+ CPPUNIT_ASSERT_EQUAL(std::string("en"), testling.getAttribute("lang", "http://www.w3.org/XML/1998/namespace"));
+ }
void testGetBoolAttribute_True() {
AttributeMap testling;
- testling["foo"] = "true";
+ testling.addAttribute("foo", "", "true");
CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));
}
void testGetBoolAttribute_1() {
AttributeMap testling;
- testling["foo"] = "1";
+ testling.addAttribute("foo", "", "1");
CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));
}
void testGetBoolAttribute_False() {
AttributeMap testling;
- testling["foo"] = "false";
+ testling.addAttribute("foo", "", "false");
CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
}
void testGetBoolAttribute_0() {
AttributeMap testling;
- testling["foo"] = "0";
+ testling.addAttribute("foo", "", "0");
CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
}
void testGetBoolAttribute_Invalid() {
AttributeMap testling;
- testling["foo"] = "bla";
+ testling.addAttribute("foo", "", "bla");
CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));
}
diff --git a/Swiften/Parser/UnitTest/StanzaParserTest.cpp b/Swiften/Parser/UnitTest/StanzaParserTest.cpp
index d57f798..2657750 100644
--- a/Swiften/Parser/UnitTest/StanzaParserTest.cpp
+++ b/Swiften/Parser/UnitTest/StanzaParserTest.cpp
@@ -40,8 +40,8 @@ class StanzaParserTest : public CppUnit::TestFixture {
MyStanzaParser testling(factoryCollection_);
AttributeMap attributes;
- attributes["foo"] = "fum";
- attributes["bar"] = "baz";
+ attributes.addAttribute("foo", "", "fum");
+ attributes.addAttribute("bar", "", "baz");
testling.handleStartElement("mystanza", "", attributes);
testling.handleStartElement("mypayload1", "", attributes);
testling.handleStartElement("child", "", attributes);
@@ -107,9 +107,9 @@ class StanzaParserTest : public CppUnit::TestFixture {
MyStanzaParser testling(factoryCollection_);
AttributeMap attributes;
- attributes["to"] = "foo@example.com/blo";
- attributes["from"] = "bar@example.com/baz";
- attributes["id"] = "id-123";
+ attributes.addAttribute("to", "", "foo@example.com/blo");
+ attributes.addAttribute("from", "", "bar@example.com/baz");
+ attributes.addAttribute("id", "", "id-123");
testling.handleStartElement("mystanza", "", attributes);
testling.handleEndElement("mypayload1", "");
diff --git a/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp b/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp
index 1cdaf54..9fdea88 100644
--- a/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp
+++ b/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp
@@ -37,6 +37,7 @@ class StreamFeaturesParserTest : public CppUnit::TestFixture {
"<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
"<sm xmlns='urn:xmpp:sm:2'/>"
"<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
+ "<ver xmlns=\"urn:xmpp:features:rosterver\"/>"
"</stream:features>"));
StreamFeatures::ref element = boost::dynamic_pointer_cast<StreamFeatures>(testling.getElement());
@@ -49,6 +50,7 @@ class StreamFeaturesParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT(element->hasAuthenticationMechanism("DIGEST-MD5"));
CPPUNIT_ASSERT(element->hasAuthenticationMechanism("PLAIN"));
CPPUNIT_ASSERT(element->hasStreamManagement());
+ CPPUNIT_ASSERT(element->hasRosterVersioning());
}
void testParse_Empty() {
diff --git a/Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp b/Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp
new file mode 100644
index 0000000..07b7b31
--- /dev/null
+++ b/Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <Swiften/Parser/StreamManagementEnabledParser.h>
+#include <Swiften/Parser/UnitTest/ElementParserTester.h>
+
+using namespace Swift;
+
+class StreamManagementEnabledParserTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(StreamManagementEnabledParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testParse() {
+ StreamManagementEnabledParser testling;
+ ElementParserTester parser(&testling);
+
+ CPPUNIT_ASSERT(parser.parse(
+ "<enabled xmlns=\"urn:xmpp:sm:3\" id=\"some-long-sm-id\" resume=\"true\"/>"));
+
+ boost::shared_ptr<StreamManagementEnabled> element = boost::dynamic_pointer_cast<StreamManagementEnabled>(testling.getElement());
+ CPPUNIT_ASSERT(element->getResumeSupported());
+ CPPUNIT_ASSERT_EQUAL(std::string("some-long-sm-id"), element->getResumeID());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(StreamManagementEnabledParserTest);
diff --git a/Swiften/Parser/UnitTest/XMLParserTest.cpp b/Swiften/Parser/UnitTest/XMLParserTest.cpp
index 426b7a0..27534a1 100644
--- a/Swiften/Parser/UnitTest/XMLParserTest.cpp
+++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp
@@ -31,6 +31,8 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testParse_InErrorState);
CPPUNIT_TEST(testParse_Incremental);
CPPUNIT_TEST(testParse_WhitespaceInAttribute);
+ CPPUNIT_TEST(testParse_AttributeWithoutNamespace);
+ CPPUNIT_TEST(testParse_AttributeWithNamespace);
CPPUNIT_TEST_SUITE_END();
public:
@@ -46,13 +48,13 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data);
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.size());
- CPPUNIT_ASSERT_EQUAL(std::string("get"), client_.events[0].attributes["type"]);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size());
+ CPPUNIT_ASSERT_EQUAL(std::string("get"), client_.events[0].attributes.getAttribute("type"));
CPPUNIT_ASSERT_EQUAL(std::string(), client_.events[0].ns);
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[1].data);
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.size());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.getEntries().size());
CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns);
CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
@@ -76,7 +78,7 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data);
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.size());
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.getEntries().size());
CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].ns);
CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
@@ -205,6 +207,28 @@ class XMLParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
CPPUNIT_ASSERT_EQUAL(std::string("presence"), client_.events[2].data);
}
+
+ void testParse_AttributeWithoutNamespace() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse(
+ "<query xmlns='http://swift.im' attr='3'/>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size());
+ CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName());
+ CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace());
+ }
+
+ void testParse_AttributeWithNamespace() {
+ ParserType testling(&client_);
+
+ CPPUNIT_ASSERT(testling.parse(
+ "<query xmlns='http://swift.im' xmlns:f='http://swift.im/f' f:attr='3'/>"));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size());
+ CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace());
+ }
private:
class Client : public XMLParserClient {
diff --git a/Swiften/Parser/XMPPParser.cpp b/Swiften/Parser/XMPPParser.cpp
index 1fb7682..adcfdf5 100644
--- a/Swiften/Parser/XMPPParser.cpp
+++ b/Swiften/Parser/XMPPParser.cpp
@@ -29,6 +29,7 @@
#include "Swiften/Parser/EnableStreamManagementParser.h"
#include "Swiften/Parser/StreamManagementEnabledParser.h"
#include "Swiften/Parser/StreamManagementFailedParser.h"
+#include "Swiften/Parser/StreamResumeParser.h"
#include "Swiften/Parser/StanzaAckParser.h"
#include "Swiften/Parser/StanzaAckRequestParser.h"
#include "Swiften/Parser/StartTLSParser.h"
@@ -182,6 +183,12 @@ ElementParser* XMPPParser::createElementParser(const std::string& element, const
else if (element == "failed" && ns == "urn:xmpp:sm:2") {
return new StreamManagementFailedParser();
}
+ else if (element == "resume" && ns == "urn:xmpp:sm:2") {
+ return new StreamResumeParser();
+ }
+ else if (element == "resumed" && ns == "urn:xmpp:sm:2") {
+ return new StreamResumeParser();
+ }
else if (element == "a" && ns == "urn:xmpp:sm:2") {
return new StanzaAckParser();
}
diff --git a/Swiften/Presence/PayloadAddingPresenceSender.cpp b/Swiften/Presence/PayloadAddingPresenceSender.cpp
index c3d1638..43071b3 100644
--- a/Swiften/Presence/PayloadAddingPresenceSender.cpp
+++ b/Swiften/Presence/PayloadAddingPresenceSender.cpp
@@ -34,7 +34,7 @@ bool PayloadAddingPresenceSender::isAvailable() const {
return sender->isAvailable();
}
-void PayloadAddingPresenceSender::setPayload(Payload::ref payload) {
+void PayloadAddingPresenceSender::setPayload(boost::shared_ptr<Payload> payload) {
this->payload = payload;
if (lastSentPresence) {
sendPresence(lastSentPresence);
diff --git a/Swiften/Presence/PayloadAddingPresenceSender.h b/Swiften/Presence/PayloadAddingPresenceSender.h
index ae82970..ba891a8 100644
--- a/Swiften/Presence/PayloadAddingPresenceSender.h
+++ b/Swiften/Presence/PayloadAddingPresenceSender.h
@@ -21,7 +21,7 @@ namespace Swift {
public:
PayloadAddingPresenceSender(PresenceSender*);
- void sendPresence(Presence::ref);
+ void sendPresence(boost::shared_ptr<Presence>);
bool isAvailable() const;
/**
@@ -30,11 +30,11 @@ namespace Swift {
* with an updated payload. Initial presence is reset when unavailable presence is
* sent.
*/
- void setPayload(Payload::ref);
+ void setPayload(boost::shared_ptr<Payload>);
private:
- Presence::ref lastSentPresence;
+ boost::shared_ptr<Presence> lastSentPresence;
PresenceSender* sender;
- Payload::ref payload;
+ boost::shared_ptr<Payload> payload;
};
}
diff --git a/Swiften/QA/ClientTest/ClientTest.cpp b/Swiften/QA/ClientTest/ClientTest.cpp
index 35bb096..09d357c 100644
--- a/Swiften/QA/ClientTest/ClientTest.cpp
+++ b/Swiften/QA/ClientTest/ClientTest.cpp
@@ -6,6 +6,7 @@
#include <boost/bind.hpp>
#include <boost/thread.hpp>
+#include <iostream>
#include "Swiften/Client/Client.h"
#include "Swiften/Network/TimerFactory.h"
diff --git a/Swiften/QA/ProxyProviderTest/.gitignore b/Swiften/QA/ProxyProviderTest/.gitignore
new file mode 100644
index 0000000..9d4b9b8
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/.gitignore
@@ -0,0 +1 @@
+ProxyProviderTest
diff --git a/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp
new file mode 100644
index 0000000..ddaee01
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010 Thilo Cestonaro
+ * Licensed under the BSD License.
+ * See Documentation/Licenses/BSD.txt for more information.
+ */
+
+#include <iostream>
+
+#include <Swiften/Network/PlatformProxyProvider.h>
+#include <Swiften/Base/foreach.h>
+
+using namespace Swift;
+
+int main(void)
+{
+ int ret = 0;
+ HostAddressPort hap;
+
+ std::cout << "constructing PlatfromProxyProvider instance ..." << std::endl;
+ PlatformProxyProvider ppp;
+
+ hap = ppp.getSOCKS5Proxy();
+ std::cout << "SOCKS5 Proxy configured: " << hap.isValid() << std::endl;
+ if(hap.isValid()) {
+ std::cout << "SOCKS5 Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl;
+ }
+
+ hap = ppp.getHTTPConnectProxy();
+ std::cout << "HTTPConnect Proxy configured: " << hap.isValid() << std::endl;
+ if(hap.isValid()) {
+ std::cout << "HTTPConnect Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl;
+ }
+
+ return ret;
+}
diff --git a/Swiften/QA/ProxyProviderTest/SConscript b/Swiften/QA/ProxyProviderTest/SConscript
new file mode 100644
index 0000000..2eb123d
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/SConscript
@@ -0,0 +1,11 @@
+import os
+
+Import("env")
+
+myenv = env.Clone()
+myenv.MergeFlags(myenv["SWIFTEN_FLAGS"])
+myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"])
+
+myenv.Program("ProxyProviderTest", [
+ "ProxyProviderTest.cpp",
+ ])
diff --git a/Swiften/QA/SConscript b/Swiften/QA/SConscript
index 25ba814..2f2be6e 100644
--- a/Swiften/QA/SConscript
+++ b/Swiften/QA/SConscript
@@ -5,7 +5,8 @@ SConscript(dirs = [
# "ReconnectTest",
"ClientTest",
# "DNSSDTest",
- "StorageTest",
+# "StorageTest",
"TLSTest",
"ScriptedTests",
+ "ProxyProviderTest",
])
diff --git a/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp b/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp
index 925c775..73df0a0 100644
--- a/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp
+++ b/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp
@@ -7,6 +7,7 @@
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <Swiften/Base/ByteArray.h>
#include "Swiften/FileTransfer/FileReadBytestream.h"
#include "SwifTools/Application/PlatformApplicationPathProvider.h"
@@ -32,16 +33,16 @@ class FileReadBytestreamTest : public CppUnit::TestFixture {
void testRead() {
std::auto_ptr<FileReadBytestream> testling(createTestling());
- ByteArray result = testling->read(10);
+ std::vector<unsigned char> result = testling->read(10);
- CPPUNIT_ASSERT_EQUAL(std::string("/*\n * Copy"), result.toString());
+ CPPUNIT_ASSERT(ByteArray::create("/*\n * Copy") == result);
}
void testRead_Twice() {
std::auto_ptr<FileReadBytestream> testling(createTestling());
testling->read(10);
- ByteArray result = testling->read(10);
+ ByteArray result(testling->read(10));
CPPUNIT_ASSERT_EQUAL(std::string("right (c) "), result.toString());
}
diff --git a/Swiften/Queries/RawRequest.h b/Swiften/Queries/RawRequest.h
index 477952f..e5b3a1d 100644
--- a/Swiften/Queries/RawRequest.h
+++ b/Swiften/Queries/RawRequest.h
@@ -31,7 +31,7 @@ namespace Swift {
RawRequest(IQ::Type type, const JID& receiver, const std::string& data, IQRouter* router) : Request(type, receiver, boost::make_shared<RawXMLPayload>(data), router) {
}
- virtual void handleResponse(Payload::ref payload, ErrorPayload::ref error) {
+ virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) {
if (error) {
onResponse(ErrorSerializer().serializePayload(error));
}
diff --git a/Swiften/Queries/Request.h b/Swiften/Queries/Request.h
index eee89e9..88eda63 100644
--- a/Swiften/Queries/Request.h
+++ b/Swiften/Queries/Request.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_Request_H
-#define SWIFTEN_Request_H
+#pragma once
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
@@ -48,15 +47,15 @@ namespace Swift {
const JID& receiver,
IQRouter* router);
- virtual void setPayload(Payload::ref payload) {
+ virtual void setPayload(boost::shared_ptr<Payload> payload) {
payload_ = payload;
}
- Payload::ref getPayload() const {
+ boost::shared_ptr<Payload> getPayload() const {
return payload_;
}
- virtual void handleResponse(Payload::ref, ErrorPayload::ref) = 0;
+ virtual void handleResponse(boost::shared_ptr<Payload>, boost::shared_ptr<ErrorPayload>) = 0;
private:
bool handleIQ(boost::shared_ptr<IQ>);
@@ -70,5 +69,3 @@ namespace Swift {
bool sent_;
};
}
-
-#endif
diff --git a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h
index 0700c65..5dd19b5 100644
--- a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h
+++ b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h
@@ -26,11 +26,11 @@ namespace Swift {
SetInBandRegistrationRequest(const JID& to, InBandRegistrationPayload::ref payload, IQRouter* router) : Request(IQ::Set, to, InBandRegistrationPayload::ref(payload), router) {
}
- virtual void handleResponse(Payload::ref payload, ErrorPayload::ref error) {
+ virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) {
onResponse(payload, error);
}
public:
- boost::signal<void (Payload::ref, ErrorPayload::ref)> onResponse;
+ boost::signal<void (boost::shared_ptr<Payload>, ErrorPayload::ref)> onResponse;
};
}
diff --git a/Swiften/Roster/GetRosterRequest.h b/Swiften/Roster/GetRosterRequest.h
index 00cf77f..a3486f0 100644
--- a/Swiften/Roster/GetRosterRequest.h
+++ b/Swiften/Roster/GetRosterRequest.h
@@ -19,6 +19,12 @@ namespace Swift {
return ref(new GetRosterRequest(router));
}
+ static ref create(IQRouter* router, const std::string& version) {
+ ref result(new GetRosterRequest(router));
+ result->getPayloadGeneric()->setVersion(version);
+ return result;
+ }
+
private:
GetRosterRequest(IQRouter* router) :
GenericRequest<RosterPayload>(IQ::Get, JID(), boost::shared_ptr<Payload>(new RosterPayload()), router) {
diff --git a/Swiften/Roster/RosterMemoryStorage.cpp b/Swiften/Roster/RosterMemoryStorage.cpp
new file mode 100644
index 0000000..cbf4563
--- /dev/null
+++ b/Swiften/Roster/RosterMemoryStorage.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Roster/RosterMemoryStorage.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace Swift {
+
+RosterMemoryStorage::RosterMemoryStorage() {
+}
+
+void RosterMemoryStorage::setRoster(boost::shared_ptr<RosterPayload> r) {
+ roster.reset();
+ if (r) {
+ roster = boost::make_shared<RosterPayload>(*r);
+ }
+}
+
+}
diff --git a/Swiften/Roster/RosterMemoryStorage.h b/Swiften/Roster/RosterMemoryStorage.h
new file mode 100644
index 0000000..b659d77
--- /dev/null
+++ b/Swiften/Roster/RosterMemoryStorage.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Roster/RosterStorage.h>
+
+namespace Swift {
+ class RosterMemoryStorage : public RosterStorage {
+ public:
+ RosterMemoryStorage();
+
+ virtual boost::shared_ptr<RosterPayload> getRoster() const {
+ return roster;
+ }
+
+ virtual void setRoster(boost::shared_ptr<RosterPayload>);
+
+ private:
+ boost::shared_ptr<RosterPayload> roster;
+ };
+}
diff --git a/Swiften/Roster/RosterStorage.cpp b/Swiften/Roster/RosterStorage.cpp
new file mode 100644
index 0000000..6bf58de
--- /dev/null
+++ b/Swiften/Roster/RosterStorage.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Roster/RosterStorage.h>
+
+namespace Swift {
+
+RosterStorage::~RosterStorage() {
+}
+
+}
diff --git a/Swiften/Roster/RosterStorage.h b/Swiften/Roster/RosterStorage.h
new file mode 100644
index 0000000..ba24cb3
--- /dev/null
+++ b/Swiften/Roster/RosterStorage.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Elements/RosterPayload.h>
+
+namespace Swift {
+ class RosterStorage {
+ public:
+ virtual ~RosterStorage();
+
+ virtual boost::shared_ptr<RosterPayload> getRoster() const = 0;
+ virtual void setRoster(boost::shared_ptr<RosterPayload>) = 0;
+ };
+}
diff --git a/Swiften/Roster/SetRosterRequest.h b/Swiften/Roster/SetRosterRequest.h
index e5ae974..606b431 100644
--- a/Swiften/Roster/SetRosterRequest.h
+++ b/Swiften/Roster/SetRosterRequest.h
@@ -19,11 +19,15 @@ namespace Swift {
typedef boost::shared_ptr<SetRosterRequest> ref;
static ref create(RosterPayload::ref payload, IQRouter* router) {
- return ref(new SetRosterRequest(payload, router));
+ return ref(new SetRosterRequest(JID(), payload, router));
+ }
+
+ static ref create(RosterPayload::ref payload, const JID& to, IQRouter* router) {
+ return ref(new SetRosterRequest(to, payload, router));
}
private:
- SetRosterRequest(boost::shared_ptr<RosterPayload> payload, IQRouter* router) : Request(IQ::Set, JID(), boost::shared_ptr<RosterPayload>(payload), router) {
+ SetRosterRequest(const JID& to, boost::shared_ptr<RosterPayload> payload, IQRouter* router) : Request(IQ::Set, to, boost::shared_ptr<RosterPayload>(payload), router) {
}
virtual void handleResponse(boost::shared_ptr<Payload> /*payload*/, ErrorPayload::ref error) {
diff --git a/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp b/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp
index 4ef1cc1..4c98673 100644
--- a/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp
+++ b/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp
@@ -16,15 +16,24 @@
#include "Swiften/Client/DummyStanzaChannel.h"
#include "Swiften/Queries/IQRouter.h"
#include "Swiften/Roster/XMPPRosterImpl.h"
+#include <Swiften/Roster/RosterMemoryStorage.h>
using namespace Swift;
class XMPPRosterControllerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(XMPPRosterControllerTest);
+ CPPUNIT_TEST(testGet_Response);
CPPUNIT_TEST(testGet_EmptyResponse);
+ CPPUNIT_TEST(testGet_NoRosterInStorage);
+ CPPUNIT_TEST(testGet_NoVersionInStorage);
+ CPPUNIT_TEST(testGet_VersionInStorage);
+ CPPUNIT_TEST(testGet_ServerDoesNotSupportVersion);
+ CPPUNIT_TEST(testGet_ResponseWithoutNewVersion);
+ CPPUNIT_TEST(testGet_ResponseWithNewVersion);
CPPUNIT_TEST(testAdd);
CPPUNIT_TEST(testModify);
CPPUNIT_TEST(testRemove);
+ CPPUNIT_TEST(testRemove_RosterStorageUpdated);
CPPUNIT_TEST(testMany);
CPPUNIT_TEST_SUITE_END();
@@ -34,20 +43,36 @@ class XMPPRosterControllerTest : public CppUnit::TestFixture {
router_ = new IQRouter(channel_);
xmppRoster_ = new XMPPRosterImpl();
handler_ = new XMPPRosterSignalHandler(xmppRoster_);
+ rosterStorage_ = new RosterMemoryStorage();
jid1_ = JID("foo@bar.com");
jid2_ = JID("alice@wonderland.lit");
jid3_ = JID("jane@austen.lit");
}
void tearDown() {
+ delete rosterStorage_;
delete handler_;
delete xmppRoster_;
delete router_;
delete channel_;
}
+ void testGet_Response() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+
+ testling->requestRoster();
+ boost::shared_ptr<RosterPayload> payload = boost::make_shared<RosterPayload>();
+ payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
+ payload->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both));
+ channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), payload));
+
+ CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount());
+ CPPUNIT_ASSERT(xmppRoster_->getItem(jid1_));
+ CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_));
+ }
+
void testGet_EmptyResponse() {
- XMPPRosterController controller(router_, xmppRoster_);
+ XMPPRosterController controller(router_, xmppRoster_, rosterStorage_);
controller.requestRoster();
@@ -55,7 +80,7 @@ class XMPPRosterControllerTest : public CppUnit::TestFixture {
}
void testAdd() {
- XMPPRosterController controller(router_, xmppRoster_);
+ XMPPRosterController controller(router_, xmppRoster_, rosterStorage_);
boost::shared_ptr<RosterPayload> payload(new RosterPayload());
payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
@@ -68,8 +93,115 @@ class XMPPRosterControllerTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(std::string("Bob"), xmppRoster_->getNameForJID(jid1_));
}
+ void testGet_NoRosterInStorage() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+ testling->setUseVersioning(true);
+
+ testling->requestRoster();
+
+ boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>();
+ CPPUNIT_ASSERT(roster->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string(""), *roster->getVersion());
+ }
+
+ void testGet_NoVersionInStorage() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+ testling->setUseVersioning(true);
+ rosterStorage_->setRoster(boost::make_shared<RosterPayload>());
+
+ testling->requestRoster();
+
+ boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>();
+ CPPUNIT_ASSERT(roster->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string(""), *roster->getVersion());
+ }
+
+ void testGet_VersionInStorage() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+ testling->setUseVersioning(true);
+ boost::shared_ptr<RosterPayload> payload(new RosterPayload());
+ payload->setVersion("foover");
+ rosterStorage_->setRoster(payload);
+
+ testling->requestRoster();
+
+ boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>();
+ CPPUNIT_ASSERT(roster->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string("foover"), *roster->getVersion());
+ }
+
+ void testGet_ServerDoesNotSupportVersion() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+ boost::shared_ptr<RosterPayload> payload(new RosterPayload());
+ payload->setVersion("foover");
+ rosterStorage_->setRoster(payload);
+
+ testling->requestRoster();
+
+ boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>();
+ CPPUNIT_ASSERT(!roster->getVersion());
+ }
+
+ void testGet_ResponseWithoutNewVersion() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+ testling->setUseVersioning(true);
+ boost::shared_ptr<RosterPayload> storedRoster(new RosterPayload());
+ storedRoster->setVersion("version10");
+ storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
+ storedRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both));
+ rosterStorage_->setRoster(storedRoster);
+ testling->requestRoster();
+
+ channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), boost::shared_ptr<RosterPayload>()));
+
+ CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount());
+ CPPUNIT_ASSERT(xmppRoster_->getItem(jid1_));
+ CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_));
+ CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent());
+ CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID());
+ CPPUNIT_ASSERT(rosterStorage_->getRoster());
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string("version10"), *rosterStorage_->getRoster()->getVersion());
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid1_));
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_));
+ }
+
+ void testGet_ResponseWithNewVersion() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+ testling->setUseVersioning(true);
+ boost::shared_ptr<RosterPayload> storedRoster(new RosterPayload());
+ storedRoster->setVersion("version10");
+ storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
+ rosterStorage_->setRoster(storedRoster);
+ testling->requestRoster();
+
+ boost::shared_ptr<RosterPayload> serverRoster(new RosterPayload());
+ serverRoster->setVersion("version12");
+ serverRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both));
+ std::vector<std::string> groups;
+ groups.push_back("foo");
+ groups.push_back("bar");
+ serverRoster->addItem(RosterItemPayload(jid3_, "Rabbit", RosterItemPayload::Both, groups));
+ channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), serverRoster));
+
+
+ CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount());
+ CPPUNIT_ASSERT(!xmppRoster_->getItem(jid1_));
+ CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_));
+ CPPUNIT_ASSERT(xmppRoster_->getItem(jid3_));
+ CPPUNIT_ASSERT_EQUAL(jid3_, handler_->getLastJID());
+ CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent());
+ CPPUNIT_ASSERT(rosterStorage_->getRoster());
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string("version12"), *rosterStorage_->getRoster()->getVersion());
+ CPPUNIT_ASSERT(!rosterStorage_->getRoster()->getItem(jid1_));
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_));
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid3_));
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(rosterStorage_->getRoster()->getItem(jid3_)->getGroups().size()));
+ }
+
void testModify() {
- XMPPRosterController controller(router_, xmppRoster_);
+ XMPPRosterController controller(router_, xmppRoster_, rosterStorage_);
boost::shared_ptr<RosterPayload> payload1(new RosterPayload());
payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1));
@@ -87,9 +219,9 @@ class XMPPRosterControllerTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(std::string("Bob2"), xmppRoster_->getNameForJID(jid1_));
}
-
+
void testRemove() {
- XMPPRosterController controller(router_, xmppRoster_);
+ XMPPRosterController controller(router_, xmppRoster_, rosterStorage_);
boost::shared_ptr<RosterPayload> payload1(new RosterPayload());
payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1));
@@ -107,8 +239,31 @@ class XMPPRosterControllerTest : public CppUnit::TestFixture {
}
+ void testRemove_RosterStorageUpdated() {
+ std::auto_ptr<XMPPRosterController> testling(createController());
+ testling->setUseVersioning(true);
+ boost::shared_ptr<RosterPayload> storedRoster(new RosterPayload());
+ storedRoster->setVersion("version10");
+ storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
+ storedRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both));
+ rosterStorage_->setRoster(storedRoster);
+ testling->requestRoster();
+ channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), boost::shared_ptr<RosterPayload>()));
+
+ boost::shared_ptr<RosterPayload> payload2(new RosterPayload());
+ payload2->setVersion("version15");
+ payload2->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Remove));
+ channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2));
+
+ CPPUNIT_ASSERT(rosterStorage_->getRoster());
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion());
+ CPPUNIT_ASSERT_EQUAL(std::string("version15"), *rosterStorage_->getRoster()->getVersion());
+ CPPUNIT_ASSERT(!rosterStorage_->getRoster()->getItem(jid1_));
+ CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_));
+ }
+
void testMany() {
- XMPPRosterController controller(router_, xmppRoster_);
+ XMPPRosterController controller(router_, xmppRoster_, rosterStorage_);
boost::shared_ptr<RosterPayload> payload1(new RosterPayload());
payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both));
channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1));
@@ -171,12 +326,18 @@ class XMPPRosterControllerTest : public CppUnit::TestFixture {
handler_->reset();
}
+
+ private:
+ XMPPRosterController* createController() {
+ return new XMPPRosterController(router_, xmppRoster_, rosterStorage_);
+ }
private:
DummyStanzaChannel* channel_;
IQRouter* router_;
XMPPRosterImpl* xmppRoster_;
XMPPRosterSignalHandler* handler_;
+ RosterMemoryStorage* rosterStorage_;
JID jid1_;
JID jid2_;
JID jid3_;
diff --git a/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp
new file mode 100644
index 0000000..d89644a
--- /dev/null
+++ b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h>
+
+#include <boost/bind.hpp>
+#include <cassert>
+
+using namespace Swift;
+
+XMPPRosterSignalHandler::XMPPRosterSignalHandler(Swift::XMPPRoster* roster) : eventCount(0) {
+ lastEvent_ = None;
+ roster->onJIDAdded.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDAdded, this, _1));
+ roster->onJIDRemoved.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDRemoved, this, _1));
+ roster->onJIDUpdated.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDUpdated, this, _1, _2, _3));
+}
+
+void XMPPRosterSignalHandler::handleJIDUpdated(const Swift::JID& jid, const std::string& oldName, const std::vector<std::string>& oldGroups) {
+ assert(lastEvent_ == None);
+ lastJID_ = jid;
+ lastOldName_ = oldName;
+ lastOldGroups_ = oldGroups;
+ lastEvent_ = Update;
+ eventCount++;
+}
diff --git a/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h
index 1bbd8e9..2cf1159 100644
--- a/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h
+++ b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h
@@ -3,34 +3,25 @@
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
+
#pragma once
-#include <boost/shared_ptr.hpp>
-#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
#include <vector>
-
#include "Swiften/Roster/XMPPRosterImpl.h"
-using namespace Swift;
-
-
enum XMPPRosterEvents {None, Add, Remove, Update};
class XMPPRosterSignalHandler {
public:
- XMPPRosterSignalHandler(XMPPRoster* roster) {
- lastEvent_ = None;
- roster->onJIDAdded.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDAdded, this, _1));
- roster->onJIDRemoved.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDRemoved, this, _1));
- roster->onJIDUpdated.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDUpdated, this, _1, _2, _3));
- }
+ XMPPRosterSignalHandler(Swift::XMPPRoster* roster);
XMPPRosterEvents getLastEvent() {
return lastEvent_;
}
- JID getLastJID() {
+ Swift::JID getLastJID() {
return lastJID_;
}
@@ -46,28 +37,28 @@ public:
lastEvent_ = None;
}
+ int getEventCount() const {
+ return eventCount;
+ }
+
private:
- void handleJIDAdded(const JID& jid) {
+ void handleJIDAdded(const Swift::JID& jid) {
lastJID_ = jid;
lastEvent_ = Add;
+ eventCount++;
}
- void handleJIDRemoved(const JID& jid) {
+ void handleJIDRemoved(const Swift::JID& jid) {
lastJID_ = jid;
lastEvent_ = Remove;
+ eventCount++;
}
- void handleJIDUpdated(const JID& jid, const std::string& oldName, const std::vector<std::string>& oldGroups) {
- CPPUNIT_ASSERT_EQUAL(None, lastEvent_);
- lastJID_ = jid;
- lastOldName_ = oldName;
- lastOldGroups_ = oldGroups;
- lastEvent_ = Update;
- }
+ void handleJIDUpdated(const Swift::JID& jid, const std::string& oldName, const std::vector<std::string>& oldGroups);
XMPPRosterEvents lastEvent_;
- JID lastJID_;
+ Swift::JID lastJID_;
std::string lastOldName_;
std::vector<std::string> lastOldGroups_;
-
+ int eventCount;
};
diff --git a/Swiften/Roster/XMPPRosterController.cpp b/Swiften/Roster/XMPPRosterController.cpp
index a294d35..bd7e079 100644
--- a/Swiften/Roster/XMPPRosterController.cpp
+++ b/Swiften/Roster/XMPPRosterController.cpp
@@ -7,20 +7,22 @@
#include "Swiften/Roster/XMPPRosterController.h"
#include <boost/bind.hpp>
+#include <iostream>
#include "Swiften/Base/foreach.h"
#include "Swiften/Elements/RosterItemPayload.h"
#include "Swiften/Queries/IQRouter.h"
#include "Swiften/Roster/GetRosterRequest.h"
#include "Swiften/Roster/XMPPRosterImpl.h"
+#include <Swiften/Roster/RosterStorage.h>
namespace Swift {
/**
* The controller does not gain ownership of these parameters.
*/
-XMPPRosterController::XMPPRosterController(IQRouter* iqRouter, XMPPRosterImpl* xmppRoster) : iqRouter_(iqRouter), rosterPushResponder_(iqRouter), xmppRoster_(xmppRoster) {
- rosterPushResponder_.onRosterReceived.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, false));
+XMPPRosterController::XMPPRosterController(IQRouter* iqRouter, XMPPRosterImpl* xmppRoster, RosterStorage* rosterStorage) : iqRouter_(iqRouter), rosterPushResponder_(iqRouter), xmppRoster_(xmppRoster), rosterStorage_(rosterStorage), useVersioning(false) {
+ rosterPushResponder_.onRosterReceived.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, false, boost::shared_ptr<RosterPayload>()));
rosterPushResponder_.start();
}
@@ -30,12 +32,24 @@ XMPPRosterController::~XMPPRosterController() {
void XMPPRosterController::requestRoster() {
xmppRoster_->clear();
- GetRosterRequest::ref rosterRequest = GetRosterRequest::create(iqRouter_);
- rosterRequest->onResponse.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, true));
+
+ boost::shared_ptr<RosterPayload> storedRoster = rosterStorage_->getRoster();
+ GetRosterRequest::ref rosterRequest;
+ if (useVersioning) {
+ std::string version = "";
+ if (storedRoster && storedRoster->getVersion()) {
+ version = *storedRoster->getVersion();
+ }
+ rosterRequest = GetRosterRequest::create(iqRouter_, version);
+ }
+ else {
+ rosterRequest = GetRosterRequest::create(iqRouter_);
+ }
+ rosterRequest->onResponse.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, true, storedRoster));
rosterRequest->send();
}
-void XMPPRosterController::handleRosterReceived(boost::shared_ptr<RosterPayload> rosterPayload, bool initial) {
+void XMPPRosterController::handleRosterReceived(boost::shared_ptr<RosterPayload> rosterPayload, bool initial, boost::shared_ptr<RosterPayload> previousRoster) {
if (rosterPayload) {
foreach(const RosterItemPayload& item, rosterPayload->getItems()) {
//Don't worry about the updated case, the XMPPRoster sorts that out.
@@ -46,9 +60,33 @@ void XMPPRosterController::handleRosterReceived(boost::shared_ptr<RosterPayload>
}
}
}
+ else if (previousRoster) {
+ // The cached version hasn't changed; emit all items
+ foreach(const RosterItemPayload& item, previousRoster->getItems()) {
+ if (item.getSubscription() != RosterItemPayload::Remove) {
+ xmppRoster_->addContact(item.getJID(), item.getName(), item.getGroups(), item.getSubscription());
+ }
+ else {
+ std::cerr << "ERROR: Stored invalid roster item" << std::endl;
+ }
+ }
+ }
if (initial) {
xmppRoster_->onInitialRosterPopulated();
}
+ if (rosterPayload && rosterPayload->getVersion() && useVersioning) {
+ saveRoster(*rosterPayload->getVersion());
+ }
+}
+
+void XMPPRosterController::saveRoster(const std::string& version) {
+ std::vector<XMPPRosterItem> items = xmppRoster_->getItems();
+ boost::shared_ptr<RosterPayload> roster(new RosterPayload());
+ roster->setVersion(version);
+ foreach(const XMPPRosterItem& item, items) {
+ roster->addItem(RosterItemPayload(item.getJID(), item.getName(), item.getSubscription(), item.getGroups()));
+ }
+ rosterStorage_->setRoster(roster);
}
}
diff --git a/Swiften/Roster/XMPPRosterController.h b/Swiften/Roster/XMPPRosterController.h
index eeb84f6..9313bb6 100644
--- a/Swiften/Roster/XMPPRosterController.h
+++ b/Swiften/Roster/XMPPRosterController.h
@@ -18,21 +18,29 @@
namespace Swift {
class IQRouter;
class XMPPRosterImpl;
+ class RosterStorage;
class XMPPRosterController {
public:
- XMPPRosterController(IQRouter *iqRouter, XMPPRosterImpl* xmppRoster);
+ XMPPRosterController(IQRouter *iqRouter, XMPPRosterImpl* xmppRoster, RosterStorage* storage);
~XMPPRosterController();
void requestRoster();
+ void setUseVersioning(bool b) {
+ useVersioning = b;
+ }
+
private:
- void handleRosterReceived(boost::shared_ptr<RosterPayload> rosterPayload, bool initial);
+ void handleRosterReceived(boost::shared_ptr<RosterPayload> rosterPayload, bool initial, boost::shared_ptr<RosterPayload> previousRoster);
+ void saveRoster(const std::string& version);
private:
IQRouter* iqRouter_;
RosterPushResponder rosterPushResponder_;
XMPPRosterImpl* xmppRoster_;
+ RosterStorage* rosterStorage_;
+ bool useVersioning;
};
}
diff --git a/Swiften/SASL/SConscript b/Swiften/SASL/SConscript
index 5a0cdef..085e49d 100644
--- a/Swiften/SASL/SConscript
+++ b/Swiften/SASL/SConscript
@@ -12,6 +12,7 @@ objects = myenv.SwiftenObject([
"DIGESTMD5ClientAuthenticator.cpp",
])
swiften_env.Append(SWIFTEN_OBJECTS = [objects])
+
env.Append(UNITTEST_SOURCES = [
File("UnitTest/PLAINMessageTest.cpp"),
File("UnitTest/PLAINClientAuthenticatorTest.cpp"),
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 46b901b..53f9201 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -6,7 +6,7 @@ Import("env")
# Flags
################################################################################
-swiften_dep_modules = ["BOOST", "LIBIDN", "ZLIB", "OPENSSL", "LIBXML", "EXPAT", "AVAHI"]
+swiften_dep_modules = ["BOOST", "GCONF", "LIBIDN", "ZLIB", "OPENSSL", "LIBXML", "EXPAT", "AVAHI"]
if env["SCONS_STAGE"] == "flags" :
env["SWIFTEN_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift")
@@ -65,25 +65,34 @@ if env["SCONS_STAGE"] == "build" :
"Client/ClientSessionStanzaChannel.cpp",
"Client/CoreClient.cpp",
"Client/Client.cpp",
+ "Client/ClientXMLTracer.cpp",
"Client/ClientSession.cpp",
"Client/MemoryStorages.cpp",
- "Client/FileStorages.cpp",
"Client/NickResolver.cpp",
"Client/NickManager.cpp",
"Client/NickManagerImpl.cpp",
+ "Client/Storages.cpp",
"Compress/ZLibCodecompressor.cpp",
"Compress/ZLibDecompressor.cpp",
"Compress/ZLibCompressor.cpp",
"Elements/DiscoInfo.cpp",
+ "Elements/Presence.cpp",
"Elements/Form.cpp",
+ "Elements/StreamFeatures.cpp",
"Elements/Element.cpp",
"Elements/IQ.cpp",
"Elements/Payload.cpp",
+ "Elements/RosterItemExchangePayload.cpp",
"Elements/RosterPayload.cpp",
"Elements/Stanza.cpp",
+ "Elements/StatusShow.cpp",
+ "Elements/StreamManagementEnabled.cpp",
+ "Elements/StreamResume.cpp",
+ "Elements/StreamResumed.cpp",
"Elements/VCard.cpp",
"Elements/MUCOccupant.cpp",
"Entity/Entity.cpp",
+ "Entity/PayloadPersister.cpp",
"MUC/MUC.cpp",
"MUC/MUCManager.cpp",
"MUC/MUCRegistry.cpp",
@@ -95,6 +104,8 @@ if env["SCONS_STAGE"] == "build" :
"Queries/Requests/GetInBandRegistrationFormRequest.cpp",
"Queries/Requests/SubmitInBandRegistrationFormRequest.cpp",
"Queries/Responders/SoftwareVersionResponder.cpp",
+ "Roster/RosterStorage.cpp",
+ "Roster/RosterMemoryStorage.cpp",
"Roster/XMPPRoster.cpp",
"Roster/XMPPRosterImpl.cpp",
"Roster/XMPPRosterController.cpp",
@@ -105,6 +116,9 @@ if env["SCONS_STAGE"] == "build" :
"Serializer/CompressRequestSerializer.cpp",
"Serializer/ElementSerializer.cpp",
"Serializer/MessageSerializer.cpp",
+ "Serializer/StreamManagementEnabledSerializer.cpp",
+ "Serializer/StreamResumeSerializer.cpp",
+ "Serializer/StreamResumedSerializer.cpp",
"Serializer/ComponentHandshakeSerializer.cpp",
"Serializer/PayloadSerializer.cpp",
"Serializer/PayloadSerializerCollection.cpp",
@@ -119,6 +133,7 @@ if env["SCONS_STAGE"] == "build" :
"Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp",
"Serializer/PayloadSerializers/ResourceBindSerializer.cpp",
+ "Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp",
"Serializer/PayloadSerializers/RosterSerializer.cpp",
"Serializer/PayloadSerializers/SecurityLabelSerializer.cpp",
"Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp",
@@ -148,6 +163,7 @@ if env["SCONS_STAGE"] == "build" :
"Server/SimpleUserRegistry.cpp",
"Server/UserRegistry.cpp",
"Session/Session.cpp",
+ "Session/SessionTracer.cpp",
"Session/SessionStream.cpp",
"Session/BasicSessionStream.cpp",
"StringCodecs/Base64.cpp",
@@ -158,6 +174,9 @@ if env["SCONS_STAGE"] == "build" :
"StringCodecs/Hexify.cpp",
]
+ if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) :
+ env.MergeFlags(env["GCONF_FLAGS"])
+
SConscript(dirs = [
"Avatars",
"Base",
@@ -179,6 +198,7 @@ if env["SCONS_STAGE"] == "build" :
"StreamManagement",
"Component",
"Config",
+ "AdHoc"
])
SConscript(test_only = True, dirs = [
"QA",
@@ -218,8 +238,6 @@ if env["SCONS_STAGE"] == "build" :
File("Elements/UnitTest/FormTest.cpp"),
File("EventLoop/UnitTest/EventLoopTest.cpp"),
File("EventLoop/UnitTest/SimpleEventLoopTest.cpp"),
- File("FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp"),
- File("FileTransfer/UnitTest/IBBSendSessionTest.cpp"),
# File("History/UnitTest/SQLiteHistoryManagerTest.cpp"),
File("JID/UnitTest/JIDTest.cpp"),
File("LinkLocal/UnitTest/LinkLocalConnectorTest.cpp"),
@@ -229,6 +247,8 @@ if env["SCONS_STAGE"] == "build" :
File("MUC/UnitTest/MUCTest.cpp"),
File("Network/UnitTest/HostAddressTest.cpp"),
File("Network/UnitTest/ConnectorTest.cpp"),
+ File("Network/UnitTest/ChainedConnectorTest.cpp"),
+ File("Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp"),
File("Parser/PayloadParsers/UnitTest/BodyParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp"),
@@ -237,6 +257,7 @@ if env["SCONS_STAGE"] == "build" :
File("Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp"),
+ File("Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/RosterParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/IBBParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp"),
@@ -259,6 +280,7 @@ if env["SCONS_STAGE"] == "build" :
File("Parser/UnitTest/SerializingParserTest.cpp"),
File("Parser/UnitTest/StanzaParserTest.cpp"),
File("Parser/UnitTest/StreamFeaturesParserTest.cpp"),
+ File("Parser/UnitTest/StreamManagementEnabledParserTest.cpp"),
File("Parser/UnitTest/XMLParserTest.cpp"),
File("Parser/UnitTest/XMPPParserTest.cpp"),
File("Presence/UnitTest/PresenceOracleTest.cpp"),
@@ -270,6 +292,7 @@ if env["SCONS_STAGE"] == "build" :
File("Queries/UnitTest/ResponderTest.cpp"),
File("Roster/UnitTest/XMPPRosterImplTest.cpp"),
File("Roster/UnitTest/XMPPRosterControllerTest.cpp"),
+ File("Roster/UnitTest/XMPPRosterSignalHandler.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp"),
File("Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp"),
@@ -277,6 +300,7 @@ if env["SCONS_STAGE"] == "build" :
File("Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/ResourceBindSerializerTest.cpp"),
+ File("Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/SecurityLabelSerializerTest.cpp"),
@@ -328,7 +352,9 @@ if env["SCONS_STAGE"] == "build" :
swiften_includes.append(include)
if root.endswith("OpenSSL") :
continue
- if file.startswith("CAres") or file.startswith("LibXML") or file.startswith("Expat") :
+ if file.startswith("CAres") or file.startswith("LibXML") or file.startswith("Expat") or file.startswith("foreach") or file.startswith("Log.h") or file.startswith("format.h") :
+ continue
+ if file.find("ProxyProvider") != -1 :
continue
swiften_header += "#include <" + include + ">\n"
swiften_includes.append(include)
diff --git a/Swiften/Serializer/IQSerializer.h b/Swiften/Serializer/IQSerializer.h
index 21ec300..784ce09 100644
--- a/Swiften/Serializer/IQSerializer.h
+++ b/Swiften/Serializer/IQSerializer.h
@@ -7,8 +7,6 @@
#ifndef SWIFTEN_IQSerializer_H
#define SWIFTEN_IQSerializer_H
-#include <cassert>
-
#include "Swiften/Serializer/GenericStanzaSerializer.h"
#include "Swiften/Elements/IQ.h"
#include "Swiften/Serializer/XML/XMLElement.h"
diff --git a/Swiften/Serializer/PayloadSerializer.h b/Swiften/Serializer/PayloadSerializer.h
index 34e6679..c4ad23b 100644
--- a/Swiften/Serializer/PayloadSerializer.h
+++ b/Swiften/Serializer/PayloadSerializer.h
@@ -4,15 +4,14 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_PAYLOADSERIALIZER_H
-#define SWIFTEN_PAYLOADSERIALIZER_H
-
-#include <boost/shared_ptr.hpp>
+#pragma once
#include <string>
-#include "Swiften/Elements/Payload.h"
+#include <boost/shared_ptr.hpp>
namespace Swift {
+ class Payload;
+
class PayloadSerializer {
public:
virtual ~PayloadSerializer();
@@ -21,5 +20,3 @@ namespace Swift {
virtual std::string serialize(boost::shared_ptr<Payload>) const = 0;
};
}
-
-#endif
diff --git a/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp
index 0fa45ce..12a38a8 100644
--- a/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp
@@ -21,7 +21,7 @@ CommandSerializer::CommandSerializer() {
}
std::string CommandSerializer::serializePayload(boost::shared_ptr<Command> command) const {
- XMLElement commandElement("command", "http://jabber.org/protocol/comands");
+ XMLElement commandElement("command", "http://jabber.org/protocol/commands");
commandElement.setAttribute("node", command->getNode());
if (!command->getSessionID().empty()) {
diff --git a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp
index 4922042..bdf5505 100644
--- a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp
@@ -7,6 +7,7 @@
#include "Swiften/Serializer/PayloadSerializers/DelaySerializer.h"
#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <Swiften/Base/String.h>
#include "Swiften/Serializer/XML/XMLElement.h"
diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp
index 53b4241..51cb90f 100644
--- a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp
@@ -129,14 +129,6 @@ boost::shared_ptr<XMLElement> FormSerializer::fieldToXML(boost::shared_ptr<FormF
fieldType = "text-multi";
multiLineify(boost::dynamic_pointer_cast<TextMultiFormField>(field)->getValue(), "value", fieldElement);
}
- else if (boost::dynamic_pointer_cast<UntypedFormField>(field)) {
- std::vector<std::string> lines = boost::dynamic_pointer_cast<UntypedFormField>(field)->getValue();
- foreach(const std::string& line, lines) {
- boost::shared_ptr<XMLElement> valueElement(new XMLElement("value"));
- valueElement->addNode(XMLTextNode::create(line));
- fieldElement->addNode(valueElement);
- }
- }
else {
assert(false);
}
diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
index 1bbcbf2..0f05580 100644
--- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
@@ -14,6 +14,7 @@
#include "Swiften/Serializer/PayloadSerializers/PrioritySerializer.h"
#include "Swiften/Serializer/PayloadSerializers/ErrorSerializer.h"
#include "Swiften/Serializer/PayloadSerializers/RosterSerializer.h"
+#include "Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h"
#include "Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h"
#include "Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h"
#include "Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h"
@@ -51,6 +52,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
serializers_.push_back(new PrioritySerializer());
serializers_.push_back(new ErrorSerializer());
serializers_.push_back(new RosterSerializer());
+ serializers_.push_back(new RosterItemExchangeSerializer());
serializers_.push_back(new MUCPayloadSerializer());
serializers_.push_back(new MUCUserPayloadSerializer());
serializers_.push_back(new MUCOwnerPayloadSerializer(this));
diff --git a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp
index d7e1613..f19874a 100644
--- a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp
@@ -6,6 +6,9 @@
#include "Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h"
+#include <boost/lexical_cast.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
#include "Swiften/Serializer/XML/XMLElement.h"
#include <Swiften/Base/String.h>
diff --git a/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp
new file mode 100644
index 0000000..c9ed6ea
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Serializer/XML/XMLTextNode.h"
+#include "Swiften/Serializer/XML/XMLRawTextNode.h"
+#include "Swiften/Serializer/XML/XMLElement.h"
+
+namespace Swift {
+
+RosterItemExchangeSerializer::RosterItemExchangeSerializer() : GenericPayloadSerializer<RosterItemExchangePayload>() {
+}
+
+std::string RosterItemExchangeSerializer::serializePayload(boost::shared_ptr<RosterItemExchangePayload> roster) const {
+ XMLElement queryElement("x", "http://jabber.org/protocol/rosterx");
+ foreach(const RosterItemExchangePayload::Item& item, roster->getItems()) {
+ boost::shared_ptr<XMLElement> itemElement(new XMLElement("item"));
+ itemElement->setAttribute("jid", item.getJID());
+ itemElement->setAttribute("name", item.getName());
+
+ switch (item.getAction()) {
+ case RosterItemExchangePayload::Item::Add: itemElement->setAttribute("action", "add"); break;
+ case RosterItemExchangePayload::Item::Modify: itemElement->setAttribute("action", "modify"); break;
+ case RosterItemExchangePayload::Item::Delete: itemElement->setAttribute("action", "delete"); break;
+ }
+
+ foreach(const std::string& group, item.getGroups()) {
+ boost::shared_ptr<XMLElement> groupElement(new XMLElement("group"));
+ groupElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(group)));
+ itemElement->addNode(groupElement);
+ }
+
+ queryElement.addNode(itemElement);
+ }
+
+ return queryElement.serialize();
+}
+
+}
diff --git a/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h
new file mode 100644
index 0000000..ec2cc13
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Serializer/GenericPayloadSerializer.h"
+#include "Swiften/Elements/RosterItemExchangePayload.h"
+
+namespace Swift {
+ class RosterItemExchangeSerializer : public GenericPayloadSerializer<RosterItemExchangePayload> {
+ public:
+ RosterItemExchangeSerializer();
+
+ virtual std::string serializePayload(boost::shared_ptr<RosterItemExchangePayload>) const;
+ };
+}
diff --git a/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp
index 40faf73..886676a 100644
--- a/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp
@@ -20,6 +20,9 @@ RosterSerializer::RosterSerializer() : GenericPayloadSerializer<RosterPayload>()
std::string RosterSerializer::serializePayload(boost::shared_ptr<RosterPayload> roster) const {
XMLElement queryElement("query", "jabber:iq:roster");
+ if (roster->getVersion()) {
+ queryElement.setAttribute("ver", *roster->getVersion());
+ }
foreach(const RosterItemPayload& item, roster->getItems()) {
boost::shared_ptr<XMLElement> itemElement(new XMLElement("item"));
itemElement->setAttribute("jid", item.getJID());
diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp
index 70fb2ac..ee9f279 100644
--- a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp
@@ -49,7 +49,7 @@ std::string StreamInitiationSerializer::serializePayload(boost::shared_ptr<Strea
siElement.addNode(fileElement);
}
- boost::shared_ptr<XMLElement> featureElement(new XMLElement("feature", "http://jabber.org/protocol/feature-neg"));
+ boost::shared_ptr<XMLElement> featureElement(new XMLElement("feature", FEATURE_NEG_NS));
if (streamInitiation->getProvidedMethods().size() > 0) {
Form::ref form(new Form(Form::FormType));
ListSingleFormField::ref field = ListSingleFormField::create();
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp
index e4a6661..5b52c0a 100644
--- a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp
@@ -96,13 +96,6 @@ class FormSerializerTest : public CppUnit::TestFixture {
field->setDescription("Tell all your friends about your new bot!");
form->addField(field);
- std::vector<std::string> values2;
- values2.push_back("foo");
- values2.push_back("bar");
- field = UntypedFormField::create(values2);
- field->setName("fum");
- form->addField(field);
-
CPPUNIT_ASSERT_EQUAL(std::string(
"<x type=\"form\" xmlns=\"jabber:x:data\">"
"<field type=\"hidden\" var=\"FORM_TYPE\">"
@@ -139,10 +132,6 @@ class FormSerializerTest : public CppUnit::TestFixture {
"<value>foo@bar.com</value>"
"<value>baz@fum.org</value>"
"</field>"
- "<field var=\"fum\">"
- "<value>foo</value>"
- "<value>bar</value>"
- "</field>"
"</x>"), testling.serialize(form));
}
};
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp
new file mode 100644
index 0000000..f4de783
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 Jan Kaluza
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h"
+
+using namespace Swift;
+
+class RosterItemExchangeSerializerTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RosterItemExchangeSerializerTest);
+ CPPUNIT_TEST(testSerialize);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ RosterItemExchangeSerializerTest() {}
+
+ void testSerialize() {
+ RosterItemExchangeSerializer testling;
+ boost::shared_ptr<RosterItemExchangePayload> roster(new RosterItemExchangePayload());
+
+ RosterItemExchangePayload::Item item1;
+ item1.setJID("foo@bar.com");
+ item1.setName("Foo @ Bar");
+ item1.setAction(RosterItemExchangePayload::Item::Add);
+ item1.addGroup("Group 1");
+ item1.addGroup("Group 2");
+ roster->addItem(item1);
+
+ RosterItemExchangePayload::Item item2;
+ item2.setJID("baz@blo.com");
+ item2.setName("Baz");
+ item2.setAction(RosterItemExchangePayload::Item::Modify);
+ roster->addItem(item2);
+
+ std::string expectedResult =
+ "<x xmlns=\"http://jabber.org/protocol/rosterx\">"
+ "<item action=\"add\" jid=\"foo@bar.com\" name=\"Foo @ Bar\">"
+ "<group>Group 1</group>"
+ "<group>Group 2</group>"
+ "</item>"
+ "<item action=\"modify\" jid=\"baz@blo.com\" name=\"Baz\"/>"
+ "</x>";
+
+ CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster));
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RosterItemExchangeSerializerTest);
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp
index b8ceac3..61316df 100644
--- a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp
@@ -11,16 +11,15 @@
using namespace Swift;
-class RosterSerializerTest : public CppUnit::TestFixture
-{
+class RosterSerializerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(RosterSerializerTest);
CPPUNIT_TEST(testSerialize);
CPPUNIT_TEST(testSerialize_ItemWithUnknownContent);
+ CPPUNIT_TEST(testSerialize_WithVersion);
+ CPPUNIT_TEST(testSerialize_WithEmptyVersion);
CPPUNIT_TEST_SUITE_END();
public:
- RosterSerializerTest() {}
-
void testSerialize() {
RosterSerializer testling;
boost::shared_ptr<RosterPayload> roster(new RosterPayload());
@@ -77,6 +76,26 @@ class RosterSerializerTest : public CppUnit::TestFixture
CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster));
}
+
+ void testSerialize_WithVersion() {
+ RosterSerializer testling;
+ boost::shared_ptr<RosterPayload> roster(new RosterPayload());
+ roster->setVersion("ver20");
+
+ std::string expectedResult = "<query ver=\"ver20\" xmlns=\"jabber:iq:roster\"/>";
+
+ CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster));
+ }
+
+ void testSerialize_WithEmptyVersion() {
+ RosterSerializer testling;
+ boost::shared_ptr<RosterPayload> roster(new RosterPayload());
+ roster->setVersion("");
+
+ std::string expectedResult = "<query ver=\"\" xmlns=\"jabber:iq:roster\"/>";
+
+ CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster));
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(RosterSerializerTest);
diff --git a/Swiften/Serializer/PresenceSerializer.h b/Swiften/Serializer/PresenceSerializer.h
index 3cb9aab..be31597 100644
--- a/Swiften/Serializer/PresenceSerializer.h
+++ b/Swiften/Serializer/PresenceSerializer.h
@@ -7,8 +7,6 @@
#ifndef SWIFTEN_PresenceSerializer_H
#define SWIFTEN_PresenceSerializer_H
-#include <cassert>
-
#include "Swiften/Serializer/GenericStanzaSerializer.h"
#include "Swiften/Elements/Presence.h"
diff --git a/Swiften/Serializer/StanzaSerializer.cpp b/Swiften/Serializer/StanzaSerializer.cpp
index cfc9a43..6bd2ef0 100644
--- a/Swiften/Serializer/StanzaSerializer.cpp
+++ b/Swiften/Serializer/StanzaSerializer.cpp
@@ -10,6 +10,7 @@
#include <typeinfo>
#include <iostream>
+#include <Swiften/Base/foreach.h>
#include "Swiften/Serializer/XML/XMLElement.h"
#include "Swiften/Serializer/XML/XMLRawTextNode.h"
#include "Swiften/Serializer/PayloadSerializer.h"
diff --git a/Swiften/Serializer/StreamFeaturesSerializer.cpp b/Swiften/Serializer/StreamFeaturesSerializer.cpp
index 915433c..11744b4 100644
--- a/Swiften/Serializer/StreamFeaturesSerializer.cpp
+++ b/Swiften/Serializer/StreamFeaturesSerializer.cpp
@@ -6,6 +6,8 @@
#include "Swiften/Serializer/StreamFeaturesSerializer.h"
+#include <boost/smart_ptr/make_shared.hpp>
+
#include "Swiften/Serializer/XML/XMLElement.h"
#include "Swiften/Serializer/XML/XMLTextNode.h"
#include "Swiften/Base/foreach.h"
@@ -49,6 +51,9 @@ std::string StreamFeaturesSerializer::serialize(boost::shared_ptr<Element> eleme
if (streamFeatures->hasStreamManagement()) {
streamFeaturesElement.addNode(boost::shared_ptr<XMLElement>(new XMLElement("sm", "urn:xmpp:sm:2")));
}
+ if (streamFeatures->hasRosterVersioning()) {
+ streamFeaturesElement.addNode(boost::make_shared<XMLElement>("ver", "urn:xmpp:features:rosterver"));
+ }
return streamFeaturesElement.serialize();
}
diff --git a/Swiften/Serializer/StreamManagementEnabledSerializer.cpp b/Swiften/Serializer/StreamManagementEnabledSerializer.cpp
new file mode 100644
index 0000000..02cf948
--- /dev/null
+++ b/Swiften/Serializer/StreamManagementEnabledSerializer.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Serializer/StreamManagementEnabledSerializer.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Elements/StreamManagementEnabled.h>
+#include <Swiften/Serializer/XML/XMLElement.h>
+
+using namespace Swift;
+
+StreamManagementEnabledSerializer::StreamManagementEnabledSerializer() : GenericElementSerializer<StreamManagementEnabled>() {
+}
+
+std::string StreamManagementEnabledSerializer::serialize(boost::shared_ptr<Element> el) const {
+ boost::shared_ptr<StreamManagementEnabled> e(boost::dynamic_pointer_cast<StreamManagementEnabled>(el));
+ XMLElement element("enabled", "urn:xmpp:sm:2");
+ if (!e->getResumeID().empty()) {
+ element.setAttribute("id", e->getResumeID());
+ }
+ if (e->getResumeSupported()) {
+ element.setAttribute("resume", "true");
+ }
+ return element.serialize();
+}
diff --git a/Swiften/Serializer/StreamManagementEnabledSerializer.h b/Swiften/Serializer/StreamManagementEnabledSerializer.h
index fc7bd86..8ee9e31 100644
--- a/Swiften/Serializer/StreamManagementEnabledSerializer.h
+++ b/Swiften/Serializer/StreamManagementEnabledSerializer.h
@@ -10,16 +10,12 @@
#include "Swiften/Elements/StreamManagementEnabled.h"
#include "Swiften/Serializer/GenericElementSerializer.h"
-#include "Swiften/Serializer/XML/XMLElement.h"
namespace Swift {
class StreamManagementEnabledSerializer : public GenericElementSerializer<StreamManagementEnabled> {
public:
- StreamManagementEnabledSerializer() : GenericElementSerializer<StreamManagementEnabled>() {
- }
+ StreamManagementEnabledSerializer();
- virtual std::string serialize(boost::shared_ptr<Element>) const {
- return XMLElement("enabled", "urn:xmpp:sm:2").serialize();
- }
+ virtual std::string serialize(boost::shared_ptr<Element>) const;
};
}
diff --git a/Swiften/Serializer/StreamResumeSerializer.cpp b/Swiften/Serializer/StreamResumeSerializer.cpp
new file mode 100644
index 0000000..a7a2e3b
--- /dev/null
+++ b/Swiften/Serializer/StreamResumeSerializer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Serializer/StreamResumeSerializer.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Elements/StreamResume.h>
+#include <Swiften/Serializer/XML/XMLElement.h>
+
+using namespace Swift;
+
+StreamResumeSerializer::StreamResumeSerializer() : GenericElementSerializer<StreamResume>() {
+}
+
+std::string StreamResumeSerializer::serialize(boost::shared_ptr<Element> el) const {
+ boost::shared_ptr<StreamResume> e(boost::dynamic_pointer_cast<StreamResume>(el));
+ XMLElement element("resume", "urn:xmpp:sm:2");
+ element.setAttribute("previd", e->getResumeID());
+ if (e->getHandledStanzasCount()) {
+ element.setAttribute("h", boost::lexical_cast<std::string>(e->getHandledStanzasCount()));
+ }
+ return element.serialize();
+}
diff --git a/Swiften/Serializer/StreamResumeSerializer.h b/Swiften/Serializer/StreamResumeSerializer.h
new file mode 100644
index 0000000..6ea7365
--- /dev/null
+++ b/Swiften/Serializer/StreamResumeSerializer.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Elements/StreamResume.h>
+#include <Swiften/Serializer/GenericElementSerializer.h>
+
+namespace Swift {
+ class StreamResumeSerializer : public GenericElementSerializer<StreamResume> {
+ public:
+ StreamResumeSerializer();
+
+ virtual std::string serialize(boost::shared_ptr<Element>) const;
+ };
+}
diff --git a/Swiften/Serializer/StreamResumedSerializer.cpp b/Swiften/Serializer/StreamResumedSerializer.cpp
new file mode 100644
index 0000000..d3beafb
--- /dev/null
+++ b/Swiften/Serializer/StreamResumedSerializer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Serializer/StreamResumedSerializer.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Elements/StreamResumed.h>
+#include <Swiften/Serializer/XML/XMLElement.h>
+
+using namespace Swift;
+
+StreamResumedSerializer::StreamResumedSerializer() : GenericElementSerializer<StreamResumed>() {
+}
+
+std::string StreamResumedSerializer::serialize(boost::shared_ptr<Element> el) const {
+ boost::shared_ptr<StreamResumed> e(boost::dynamic_pointer_cast<StreamResumed>(el));
+ XMLElement element("resumed", "urn:xmpp:sm:2");
+ element.setAttribute("previd", e->getResumeID());
+ if (e->getHandledStanzasCount()) {
+ element.setAttribute("h", boost::lexical_cast<std::string>(e->getHandledStanzasCount()));
+ }
+ return element.serialize();
+}
diff --git a/Swiften/Serializer/StreamResumedSerializer.h b/Swiften/Serializer/StreamResumedSerializer.h
new file mode 100644
index 0000000..38d846f
--- /dev/null
+++ b/Swiften/Serializer/StreamResumedSerializer.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Elements/StreamResumed.h>
+#include <Swiften/Serializer/GenericElementSerializer.h>
+
+namespace Swift {
+ class StreamResumedSerializer : public GenericElementSerializer<StreamResumed> {
+ public:
+ StreamResumedSerializer();
+
+ virtual std::string serialize(boost::shared_ptr<Element>) const;
+ };
+}
diff --git a/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp b/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp
index 65caa81..aa896c2 100644
--- a/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp
+++ b/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp
@@ -32,6 +32,7 @@ class StreamFeaturesSerializerTest : public CppUnit::TestFixture
streamFeatures->setHasResourceBind();
streamFeatures->setHasSession();
streamFeatures->setHasStreamManagement();
+ streamFeatures->setHasRosterVersioning();
CPPUNIT_ASSERT_EQUAL(std::string(
"<stream:features>"
@@ -47,6 +48,7 @@ class StreamFeaturesSerializerTest : public CppUnit::TestFixture
"<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
"<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
"<sm xmlns=\"urn:xmpp:sm:2\"/>"
+ "<ver xmlns=\"urn:xmpp:features:rosterver\"/>"
"</stream:features>"), testling.serialize(streamFeatures));
}
};
diff --git a/Swiften/Serializer/XMPPSerializer.cpp b/Swiften/Serializer/XMPPSerializer.cpp
index 06f3558..19a30ce 100644
--- a/Swiften/Serializer/XMPPSerializer.cpp
+++ b/Swiften/Serializer/XMPPSerializer.cpp
@@ -4,36 +4,38 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Serializer/XMPPSerializer.h"
+#include <Swiften/Serializer/XMPPSerializer.h>
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <iostream>
#include <cassert>
-#include "Swiften/Elements/ProtocolHeader.h"
-#include "Swiften/Base/foreach.h"
-#include "Swiften/Serializer/CompressRequestSerializer.h"
-#include "Swiften/Serializer/CompressFailureSerializer.h"
-#include "Swiften/Serializer/StreamErrorSerializer.h"
-#include "Swiften/Serializer/StreamFeaturesSerializer.h"
-#include "Swiften/Serializer/AuthRequestSerializer.h"
-#include "Swiften/Serializer/AuthFailureSerializer.h"
-#include "Swiften/Serializer/AuthSuccessSerializer.h"
-#include "Swiften/Serializer/AuthChallengeSerializer.h"
-#include "Swiften/Serializer/AuthResponseSerializer.h"
-#include "Swiften/Serializer/EnableStreamManagementSerializer.h"
-#include "Swiften/Serializer/StreamManagementEnabledSerializer.h"
-#include "Swiften/Serializer/StreamManagementFailedSerializer.h"
-#include "Swiften/Serializer/StanzaAckSerializer.h"
-#include "Swiften/Serializer/StanzaAckRequestSerializer.h"
-#include "Swiften/Serializer/StartTLSRequestSerializer.h"
-#include "Swiften/Serializer/StartTLSFailureSerializer.h"
-#include "Swiften/Serializer/TLSProceedSerializer.h"
-#include "Swiften/Serializer/MessageSerializer.h"
-#include "Swiften/Serializer/PresenceSerializer.h"
-#include "Swiften/Serializer/IQSerializer.h"
-#include "Swiften/Serializer/ComponentHandshakeSerializer.h"
+#include <Swiften/Elements/ProtocolHeader.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Serializer/CompressRequestSerializer.h>
+#include <Swiften/Serializer/CompressFailureSerializer.h>
+#include <Swiften/Serializer/StreamErrorSerializer.h>
+#include <Swiften/Serializer/StreamFeaturesSerializer.h>
+#include <Swiften/Serializer/AuthRequestSerializer.h>
+#include <Swiften/Serializer/AuthFailureSerializer.h>
+#include <Swiften/Serializer/AuthSuccessSerializer.h>
+#include <Swiften/Serializer/AuthChallengeSerializer.h>
+#include <Swiften/Serializer/AuthResponseSerializer.h>
+#include <Swiften/Serializer/EnableStreamManagementSerializer.h>
+#include <Swiften/Serializer/StreamManagementEnabledSerializer.h>
+#include <Swiften/Serializer/StreamResumeSerializer.h>
+#include <Swiften/Serializer/StreamResumedSerializer.h>
+#include <Swiften/Serializer/StreamManagementFailedSerializer.h>
+#include <Swiften/Serializer/StanzaAckSerializer.h>
+#include <Swiften/Serializer/StanzaAckRequestSerializer.h>
+#include <Swiften/Serializer/StartTLSRequestSerializer.h>
+#include <Swiften/Serializer/StartTLSFailureSerializer.h>
+#include <Swiften/Serializer/TLSProceedSerializer.h>
+#include <Swiften/Serializer/MessageSerializer.h>
+#include <Swiften/Serializer/PresenceSerializer.h>
+#include <Swiften/Serializer/IQSerializer.h>
+#include <Swiften/Serializer/ComponentHandshakeSerializer.h>
namespace Swift {
@@ -56,6 +58,8 @@ XMPPSerializer::XMPPSerializer(PayloadSerializerCollection* payloadSerializers,
serializers_.push_back(boost::make_shared<EnableStreamManagementSerializer>());
serializers_.push_back(boost::make_shared<StreamManagementEnabledSerializer>());
serializers_.push_back(boost::make_shared<StreamManagementFailedSerializer>());
+ serializers_.push_back(boost::make_shared<StreamResumeSerializer>());
+ serializers_.push_back(boost::make_shared<StreamResumedSerializer>());
serializers_.push_back(boost::make_shared<StanzaAckSerializer>());
serializers_.push_back(boost::make_shared<StanzaAckRequestSerializer>());
serializers_.push_back(boost::make_shared<ComponentHandshakeSerializer>());
diff --git a/Swiften/Session/SessionTracer.cpp b/Swiften/Session/SessionTracer.cpp
new file mode 100644
index 0000000..6d41e40
--- /dev/null
+++ b/Swiften/Session/SessionTracer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Session/SessionTracer.h>
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+SessionTracer::SessionTracer(boost::shared_ptr<Session> session) : session(session) {
+ session->onDataRead.connect(boost::bind(&SessionTracer::printData, this, '<', _1));
+ session->onDataWritten.connect(boost::bind(&SessionTracer::printData, this, '>', _1));
+}
+
+void SessionTracer::printData(char direction, const ByteArray& data) {
+ std::cerr << direction << direction << " " << session->getLocalJID() << " ";
+ for (unsigned int i = 0; i < 72 - session->getLocalJID().toString().size() - session->getRemoteJID().toString().size(); ++i) {
+ std::cerr << direction;
+ }
+ std::cerr << " " << session->getRemoteJID()<< " " << direction << direction << std::endl;
+ std::cerr << data.toString() << std::endl;
+}
+
+}
diff --git a/Swiften/Session/SessionTracer.h b/Swiften/Session/SessionTracer.h
index cce45eb..51b8d16 100644
--- a/Swiften/Session/SessionTracer.h
+++ b/Swiften/Session/SessionTracer.h
@@ -6,29 +6,18 @@
#pragma once
-#include <iostream>
+#include <string>
#include "Swiften/Session/Session.h"
-#include <string>
#include "Swiften/Base/ByteArray.h"
namespace Swift {
class SessionTracer {
public:
- SessionTracer(boost::shared_ptr<Session> session) : session(session) {
- session->onDataRead.connect(boost::bind(&SessionTracer::printData, this, '<', _1));
- session->onDataWritten.connect(boost::bind(&SessionTracer::printData, this, '>', _1));
- }
+ SessionTracer(boost::shared_ptr<Session> session);
private:
- void printData(char direction, const ByteArray& data) {
- std::cerr << direction << direction << " " << session->getLocalJID() << " ";
- for (unsigned int i = 0; i < 72 - session->getLocalJID().toString().size() - session->getRemoteJID().toString().size(); ++i) {
- std::cerr << direction;
- }
- std::cerr << " " << session->getRemoteJID()<< " " << direction << direction << std::endl;
- std::cerr << data.toString() << std::endl;
- }
+ void printData(char direction, const ByteArray& data);
boost::shared_ptr<Session> session;
};
diff --git a/Swiften/StreamManagement/StanzaAckRequester.cpp b/Swiften/StreamManagement/StanzaAckRequester.cpp
index f7d603b..4b626c9 100644
--- a/Swiften/StreamManagement/StanzaAckRequester.cpp
+++ b/Swiften/StreamManagement/StanzaAckRequester.cpp
@@ -7,6 +7,7 @@
#include "Swiften/StreamManagement/StanzaAckRequester.h"
#include <boost/numeric/conversion/cast.hpp>
+#include <iostream>
#include "Swiften/Elements/Message.h"
diff --git a/Swiften/StreamStack/CompressionLayer.h b/Swiften/StreamStack/CompressionLayer.h
index b8293a8..7d8656e 100644
--- a/Swiften/StreamStack/CompressionLayer.h
+++ b/Swiften/StreamStack/CompressionLayer.h
@@ -27,7 +27,7 @@ namespace Swift {
try {
writeDataToChildLayer(compressor_.process(data));
}
- catch (const ZLibException& e) {
+ catch (const ZLibException&) {
onError();
}
}
@@ -36,7 +36,7 @@ namespace Swift {
try {
writeDataToParentLayer(decompressor_.process(data));
}
- catch (const ZLibException& e) {
+ catch (const ZLibException&) {
onError();
}
}
diff --git a/Swiften/StreamStack/ConnectionLayer.cpp b/Swiften/StreamStack/ConnectionLayer.cpp
new file mode 100644
index 0000000..00b4289
--- /dev/null
+++ b/Swiften/StreamStack/ConnectionLayer.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/StreamStack/ConnectionLayer.h>
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+ConnectionLayer::ConnectionLayer(boost::shared_ptr<Connection> connection) : connection(connection) {
+ connection->onDataRead.connect(boost::bind(&ConnectionLayer::writeDataToParentLayer, this, _1));
+}
+
+ConnectionLayer::~ConnectionLayer() {
+ connection->onDataRead.disconnect(boost::bind(&ConnectionLayer::writeDataToParentLayer, this, _1));
+}
+
+
+}
diff --git a/Swiften/StreamStack/ConnectionLayer.h b/Swiften/StreamStack/ConnectionLayer.h
index 0da0900..bd9c093 100644
--- a/Swiften/StreamStack/ConnectionLayer.h
+++ b/Swiften/StreamStack/ConnectionLayer.h
@@ -6,9 +6,7 @@
#pragma once
-#include "Swiften/Base/boost_bsignals.h"
#include <boost/shared_ptr.hpp>
-#include <boost/bind.hpp>
#include "Swiften/StreamStack/LowLayer.h"
#include "Swiften/Network/Connection.h"
@@ -16,13 +14,8 @@
namespace Swift {
class ConnectionLayer : public LowLayer {
public:
- ConnectionLayer(boost::shared_ptr<Connection> connection) : connection(connection) {
- connection->onDataRead.connect(boost::bind(&ConnectionLayer::writeDataToParentLayer, this, _1));
- }
-
- ~ConnectionLayer() {
- connection->onDataRead.disconnect(boost::bind(&ConnectionLayer::writeDataToParentLayer, this, _1));
- }
+ ConnectionLayer(boost::shared_ptr<Connection> connection);
+ ~ConnectionLayer();
void writeData(const ByteArray& data) {
connection->write(data);
diff --git a/Swiften/StreamStack/SConscript b/Swiften/StreamStack/SConscript
index 022c695..06fcc03 100644
--- a/Swiften/StreamStack/SConscript
+++ b/Swiften/StreamStack/SConscript
@@ -6,6 +6,7 @@ sources = [
"HighLayer.cpp",
"LowLayer.cpp",
"StreamStack.cpp",
+ "ConnectionLayer.cpp",
"TLSLayer.cpp",
"WhitespacePingLayer.cpp",
"XMPPLayer.cpp",
diff --git a/Swiften/StreamStack/StreamStack.h b/Swiften/StreamStack/StreamStack.h
index 562245e..c9ebecd 100644
--- a/Swiften/StreamStack/StreamStack.h
+++ b/Swiften/StreamStack/StreamStack.h
@@ -11,7 +11,6 @@
#include <vector>
#include "Swiften/Elements/Stanza.h"
-#include "Swiften/Base/foreach.h"
namespace Swift {
class XMPPLayer;
@@ -30,8 +29,8 @@ namespace Swift {
}
template<typename T> T* getLayer() {
- foreach(StreamLayer* streamLayer, layers_) {
- T* layer = dynamic_cast<T*>(streamLayer);
+ for (size_t i = 0; i < layers_.size(); ++i) {
+ T* layer = dynamic_cast<T*>(layers_[i]);
if (layer) {
return layer;
}
diff --git a/Swiften/StringCodecs/SHA1.cpp b/Swiften/StringCodecs/SHA1.cpp
index 9882f70..2703796 100644
--- a/Swiften/StringCodecs/SHA1.cpp
+++ b/Swiften/StringCodecs/SHA1.cpp
@@ -4,10 +4,14 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
+#include <Swiften/StringCodecs/SHA1.h>
+
#include "Swiften/Base/Platform.h"
#pragma GCC diagnostic ignored "-Wold-style-cast"
+using namespace Swift;
+
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
@@ -25,21 +29,9 @@ A million repetitions of "a"
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
-#include <boost/cstdint.hpp>
#include <stdio.h>
#include <string.h>
-typedef struct {
- boost::uint32_t state[5];
- boost::uint32_t count[2];
- boost::uint8_t buffer[64];
-} SHA1_CTX;
-
-void SHA1Transform(boost::uint32_t state[5], boost::uint8_t buffer[64]);
-void SHA1Init(SHA1_CTX* context);
-void SHA1Update(SHA1_CTX* context, boost::uint8_t* data, unsigned int len);
-void SHA1Final(boost::uint8_t digest[20], SHA1_CTX* context);
-
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
@@ -63,7 +55,7 @@ void SHA1Final(boost::uint8_t digest[20], SHA1_CTX* context);
/* Hash a single 512-bit block. This is the core of the algorithm. */
-void SHA1Transform(boost::uint32_t state[5], boost::uint8_t buffer[64])
+void SHA1::Transform(boost::uint32_t state[5], boost::uint8_t buffer[64])
{
boost::uint32_t a, b, c, d, e;
typedef union {
@@ -118,7 +110,7 @@ static boost::uint8_t workspace[64];
/* SHA1Init - Initialize new context */
-void SHA1Init(SHA1_CTX* context)
+void SHA1::Init(SHA1::CTX* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
@@ -132,7 +124,7 @@ void SHA1Init(SHA1_CTX* context)
/* Run your data through this. */
-void SHA1Update(SHA1_CTX* context, boost::uint8_t* data, unsigned int len)
+void SHA1::Update(SHA1::CTX* context, boost::uint8_t* data, unsigned int len)
{
unsigned int i, j;
@@ -141,9 +133,9 @@ unsigned int i, j;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
+ Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
- SHA1Transform(context->state, &data[i]);
+ Transform(context->state, &data[i]);
}
j = 0;
}
@@ -154,7 +146,7 @@ unsigned int i, j;
/* Add padding and return the message digest. */
-void SHA1Final(boost::uint8_t digest[20], SHA1_CTX* context)
+void SHA1::Final(boost::uint8_t digest[20], SHA1::CTX* context)
{
boost::uint32_t i, j;
boost::uint8_t finalcount[8];
@@ -163,11 +155,11 @@ boost::uint8_t finalcount[8];
finalcount[i] = (boost::uint8_t) ((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
- SHA1Update(context, (boost::uint8_t *)("\200"), 1);
+ Update(context, (boost::uint8_t *)("\200"), 1);
while ((context->count[0] & 504) != 448) {
- SHA1Update(context, (boost::uint8_t *)("\0"), 1);
+ Update(context, (boost::uint8_t *)("\0"), 1);
}
- SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++) {
digest[i] = (boost::uint8_t)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
@@ -179,24 +171,43 @@ boost::uint8_t finalcount[8];
memset(context->count, 0, 8);
memset(&finalcount, 0, 8);
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
- SHA1Transform(context->state, context->buffer);
+ Transform(context->state, context->buffer);
#endif
}
// -----------------------------------------------------------------------------
-#include "Swiften/StringCodecs/SHA1.h"
-
namespace Swift {
+SHA1::SHA1() {
+ Init(&context);
+}
+
+SHA1& SHA1::update(const std::vector<unsigned char>& input) {
+ std::vector<unsigned char> inputCopy(input);
+ Update(&context, (boost::uint8_t*) ByteArray::data(inputCopy), inputCopy.size());
+ return *this;
+}
+
+std::vector<unsigned char> SHA1::getHash() const {
+ std::vector<unsigned char> digest;
+ digest.resize(20);
+ CTX contextCopy(context);
+ Final((boost::uint8_t*) ByteArray::data(digest), &contextCopy);
+ return digest;
+}
+
ByteArray SHA1::getHash(const ByteArray& input) {
- ByteArray inputCopy(input);
+ CTX context;
+ Init(&context);
+
+ std::vector<unsigned char> inputCopy(input.getVector());
+ Update(&context, (boost::uint8_t*) ByteArray::data(inputCopy), inputCopy.size());
+
ByteArray digest;
digest.resize(20);
- SHA1_CTX context;
- SHA1Init(&context);
- SHA1Update(&context, (boost::uint8_t*) inputCopy.getData(), inputCopy.getSize());
- SHA1Final((boost::uint8_t*) digest.getData(), &context);
+ Final((boost::uint8_t*) digest.getData(), &context);
+
return digest;
}
diff --git a/Swiften/StringCodecs/SHA1.h b/Swiften/StringCodecs/SHA1.h
index fc5ba0e..9c0232a 100644
--- a/Swiften/StringCodecs/SHA1.h
+++ b/Swiften/StringCodecs/SHA1.h
@@ -6,11 +6,38 @@
#pragma once
+#include <vector>
+#include <boost/cstdint.hpp>
+
#include "Swiften/Base/ByteArray.h"
namespace Swift {
class SHA1 {
public:
+ SHA1();
+
+ SHA1& update(const std::vector<unsigned char>& data);
+ std::vector<unsigned char> getHash() const;
+
+ /**
+ * Equivalent of:
+ * SHA1().update(data),getHash(), but slightly more efficient and
+ * convenient.
+ */
static ByteArray getHash(const ByteArray& data);
+
+ private:
+ typedef struct {
+ boost::uint32_t state[5];
+ boost::uint32_t count[2];
+ boost::uint8_t buffer[64];
+ } CTX;
+ static void Init(CTX* context);
+ static void Transform(boost::uint32_t state[5], boost::uint8_t buffer[64]);
+ static void Update(CTX* context, boost::uint8_t* data, unsigned int len);
+ static void Final(boost::uint8_t digest[20], CTX* context);
+
+ private:
+ CTX context;
};
}
diff --git a/Swiften/StringCodecs/UnitTest/SHA1Test.cpp b/Swiften/StringCodecs/UnitTest/SHA1Test.cpp
index 9434235..984f512 100644
--- a/Swiften/StringCodecs/UnitTest/SHA1Test.cpp
+++ b/Swiften/StringCodecs/UnitTest/SHA1Test.cpp
@@ -16,18 +16,65 @@ using namespace Swift;
class SHA1Test : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(SHA1Test);
CPPUNIT_TEST(testGetHash);
- CPPUNIT_TEST(testGetHash_Twice);
+ CPPUNIT_TEST(testGetHash_TwoUpdates);
+ CPPUNIT_TEST(testGetHash_TwoGetHash);
CPPUNIT_TEST(testGetHash_NoData);
+ CPPUNIT_TEST(testGetHash_InterleavedUpdate);
+ CPPUNIT_TEST(testGetHashStatic);
+ CPPUNIT_TEST(testGetHashStatic_Twice);
+ CPPUNIT_TEST(testGetHashStatic_NoData);
CPPUNIT_TEST_SUITE_END();
public:
void testGetHash() {
+ SHA1 sha;
+ sha.update(ByteArray::create("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray::create("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
+ }
+
+ void testGetHash_TwoUpdates() {
+ SHA1 sha;
+ sha.update(ByteArray::create("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<"));
+ sha.update(ByteArray::create("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray::create("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
+ }
+
+ void testGetHash_TwoGetHash() {
+ SHA1 sha;
+ sha.update(ByteArray::create("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+
+ sha.getHash();
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray::create("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
+ }
+
+ void testGetHash_InterleavedUpdate() {
+ SHA1 sha;
+
+ sha.update(ByteArray::create("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<"));
+ sha.getHash();
+ sha.update(ByteArray::create("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray::create("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
+ }
+
+
+ void testGetHash_NoData() {
+ SHA1 sha;
+ sha.update(std::vector<unsigned char>());
+
+ CPPUNIT_ASSERT_EQUAL(ByteArray::create("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), sha.getHash());
+ }
+
+ void testGetHashStatic() {
ByteArray result(SHA1::getHash("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
CPPUNIT_ASSERT_EQUAL(ByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
}
- void testGetHash_Twice() {
+ void testGetHashStatic_Twice() {
ByteArray input("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<");
SHA1::getHash(input);
ByteArray result(SHA1::getHash(input));
@@ -35,7 +82,7 @@ class SHA1Test : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(ByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
}
- void testGetHash_NoData() {
+ void testGetHashStatic_NoData() {
ByteArray result(SHA1::getHash(ByteArray()));
CPPUNIT_ASSERT_EQUAL(ByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), result);
diff --git a/Swiften/VCards/SConscript b/Swiften/VCards/SConscript
index e980ba3..c20c17d 100644
--- a/Swiften/VCards/SConscript
+++ b/Swiften/VCards/SConscript
@@ -3,6 +3,5 @@ Import("swiften_env")
objects = swiften_env.SwiftenObject([
"VCardManager.cpp",
"VCardStorage.cpp",
- "VCardFileStorage.cpp",
])
swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/VCards/VCardFileStorage.cpp b/Swiften/VCards/VCardFileStorage.cpp
deleted file mode 100644
index a246838..0000000
--- a/Swiften/VCards/VCardFileStorage.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include "Swiften/VCards/VCardFileStorage.h"
-
-#include <boost/filesystem/fstream.hpp>
-
-#include <Swiften/Base/String.h>
-#include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/StringCodecs/SHA1.h>
-#include <Swiften/Base/foreach.h>
-#include "Swiften/JID/JID.h"
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/Elements/VCard.h"
-#include "Swiften/Serializer/PayloadSerializers/VCardSerializer.h"
-#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h"
-#include "Swiften/Parser/PayloadParsers/VCardParser.h"
-
-namespace Swift {
-
-VCardFileStorage::VCardFileStorage(boost::filesystem::path dir) : vcardsPath(dir) {
- cacheFile = vcardsPath / "phashes";
- if (boost::filesystem::exists(cacheFile)) {
- try {
- boost::filesystem::ifstream file(cacheFile);
- std::string line;
- if (file.is_open()) {
- while (!file.eof()) {
- getline(file, line);
- std::pair<std::string, std::string> r = String::getSplittedAtFirst(line, ' ');
- JID jid(r.second);
- if (jid.isValid()) {
- photoHashes.insert(std::make_pair(jid, r.first));
- }
- else if (!r.first.empty() || !r.second.empty()) {
- std::cerr << "Invalid entry in phashes file" << std::endl;
- }
- }
- }
- }
- catch (...) {
- std::cerr << "Error reading phashes file" << std::endl;
- }
- }
-}
-
-boost::shared_ptr<VCard> VCardFileStorage::getVCard(const JID& jid) const {
- boost::filesystem::path vcardPath(getVCardPath(jid));
- if (boost::filesystem::exists(vcardPath)) {
- ByteArray data;
- data.readFromFile(vcardPath.string());
-
- VCardParser parser;
- PayloadParserTester tester(&parser);
- tester.parse(data.toString());
- return boost::dynamic_pointer_cast<VCard>(parser.getPayload());
- }
- else {
- return boost::shared_ptr<VCard>();
- }
-}
-
-void VCardFileStorage::setVCard(const JID& jid, VCard::ref v) {
- boost::filesystem::path vcardPath(getVCardPath(jid));
- if (!boost::filesystem::exists(vcardPath.parent_path())) {
- try {
- boost::filesystem::create_directories(vcardPath.parent_path());
- }
- catch (const boost::filesystem::filesystem_error& e) {
- std::cerr << "ERROR: " << e.what() << std::endl;
- }
- }
- boost::filesystem::ofstream file(getVCardPath(jid));
- file << VCardSerializer().serializePayload(v);
- file.close();
- getAndUpdatePhotoHash(jid, v);
-}
-
-boost::filesystem::path VCardFileStorage::getVCardPath(const JID& jid) const {
- std::string file(jid.toString());
- String::replaceAll(file, '/', "%2f");
- return boost::filesystem::path(vcardsPath / (file + ".xml"));
-}
-
-std::string VCardFileStorage::getPhotoHash(const JID& jid) const {
- PhotoHashMap::const_iterator i = photoHashes.find(jid);
- if (i != photoHashes.end()) {
- return i->second;
- }
- else {
- VCard::ref vCard = getVCard(jid);
- return getAndUpdatePhotoHash(jid, vCard);
- }
-}
-
-std::string VCardFileStorage::getAndUpdatePhotoHash(const JID& jid, VCard::ref vCard) const {
- std::string hash;
- if (vCard && !vCard->getPhoto().isEmpty()) {
- hash = Hexify::hexify(SHA1::getHash(vCard->getPhoto()));
- }
- std::pair<PhotoHashMap::iterator, bool> r = photoHashes.insert(std::make_pair(jid, hash));
- if (r.second) {
- savePhotoHashes();
- }
- else if (r.first->second != hash) {
- r.first->second = hash;
- savePhotoHashes();
- }
- return hash;
-}
-
-void VCardFileStorage::savePhotoHashes() const {
- try {
- boost::filesystem::ofstream file(cacheFile);
- for (PhotoHashMap::const_iterator i = photoHashes.begin(); i != photoHashes.end(); ++i) {
- file << i->second << " " << i->first.toString() << std::endl;
- }
- file.close();
- }
- catch (...) {
- std::cerr << "Error writing vcards file" << std::endl;
- }
-}
-
-
-}
diff --git a/Swiften/VCards/VCardFileStorage.h b/Swiften/VCards/VCardFileStorage.h
deleted file mode 100644
index 26bf4b2..0000000
--- a/Swiften/VCards/VCardFileStorage.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-#include <boost/filesystem.hpp>
-#include <string>
-#include <map>
-
-#include "Swiften/VCards/VCardStorage.h"
-
-namespace Swift {
- class VCardFileStorage : public VCardStorage {
- public:
- VCardFileStorage(boost::filesystem::path dir);
-
- virtual VCard::ref getVCard(const JID& jid) const;
- virtual void setVCard(const JID& jid, VCard::ref v);
-
- virtual std::string getPhotoHash(const JID&) const;
-
- private:
- boost::filesystem::path getVCardPath(const JID&) const;
-
- std::string getAndUpdatePhotoHash(const JID& jid, VCard::ref vcard) const;
- void savePhotoHashes() const;
-
- private:
- boost::filesystem::path vcardsPath;
- boost::filesystem::path cacheFile;
- typedef std::map<JID, std::string> PhotoHashMap;
- mutable PhotoHashMap photoHashes;
- };
-}