func newObfs4ClientConn(conn net.Conn, args *obfs4ClientArgs) (c *obfs4Conn, err error) { // Generate the initial protocol polymorphism distribution(s). var seed *drbg.Seed if seed, err = drbg.NewSeed(); err != nil { return } lenDist := probdist.New(seed, 0, framing.MaximumSegmentLength, biasedDist) var iatDist *probdist.WeightedDist if args.iatMode != iatNone { var iatSeed *drbg.Seed iatSeedSrc := sha256.Sum256(seed.Bytes()[:]) if iatSeed, err = drbg.SeedFromBytes(iatSeedSrc[:]); err != nil { return } iatDist = probdist.New(iatSeed, 0, maxIATDelay, biasedDist) } // Allocate the client structure. c = &obfs4Conn{conn, false, lenDist, iatDist, args.iatMode, bytes.NewBuffer(nil), bytes.NewBuffer(nil), nil, nil} // Start the handshake timeout. deadline := time.Now().Add(clientHandshakeTimeout) if err = conn.SetDeadline(deadline); err != nil { return nil, err } if err = c.clientHandshake(args.nodeID, args.publicKey, args.sessionKey); err != nil { return nil, err } // Stop the handshake timeout. if err = conn.SetDeadline(time.Time{}); err != nil { return nil, err } return }
func (conn *obfs4Conn) readPackets() (err error) { // Attempt to read off the network. var buf [consumeReadSize]byte rdLen, rdErr := conn.Conn.Read(buf[:]) conn.receiveBuffer.Write(buf[:rdLen]) var decoded [framing.MaximumFramePayloadLength]byte for conn.receiveBuffer.Len() > 0 { // Decrypt an AEAD frame. decLen := 0 decLen, err = conn.decoder.Decode(decoded[:], conn.receiveBuffer) if err == framing.ErrAgain { break } else if err != nil { break } else if decLen < packetOverhead { err = InvalidPacketLengthError(decLen) break } // Decode the packet. pkt := decoded[0:decLen] pktType := pkt[0] payloadLen := binary.BigEndian.Uint16(pkt[1:]) if int(payloadLen) > len(pkt)-packetOverhead { err = InvalidPayloadLengthError(int(payloadLen)) break } payload := pkt[3 : 3+payloadLen] switch pktType { case packetTypePayload: if payloadLen > 0 { conn.receiveDecodedBuffer.Write(payload) } case packetTypePrngSeed: // Only regenerate the distribution if we are the client. if len(payload) == seedPacketPayloadLength && !conn.isServer { var seed *drbg.Seed seed, err = drbg.SeedFromBytes(payload) if err != nil { break } conn.lenDist.Reset(seed) if conn.iatDist != nil { iatSeedSrc := sha256.Sum256(seed.Bytes()[:]) iatSeed, err := drbg.SeedFromBytes(iatSeedSrc[:]) if err != nil { break } conn.iatDist.Reset(iatSeed) } } default: // Ignore unknown packet types. } } // Read errors (all fatal) take priority over various frame processing // errors. if rdErr != nil { return rdErr } return }