Skip to content
Snippets Groups Projects
Commit b7edf7d9 authored by Benjamin Wenger's avatar Benjamin Wenger
Browse files

improced docs

parent d1f70140
Branches master
No related tags found
3 merge requests!510Release,!207WIP: Client Restructure,!203Symmetric broadcast
...@@ -32,7 +32,7 @@ import ( ...@@ -32,7 +32,7 @@ import (
"time" "time"
) )
// SendCMIX sends a "raw" cMix message payload to the provided recipient. // Send sends a "raw" cMix message payload to the provided recipient.
// Returns the round ID of the round the payload was sent or an error if it // Returns the round ID of the round the payload was sent or an error if it
// fails. // fails.
// This does not have end-to-end encryption on it and is used exclusively as // This does not have end-to-end encryption on it and is used exclusively as
......
...@@ -41,7 +41,7 @@ type TargetedCmixMessage struct { ...@@ -41,7 +41,7 @@ type TargetedCmixMessage struct {
Mac []byte Mac []byte
} }
// SendManyCMIX sends many "raw" cMix message payloads to the provided // SendMany sends many "raw" cMix message payloads to the provided
// recipients all in the same round. // recipients all in the same round.
// Returns the round ID of the round the payloads was sent or an error if it // Returns the round ID of the round the payloads was sent or an error if it
// fails. // fails.
......
...@@ -32,6 +32,11 @@ type listener struct { ...@@ -32,6 +32,11 @@ type listener struct {
net cmix.Client net cmix.Client
} }
// Listen allows a server to listen for single use requests. It will register
// a service relative to the tag and myID as the identifier. Only a single
// listener can be active for a tag-myID pair, and error will return if that
// is violated. When requests are receved, they will be called on the
// Receiver interface.
func Listen(tag string, myId *id.ID, privkey *cyclic.Int, net cmix.Client, func Listen(tag string, myId *id.ID, privkey *cyclic.Int, net cmix.Client,
e2eGrp *cyclic.Group, cb Receiver) Listener { e2eGrp *cyclic.Group, cb Receiver) Listener {
......
...@@ -55,6 +55,10 @@ func NewRequest(externalPayloadSize, pubKeySize int) Request { ...@@ -55,6 +55,10 @@ func NewRequest(externalPayloadSize, pubKeySize int) Request {
return tm return tm
} }
func GetRequestPayloadSize(externalPayloadSize, pubKeySize int) uint {
return uint(externalPayloadSize - transmitMessageVersionSize - pubKeySize)
}
// mapRequest builds a message mapped to the passed in data. It is // mapRequest builds a message mapped to the passed in data. It is
// mapped by reference; a copy is not made. // mapped by reference; a copy is not made.
func mapRequest(data []byte, pubKeySize int) Request { func mapRequest(data []byte, pubKeySize int) Request {
...@@ -160,6 +164,10 @@ func NewRequestPayload(payloadSize int, payload []byte, maxMsgs uint8) RequestPa ...@@ -160,6 +164,10 @@ func NewRequestPayload(payloadSize int, payload []byte, maxMsgs uint8) RequestPa
return mp return mp
} }
func GetRequestContentsSize(payloadSize uint) uint {
return payloadSize - transmitPlMinSize
}
// mapRequestPayload builds a message payload mapped to the passed in // mapRequestPayload builds a message payload mapped to the passed in
// data. It is mapped by reference; a copy is not made. // data. It is mapped by reference; a copy is not made.
func mapRequestPayload(data []byte) RequestPayload { func mapRequestPayload(data []byte) RequestPayload {
......
...@@ -66,7 +66,10 @@ func (r Request) String() string { ...@@ -66,7 +66,10 @@ func (r Request) String() string {
r.dhKey.Text(10), r.tag, r.maxParts) r.dhKey.Text(10), r.tag, r.maxParts)
} }
// // Respond is used to respond to the request. It sends a payload up to
// r.GetMaxResponseLength(). It will chunk the message into multiple
// cmix messages if it is too long for a single message. It will fail
// If a single cmix message cannot be sent.
func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams,
timeout time.Duration) ([]id.Round, error) { timeout time.Duration) ([]id.Round, error) {
// make sure this has only been run once // make sure this has only been run once
...@@ -108,8 +111,6 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, ...@@ -108,8 +111,6 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams,
failed := uint32(0) failed := uint32(0)
for i := 0; i < len(parts); i++ { for i := 0; i < len(parts); i++ {
// fixme: handle the case where a send fails, also on failures,
// unset use
go func(j int) { go func(j int) {
defer wg.Done() defer wg.Done()
partFP, ecrPart, mac := cyphers[j].Encrypt(parts[j]) partFP, ecrPart, mac := cyphers[j].Encrypt(parts[j])
......
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
"time" "time"
) )
// Response interface allows for callbacks to
type Response interface { type Response interface {
Callback(payload []byte, receptionID receptionID.EphemeralIdentity, Callback(payload []byte, receptionID receptionID.EphemeralIdentity,
round rounds.Round, err error) round rounds.Round, err error)
...@@ -28,13 +29,53 @@ type Response interface { ...@@ -28,13 +29,53 @@ type Response interface {
type RequestParams struct { type RequestParams struct {
Timeout time.Duration Timeout time.Duration
MaxMessages uint8 MaxResponseMessages uint8
CmixParam cmix.CMIXParams CmixParam cmix.CMIXParams
} }
func GetDefaultRequestParams() RequestParams {
return RequestParams{
Timeout: 30 * time.Second,
MaxResponseMessages: 255,
CmixParam: cmix.GetDefaultCMIXParams(),
}
}
// GetMaxRequestSize returns the max size of a request payload
func GetMaxRequestSize(net cmix.Client, e2eGrp *cyclic.Group) uint {
payloadSize := message.GetRequestPayloadSize(net.GetMaxMessageLength(),
e2eGrp.GetP().ByteLen())
return message.GetRequestContentsSize(payloadSize)
}
/* Single is a system which allows for an end to end encrypted anonymous
request to be sent to another cmix client, and for them to respond. The
system allows for communication over the mixnet without an interactive
key negotiation because the payload inherently carries the negotiation with
it. When sending a new request, a client create a new discreet log Dh keypair
as well as a new ID. As a result of the fact that the client never
identifies itself, the system allows the client to stay anonymous while
contacting the remote.
*/
// TransmitRequest Sends a request to the recipient with the given tag containing
// the given payload. The request is identified as coming from a new user ID and
// the recipient of the request responds to that address. As a result, this request
// does not reveal the identity of the sender,
// the current implementation only allows for a cing cmix request payload.
// Because the request payload itself must include negotiation materials, it is
// limited to just a few thousand bits of payload, and will return an error if
// the payload is too large. GetMaxRequestSize() can be used to get this max
// size
// The network follower must be running and healthy to transmit
func TransmitRequest(recipient contact.Contact, tag string, payload []byte, func TransmitRequest(recipient contact.Contact, tag string, payload []byte,
callback Response, param RequestParams, net cmix.Client, rng csprng.Source, callback Response, param RequestParams, net cmix.Client, rng csprng.Source,
e2eGrp *cyclic.Group) (id.Round, receptionID.EphemeralIdentity, error) { e2eGrp *cyclic.Group) (id.Round, receptionID.EphemeralIdentity, error) {
if !net.IsHealthy() {
return 0, receptionID.EphemeralIdentity{}, errors.New("Cannot " +
"send singe use when network is not healthy")
}
// get address ID address space size; this blocks until the address space // get address ID address space size; this blocks until the address space
// size is set for the first time // size is set for the first time
addressSize := net.GetAddressSpace() addressSize := net.GetAddressSpace()
...@@ -50,7 +91,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, ...@@ -50,7 +91,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte,
request := message.NewRequest(net.GetMaxMessageLength(), request := message.NewRequest(net.GetMaxMessageLength(),
e2eGrp.GetP().ByteLen()) e2eGrp.GetP().ByteLen())
requestPayload := message.NewRequestPayload(request.GetPayloadSize(), requestPayload := message.NewRequestPayload(request.GetPayloadSize(),
payload, param.MaxMessages) payload, param.MaxResponseMessages)
// Generate new user ID and address ID // Generate new user ID and address ID
var sendingID receptionID.EphemeralIdentity var sendingID receptionID.EphemeralIdentity
...@@ -73,7 +114,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, ...@@ -73,7 +114,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte,
request.SetPayload(encryptedPayload) request.SetPayload(encryptedPayload)
//register the response pickup //register the response pickup
collator := message.NewCollator(param.MaxMessages) collator := message.NewCollator(param.MaxResponseMessages)
timeoutKillChan := make(chan bool) timeoutKillChan := make(chan bool)
callbackOnce := sync.Once{} callbackOnce := sync.Once{}
wrapper := func(payload []byte, receptionID receptionID.EphemeralIdentity, wrapper := func(payload []byte, receptionID receptionID.EphemeralIdentity,
...@@ -88,9 +129,9 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, ...@@ -88,9 +129,9 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte,
}) })
} }
cyphers := makeCyphers(dhKey, param.MaxMessages) cyphers := makeCyphers(dhKey, param.MaxResponseMessages)
for i := uint8(0); i < param.MaxMessages; i++ { for i := uint8(0); i < param.MaxResponseMessages; i++ {
processor := responceProcessor{ processor := responceProcessor{
sendingID: sendingID, sendingID: sendingID,
c: collator, c: collator,
...@@ -196,6 +237,8 @@ func makeIDs(msg message.RequestPayload, publicKey *cyclic.Int, ...@@ -196,6 +237,8 @@ func makeIDs(msg message.RequestPayload, publicKey *cyclic.Int,
}, nil }, nil
} }
// waitForTimeout is a long running thread which handles timing out a request.
// It can be canceled by channel
func waitForTimeout(kill chan bool, callback callbackWrapper, timeout time.Duration) { func waitForTimeout(kill chan bool, callback callbackWrapper, timeout time.Duration) {
timer := time.NewTimer(timeout) timer := time.NewTimer(timeout)
select { select {
......
...@@ -12,7 +12,8 @@ import ( ...@@ -12,7 +12,8 @@ import (
type callbackWrapper func(payload []byte, type callbackWrapper func(payload []byte,
receptionID receptionID.EphemeralIdentity, round rounds.Round, err error) receptionID receptionID.EphemeralIdentity, round rounds.Round, err error)
//by fingerprint // responceProcessor Message.Processor interface registered with cmix.Client.
// One is registered for each potential fingerprint.
type responceProcessor struct { type responceProcessor struct {
sendingID receptionID.EphemeralIdentity sendingID receptionID.EphemeralIdentity
c *message.Collator c *message.Collator
...@@ -22,6 +23,8 @@ type responceProcessor struct { ...@@ -22,6 +23,8 @@ type responceProcessor struct {
recipient *contact.Contact recipient *contact.Contact
} }
// Process decrypts a response part and adds it to the collator - returning
// a full response to the callback when all parts are received.
func (rsp *responceProcessor) Process(ecrMsg format.Message, func (rsp *responceProcessor) Process(ecrMsg format.Message,
receptionID receptionID.EphemeralIdentity, receptionID receptionID.EphemeralIdentity,
round rounds.Round) { round rounds.Round) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment