Decentralized Instant Messaging Protocol (Objective-C)
Handshake Command Protocol
0. (C-S) handshake start
(S-C) handshake again with new session
(C-S) handshake restart with new session
(S-C) handshake success
#import < DIMCore/DIMCore.h>
NS_ASSUME_NONNULL_BEGIN
#define DKDCommand_Handshake @" handshake"
typedef NS_ENUM (UInt8, DKDHandshakeState) {
DKDHandshake_Init,
DKDHandshake_Start, // C -> S, without session key (or session expired)
DKDHandshake_Again, // S -> C, with new session key
DKDHandshake_Restart, // C -> S, with new session key
DKDHandshake_Success, // S -> C, handshake accepted
};
#ifdef __cplusplus
extern " C" {
#endif
DKDHandshakeState DKDHandshakeCheckState (NSString *title, NSString *_Nullable session);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
/* *
* Handshake command: {
*
* "type" : i2s(0x88),
* "sn" : 123,
*
* "command" : "handshake", // command name
* "title" : "Hello world!", // "DIM?", "DIM!"
* "session" : "{SESSION_KEY}" // session key
* }
*/
@protocol DKDHandshakeCommand <DKDCommand>
@property (readonly , strong , nonatomic ) NSString *title;
@property (readonly , strong , nonatomic , nullable ) NSString *sessionKey;
@property (readonly , nonatomic ) DKDHandshakeState state;
@end
@interface DIMHandshakeCommand : DIMCommand <DKDHandshakeCommand>
- (instancetype )initWithTitle : (NSString *)title
sessionKey : (nullable NSString *)session ;
- (instancetype )initWithSessionKey : (nullable NSString *)session ;
@end
NS_ASSUME_NONNULL_END
#import " DIMHandshakeCommand.h"
DKDHandshakeState DKDHandshakeCheckState (NSString *title, NSString *_Nullable session) {
if ([title isEqualToString: @" DIM!" ]/* || [title isEqualToString:@"OK!"]*/ ) {
return DKDHandshake_Success;
} else if ([title isEqualToString: @" DIM?" ]) {
return DKDHandshake_Again;
} else if ([session length ] == 0 ) {
return DKDHandshake_Start;
} else {
return DKDHandshake_Restart;
}
}
@interface DIMHandshakeCommand ()
@property (strong , nonatomic ) NSString *title;
@property (strong , nonatomic , nullable ) NSString *sessionKey;
@property (nonatomic ) DKDHandshakeState state;
@end
@implementation DIMHandshakeCommand
/* designated initializer */
- (instancetype )initWithDictionary : (NSDictionary *)dict {
if (self = [super initWithDictionary: dict]) {
// lazy
_title = nil ;
_sessionKey = nil ;
_state = DKDHandshake_Init;
}
return self;
}
/* designated initializer */
- (instancetype )initWithType : (NSString *)type {
if (self = [super initWithType: type]) {
_title = nil ;
_sessionKey = nil ;
_state = DKDHandshake_Init;
}
return self;
}
- (instancetype )initWithTitle : (NSString *)title
sessionKey : (nullable NSString *)session {
if (self = [self initWithCmd: DKDCommand_Handshake]) {
// title
if (title) {
[self setObject: title forKey: @" title" ];
}
_title = title;
// session key
if (session) {
[self setObject: session forKey: @" session" ];
}
_sessionKey = session;
_state = DKDHandshake_Init;
}
return self;
}
- (instancetype )initWithSessionKey : (nullable NSString *)session {
return [self initWithTitle: @" Hello world!" sessionKey: session];
}
- (id )copyWithZone : (nullable NSZone *)zone {
DIMHandshakeCommand *content = [super copyWithZone: zone];
if (content) {
content.title = _title;
content.sessionKey = _sessionKey;
content.state = _state;
}
return content;
}
// Override
- (NSString *)title {
if (!_title) {
_title = [self objectForKey: @" title" ];
}
return _title;
}
// Override
- (nullable NSString *)sessionKey {
if (!_sessionKey) {
_sessionKey = [self objectForKey: @" session" ];
}
return _sessionKey;
}
// Override
- (DKDHandshakeState)state {
if (_state == DKDHandshake_Init) {
_state = DKDHandshakeCheckState (self.title , self.sessionKey );
}
return _state;
}
@end
#import < DIMCore/DIMCore.h>
NS_ASSUME_NONNULL_BEGIN
/* *
* Content for Application 0nly: {
*
* "type" : i2s(0xA0),
* "sn" : 123,
*
* "app" : "{APP_ID}", // application (e.g.: "chat.dim.sechat")
* "extra" : info // others
* }
*/
@interface DIMApplicationContent : DIMContent <DKDAppContent>
- (instancetype )initWithApplication : (NSString *)app ;
@end
NS_ASSUME_NONNULL_END
#import " DIMApplicationContent.h"
@implementation DIMApplicationContent
- (instancetype )initWithApplication : (NSString *)app {
if (self = [self initWithType: DKDContentType_Application]) {
[self setObject: app forKey: @" app" ];
}
return self;
}
// Override
- (NSString *)application {
return [self stringForKey: @" app" defaultValue: @" " ];
}
@end
Copyright © 2018-2026 Albert Moky