### Respond to Incoming Messages with Swift Client
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Examples.rst
This Swift client example demonstrates how to listen for incoming XMPP messages and automatically respond to them. It covers connection, authentication, session establishment, and message handling.
```swift
import TigaseClient
let client = Client(host: "your.xmpp.host", port: 5222)
client.connect()
client.authenticate(username: "user@domain.com", password: "password")
client.establishSession()
// Handle incoming messages and respond
client.onMessageReceived = {
message in
print("Received message from \(message.from.bareJid): \(message.body)")
let reply = Message(to: message.from, body: "I received your message.")
client.sendMessage(message: reply)
}
// Keep the client running to receive messages
RunLoop.main.run()
```
--------------------------------
### Send XMPP Message with Swift Client
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Examples.rst
This Swift client example demonstrates how to send an XMPP message to a specified recipient. It connects to the server, authenticates, establishes a session, and then sends the message.
```swift
import TigaseClient
let client = Client(host: "your.xmpp.host", port: 5222)
client.connect()
client.authenticate(username: "sender@domain.com", password: "Pa$$w0rd")
client.establishSession()
let message = Message(to: "recipient@domain.com", body: "Hello from Tigase Martin!")
client.sendMessage(message: message)
client.disconnect()
```
--------------------------------
### Utilize PubSub with Swift Client
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Examples.rst
This Swift example illustrates how to leverage the Tigase Martin client for Publish-Subscribe (PubSub) operations. It covers creating a PubSub node, publishing items, receiving notifications, retrieving items, and deleting a PubSub node.
```swift
import TigaseClient
let client = Client(host: "your.xmpp.host", port: 5222)
client.connect()
client.authenticate(username: "user@domain.com", password: "password")
client.establishSession()
let pubSubService = "pubsub.your.xmpp.host"
let nodeName = "my_test_node"
// Create a PubSub node
client.createPubSubNode(serviceJid: pubSubService, node: nodeName)
// Publish an item
client.publishPubSubItem(serviceJid: pubSubService, node: nodeName, itemId: "1", payload: "Some payload")
// Receive notifications
client.onPubSubNotification = {
notification in
print("Received PubSub notification for node: \(notification.node)")
}
// Retrieve items
client.retrievePubSubItems(serviceJid: pubSubService, node: nodeName)
// Delete a PubSub node
client.deletePubSubNode(serviceJid: pubSubService, node: nodeName)
// Keep the client running
RunLoop.main.run()
```
--------------------------------
### Initiate XMPP Client Login
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Starts the XMPP client's login process, which includes DNS resolution, establishing a TCP connection, and setting up the XMPP stream. This method should be called after all necessary configurations are complete.
```swift
client.login();
```
--------------------------------
### Manage Presence and Handle Incoming Presences with Swift Client
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Examples.rst
This Swift example shows how to connect to an XMPP server, set your client's presence to 'Do not disturb' with a status message, and handle incoming presence updates from contacts. This functionality requires a non-empty roster and at least one available contact.
```swift
import TigaseClient
let client = Client(host: "your.xmpp.host", port: 5222)
client.connect()
client.authenticate(username: "user@domain.com", password: "password")
client.establishSession()
// Set presence to 'Do not disturb'
client.setPresence(type: .unavailable, show: .away, status: "Do not disturb me!")
// Handle incoming presences
client.onPresenceReceived = {
presence in
print("Received presence from: \(presence.from.bareJid)")
}
// Keep the client running to receive presence updates
RunLoop.main.run()
```
--------------------------------
### Interact with MUC using Swift Client
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Examples.rst
This Swift example demonstrates how to use the Tigase Martin client to interact with Multi-User Chat (MUC) rooms. It covers joining a room, sending messages to the room, and handling information about room occupants.
```swift
import TigaseClient
let client = Client(host: "your.xmpp.host", port: 5222)
client.connect()
client.authenticate(username: "user@domain.com", password: "password")
client.establishSession()
// Join a MUC room
let mucRoom = "roomname@conference.your.xmpp.host"
client.joinMucRoom(roomJid: mucRoom, nick: "MyNick")
// Send a message to the MUC room
client.sendMucMessage(roomJid: mucRoom, body: "Hello room!")
// Handle occupant information (example)
client.onMucOccupantPresence = {
presence in
print("\(presence.from.resource) is in \(presence.from.bareJid)")
}
// Keep the client running
RunLoop.main.run()
```
--------------------------------
### DiscoveryModule: Discover XMPP Server Features and Items (Swift)
Source: https://context7.com/tigase/martin/llms.txt
This snippet illustrates the usage of the DiscoveryModule for XMPP Service Discovery (XEP-0030). It shows how to discover server features, identities, items, and query specific component information. It also includes an example of monitoring server feature updates using Combine. The Martin library is a key dependency.
```swift
import Martin
import Combine
let client = XMPPClient()
let identity = DiscoveryModule.Identity(
category: "client",
type: "mobile",
name: "MyApp v1.0"
)
let discoModule = DiscoveryModule(identity: identity)
client.modulesManager.register(discoModule)
// Discover server features
discoModule.discoverServerFeatures { result in
switch result {
case .success(let info):
print("✓ Server features:")
for feature in info.features {
print(" - (feature)")
}
print("\nServer identities:")
for identity in info.identities {
print(" - (identity.category)/(identity.type): (identity.name ?? "")")
}
case .failure(let error):
print("✗ Discovery failed: (error)")
}
}
// Discover items on server
let serverJid = JID("example.com")
discoModule.getItems(for: serverJid) { result in
switch result {
case .success(let items):
print("Available services:")
for item in items.items {
print(" \(item.jid): (item.name ?? "")")
}
case .failure(let error):
print("Error: (error)")
}
}
// Query specific component info
let componentJid = JID("conference.example.com")
discoModule.getInfo(for: componentJid, node: nil) { result in
switch result {
case .success(let info):
if info.features.contains("http://jabber.org/protocol/muc") {
print("✓ Component supports multi-user chat")
}
case .failure(let error):
print("Query failed: (error)")
}
}
// Monitor server features using Combine
var cancellables = Set()
discoModule.$serverDiscoResult.sink { discoResult in
print("Server features updated: (discoResult.features.count) features available")
}.store(in: &cancellables)
```
--------------------------------
### Instant Messaging with Combine Publishers in Swift
Source: https://context7.com/tigase/martin/llms.txt
Demonstrates sending and receiving one-to-one chat messages using the MessageModule. It leverages Combine publishers for real-time message reception and includes examples for sending new messages and replies. Requires the Martin and Combine frameworks.
```swift
import Martin
import Combine
let client = XMPPClient()
let chatManager = DefaultChatManager()
let messageModule = MessageModule(chatManager: chatManager)
client.modulesManager.register(messageModule)
// Subscribe to incoming messages using Combine
var cancellables = Set()
messageModule.messagesPublisher.sink { messageReceived in
let message = messageReceived.message
let chat = messageReceived.chat
print("From: (message.from?.stringValue ?? "unknown")")
print("Body: (message.body ?? "")")
print("Chat ID: (chat.id)")
// Send reply
let reply = chat.createMessage(text: "Got your message!")
reply.id = UUID().uuidString
client.context.writer.write(reply)
}.store(in: &cancellables)
// Send a new message
let recipientJid = BareJID("bob@example.com")
if let chat = chatManager.chat(for: client.context, with: recipientJid) ??
chatManager.createChat(for: client.context, with: recipientJid) {
let message = chat.createMessage(text: "Hello, Bob!")
message.id = UUID().uuidString
message.type = .chat
client.context.writer.write(message)
}
```
--------------------------------
### Swift: Create and Use JIDs and BareJIDs for XMPP Addresses
Source: https://context7.com/tigase/martin/llms.txt
Demonstrates creating BareJID (user@domain) and full JID (user@domain/resource) instances in Swift. It covers accessing components like localpart, domain, and resource, performing comparisons, using them in collections (Set, Dictionary), and their Codable support for persistence.
```swift
import Martin
// Create BareJID (user@domain)
let bareJid1 = BareJID("alice@example.com")
let bareJid2 = BareJID(localPart: "bob", domain: "example.com")
print(bareJid1.stringValue) // "alice@example.com"
print(bareJid1.localPart) // Optional("alice")
print(bareJid1.domain) // "example.com"
// Create full JID (user@domain/resource)
let fullJid1 = JID("alice@example.com/mobile")
let fullJid2 = JID(bareJid1, resource: "desktop")
let fullJid3 = JID(BareJID("charlie@example.com"))
print(fullJid1.stringValue) // "alice@example.com/mobile"
print(fullJid1.resource) // Optional("mobile")
print(fullJid1.bareJid.stringValue) // "alice@example.com"
print(fullJid1.withoutResource) // JID without resource part
// JID comparison and hashing
let jid1 = JID("user@example.com/resource1")
let jid2 = JID("user@example.com/resource2")
if jid1.bareJid == jid2.bareJid {
print("Same user, different resources")
}
// Use in collections
var contactSet: Set = []
contactSet.insert(BareJID("alice@example.com"))
contactSet.insert(BareJID("bob@example.com"))
var resourceMap: [JID: String] = [:]
resourceMap[JID("alice@example.com/mobile")] = "Mobile device"
resourceMap[JID("alice@example.com/desktop")] = "Desktop client"
// Codable support for persistence
struct UserAccount: Codable {
let jid: BareJID
let nickname: String
}
let account = UserAccount(jid: BareJID("alice@example.com"), nickname: "Alice")
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(account) {
// Save to disk or send over network
print(String(data: jsonData, encoding: .utf8) ?? "")
}
```
--------------------------------
### Manage XMPP Client Connection and Events in Swift
Source: https://context7.com/tigase/martin/llms.txt
This Swift code demonstrates how to set up and manage an XMPP client connection using the Martin library. It includes registering essential XMPP modules, configuring user credentials, setting up an event handler for session, message, and roster events, and initiating the connection. The code also shows how to gracefully disconnect.
```swift
import Martin
import TigaseLogging
// Create and configure XMPP client
let client = XMPPClient()
// Register required modules
client.modulesManager.register(StreamFeaturesModule())
client.modulesManager.register(SaslModule())
client.modulesManager.register(ResourceBinderModule())
client.modulesManager.register(SessionEstablishmentModule())
client.modulesManager.register(RosterModule(rosterManager: DefaultRosterManager()))
client.modulesManager.register(PresenceModule(store: DefaultPresenceStore()))
client.modulesManager.register(MessageModule(chatManager: DefaultChatManager()))
client.modulesManager.register(DiscoveryModule())
client.modulesManager.register(PingModule())
// Configure connection credentials
client.connectionConfiguration.userJid = BareJID("user@example.com")
client.connectionConfiguration.credentials = .password(password: "secretPassword123")
// Set up event handler
class MyEventHandler: EventHandler {
func handle(event: Event) {
switch event {
case let e as SessionEstablishmentModule.SessionEstablishmentSuccessEvent:
print("✓ Connected and authenticated successfully")
case let e as MessageModule.MessageReceivedEvent:
print("📩 Message from (e.message.from?.stringValue ?? "unknown"): (e.message.body ?? "")")
case let e as RosterModule.ItemUpdatedEvent:
print("👤 Roster updated: (e.rosterItem.jid)")
default:
break
}
}
}
let handler = MyEventHandler()
client.context.eventBus.register(handler, for:
SessionEstablishmentModule.SessionEstablishmentSuccessEvent.TYPE,
MessageModule.MessageReceivedEvent.TYPE,
RosterModule.ItemUpdatedEvent.TYPE
)
// Connect to server
client.login()
// Later, disconnect gracefully
_ = client.disconnect()
```
--------------------------------
### Connect XMPP Client using Swift Concurrency (async/await)
Source: https://context7.com/tigase/martin/llms.txt
This Swift code snippet illustrates connecting to an XMPP server using the Martin library with modern Swift concurrency (async/await). It demonstrates registering modules, setting credentials, and handling connection and disconnection within a Task, including robust error handling for connection issues.
```swift
import Martin
Task {
let client = XMPPClient()
// Register modules
client.modulesManager.register(StreamFeaturesModule())
client.modulesManager.register(SaslModule())
client.modulesManager.register(ResourceBinderModule())
client.modulesManager.register(SessionEstablishmentModule())
// Configure credentials
client.connectionConfiguration.userJid = BareJID("alice@xmpp.example.org")
client.connectionConfiguration.credentials = .password(password: "alicePassword")
do {
// Connect and wait for authentication
try await client.loginAndWait()
print("✓ Successfully connected")
// Do work...
try await Task.sleep(nanoseconds: 60_000_000_000) // 60 seconds
// Disconnect gracefully
try await client.disconnect()
print("✓ Disconnected cleanly")
} catch {
print("✗ Connection error: (error)")
}
}
```
--------------------------------
### Create XMPP Client Instance
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Initializes an instance of the XMPPClient class, which is the core implementation for an XMPP client in the TigaseSwift library. This is the first step to utilizing the library's functionalities.
```swift
var client = XMPPClient();
```
--------------------------------
### Swift XMPP Connection Testing (XEP-0199) with Martin
Source: https://context7.com/tigase/martin/llms.txt
Demonstrates using the PingModule in Swift to test XMPP connection liveness and measure round-trip times. It shows how to ping the server, ping a contact using async/await, and implement periodic keepalive pings to detect connectivity issues. Requires the Martin library.
```swift
import Martin
let client = XMPPClient()
let pingModule = PingModule()
client.modulesManager.register(pingModule)
// Ping the server
let serverJid = JID(client.connectionConfiguration.userJid.domain)
pingModule.ping(serverJid, timeout: 30.0) { result in
switch result {
case .success:
print("✓ Server is responding")
case .failure(let error):
print("✗ Ping failed: (error)")
}
}
// Ping another user using async/await
Task {
let contactJid = JID("bob@example.com")
do {
try await pingModule.ping(contactJid)
print("✓ Contact is online and responding")
} catch {
print("✗ Contact not responding: (error)")
}
}
// Implement periodic keepalive
Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { _ in
pingModule.ping(serverJid) { result in
if case .failure = result {
print("⚠️ Server connectivity issue detected")
}
}
}
```
--------------------------------
### Swift HTTP File Upload (XEP-0363) with Martin
Source: https://context7.com/tigase/martin/llms.txt
Demonstrates uploading files via HTTP using the HttpFileUploadModule in Swift. It registers the module, discovers an HTTP upload component, requests an upload slot, uploads the file data to the provided PUT URL, and shares the download link via an XMPP message. Dependencies include the Martin library and Foundation.
```swift
import Martin
import Foundation
let client = XMPPClient()
let uploadModule = HttpFileUploadModule()
client.modulesManager.register(uploadModule)
// Find HTTP upload component
uploadModule.findHttpUploadComponent { result in
switch result {
case .success(let components):
guard let component = components.first else {
print("No upload component available")
return
}
print("✓ Upload component: (component.jid)")
print(" Max file size: (component.maxSize) bytes")
// Request upload slot
let filename = "vacation-photo.jpg"
let fileSize = 2_485_760 // bytes
let contentType = "image/jpeg"
uploadModule.requestUploadSlot(
componentJid: component.jid,
filename: filename,
size: fileSize,
contentType: contentType
) { slotResult in
switch slotResult {
case .success(let slot):
print("✓ Upload slot received")
print(" PUT URL: (slot.putUri)")
print(" GET URL: (slot.getUri)")
// Upload file to PUT URL
guard let fileData = loadImageData(),
let putURL = URL(string: slot.putUri) else {
return
}
var request = URLRequest(url: putURL)
request.httpMethod = "PUT"
request.httpBody = fileData
// Add custom headers from slot
for (header, value) in slot.putHeaders {
request.setValue(value, forHTTPHeaderField: header)
}
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("✗ Upload failed: (error)")
return
}
if let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 201 {
print("✓ File uploaded successfully")
// Share download URL in chat
let recipientJid = BareJID("friend@example.com")
let message = Message()
message.to = JID(recipientJid)
message.type = .chat
message.body = slot.getUri
message.id = UUID().uuidString
client.context.writer.write(message)
}
}.resume()
case .failure(let error):
print("✗ Failed to get upload slot: (error)")
}
}
case .failure(let error):
print("✗ Component discovery failed: (error)")
}
}
func loadImageData() -> Data? {
// Load your file data here
return nil
}
```
--------------------------------
### MucModule: Join and Manage XMPP Chat Rooms (Swift)
Source: https://context7.com/tigase/martin/llms.txt
This snippet demonstrates how to use the MucModule to join, send messages to, and manage XMPP multi-user chat rooms. It covers room joining, message broadcasting, handling invitations, and retrieving room configuration. Dependencies include the Martin library and Combine for reactive programming.
```swift
import Martin
import Combine
let client = XMPPClient()
let roomManager = DefaultRoomManager()
let mucModule = MucModule(roomManager: roomManager)
client.modulesManager.register(mucModule)
// Join a chat room
let roomJid = BareJID("developers@conference.example.com")
let nickname = "Alice"
let password: String? = nil
mucModule.join(roomJid: roomJid, nickname: nickname, password: password) { result in
switch result {
case .success(let room):
print("✓ Joined room: (room.jid)")
print(" Room name: (room.name ?? "unnamed")")
print(" Your nickname: (room.nickname)")
// Send message to room
let groupMessage = room.createMessage(text: "Hello everyone!")
groupMessage.id = UUID().uuidString
client.context.writer.write(groupMessage)
case .failure(let error):
print("✗ Failed to join room: (error)")
}
}
// Subscribe to room messages
var cancellables = Set()
mucModule.messagesPublisher.sink { messageReceived in
let message = messageReceived.message
let room = messageReceived.room
print("Room: (room.jid)")
print("From: (message.from?.resource ?? "unknown")")
print("Message: (message.body ?? "")")
}.store(in: &cancellables)
// Handle room invitations
mucModule.inivitationsPublisher.sink { invitation in
print("📩 Invitation to room: (invitation.roomJid)")
print(" From: (invitation.inviter?.stringValue ?? "unknown")")
// Accept invitation
mucModule.join(
roomJid: invitation.roomJid,
nickname: "Alice",
password: invitation.password
) { _ in } // Ignore result for brevity
}.store(in: &cancellables)
// Get room configuration (owners only)
if let room = roomManager.room(for: client.context, with: roomJid) {
mucModule.getRoomConfiguration(roomJid: JID(room.jid)) { result in
switch result {
case .success(let config):
print("Room configuration loaded")
// Modify and save configuration
case .failure(let error):
print("Failed to get config: (error)")
}
}
// Leave room
mucModule.leave(room: room)
}
```
--------------------------------
### Contact List Management with RosterModule in Swift
Source: https://context7.com/tigase/martin/llms.txt
Provides functionality for managing a user's contact list using the RosterModule. This includes requesting the roster, adding, updating, and removing contacts, as well as subscribing to roster change events via Combine publishers. Requires the Martin framework.
```swift
import Martin
let client = XMPPClient()
let rosterManager = DefaultRosterManager()
let rosterModule = RosterModule(rosterManager: rosterManager)
client.modulesManager.register(rosterModule)
// Request roster from server
rosterModule.requestRoster { result in
switch result {
case .success:
print("✓ Roster loaded successfully")
// Access roster items
let items = rosterManager.items(for: client.context)
for item in items {
print("Contact: (item.jid) - (item.name ?? "no name")")
print(" Subscription: (item.subscription)")
print(" Groups: (item.groups)")
}
case .failure(let error):
print("✗ Failed to load roster: (error)")
}
}
// Add a new contact
let newContactJid = JID("charlie@example.com")
rosterModule.addItem(
jid: newContactJid,
name: "Charlie",
groups: ["Friends", "Work"]
) { result in
switch result {
case .success:
print("✓ Contact added successfully")
case .failure(let error):
print("✗ Failed to add contact: (error)")
}
}
// Update existing contact
rosterModule.updateItem(
jid: newContactJid,
name: "Charlie Smith",
groups: ["Friends"]
) { result in
switch result {
case .success:
print("✓ Contact updated")
case .failure(let error):
print("✗ Update failed: (error)")
}
}
// Remove contact
rosterModule.removeItem(jid: newContactJid) { result in
if case .success = result {
print("✓ Contact removed")
}
}
// Subscribe to roster changes using Combine
var cancellables = Set()
rosterModule.events.sink { action in
switch action {
case .addedOrUpdated(let item):
print("👤 Roster item added/updated: (item.jid)")
case .removed(let jid):
print("👤 Roster item removed: (jid)")
}
}.store(in: &cancellables)
```
--------------------------------
### Swift: Create, Parse, and Manipulate XMPP Stanzas
Source: https://context7.com/tigase/martin/llms.txt
Shows how to construct XMPP stanzas (Message, IQ) in Swift, including setting recipients, senders, types, and adding custom XML elements. It also covers parsing incoming stanzas to extract information like sender, recipient, ID, type, delay information, errors, and child elements.
```swift
import Martin
// Create custom message stanza
let message = Message()
message.to = JID("recipient@example.com")
message.from = JID("sender@example.com/mobile")
message.type = .chat
message.id = UUID().uuidString
message.body = "Hello, XMPP!"
// Add custom XML elements
let customElement = Element(name: "custom", xmlns: "http://example.com/custom")
customElement.setAttribute("attribute", value: "value")
customElement.addChild(Element(name: "data", cdata: "Some data"))
message.addChild(customElement)
// Parse received stanza
func handleIncomingStanza(_ stanza: Stanza) {
print("Stanza name: (stanza.name)")
print("From: (stanza.from?.stringValue ?? "none")")
print("To: (stanza.to?.stringValue ?? "none")")
print("ID: (stanza.id ?? "none")")
print("Type: (stanza.type?.rawValue ?? "none")")
// Check for delay
if let delay = stanza.delay {
print("Delayed delivery - timestamp: (delay.stamp)")
print("Reason: (delay.from?.stringValue ?? "unknown")")
}
// Parse error stanza
if let error = stanza.error {
print("Error condition: (error.errorCondition)")
print("Error text: (error.text ?? "no description")")
}
// Find child elements
if let customEl = stanza.findChild(name: "custom", xmlns: "http://example.com/custom") {
let attributeValue = customEl.getAttribute("attribute")
print("Custom attribute: (attributeValue ?? "not found")")
}
}
// Create IQ stanza for queries
let iq = Iq()
iq.type = .get
iq.to = JID("service.example.com")
iq.id = UUID().uuidString
let query = Element(name: "query", xmlns: "http://jabber.org/protocol/disco#info")
iq.addChild(query)
// Create result stanza
let result = iq.makeResult(type: .result)
result.type = .result
```
--------------------------------
### Send IQ Stanza and Wait for Response (AsyncCallback Protocol)
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Sends an IQ stanza and waits for a response using an implementation of the 'AsyncCallback' protocol. This allows for structured handling of asynchronous responses. Supports custom timeouts.
```swift
client.context.writer?.write(stanza, timeout: 45, callback: callback);
```
--------------------------------
### Configure User Credentials for Authentication
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Sets the user's JID (Jabber ID) and password within the client's connection configuration for authentication. This is required for most XMPP authentication mechanisms.
```swift
let userJID = BareJID("user@domain.com");
client.connectionConfiguration.setUserJID(userJID);
client.connectionConfiguration.setUserPassword("Pa$$w0rd");
```
--------------------------------
### Send IQ Stanza and Wait for Response (Multiple Callbacks)
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Sends an IQ stanza and waits for a specific response, handling success, error conditions, or timeouts via separate callbacks. Supports custom timeouts, with a default of 30 seconds.
```swift
client.context.writer?.write(stanza, timeout: 45, onSuccess: {(response) in
// response received with type equal `result`
}, onError: {(response, errorCondition) in
// received response with type equal `error`
}, onTimeout: {
// no response was received in specified time
});
```
--------------------------------
### Configure Anonymous Authentication
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Configures the client for anonymous authentication by setting only the server domain, without specifying a user JID or password. This allows connecting to servers that support anonymous login.
```swift
client.connectionConfiguration.setDomain(domain);
```
--------------------------------
### Send IQ Stanza and Wait for Response (Single Callback)
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Sends an IQ stanza and waits for any response (result, error, or timeout) using a single callback. Distinguishes between response types by checking the received stanza or nil for timeouts. Supports custom timeouts.
```swift
client.context.writer?.write(stanza, timeout: 45, callback: {(response) in
// will be called on `result`, `error` or in case of timeout
});
```
--------------------------------
### Send Custom XMPP Stanza Without Response
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Sends a custom XMPP stanza to the server without waiting for a reply. This is useful for fire-and-forget messages. Requires an active connection, as 'writer' can be nil.
```swift
client.context.writer?.write(stanza);
```
--------------------------------
### Register StreamFeaturesModule
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Registers the StreamFeaturesModule with the client's modules manager. This module is responsible for handling XMPP stream features, which is a fundamental part of the XMPP communication protocol.
```swift
client.modulesManager.register(StreamFeaturesModule());
```
--------------------------------
### Disconnect Tigase Swift XMPP Client
Source: https://github.com/tigase/martin/blob/master/Documentation/src/main/restructured/Basics.rst
Properly disconnects from the server, closing both XMPP and TCP connections. This is the standard method for ending a client session.
```swift
client.disconnect();
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.