fix
[libotrd.git] / test_cl.d
blob693f7e384f5cf2a20256ff78958581b1e456d486
1 module test_cl;
2 //version = CREATE_KEYS;
4 import core.stdc.stdio : stderr, fprintf;
6 //import std.stdio;
7 import std.string;
9 import otr;
10 import client;
13 ////////////////////////////////////////////////////////////////////////////////
14 void logmsg (const(char)* msg) {
15 if (msg is null) return;
16 while (*msg) {
17 char ch = *msg++;
18 if (ch == '\n') {
19 fprintf(stderr, "\n");
20 } else if (ch < ' ' || ch == 127) {
21 fprintf(stderr, "\\x%02x", ch);
22 } else {
23 fprintf(stderr, "%c", ch);
28 ////////////////////////////////////////////////////////////////////////////////
29 enum PROTO_NAME = "psyc";
32 ////////////////////////////////////////////////////////////////////////////////
33 enum GET_CLIENT(string var_) = "Client "~var_~" = cast(Client)opdata;";
36 OtrlPolicy otrPolicyCB (void* opdata, ConnContext* context) { return OTRL_POLICY_DEFAULT; }
37 int otrMaxMsgSizeCB (void* opdata, ConnContext* context) { return 65530; }
40 ////////////////////////////////////////////////////////////////////////////////
41 void otrCreateKeyCB (void *opdata, const(char)* accountname, const(char)* protocol) {
42 import core.stdc.string : strlen;
43 import core.stdc.stdio : sprintf;
45 fprintf(stderr, "+++ otrCreateKeyCB: acc=[%s]; proto=[%s]\n", accountname, protocol);
47 mixin(GET_CLIENT!`cl`);
49 char *fname = otrl_mallocT!char(strlen(cl.account)+1024);
50 sprintf(fname, ".otrdata.%s.privkey", cl.account);
52 void *keyp;
53 if (otrl_privkey_generate_start(cl.mOTRState, cl.account, PROTO_NAME, &keyp)) {
54 fprintf(stderr, "ERROR: can't generate new private key for '%s'!\n", cl.account);
55 throw new Error("ABORT!");
57 // this (otrl_privkey_generate_calculate) can be called in separate thread
58 // if it returns gcry_error(GPG_ERR_EEXIST), then a privkey creation for
59 // this accountname/protocol is already in progress, and *newkeyp will
60 // be set to null.
61 fprintf(stderr, " started (key generation)...\n");
62 // generation
63 if (otrl_privkey_generate_calculate(keyp)) {
64 fprintf(stderr, "ERROR: can't generate new private key for '%s'!\n", cl.account);
65 throw new Error("ABORT!");
67 fprintf(stderr, " finishing (key generation)...\n");
68 // finish it
69 if (otrl_privkey_generate_finish(cl.mOTRState, keyp, fname)) {
70 fprintf(stderr, "ERROR: can't generate new private key for '%s'!\n", cl.account);
71 throw new Error("ABORT!");
73 // no need to load it, as it is already here
75 fprintf(stderr, " loading...\n");
76 // load generated key
77 if (otrl_privkey_read(cl.mOTRState, fname)) {
78 fprintf(stderr, "ERROR: can't load private key for '%s'!\n", cl.account);
79 throw new Error("ABORT!");
83 otrl_mfree(fname);
87 ////////////////////////////////////////////////////////////////////////////////
88 /* Report whether you think the given user is online. Return 1 if
89 * you think he is, 0 if you think he isn't, -1 if you're not sure.
91 * If you return 1, messages such as heartbeats or other
92 * notifications may be sent to the user, which could result in "not
93 * logged in" errors if you're wrong. */
94 int otrIsLoggedInCB (void *opdata, const(char)* accountname, const(char)* protocol, const(char)* recipient) {
95 fprintf(stderr, "+++ otrIsLoggedInCB: acc=[%s]; proto=[%s]; recp=[%s]\n", accountname, protocol, recipient);
96 return 1;
100 ////////////////////////////////////////////////////////////////////////////////
101 void otrUpdateContextListCB (void *opdata) {
102 import core.stdc.string : strcmp;
104 mixin(GET_CLIENT!`cl`);
105 ConnContext *context = cl.mOTRState.context_root;
106 while (context) {
107 ConnContext *next = context.next;
108 Client cc = clientFind(context.username);
109 if (cc) {
110 int verified =
111 context.active_fingerprint && context.active_fingerprint.trust &&
112 (strcmp(context.active_fingerprint.trust, "verified") == 0 || strcmp(context.active_fingerprint.trust, "smp") == 0);
113 if (cc.verified != verified) {
114 cc.verified = verified;
115 fprintf(stderr, "** '%s' is %sverified\n", cc.account, (verified ? "".ptr : "NOT ".ptr));
117 if (context.msgstate == OTRL_MSGSTATE_ENCRYPTED) {
118 if (!cc.inOTR) {
119 cc.inOTR = 1;
120 fprintf(stderr, "** '%s' in OTR mode\n", cc.account);
122 } else {
123 if (cc.inOTR) {
124 cc.inOTR = 0;
125 fprintf(stderr, "** '%s' in PLAIN mode\n", cc.account);
128 } else {
129 fprintf(stderr, "ERROR: '%s' not found!\n", context.username);
131 context = next;
136 ////////////////////////////////////////////////////////////////////////////////
137 void otrSendMsgCB (void *opdata, const(char)* accountname, const(char)* protocol, const(char)* recipient, const(char)* message) {
138 fprintf(stderr, "+++ otrSendMsgCB: acc=[%s]; proto=[%s]; recp=[%s]; msg=[", accountname, protocol, recipient);
139 logmsg(message);
140 fprintf(stderr, "]\n");
141 mixin(GET_CLIENT!`cl`);
142 Client recl = clientFind(recipient);
143 if (recl is null) {
144 fprintf(stderr, " ERROR: can't find recipient!\n");
145 return;
147 recl.mbuf.push(cl.account, message);
151 ////////////////////////////////////////////////////////////////////////////////
152 void otrNewFingerCB (void *opdata, OtrlUserState us, const(char)* accountname, const(char)* protocol,
153 const(char)* username, ref ubyte[20] fingerprint)
155 //mixin(GET_CLIENT!`cl`);
156 fprintf(stderr, "+++ otrSendMsgCB: acc=[%s]; proto=[%s]; user=[%s]\n", accountname, protocol, username);
157 ConnContext *context = otrl_context_find(us, username, accountname, protocol, OTRL_INSTAG_BEST, 1/*TRUE*/, null, null, null);
158 if (!context) {
159 fprintf(stderr, "NO CONTEXT!\n");
160 throw new Error("ABORT!");
162 // don't add unknown fingerprint
163 char[OTRL_PRIVKEY_FPRINT_HUMAN_LEN] hash;
164 Fingerprint *fp = otrl_context_find_fingerprint(context, fingerprint, 0/*FALSE*/, null);
165 if (fp) {
166 otrl_privkey_hash_to_human(hash, fp.fingerprint[0..20]);
167 fprintf(stderr, " known %strusted fingerprint: %s\n", (otrl_context_is_fingerprint_trusted(fp) ? "".ptr : "un".ptr), hash.ptr);
168 // trust it (user query)
169 otrl_context_set_trust(fp, "verified");
170 } else {
171 otrl_privkey_hash_to_human(hash, fingerprint);
172 fprintf(stderr, " new fingerprint: %s\n", hash.ptr);
173 // don't trust -- don't add
174 // otrl_context_set_trust(fp, ""); // not trusted
175 // add fingerprint
176 fp = otrl_context_find_fingerprint(context, fingerprint, 1/*TRUE*/, null);
177 if (!fp) {
178 fprintf(stderr, " error adding fingerprint!\n");
179 return;
181 // make it trusted
182 otrl_context_set_trust(fp, "verified");
183 //otrl_privkey_write_fingerprints(us, fname);
188 ////////////////////////////////////////////////////////////////////////////////
189 void otrWriteFingersCB (void *opdata) {
190 import core.stdc.string : strlen;
191 import core.stdc.stdio : sprintf;
193 mixin(GET_CLIENT!`cl`);
194 fprintf(stderr, "+++ otrWriteFingersCB: acc=[%s]\n", cl.account);
196 char *fname = otrl_mallocT!char(strlen(cl.account)+1024);
197 sprintf(fname, ".otrdata.%s.fingers", cl.account);
199 if (otrl_privkey_write_fingerprints(cl.mOTRState, fname)) {
200 fprintf(stderr, " error writing fingerprints\n");
203 otrl_mfree(fname);
207 ////////////////////////////////////////////////////////////////////////////////
208 void otrGoneSecureCB (void *opdata, ConnContext *context) {
209 mixin(GET_CLIENT!`cl`);
210 fprintf(stderr, "+++ otrGoneSecureCB: username=[%s]; acc=[%s]; proto=[%s]\n", context.username, context.accountname, context.protocol);
211 if (!cl.inOTR) {
212 cl.inOTR = 1;
213 fprintf(stderr, "'%s' gone secure\n", cl.account);
218 void otrGoneInsecureCB (void *opdata, ConnContext *context) {
219 mixin(GET_CLIENT!`cl`);
220 fprintf(stderr, "+++ otrGoneInsecureCB: username=[%s]; acc=[%s]; proto=[%s]\n", context.username, context.accountname, context.protocol);
221 if (cl.inOTR) {
222 cl.inOTR = 0;
223 fprintf(stderr, "'%s' gone insecure\n", cl.account);
228 void otrStillSecureCB (void *opdata, ConnContext *context, int isReply) {
229 mixin(GET_CLIENT!`cl`);
230 fprintf(stderr, "+++ otrStillSecureCB: username=[%s]; acc=[%s]; proto=[%s]; reply=%d\n", context.username, context.accountname, context.protocol, isReply);
231 if (!cl.inOTR) {
232 cl.inOTR = 1;
233 fprintf(stderr, "'%s' still secure\n", cl.account);
238 ////////////////////////////////////////////////////////////////////////////////
239 const(char)* otrErrorMsgCB (void *opdata, ConnContext *context, OtrlErrorCode err_code) {
240 import core.stdc.string : strcpy, strlen;
242 const(char)* msg = "OTRL_ERRCODE_UNKNOWN";
243 switch (err_code) {
244 case OTRL_ERRCODE_ENCRYPTION_ERROR: msg = "OTRL_ERRCODE_ENCRYPTION_ERROR"; break;
245 case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE: msg = "OTRL_ERRCODE_MSG_NOT_IN_PRIVATE"; break;
246 case OTRL_ERRCODE_MSG_UNREADABLE: msg = "OTRL_ERRCODE_MSG_UNREADABLE"; break;
247 case OTRL_ERRCODE_MSG_MALFORMED: msg = "OTRL_ERRCODE_MSG_MALFORMED"; break;
248 default:
250 /* copy any info from context? */
251 char *res = otrl_mallocT!char(strlen(msg)+1);
252 strcpy(res, msg);
253 return res;
257 void otrErrorMsgFreeCB (void *opdata, const(char)* err_msg) {
258 otrl_mfree(cast(char *)err_msg);
262 ////////////////////////////////////////////////////////////////////////////////
263 void otrHandleMsgEventCB (void *opdata, OtrlMessageEvent msg_event, ConnContext *context,
264 const(char)* message, gcry_error_t err)
266 import core.stdc.stdio : stderr, fprintf;
268 const(char)* msg = "OTRL_MSGEVENT_UNKNOWN";
269 switch (msg_event) {
270 case OTRL_MSGEVENT_NONE: msg = "OTRL_MSGEVENT_NONE"; break;
271 case OTRL_MSGEVENT_ENCRYPTION_REQUIRED: msg = "OTRL_MSGEVENT_ENCRYPTION_REQUIRED"; break;
272 case OTRL_MSGEVENT_ENCRYPTION_ERROR: msg = "OTRL_MSGEVENT_ENCRYPTION_ERROR"; break;
273 case OTRL_MSGEVENT_CONNECTION_ENDED: msg = "OTRL_MSGEVENT_CONNECTION_ENDED"; break;
274 case OTRL_MSGEVENT_SETUP_ERROR: msg = "OTRL_MSGEVENT_SETUP_ERROR"; break;
275 case OTRL_MSGEVENT_MSG_REFLECTED: msg = "OTRL_MSGEVENT_MSG_REFLECTED"; break;
276 case OTRL_MSGEVENT_MSG_RESENT: msg = "OTRL_MSGEVENT_MSG_RESENT"; break;
277 case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE: msg = "OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE"; break;
278 case OTRL_MSGEVENT_RCVDMSG_UNREADABLE: msg = "OTRL_MSGEVENT_RCVDMSG_UNREADABLE"; break;
279 case OTRL_MSGEVENT_RCVDMSG_MALFORMED: msg = "OTRL_MSGEVENT_RCVDMSG_MALFORMED"; break;
280 case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD: msg = "OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD"; break;
281 case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT: msg = "OTRL_MSGEVENT_LOG_HEARTBEAT_SENT"; break;
282 case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR: msg = "OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR"; break;
283 case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED: msg = "OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED"; break;
284 case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED: msg = "OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED"; break;
285 case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: msg = "OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE"; break;
286 default:
288 mixin(GET_CLIENT!`cl`);
289 fprintf(stderr, "acc:[%s]: msgevent: %s\n", cl.account, msg);
293 ////////////////////////////////////////////////////////////////////////////////
294 void otrCreateInsTagCB (void *opdata, const(char)* accountname, const(char)* protocol) {
295 import core.stdc.string : strlen;
296 import core.stdc.stdio : sprintf;
298 fprintf(stderr, "otrCreateInsTagCB: acc=[%s]; proto=[%s]\n", accountname, protocol);
299 mixin(GET_CLIENT!`cl`);
300 char *fname = otrl_mallocT!char(strlen(cl.account)+1024);
301 sprintf(fname, ".otrdata.%s.instag", cl.account);
302 if (otrl_instag_generate(cl.mOTRState, fname, accountname, protocol)) {
303 fprintf(stderr, " ERROR generating instag!\n");
305 otrl_mfree(fname);
309 ////////////////////////////////////////////////////////////////////////////////
310 void otrHandleSMPEvent (void *opdata, OtrlSMPEvent smp_event, ConnContext *context, ushort progress_percent, char *question);
313 ////////////////////////////////////////////////////////////////////////////////
314 static OtrlMessageAppOps ops = {
315 policy: &otrPolicyCB,
316 create_privkey: &otrCreateKeyCB, // can be null
317 is_logged_in: &otrIsLoggedInCB, // can be null
318 inject_message: &otrSendMsgCB,
319 update_context_list: &otrUpdateContextListCB, // can be null
320 new_fingerprint: &otrNewFingerCB, // can be null
321 write_fingerprints: &otrWriteFingersCB, // can be null
322 gone_secure: &otrGoneSecureCB,
323 gone_insecure: &otrGoneInsecureCB, // can be null
324 still_secure: &otrStillSecureCB, // can be null
325 max_message_size: &otrMaxMsgSizeCB,
326 account_name: null, // allocate human-friendly account name
327 account_name_free: null, // free human-friendly account name
328 received_symkey: null, // we don't have extra symkeys
329 otr_error_message: &otrErrorMsgCB,
330 otr_error_message_free: &otrErrorMsgFreeCB,
331 resent_msg_prefix: null, // allocate human-friendly resent prefix
332 resent_msg_prefix_free: null, // free human-friendly resent prefix
333 handle_smp_event: &otrHandleSMPEvent, // can be null
334 handle_msg_event: &otrHandleMsgEventCB,
335 create_instag: &otrCreateInsTagCB, // CAN'T BE null!
336 convert_msg: null, // convert msg
337 convert_free: null, // free converted msg
338 timer_control: null, // timer control
342 ////////////////////////////////////////////////////////////////////////////////
343 void otrHandleSMPEvent (void *opdata, OtrlSMPEvent smp_event, ConnContext *context, ushort progress_percent, char *question) {
344 import core.stdc.string : strlen;
346 mixin(GET_CLIENT!`cl`);
347 fprintf(stderr, "+++ otrHandleSMPEvent: event=%u; user=[%s]; account=[%s]; proto=[%s]", cast(uint)smp_event, context.username, context.accountname, context.protocol);
348 if (smp_event == OTRL_SMPEVENT_ASK_FOR_SECRET) {
349 fprintf(stderr, " ask_for_secret");
350 //otrl_message_abort_smp(cl.mOTRState, &ops, opdata, context);
351 const(char)* qq = "who is john doe?";
352 otrl_message_respond_smp(cl.mOTRState, &ops, opdata, context, cast(const(ubyte)*)qq, strlen(qq));
353 return;
355 if (smp_event == OTRL_SMPEVENT_ASK_FOR_ANSWER) {
356 fprintf(stderr, " ask_for_answer: [%s]", question);
357 const(char)* qa = "who is john doe?";
358 otrl_message_respond_smp(cl.mOTRState, &ops, opdata, context, cast(const(ubyte)*)qa, strlen(qa));
359 return;
361 if (smp_event == OTRL_SMPEVENT_CHEATED /*|| smp_event == OTRL_SMPEVENT_ERROR*/) {
362 fprintf(stderr, " ** protocol violated, aborting");
363 otrl_message_abort_smp(cl.mOTRState, &ops, opdata, context);
364 otrl_sm_state_free(context.smstate);
365 return;
367 if (smp_event == OTRL_SMPEVENT_SUCCESS) {
368 if (context.smstate.received_question) {
369 fprintf(stderr, " ** correct answer, you are trusted");
370 } else {
371 fprintf(stderr, " ** secrets proved equal, fingerprint trusted");
373 otrl_sm_state_free(context.smstate);
374 return;
376 if (smp_event == OTRL_SMPEVENT_FAILURE) {
377 if (context.smstate.received_question) {
378 fprintf(stderr, " ** wrong answer, you are not trusted");
379 } else {
380 fprintf(stderr, " ** secrets did not match, fingerprint not trusted");
382 otrl_sm_state_free(context.smstate);
383 return;
385 if (smp_event == OTRL_SMPEVENT_FAILURE) {
386 fprintf(stderr, " ** received abort");
387 otrl_sm_state_free(context.smstate);
388 return;
390 if (smp_event == OTRL_SMPEVENT_ERROR) {
391 fprintf(stderr, " ** protocol error, aborting");
392 otrl_message_abort_smp(cl.mOTRState, &ops, opdata, context);
393 otrl_sm_state_free(context.smstate);
394 return;
399 ////////////////////////////////////////////////////////////////////////////////
400 static void sendMessage (const(char)* from, const(char)* to, const(char)* msg) {
401 if (msg is null) return;
403 Client fcl = clientFind(from);
404 if (fcl is null) {
405 fprintf(stderr, "ERROR: sender '%s' not found!\n", from);
406 return;
409 Client tcl = clientFind(to);
410 if (tcl is null) {
411 fprintf(stderr, "ERROR: receiver '%s' not found!\n", to);
412 return;
415 char *newMsg = null;
416 gcry_error_t err = otrl_message_sending(
417 fcl.mOTRState,
418 &ops,
419 cast(void*)fcl,
420 fcl.account,
421 PROTO_NAME.ptr,
422 tcl.account,
423 OTRL_INSTAG_BEST,
424 msg,
425 null,
426 &newMsg,
427 OTRL_FRAGMENT_SEND_ALL/*_BUT_LAST*/,
428 null, null, null);
430 if (newMsg) {
431 // send last part
432 //otrSendMsgCB((void *)fcl, fcl.account, PROTO_NAME, tcl.account, newMsg);
433 // free last part
434 otrl_message_free(newMsg);
435 fprintf(stderr, "OTR message sent from '%s' to '%s'\n", from, to);
438 if (err) {
439 // do not send out plain text
440 fprintf(stderr, "OTR message ERROR from '%s' to '%s'\n", from, to);
445 ////////////////////////////////////////////////////////////////////////////////
446 // return bool: !0 if there was a message
447 static int readMessage (Client cl) {
448 if (cl is null || cl.mbuf.length == 0) return 0; // no messages
449 fprintf(stderr, "+++ readMessage for '%s' (%u message(s) in queue)\n", cl.account, cl.mbuf.length);
450 char *msg = cl.mbuf.data[0];
451 char *sender = cl.mbuf.sender[0];
452 char *newMsg = null;
453 OtrlTLV *tlvs = null;
454 ConnContext *ctx = null;
455 int internal = otrl_message_receiving(
456 cl.mOTRState,
457 &ops,
458 cast(void*)cl,
459 cl.account,
460 PROTO_NAME,
461 sender, msg,
462 &newMsg, &tlvs, &ctx,
463 null, null);
465 if (ctx) {
466 fprintf(stderr, "readMessage: ACC=[%s]; user=[%s]; account=[%s]; proto=[%s]\n", cl.account, ctx.username, ctx.accountname, ctx.protocol);
467 } else {
468 fprintf(stderr, "readMessage: ACC=[%s]; NO CONTEXT!\n", cl.account);
470 fprintf(stderr, "readMessage: ACC=[%s]; sender=[%s]\n", cl.account, sender);
472 int disconnected = 0;
473 if (tlvs) {
474 OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
475 if (tlv) disconnected = 1;
476 if (tlvs) otrl_tlv_free(tlvs);
477 if (disconnected) fprintf(stderr, "RECV: 'disconnected' TLV found!\n");
480 if (newMsg) {
481 if (internal) {
482 fprintf(stderr, "RECV INTERNAL: from '%s': [", sender);
483 } else {
484 fprintf(stderr, "RECV: from '%s': [", sender);
486 logmsg(newMsg);
487 fprintf(stderr, "]\n");
488 otrl_message_free(newMsg);
489 } else {
490 fprintf(stderr, "RECV %sPLAIN: from '%s': [", (internal ? "INTERNAL ".ptr : "".ptr), sender);
491 logmsg(msg);
492 fprintf(stderr, "]\n");
495 cl.mbuf.popFirst;
496 return 1;
500 ////////////////////////////////////////////////////////////////////////////////
501 static void otrStart (const(char)* from, const(char)* to) {
502 sendMessage(from, to, "?OTR?"); // libotr will transform this to handshake
506 ////////////////////////////////////////////////////////////////////////////////
507 Client[2] cls;
510 void checkMessages (size_t idx) {
511 Client cl = cls[idx];
512 fprintf(stderr, "=== POLLING '%s' ===\n", cl.account);
513 otrl_message_poll(cl.mOTRState, &ops, cast(void*)cl);
514 while (readMessage(cl)) {}
518 int hasAnyMessages () {
519 for (size_t idx = 0; idx < 2; ++idx) {
520 Client cl = cls[idx];
521 if (cl.mbuf.length > 0) return 1;
523 return 0;
527 void checkAllMessages () {
528 while (hasAnyMessages()) {
529 for (size_t idx = 0; idx < 2; ++idx) checkMessages(idx);
534 ////////////////////////////////////////////////////////////////////////////////
535 static Client newClient (const(char)* account) {
536 import core.stdc.string : strlen;
537 import core.stdc.stdio : sprintf;
539 Client cl = clientAdd(account);
540 cl.inOTR = 0;
541 cl.verified = 0;
543 char *fname = otrl_mallocT!char(strlen(cl.account)+1024);
545 sprintf(fname, ".otrdata.%s.fingers", cl.account);
546 otrl_privkey_read_fingerprints(cl.mOTRState, fname, null, null);
548 sprintf(fname, ".otrdata.%s.instags", cl.account);
549 otrl_instag_read(cl.mOTRState, fname);
551 sprintf(fname, ".otrdata.%s.instag", cl.account);
552 if (otrl_instag_read(cl.mOTRState, fname)) {
553 fprintf(stderr, "no instag for '%s', but have no fear, it will be generated!\n", cl.account);
556 sprintf(fname, ".otrdata.%s.privkey", cl.account);
557 if (otrl_privkey_read(cl.mOTRState, fname)) {
558 version(CREATE_KEYS) {
559 fprintf(stderr, "no private key for '%s', generating new...\n", cl.account);
561 if (otrl_privkey_generate(cl.mOTRState, fname, cl.account, PROTO_NAME)) {
562 fprintf(stderr, "ERROR: can't generate new private key for '%s'!\n", cl.account);
563 throw new Error("ABORT!");
566 void *keyp;
567 if (otrl_privkey_generate_start(cl.mOTRState, cl.account, PROTO_NAME, &keyp)) {
568 fprintf(stderr, "ERROR: can't generate new private key for '%s'!\n", cl.account);
569 throw new Error("ABORT!");
571 fprintf(stderr, " started...\n");
572 // generation
573 if (otrl_privkey_generate_calculate(keyp)) {
574 fprintf(stderr, "ERROR: can't generate new private key for '%s'!\n", cl.account);
575 throw new Error("ABORT!");
577 fprintf(stderr, " finishing...\n");
578 // finish it
579 if (otrl_privkey_generate_finish(cl.mOTRState, keyp, fname)) {
580 fprintf(stderr, "ERROR: can't generate new private key for '%s'!\n", cl.account);
581 throw new Error("ABORT!");
583 fprintf(stderr, " loading...\n");
584 // load generated key
585 if (otrl_privkey_read(cl.mOTRState, fname)) {
586 fprintf(stderr, "ERROR: can't load private key for '%s'!\n", cl.account);
587 throw new Error("ABORT!");
592 otrl_mfree(fname);
593 return cl;
597 ////////////////////////////////////////////////////////////////////////////////
598 int main () {
599 //OTRL_INIT;
601 cls[0] = newClient("alice");
602 cls[1] = newClient("miriel");
604 fprintf(stderr, "=== ALICE STARTING ===\n");
605 otrStart("alice", "miriel"); // alice initiates OTR
606 fprintf(stderr, "=== ALICE STARTED ===\n");
607 checkAllMessages();
609 fprintf(stderr, "=== ALICE HELLOING ===\n");
610 sendMessage("alice", "miriel", "hello, miri!");
611 fprintf(stderr, "=== ALICE HELLOED ===\n");
612 checkAllMessages();
614 fprintf(stderr, "=== MIRIEL HELLOING ===\n");
615 sendMessage("miriel", "alice", "hello, alice!");
616 fprintf(stderr, "=== MIRIEL HELLOED ===\n");
617 checkAllMessages();
619 return 0;