예제 #1
0
파일: dial.go 프로젝트: davidlazar/vuvuzela
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
}
예제 #2
0
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
}