func (mod *module) handle_connect(ch *e3x.Channel) { defer ch.Kill() var ( from hashname.H localIdent *e3x.Identity remoteIdent *e3x.Identity handshake cipherset.Handshake innerData = bufpool.New() err error ) localIdent, err = mod.e.LocalIdentity() if err != nil { return } pkt, err := ch.ReadPacket() if err != nil { return } pkt.Body(innerData.SetLen(pkt.BodyLen()).RawBytes()[:0]) inner, err := lob.Decode(innerData) if err != nil { return } innerHdr := inner.Header() if innerHdr.IsBinary() && len(innerHdr.Bytes) == 1 { // handshake var ( csid = innerHdr.Bytes[0] key = localIdent.Keys()[csid] ) if key == nil { return } handshake, err = cipherset.DecryptHandshake(csid, key, inner.Body(nil)) if err != nil { return } from, err = hashname.FromIntermediates(handshake.Parts()) if err != nil { return } remoteIdent, err = e3x.NewIdentity(cipherset.Keys{ handshake.CSID(): handshake.PublicKey(), }, handshake.Parts(), nil) if err != nil { return } } else { // key packet var parts = make(cipherset.Parts) var csid uint8 for key, value := range inner.Header().Extra { if len(key) != 2 { continue } keyData, err := hex.DecodeString(key) if err != nil { continue } partCSID := keyData[0] switch v := value.(type) { case bool: csid = partCSID case string: parts[partCSID] = v } } hn, err := hashname.FromKeyAndIntermediates(csid, inner.Body(nil), parts) if err != nil { return } from = hn pubKey, err := cipherset.DecodeKeyBytes(csid, inner.Body(nil), nil) if err != nil { return } remoteIdent, err = e3x.NewIdentity(cipherset.Keys{csid: pubKey}, parts, nil) if err != nil { return } } if from == "" { return } if mod.config.AllowConnect != nil && !mod.config.AllowConnect(from, ch.RemoteHashname()) { return } x, err := mod.e.CreateExchange(remoteIdent) if err != nil { return } // when the BODY contains a handshake if handshake != nil { routerExchange := ch.Exchange() routerAddr := &peerAddr{ router: routerExchange.RemoteHashname(), } conn := newConnection(x.RemoteHashname(), routerAddr, routerExchange, func() { mod.unregisterConnection(routerExchange, x.LocalToken()) }) pipe, added := x.AddPipeConnection(conn, nil) if added { mod.registerConnection(routerExchange, x.LocalToken(), conn) } resp, ok := x.ApplyHandshake(handshake, pipe) if !ok { return } if resp != nil { err = mod.peerVia(ch.Exchange(), from, resp) if err != nil { return } } } // when the BODY contains a key packet if handshake == nil { pkt, err := x.GenerateHandshake() if err != nil { return } err = mod.peerVia(ch.Exchange(), from, pkt) if err != nil { return } } // Notify on-exchange callbacks mod.getIntroduction(from).resolve(x, nil) }
func (e *Endpoint) accept(conn net.Conn) { var ( token cipherset.Token msg = bufpool.New() err error n int ) n, err = conn.Read(msg.RawBytes()[:1500]) if err != nil { msg.Free() conn.Close() return } msg.SetLen(n) // msg is either a handshake or a channel packet // when msg is a handshake decrypt it and pass it to the associated exchange // when msg is a channel packet lookup the exchange and pass it the msg // always associate the conn with the exchange if msg.Len() < 2 { if e.endpointHooks.DropPacket(msg.Get(nil), conn, nil) != ErrStopPropagation { conn.Close() } msg.Free() return // to short } token = cipherset.ExtractToken(msg.RawBytes()) e.mtx.Lock() exchange := e.tokens[token] e.mtx.Unlock() if exchange != nil { exchange.received(newMessage(msg, newPipe(e.transport, conn, nil, exchange))) return } if raw := msg.RawBytes(); len(raw) < 3 || raw[0] != 0 || raw[1] != 1 { if e.endpointHooks.DropPacket(msg.Get(nil), conn, nil) != ErrStopPropagation { conn.Close() } msg.Free() return // to short } localIdent, err := e.LocalIdentity() if err != nil { if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation { conn.Close() } e.traceDroppedPacket(msg.Get(nil), conn, err.Error()) msg.Free() return // drop } // handle handshakes e.mtx.Lock() defer e.mtx.Unlock() var ( csid = msg.RawBytes()[2] key = e.keys[csid] ) if key == nil { if e.endpointHooks.DropPacket(msg.Get(nil), conn, nil) != ErrStopPropagation { conn.Close() } msg.Free() return // no key for csid } handshake, err := cipherset.DecryptHandshake(csid, key, msg.RawBytes()[3:]) if err != nil { if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation { conn.Close() } e.traceDroppedPacket(msg.Get(nil), conn, err.Error()) msg.Free() return // drop } hn, err := hashname.FromKeyAndIntermediates(csid, handshake.PublicKey().Public(), handshake.Parts()) if err != nil { if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation { conn.Close() } e.traceDroppedPacket(msg.Get(nil), conn, err.Error()) msg.Free() return // drop } exchange = e.hashnames[hn] if exchange != nil { oldLocalToken := exchange.LocalToken() oldRemoteToken := exchange.RemoteToken() exchange.received(newMessage(msg, newPipe(e.transport, conn, nil, exchange))) newLocalToken := exchange.LocalToken() newRemoteToken := exchange.RemoteToken() if oldLocalToken != newLocalToken { delete(e.tokens, oldLocalToken) e.tokens[newLocalToken] = exchange } if oldRemoteToken != newRemoteToken { delete(e.tokens, oldRemoteToken) e.tokens[newRemoteToken] = exchange } return } exchange, err = newExchange(localIdent, nil, handshake, e.log, registerEndpoint(e)) if err != nil { if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation { conn.Close() } e.traceDroppedPacket(msg.Get(nil), conn, err.Error()) msg.Free() return // drop } e.hashnames[hn] = exchange e.tokens[exchange.LocalToken()] = exchange e.tokens[exchange.RemoteToken()] = exchange exchange.state = ExchangeDialing exchange.received(newMessage(msg, newPipe(e.transport, conn, nil, exchange))) }