Index: src/MTXClient.h ================================================================== --- src/MTXClient.h +++ src/MTXClient.h @@ -140,10 +140,18 @@ accessToken: (OFString *)accessToken homeserver: (OFURL *)homeserver storage: (id )storage OF_DESIGNATED_INITIALIZER; +/** + * @brief Performs a sync. + * + * @param block A block to call when a sync was performed + */ +- (void)syncWithTimeout: (of_time_interval_t)timeout + block: (mtx_client_response_block_t)block; + /** * @brief Logs out the device and invalidates the access token. * * @warning The client can no longer be used after this succeeded! * Index: src/MTXClient.m ================================================================== --- src/MTXClient.m +++ src/MTXClient.m @@ -27,10 +27,11 @@ #import "MTXJoinRoomFailedException.h" #import "MTXLeaveRoomFailedException.h" #import "MTXLoginFailedException.h" #import "MTXLogoutFailedException.h" #import "MTXSendMessageFailedException.h" +#import "MTXSyncFailedException.h" static void validateHomeserver(OFURL *homeserver) { if (![homeserver.scheme isEqual: @"http"] && @@ -192,10 +193,39 @@ { return [MTXRequest requestWithPath: path accessToken: _accessToken homeserver: _homeserver]; } + +- (void)syncWithTimeout: (of_time_interval_t)timeout + block: (mtx_client_response_block_t)block +{ + void *pool = objc_autoreleasePoolPush(); + MTXRequest *request = [self + requestWithPath: @"/_matrix/client/r0/sync"]; + unsigned long long timeoutMs = timeout * 1000; + request.query = [OFString stringWithFormat: @"timeout=%llu", timeoutMs]; + [request performWithBlock: ^ (mtx_response_t response, int statusCode, + id exception) { + if (exception != nil) { + block(exception); + return; + } + + if (statusCode != 200) { + block([MTXSyncFailedException + exceptionWithStatusCode: statusCode + response: response + client: self]); + return; + } + + block(nil); + }]; + + objc_autoreleasePoolPop(pool); +} - (void)logOutWithBlock: (mtx_client_response_block_t)block { void *pool = objc_autoreleasePoolPush(); MTXRequest *request = Index: src/MTXRequest.h ================================================================== --- src/MTXRequest.h +++ src/MTXRequest.h @@ -68,10 +68,15 @@ /** * @brief The path of the request. */ @property (copy, nonatomic) OFString *path; +/** + * @brief The query for the request. + */ +@property (copy, nullable, nonatomic) OFString *query; + /** * @brief An optional body to send along with the request. * * This is a dictionary that gets serialized to JSON when the request is sent. */ Index: src/MTXRequest.m ================================================================== --- src/MTXRequest.m +++ src/MTXRequest.m @@ -95,10 +95,11 @@ /* Not the best exception to indicate it's already in-flight. */ @throw [OFAlreadyConnectedException exception]; OFMutableURL *requestURL = [[_homeserver mutableCopy] autorelease]; requestURL.path = _path; + requestURL.query = _query; OFMutableDictionary *headers = [OFMutableDictionary dictionary]; headers[@"User-Agent"] = @"ObjMatrix"; if (_accessToken != nil) headers[@"Authorization"] = Index: src/ObjMatrix.h ================================================================== --- src/ObjMatrix.h +++ src/ObjMatrix.h @@ -23,10 +23,13 @@ #import "MTXClient.h" #import "MTXRequest.h" #import "MTXSQLite3Storage.h" #import "MTXStorage.h" +#import "MTXClientException.h" #import "MTXFetchRoomListFailedException.h" #import "MTXJoinRoomFailedException.h" #import "MTXLeaveRoomFailedException.h" #import "MTXLoginFailedException.h" #import "MTXLogoutFailedException.h" +#import "MTXSendMessageFailedException.h" +#import "MTXSyncFailedException.h" Index: src/exceptions/MTXFetchRoomListFailedException.m ================================================================== --- src/exceptions/MTXFetchRoomListFailedException.m +++ src/exceptions/MTXFetchRoomListFailedException.m @@ -26,9 +26,9 @@ @implementation MTXFetchRoomListFailedException - (OFString *)description { return [OFString stringWithFormat: - @"Failed to fetch room list for %@: %@", - self.client.userID, self.response]; + @"Failed to fetch room list for %@ with status code %d: %@", + self.client.userID, self.statusCode, self.response]; } @end Index: src/exceptions/MTXJoinRoomFailedException.m ================================================================== --- src/exceptions/MTXJoinRoomFailedException.m +++ src/exceptions/MTXJoinRoomFailedException.m @@ -63,9 +63,9 @@ } - (OFString *)description { return [OFString stringWithFormat: - @"Failed to join room %@ for %@: %@", - _room, self.client.userID, self.response]; + @"Failed to join room %@ for %@ with status code %d: %@", + _room, self.client.userID, self.statusCode, self.response]; } @end Index: src/exceptions/MTXLeaveRoomFailedException.m ================================================================== --- src/exceptions/MTXLeaveRoomFailedException.m +++ src/exceptions/MTXLeaveRoomFailedException.m @@ -63,9 +63,9 @@ } - (OFString *)description { return [OFString stringWithFormat: - @"Failed to leave room %@ for %@: %@", - _roomID, self.client.userID, self.response]; + @"Failed to leave room %@ for %@ with status code %d: %@", + _roomID, self.client.userID, self.statusCode, self.response]; } @end Index: src/exceptions/MTXLoginFailedException.m ================================================================== --- src/exceptions/MTXLoginFailedException.m +++ src/exceptions/MTXLoginFailedException.m @@ -64,9 +64,9 @@ } - (OFString *)description { return [OFString stringWithFormat: - @"Failed to log in user %@ on %@: %@", - _user, _homeserver, _response]; + @"Failed to log in user %@ on %@ with status code %d: %@", + _user, _homeserver, _statusCode, _response]; } @end Index: src/exceptions/MTXLogoutFailedException.m ================================================================== --- src/exceptions/MTXLogoutFailedException.m +++ src/exceptions/MTXLogoutFailedException.m @@ -26,9 +26,9 @@ @implementation MTXLogoutFailedException - (OFString *)description { return [OFString stringWithFormat: - @"Failed to log out user %@: %@", - self.client.userID, self.response]; + @"Failed to log out user %@ with status code: %@", + self.client.userID, self.statusCode, self.response]; } @end Index: src/exceptions/MTXSendMessageFailedException.m ================================================================== --- src/exceptions/MTXSendMessageFailedException.m +++ src/exceptions/MTXSendMessageFailedException.m @@ -68,9 +68,9 @@ } - (OFString *)description { return [OFString stringWithFormat: - @"Failed to send message to room %@ for %@: %@", - _roomID, self.client.userID, self.response]; + @"Failed to send message to room %@ for %@ with status code %d: %@", + _roomID, self.client.userID, self.statusCode, self.response]; } @end ADDED src/exceptions/MTXSyncFailedException.h Index: src/exceptions/MTXSyncFailedException.h ================================================================== --- /dev/null +++ src/exceptions/MTXSyncFailedException.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020, Jonathan Schleifer + * + * https://fossil.nil.im/objmatrix + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +#import "MTXClientException.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface MTXSyncFailedException: MTXClientException +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/MTXSyncFailedException.m Index: src/exceptions/MTXSyncFailedException.m ================================================================== --- /dev/null +++ src/exceptions/MTXSyncFailedException.m @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Jonathan Schleifer + * + * https://fossil.nil.im/objmatrix + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "MTXSyncFailedException.h" + +#import "MTXClient.h" + +@implementation MTXSyncFailedException +- (OFString *)description +{ + return [OFString stringWithFormat: + @"Failed to sync for user %@ with status code %d: %@", + self.client.userID, self.statusCode, self.response]; +} +@end Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -7,11 +7,12 @@ MTXFetchRoomListFailedException.m \ MTXJoinRoomFailedException.m \ MTXLeaveRoomFailedException.m \ MTXLoginFailedException.m \ MTXLogoutFailedException.m \ - MTXSendMessageFailedException.m + MTXSendMessageFailedException.m \ + MTXSyncFailedException.m INCLUDES = ${SRCS:.m=.h} include ../../buildsys.mk CPPFLAGS += -I. -I.. Index: tests/tests.m ================================================================== --- tests/tests.m +++ tests/tests.m @@ -60,10 +60,25 @@ } _client = [client retain]; of_log(@"Logged in client: %@", _client); + [self sync]; + }]; +} + +- (void)sync +{ + [_client syncWithTimeout: 5 + block: ^ (id exception) { + if (exception != nil) { + of_log(@"Failed to sync: %@", exception); + [OFApplication terminateWithStatus: 1]; + } + + of_log(@"Synced"); + [self fetchRoomList]; }]; } - (void)fetchRoomList