o3ma/o3

you have to receive before you can send

V-inz opened this issue · 3 comments

V-inz commented

working on o3demo issue #7 I found a more basic error:
You have to receive (pending offline-messages) before you can send!

What I did:

  1. I copied two instances of the o3demo: o3demo1 and o3demo2. I removed the auto-answer and copied four initial messages.
  2. Starting them and sending the initial messages to a third party works fine.
  3. Starting them and sending to each other, with starting o3demo2 about 5 sec later will block o3demo2 while sending its first initial message.
  4. o3demo2 will not work anymore (restart, ...), until you generate a new Threema-ID. This is, what kolAflash did here: o3demo issue #7. Thus the pending offline-messages from o3demo1 "killed" o3demo2.
  5. Now I stopped o3demo1 and sent four offline-messages from third party to o3demo1. Restarting o3demo1, I can see o3demo1 is "dead" too.

Kind of "solve":

  1. Ichanged o3demo1 and o3demo2 to not send the initial messages but do the receive.
  2. Both receive just the latest offline-message in their pipe and work again as they did from start.

So I draw the conclusion, you have to receive all pending offline-messages before you can send your first message.
I did not try to find, whether this block comes from Threema servers or from the o3ma/o3-lib.
I'd expect the o3ma/o3-lib because Threema servers should not delete all pending offline-messages except the latest, only because I tried to send.

(Maybe this is dependent on some timing during startup of the demo. So maybe you can see it on one computer but not the other. I saw it on a Raspberry Pi 2 but not on my desktop.)

V-inz commented

I tried to verify this by first starting the receive-loop in background (see below) and after a delay sending messages.
To be honest, I have to admit that this does not help.

Next presumption would be, there are problems receiving messages in rapid succession.

	// handle incoming messages
	c := make(chan error, 1)
	go func() {  // background rcv-loop
		fmt.Println("handle incoming messages")
		for receivedMessage := range receiveMsgChan {

			...

		}
		c<-nil
	}()

	time.Sleep(2000 * time.Millisecond)

	// send our initial message to our recipient
	for i := 1; i <= 4; i++ {
		txt := fmt.Sprintf("Initial message %d from o3demo1", i)
		fmt.Printf("%s to [%s]\n", txt, rid)
		err = ctx.SendTextMessage(rid, txt, sendMsgChan)
		if err != nil {
			log.Fatal(err)
		}
	}

	<-c // Wait for receivedMessage-Loop to exit
V-inz commented

I think I need some help :)
Again I start a client with 4 pending offline-messages on the threema-servers.

In communicationhandler.go inside func (sc *SessionContext) receiveLoop() section case messagePacket: a correct new message is received and pumped into the sc.receiveMsgChan.
I can see the text of the message, when I put fmt.Printf("\nreceiveLoop: messagePacket: [[%v]]\n", rmsg.Msg) right in front of it.

But in the o3demo, where the same channel is polled via for receivedMessage := range receiveMsgChan, there is an event only for the first offline-message.
The second message is pushed into the channel, I can see it, but never comes out of it.

And now the receiving and sending is blocked.
I can't understand this, because (I think) I do not understand golang channels correctly.

P.S:
I can make things work, when a change receiveMsgChan to a Buffered Channel of not too small size. 500 works. But I think this is not a solution, because messages should no be received faster than they can be worked off.

You were right with your assessment about buffered channels. We should (and wanted to, if I remember correctly) have done that from the beginning. I added buffered channels in 3d612b6. We'll have to find a more scalable solution in the long run but this should fix the error in question and will allow you to use the demo as is.