func (srv *DialService) Close(Round uint32, _ *struct{}) error { log.WithFields(log.Fields{"service": "dial", "rpc": "Close", "round": Round}).Info() round, err := srv.getRound(Round, dialRoundOpen) if err != nil { return err } srv.filterIncoming(round) round.noiseWg.Wait() round.incoming = append(round.incoming, round.noise...) shuffler := shuffle.New(rand.Reader, len(round.incoming)) shuffler.Shuffle(round.incoming) if !srv.LastServer { if err := NewDialRound(srv.Client, Round); err != nil { return fmt.Errorf("NewDialRound: %s", err) } srv.Idle.Unlock() if err := RunDialRound(srv.Client, Round, round.incoming); err != nil { return fmt.Errorf("RunDialRound: %s", err) } round.incoming = nil } else { srv.Idle.Unlock() } round.noise = nil round.status = dialRoundClosed return nil }
func (srv *ConvoService) Close(Round uint32, _ *struct{}) error { log.WithFields(log.Fields{"service": "convo", "rpc": "Close", "round": Round}).Info() round, err := srv.getRound(Round, convoRoundOpen) if err != nil { return err } srv.filterIncoming(round) if !srv.LastServer { round.noiseWg.Wait() outgoing := append(round.incoming, round.noise...) round.noise = nil shuffler := shuffle.New(rand.Reader, len(outgoing)) shuffler.Shuffle(outgoing) if err := NewConvoRound(srv.Client, Round); err != nil { return fmt.Errorf("NewConvoRound: %s", err) } srv.Idle.Unlock() replies, err := RunConvoRound(srv.Client, Round, outgoing) if err != nil { return fmt.Errorf("RunConvoRound: %s", err) } shuffler.Unshuffle(replies) round.replies = replies[:round.numIncoming] } else { exchanges := make([]*ConvoExchange, len(round.incoming)) concurrency.ParallelFor(len(round.incoming), func(p *concurrency.P) { for i, ok := p.Next(); ok; i, ok = p.Next() { exchanges[i] = new(ConvoExchange) if err := exchanges[i].Unmarshal(round.incoming[i]); err != nil { log.WithFields(log.Fields{"bug": true, "call": "ConvoExchange.Unmarshal"}).Error(err) } } }) var singles, doubles int64 deadDrops := make(map[DeadDrop][]int) for i, ex := range exchanges { drop := deadDrops[ex.DeadDrop] if len(drop) == 0 { singles++ deadDrops[ex.DeadDrop] = append(drop, i) } else if len(drop) == 1 { singles-- doubles++ deadDrops[ex.DeadDrop] = append(drop, i) } } round.replies = make([][]byte, len(round.incoming)) concurrency.ParallelFor(len(exchanges), func(p *concurrency.P) { for i, ok := p.Next(); ok; i, ok = p.Next() { ex := exchanges[i] drop := deadDrops[ex.DeadDrop] if len(drop) == 1 { round.replies[i] = ex.EncryptedMessage[:] } if len(drop) == 2 { var k int if i == drop[0] { k = drop[1] } else { k = drop[0] } round.replies[i] = exchanges[k].EncryptedMessage[:] } } }) srv.Idle.Unlock() ac := &AccessCount{ Singles: singles, Doubles: doubles, } select { case srv.AccessCounts <- ac: default: } } round.status = convoRoundClosed return nil }