Decentralized Instant Messaging Protocol (Dart)
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 'package:dimp/protocol.dart' ;
class HandshakeState {
static const int START = 0 ; // C -> S, without session key (or session expired)
static const int AGAIN = 1 ; // S -> C, with new session key
static const int RESTART = 2 ; // C -> S, with new session key
static const int SUCCESS = 3 ; // S -> C, handshake accepted
static int checkState (String title, String ? session) {
if (title == 'DIM!' /* || title == 'OK!'*/ ) {
return SUCCESS ;
} else if (title == 'DIM?' ) {
return AGAIN ;
} else if (session == null ) {
return START ;
} else {
return RESTART ;
}
}
}
/// Handshake command: {
/// "type" : i2s(0x88),
/// "sn" : 123,
///
/// "command" : "handshake", // command name
/// "title" : "Hello world!", // "DIM?", "DIM!"
/// "session" : "{SESSION_KEY}" // session key
/// }
abstract interface class HandshakeCommand implements Command {
static const String HANDSHAKE = 'handshake' ;
String get title;
String ? get sessionKey;
int get state;
static HandshakeCommand start () =>
BaseHandshakeCommand .from ('Hello world!' );
static HandshakeCommand restart (String session) =>
BaseHandshakeCommand .from ('Hello world!' , sessionKey: session);
static HandshakeCommand again (String session) =>
BaseHandshakeCommand .from ('DIM?' , sessionKey: session);
static HandshakeCommand success (String ? session) =>
BaseHandshakeCommand .from ('DIM!' , sessionKey: session);
}
class BaseHandshakeCommand extends BaseCommand implements HandshakeCommand {
BaseHandshakeCommand (super .dict);
BaseHandshakeCommand .from (String title, {String ? sessionKey})
: super .fromCmd (HandshakeCommand .HANDSHAKE ) {
// text message
this ['title' ] = title;
// session key
if (sessionKey != null ) {
this ['session' ] = sessionKey;
}
}
@override
String get title => getString ('title' ) ?? '' ;
@override
String ? get sessionKey => getString ('session' );
@override
int get state => HandshakeState .checkState (title, sessionKey);
}
import 'package:dimp/protocol.dart' ;
/// Content for Application 0nly: {
/// "type" : i2s(0xA0),
/// "sn" : 123,
///
/// "app" : "{APP_ID}", // application (e.g.: "chat.dim.sechat")
/// "extra" : info // others
/// }
abstract interface class AppContent implements Content {
/// get App ID
String get application;
}
/// Customized Content: {
/// "type" : i2s(0xCC),
/// "sn" : 123,
///
/// "app" : "{APP_ID}", // application (e.g.: "chat.dim.sechat")
/// "mod" : "{MODULE}", // module name (e.g.: "drift_bottle")
/// "act" : "{ACTION}", // action name (3.g.: "throw")
/// "extra" : info // action parameters
/// }
abstract interface class CustomizedContent implements Content {
/// get Module name
String get module;
/// get Action name
String get action;
//
// Factory
//
static CustomizedContent create ({String ? type,
required String app, required String mod, required String act
}) => type == null
? AppCustomizedContent .from (app: app, mod: mod, act: act)
: AppCustomizedContent .fromType (type, app: app, mod: mod, act: act);
}
/// Application Customized Content
class AppCustomizedContent extends BaseContent implements AppContent , CustomizedContent {
AppCustomizedContent (super .dict);
AppCustomizedContent .fromType (String msgType, {
required String app, required String mod, required String act
}) : super .fromType (msgType) {
this ['app' ] = app;
this ['mod' ] = mod;
this ['act' ] = act;
}
AppCustomizedContent .from ({
required String app, required String mod, required String act
}) : this .fromType (ContentType .CUSTOMIZED , app: app, mod: mod, act: act);
@override
String get application => getString ('app' ) ?? '' ;
@override
String get module => getString ('mod' ) ?? '' ;
@override
String get action => getString ('act' ) ?? '' ;
}
Copyright © 2023-2026 Albert Moky