Beispiel #1
0
func RunDialRound(client *vrpc.Client, round uint32, onions [][]byte) error {
	spans := concurrency.Spans(len(onions), 4000)
	calls := make([]*vrpc.Call, len(spans))

	concurrency.ParallelFor(len(calls), func(p *concurrency.P) {
		for i, ok := p.Next(); ok; i, ok = p.Next() {
			span := spans[i]
			calls[i] = &vrpc.Call{
				Method: "DialService.Add",
				Args: &DialAddArgs{
					Round:  round,
					Onions: onions[span.Start : span.Start+span.Count],
				},
				Reply: nil,
			}
		}
	})

	if err := client.CallMany(calls); err != nil {
		return fmt.Errorf("Add: %s", err)
	}

	if err := client.Call("DialService.Close", round, nil); err != nil {
		return fmt.Errorf("Close: %s", err)
	}

	return nil
}
Beispiel #2
0
func FillWithFakeSingles(dest [][]byte, nonce *[24]byte, nextKeys []*[32]byte) {
	concurrency.ParallelFor(len(dest), func(p *concurrency.P) {
		for i, ok := p.Next(); ok; i, ok = p.Next() {
			var exchange [SizeConvoExchange]byte
			rand.Read(exchange[:])
			onion, _ := onionbox.Seal(exchange[:], nonce, nextKeys)
			dest[i] = onion
		}
	})
}
Beispiel #3
0
func FillWithFakeDoubles(dest [][]byte, nonce *[24]byte, nextKeys []*[32]byte) {
	concurrency.ParallelFor(len(dest)/2, func(p *concurrency.P) {
		for i, ok := p.Next(); ok; i, ok = p.Next() {
			var exchange1 [SizeConvoExchange]byte
			var exchange2 [SizeConvoExchange]byte
			rand.Read(exchange1[:])
			copy(exchange2[0:16], exchange1[0:16])
			rand.Read(exchange2[16:])
			onion1, _ := onionbox.Seal(exchange1[:], nonce, nextKeys)
			onion2, _ := onionbox.Seal(exchange2[:], nonce, nextKeys)
			dest[i*2] = onion1
			dest[i*2+1] = onion2
		}
	})
}
Beispiel #4
0
func FillWithFakeIntroductions(dest [][]byte, noiseCounts []uint32, nonce *[24]byte, nextKeys []*[32]byte) {
	buckets := make([]int, len(dest))
	idx := 0
	for b, count := range noiseCounts {
		for i := uint32(0); i < count; i++ {
			buckets[idx] = b
			idx++
		}
	}

	concurrency.ParallelFor(len(dest), func(p *concurrency.P) {
		for i, ok := p.Next(); ok; i, ok = p.Next() {
			var exchange [SizeDialExchange]byte
			binary.BigEndian.PutUint32(exchange[0:4], uint32(buckets[i]))
			rand.Read(exchange[4:])
			onion, _ := onionbox.Seal(exchange[:], nonce, nextKeys)
			dest[i] = onion
		}
	})
}
Beispiel #5
0
func RunConvoRound(client *vrpc.Client, round uint32, onions [][]byte) ([][]byte, error) {
	openArgs := &ConvoOpenArgs{
		Round:       round,
		NumIncoming: len(onions),
	}
	if err := client.Call("ConvoService.Open", openArgs, nil); err != nil {
		return nil, fmt.Errorf("Open: %s", err)
	}

	spans := concurrency.Spans(len(onions), 4000)
	calls := make([]*vrpc.Call, len(spans))

	concurrency.ParallelFor(len(calls), func(p *concurrency.P) {
		for i, ok := p.Next(); ok; i, ok = p.Next() {
			span := spans[i]
			calls[i] = &vrpc.Call{
				Method: "ConvoService.Add",
				Args: &ConvoAddArgs{
					Round:  round,
					Offset: span.Start,
					Onions: onions[span.Start : span.Start+span.Count],
				},
				Reply: nil,
			}
		}
	})

	if err := client.CallMany(calls); err != nil {
		return nil, fmt.Errorf("Add: %s", err)
	}

	if err := client.Call("ConvoService.Close", round, nil); err != nil {
		return nil, fmt.Errorf("Close: %s", err)
	}

	concurrency.ParallelFor(len(calls), func(p *concurrency.P) {
		for i, ok := p.Next(); ok; i, ok = p.Next() {
			span := spans[i]
			calls[i] = &vrpc.Call{
				Method: "ConvoService.Get",
				Args: &ConvoGetArgs{
					Round:  round,
					Offset: span.Start,
					Count:  span.Count,
				},
				Reply: new(ConvoGetResult),
			}
		}
	})

	if err := client.CallMany(calls); err != nil {
		return nil, fmt.Errorf("Get: %s", err)
	}

	replies := make([][]byte, len(onions))
	concurrency.ParallelFor(len(calls), func(p *concurrency.P) {
		for i, ok := p.Next(); ok; i, ok = p.Next() {
			span := spans[i]
			copy(replies[span.Start:span.Start+span.Count], calls[i].Reply.(*ConvoGetResult).Onions)
		}
	})

	if err := client.Call("ConvoService.Delete", round, nil); err != nil {
		return nil, fmt.Errorf("Delete: %s", err)
	}

	return replies, nil
}
Beispiel #6
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
}