github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/apps/mixnet/router.go (about)

     1  // Copyright (c) 2015, Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package mixnet
    16  
    17  import (
    18  	"crypto/rand"
    19  	"crypto/tls"
    20  	"crypto/x509"
    21  	"crypto/x509/pkix"
    22  	"encoding/binary"
    23  	"errors"
    24  	"io"
    25  	"log"
    26  	"net"
    27  	"strings"
    28  	"sync"
    29  	"time"
    30  
    31  	"golang.org/x/crypto/nacl/box"
    32  
    33  	"github.com/golang/glog"
    34  	"github.com/golang/protobuf/proto"
    35  	"github.com/jlmucb/cloudproxy/go/tao"
    36  )
    37  
    38  // RouterContext stores the runtime environment for a Tao-delegated router.
    39  type RouterContext struct {
    40  	keys       *tao.Keys    // Signing keys of this hosted program.
    41  	domain     *tao.Domain  // Policy guard and public key.
    42  	listener   net.Listener // Socket where server listens for proxies/routers
    43  	publicKey  *[32]byte
    44  	privateKey *[32]byte
    45  
    46  	addr string
    47  
    48  	// Data structures for queueing and batching messages
    49  	queue     *Queue
    50  	proxyReq  *Queue
    51  	proxyResp *Queue
    52  
    53  	// Connections to next hop routers
    54  	conns map[string]*Conn
    55  	// Maps circuit id to circuits
    56  	circuits map[uint64]*Circuit
    57  	// Used to check duplicate connection ids
    58  	connIds struct {
    59  		sync.Mutex
    60  		m map[uint32]bool
    61  	}
    62  
    63  	// address of the directories
    64  	directories []string
    65  	// list of available servers and their keys for exit encryption
    66  	dirLock    *sync.Mutex
    67  	directory  []string
    68  	serverKeys [][]byte
    69  
    70  	mapLock *sync.RWMutex
    71  
    72  	// The queues and error handlers are instantiated as go routines; these
    73  	// channels are for tearing them down.
    74  	killQueue             chan bool
    75  	killQueueErrorHandler chan bool
    76  
    77  	network string        // Network protocol, e.g. "tcp"
    78  	timeout time.Duration // Timeout on read/write/dial.
    79  
    80  	errs chan error
    81  	done chan bool
    82  }
    83  
    84  // NewRouterContext generates new keys, loads a local domain configuration from
    85  // path and binds an anonymous listener socket to addr using network protocol.
    86  // It also creates a regular listener socket for other routers to connect to.
    87  // A delegation is requested from the Tao t which is  nominally
    88  // the parent of this hosted program.
    89  func NewRouterContext(path, network, addr string, timeout time.Duration,
    90  	directories []string, batchSize int,
    91  	x509Identity *pkix.Name, t tao.Tao) (r *RouterContext, err error) {
    92  
    93  	r = new(RouterContext)
    94  	r.network = network
    95  	r.timeout = timeout
    96  
    97  	r.addr = addr
    98  	port := addr
    99  	if addr != "127.0.0.1:0" {
   100  		port = ":" + strings.Split(addr, ":")[1]
   101  	}
   102  
   103  	r.conns = make(map[string]*Conn)
   104  	r.circuits = make(map[uint64]*Circuit)
   105  	r.connIds = struct {
   106  		sync.Mutex
   107  		m map[uint32]bool
   108  	}{m: make(map[uint32]bool)}
   109  
   110  	r.dirLock = new(sync.Mutex)
   111  	r.mapLock = new(sync.RWMutex)
   112  
   113  	r.errs = make(chan error)
   114  	r.done = make(chan bool)
   115  
   116  	// Generate keys and get attestation from parent.
   117  	if r.keys, err = tao.NewTemporaryTaoDelegatedKeys(tao.Signing|tao.Crypting, t); err != nil {
   118  		return nil, err
   119  	}
   120  
   121  	// Create a certificate.
   122  	pkInt := tao.PublicKeyAlgFromSignerAlg(*r.keys.SigningKey.Header.KeyType)
   123  	sigInt := tao.SignatureAlgFromSignerAlg(*r.keys.SigningKey.Header.KeyType)
   124  	r.keys.Cert, err = r.keys.SigningKey.CreateSelfSignedX509(pkInt, sigInt, int64(1), x509Identity)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	// Load domain from local configuration.
   130  	if r.domain, err = tao.LoadDomain(path, nil); err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	// Encode TLS certificate.
   135  	cert, err := tao.EncodeTLSCert(r.keys)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	tlsConfig := &tls.Config{
   141  		RootCAs:            x509.NewCertPool(),
   142  		Certificates:       []tls.Certificate{*cert},
   143  		InsecureSkipVerify: true,
   144  		ClientAuth:         tls.RequestClientCert,
   145  	}
   146  
   147  	if r.listener, err = Listen(network, port, tlsConfig,
   148  		r.domain.Guard, r.domain.Keys.VerifyingKey, r.keys.Delegation); err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	// NaCl keys
   153  	r.publicKey, r.privateKey, err = box.GenerateKey(rand.Reader)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	r.directories = directories
   159  	r.register()
   160  	go r.updateDirectory()
   161  
   162  	// Instantiate the queues.
   163  	r.queue = NewQueue(network, t, batchSize, timeout)
   164  	r.proxyReq = NewQueue(network, t, batchSize, timeout)
   165  	r.proxyResp = NewQueue(network, t, batchSize, timeout)
   166  	r.killQueue = make(chan bool)
   167  	r.killQueueErrorHandler = make(chan bool)
   168  	go r.queue.DoQueue(r.killQueue)
   169  	go r.proxyReq.DoQueue(r.killQueue)
   170  	go r.proxyResp.DoQueue(r.killQueue)
   171  	go r.queue.DoQueueErrorHandler(r.queue, r.killQueueErrorHandler)
   172  	go r.proxyReq.DoQueueErrorHandler(r.queue, r.killQueueErrorHandler)
   173  	go r.proxyResp.DoQueueErrorHandler(r.queue, r.killQueueErrorHandler)
   174  
   175  	return r, nil
   176  }
   177  
   178  func (r *RouterContext) register() {
   179  	if r.addr == "127.0.0.1:0" {
   180  		r.addr = r.listener.Addr().String()
   181  	}
   182  	for _, dirAddr := range r.directories {
   183  		err := r.Register(dirAddr)
   184  		if err != nil {
   185  			log.Println("Register err:", err)
   186  		}
   187  	}
   188  }
   189  
   190  func (r *RouterContext) directoryConsensus() []string {
   191  	r.dirLock.Lock()
   192  	defer r.dirLock.Unlock()
   193  	for _, dirAddr := range r.directories {
   194  		directory, keys, err := r.GetDirectory(dirAddr)
   195  		if err != nil {
   196  			log.Println("GetDirectory err:", err)
   197  		}
   198  		// TODO(kwonalbert): Check directory consensus
   199  		r.directory = directory
   200  		r.serverKeys = keys
   201  	}
   202  	directory := make([]string, len(r.directory))
   203  	copy(directory, r.directory)
   204  	return directory
   205  }
   206  
   207  func (r *RouterContext) updateDirectory() {
   208  	for {
   209  		r.directoryConsensus()
   210  		time.Sleep(DefaultUpdateFrequency)
   211  	}
   212  }
   213  
   214  // AcceptRouter Waits for connectons from other routers.
   215  func (r *RouterContext) Accept() (*Conn, error) {
   216  	c, err := r.listener.Accept()
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  	id, err := r.newConnID()
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	conn := &Conn{c, id, r.timeout, make(map[uint64]*Circuit), new(sync.RWMutex), true}
   225  	if len(c.(*tls.Conn).ConnectionState().PeerCertificates) > 0 {
   226  		conn.withProxy = false
   227  	}
   228  	go r.handleConn(conn)
   229  	return conn, nil
   230  }
   231  
   232  // DialRouter connects to a remote Tao-delegated mixnet router.
   233  func (r *RouterContext) DialRouter(network, addr string) (*Conn, error) {
   234  	c, err := tao.Dial(network, addr, r.domain.Guard, r.domain.Keys.VerifyingKey, r.keys)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	id, err := r.newConnID()
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  	conn := &Conn{c, id, r.timeout, make(map[uint64]*Circuit), new(sync.RWMutex), false}
   243  	r.conns[addr] = conn
   244  	go r.handleConn(conn)
   245  	return conn, nil
   246  }
   247  
   248  // Register the current router to a directory server
   249  func (r *RouterContext) Register(dirAddr string) error {
   250  	c, err := tao.Dial(r.network, dirAddr, r.domain.Guard, r.domain.Keys.VerifyingKey, r.keys)
   251  	if err != nil {
   252  		return err
   253  	}
   254  	err = RegisterRouter(c, []string{r.addr}, [][]byte{(*r.publicKey)[:]})
   255  	if err != nil {
   256  		return err
   257  	}
   258  	return c.Close()
   259  
   260  }
   261  
   262  // Read the directory from a directory server
   263  func (r *RouterContext) GetDirectory(dirAddr string) ([]string, [][]byte, error) {
   264  	c, err := tao.Dial(r.network, dirAddr, r.domain.Guard, r.domain.Keys.VerifyingKey, r.keys)
   265  	if err != nil {
   266  		return nil, nil, err
   267  	}
   268  	directory, keys, err := GetDirectory(c)
   269  	if err != nil {
   270  		return nil, nil, err
   271  	}
   272  	return directory, keys, c.Close()
   273  }
   274  
   275  func (r *RouterContext) DeleteRouter() {
   276  	dm := &DirectoryMessage{
   277  		Type:  DirectoryMessageType_DELETE.Enum(),
   278  		Addrs: []string{r.addr},
   279  		Keys:  nil,
   280  	}
   281  	b, err := proto.Marshal(dm)
   282  	if err != nil {
   283  		log.Println(err)
   284  	}
   285  
   286  	for _, dirAddr := range r.directories {
   287  		c, err := tao.Dial(r.network, dirAddr, r.domain.Guard, r.domain.Keys.VerifyingKey, r.keys)
   288  		if err != nil {
   289  			log.Println(err)
   290  		}
   291  		_, err = c.Write(b)
   292  		if err != nil {
   293  			log.Println(err)
   294  		}
   295  		c.Read([]byte{0})
   296  	}
   297  }
   298  
   299  // Close releases any resources held by the hosted program.
   300  func (r *RouterContext) Close() {
   301  	r.killQueue <- true
   302  	r.killQueue <- true
   303  	r.killQueue <- true
   304  	r.killQueueErrorHandler <- true
   305  	r.killQueueErrorHandler <- true
   306  	r.killQueueErrorHandler <- true
   307  	if r.listener != nil {
   308  		r.listener.Close()
   309  	}
   310  	for _, conn := range r.conns {
   311  		r.done <- true
   312  		for _, circuit := range conn.circuits {
   313  			circuit.Close()
   314  		}
   315  		conn.Close()
   316  	}
   317  	r.DeleteRouter()
   318  }
   319  
   320  // Return a random circuit ID
   321  func (r *RouterContext) newID() (uint64, error) {
   322  	id := uint64(0)
   323  	ok := true
   324  	// Reserve ids < 2^32 to connection ids
   325  	for ok || id < (1<<32) {
   326  		b := make([]byte, 8)
   327  		if _, err := rand.Read(b); err != nil {
   328  			return 0, err
   329  		}
   330  		id = binary.LittleEndian.Uint64(b)
   331  		_, ok = r.circuits[id]
   332  	}
   333  	return id, nil
   334  }
   335  
   336  // Return a random connection ID
   337  func (r *RouterContext) newConnID() (uint32, error) {
   338  	r.connIds.Lock()
   339  	var id uint32
   340  	ok := true
   341  	for ok {
   342  		b := make([]byte, 8)
   343  		if _, err := rand.Read(b); err != nil {
   344  			return 0, err
   345  		}
   346  		id = binary.LittleEndian.Uint32(b)
   347  		_, ok = r.connIds.m[id]
   348  	}
   349  	r.connIds.m[id] = true
   350  	r.connIds.Unlock()
   351  	return id, nil
   352  }
   353  
   354  // Handle errors internal to the router
   355  // When instantiating a real router (not for testing),
   356  // one start this function as well to handle the errors
   357  func (r *RouterContext) HandleErr() {
   358  	for {
   359  		err := <-r.errs
   360  		if err != nil {
   361  			// TODO(kwonalbert) Handle errors properly
   362  			glog.Error("Router err:", err)
   363  		}
   364  	}
   365  }
   366  
   367  // handleConn reads a directive or a message from a proxy. The directives
   368  // are handled here, but actual messages are handled in handleMessages
   369  func (r *RouterContext) handleConn(c *Conn) {
   370  	for {
   371  		var err error
   372  		cell := make([]byte, CellBytes)
   373  		if _, err = c.Read(cell); err != nil {
   374  			if err == io.EOF {
   375  				break
   376  			} else {
   377  				select {
   378  				case <-r.done: // Indicate this is done
   379  				case r.errs <- err:
   380  				}
   381  				break
   382  			}
   383  		}
   384  
   385  		id := getID(cell)
   386  		r.mapLock.RLock()
   387  		sendQ, respQ := r.queue, r.queue
   388  		circ, ok := r.circuits[id]
   389  		var nextCirc *Circuit
   390  		var sId, rId uint64
   391  		if ok {
   392  			nextCirc = circ.next
   393  			sId = nextCirc.id
   394  			if circ.entry {
   395  				sendQ = r.proxyReq
   396  				respQ = r.proxyResp
   397  			}
   398  			if nextCirc.entry {
   399  				respQ = r.proxyResp
   400  				rId = uint64(nextCirc.conn.id)
   401  			} else {
   402  				rId = nextCirc.id
   403  			}
   404  		}
   405  		if c.withProxy {
   406  			sId, rId = uint64(c.id), uint64(c.id)
   407  		}
   408  		r.mapLock.RUnlock()
   409  
   410  		if cell[TYPE] == msgCell {
   411  			if !circ.exit { // if it's not exit, just relay the cell
   412  				binary.LittleEndian.PutUint64(cell[ID:], nextCirc.id)
   413  				if !circ.forward {
   414  					sendQ.EnqueueMsg(sId, cell, nextCirc.conn, c)
   415  				} else {
   416  					respQ.EnqueueMsg(rId, cell, nextCirc.conn, c)
   417  				}
   418  			} else { // actually handle the message
   419  				c.GetCircuit(id).BufferCell(cell, err)
   420  			}
   421  		} else if cell[TYPE] == dirCell { // Handle a directive.
   422  			var d Directive
   423  			if err = unmarshalDirective(cell, &d); err != nil {
   424  				r.errs <- err
   425  				break
   426  			}
   427  
   428  			// relay the errors back to users
   429  			if *d.Type == DirectiveType_ERROR {
   430  				binary.LittleEndian.PutUint64(cell[ID:], nextCirc.id)
   431  				respQ.EnqueueMsg(rId, cell, nextCirc.conn, c)
   432  			} else if *d.Type == DirectiveType_CREATE {
   433  				err := r.handleCreate(d, c, id, sendQ, respQ, sId, rId)
   434  				if err != nil {
   435  					r.errs <- err
   436  					break
   437  				}
   438  			} else if *d.Type == DirectiveType_DESTROY {
   439  				err := r.handleDestroy(d, c, circ, sendQ, respQ, sId, rId)
   440  				if err != nil {
   441  					r.errs <- err
   442  					break
   443  				}
   444  			} else if *d.Type == DirectiveType_CREATED {
   445  				// Simply relay created back
   446  				cell, err = marshalDirective(nextCirc.id, dirCreated)
   447  				if err != nil {
   448  					r.errs <- err
   449  					break
   450  				}
   451  				respQ.EnqueueMsg(rId, cell, nextCirc.conn, c)
   452  			} else if *d.Type == DirectiveType_DESTROYED {
   453  				cell, err = marshalDirective(nextCirc.id, dirDestroyed)
   454  				if err != nil {
   455  					r.errs <- err
   456  					break
   457  				}
   458  				empty := r.delete(c, circ)
   459  				// Close the forward circuit if it's an exit or empty now
   460  				// Relay back destroyed
   461  				sendQ.Close(sId, nil, empty, c, nextCirc.conn)
   462  				respQ.Close(rId, cell, empty, nextCirc.conn, nil)
   463  				if empty {
   464  					break
   465  				}
   466  			}
   467  		} else { // Unknown cell type, return an error.
   468  			if err = r.SendError(respQ, rId, id, errBadCellType, c); err != nil {
   469  				r.errs <- err
   470  				break
   471  			}
   472  		}
   473  	}
   474  }
   475  
   476  func member(s string, set []string) bool {
   477  	for _, member := range set {
   478  		if member == s {
   479  			return true
   480  		}
   481  	}
   482  	return false
   483  }
   484  
   485  // handleCreated handles the create directive by either relaying it on
   486  // (which opens a new connection), or sending back created directive
   487  // if this is an exit.
   488  func (r *RouterContext) handleCreate(d Directive, c *Conn, id uint64,
   489  	sendQ, respQ *Queue, sId, rId uint64) error {
   490  	if c.withProxy {
   491  		// Get the most recent directory before forming a circuit
   492  		directory := r.directoryConsensus()
   493  
   494  		if len(directory) < len(d.Addrs)-1 {
   495  			err := errors.New("Not enough servers online")
   496  			if e := r.SendError(respQ, rId, id, err, c); e != nil {
   497  				return e
   498  			}
   499  		}
   500  
   501  		// A fresh path of the same length if user has no preference
   502  		// (Random selection without replacement)
   503  		for _, router := range d.Addrs {
   504  			for i, addr := range directory {
   505  				if addr == router {
   506  					directory[i] = directory[len(directory)-1]
   507  					directory = directory[:len(directory)-1]
   508  					break
   509  				}
   510  			}
   511  		}
   512  		for i := 1; i < len(d.Addrs)-1; i++ {
   513  			if d.Addrs[i] != "" {
   514  				// TODO(kwonalbert) Currently, we allow the
   515  				// clients to pick the path, if they want,
   516  				// mostly for testing. But for better security,
   517  				// we should not allows this for final version.
   518  				continue
   519  			}
   520  			b := make([]byte, LEN_SIZE)
   521  			if _, err := rand.Read(b); err != nil {
   522  				return err
   523  			}
   524  			idx := int(binary.LittleEndian.Uint32(b)) % len(directory)
   525  			d.Addrs[i] = directory[idx]
   526  			directory[idx] = directory[len(directory)-1]
   527  			directory = directory[:len(directory)-1]
   528  		}
   529  	}
   530  
   531  	r.mapLock.Lock()
   532  	defer r.mapLock.Unlock()
   533  
   534  	newId, err := r.newID()
   535  	if err != nil {
   536  		return err
   537  	}
   538  	circuit := NewCircuit(c, id, c.withProxy, false, false)
   539  	newCirc := NewCircuit(nil, newId, false, false, true)
   540  	circuit.next = newCirc
   541  	newCirc.next = circuit
   542  
   543  	c.AddCircuit(circuit)
   544  	r.circuits[id] = circuit
   545  
   546  	// Add next hop for this circuit to queue and send a CREATED
   547  	// directive to sender to inform the sender.
   548  	relayIdx := -1
   549  	for i, addr := range d.Addrs {
   550  		if addr == r.addr {
   551  			relayIdx = i
   552  		}
   553  	}
   554  	if relayIdx != len(d.Addrs)-2 { // last addr is the final dest, so check -2
   555  		// Relay the CREATE message
   556  		if err != nil {
   557  			return err
   558  		}
   559  		var nextConn *Conn
   560  		if _, ok := r.conns[d.Addrs[relayIdx+1]]; !ok {
   561  			nextConn, err = r.DialRouter(r.network, d.Addrs[relayIdx+1])
   562  			if err != nil {
   563  				if e := r.SendError(respQ, rId, id, err, c); e != nil {
   564  					return e
   565  				}
   566  			}
   567  		} else {
   568  			nextConn = r.conns[d.Addrs[relayIdx+1]]
   569  		}
   570  		newCirc.conn = nextConn
   571  		nextConn.AddCircuit(newCirc)
   572  		r.circuits[newId] = newCirc
   573  
   574  		nextCell, err := marshalDirective(newId, &d)
   575  		if err != nil {
   576  			return err
   577  		}
   578  		// middle node, then just queue to the generic queue, not one of the proxy queue
   579  		if !c.withProxy {
   580  			sId = newId
   581  		}
   582  		sendQ.EnqueueMsg(sId, nextCell, nextConn, c)
   583  	} else {
   584  		// Response id should be just id here not rId if it's not an entry
   585  		var key [32]byte
   586  		copy(key[:], d.Key)
   587  		circuit.exit = true
   588  		circuit.SetKeys(&key, r.publicKey, r.privateKey)
   589  		if !c.withProxy {
   590  			sId = newId
   591  			rId = id
   592  		}
   593  
   594  		dest, ok := circuit.Decrypt([]byte(d.Addrs[len(d.Addrs)-1]))
   595  		if !ok {
   596  			log.Fatal("Misauthenticated ciphertext")
   597  		}
   598  		go r.handleMessage(string(dest), circuit, sendQ, respQ, sId, rId)
   599  		// Tell the previous hop (proxy or router) it's created
   600  		cell, err := marshalDirective(id, dirCreated)
   601  		if err != nil {
   602  			return err
   603  		}
   604  		respQ.EnqueueMsg(rId, cell, c, nil)
   605  	}
   606  	return nil
   607  }
   608  
   609  // handleDestroy handles the destroy directive by either relaying it on,
   610  // or sending back destroyed directive if this is an exit
   611  func (r *RouterContext) handleDestroy(d Directive, c *Conn, circ *Circuit,
   612  	sendQ, respQ *Queue, sId, rId uint64) error {
   613  	// Close the connection if you are an exit for this circuit
   614  
   615  	if !c.Member(circ.id) {
   616  		return errors.New("Cannot destroy a circuit that does not belong to the connection")
   617  	}
   618  
   619  	if circ.exit {
   620  		// Send back destroyed msg
   621  		cell, err := marshalDirective(circ.id, dirDestroyed)
   622  		if err != nil {
   623  			return err
   624  		}
   625  		if circ.next.conn != nil {
   626  			circ.next.conn.Close()
   627  		}
   628  		empty := r.delete(c, circ) // there is not previous id for this, so delete id
   629  		respQ.Close(rId, cell, empty, circ.conn, circ.conn)
   630  	} else {
   631  		nextCell, err := marshalDirective(circ.next.id, dirDestroy)
   632  		if err != nil {
   633  			return err
   634  		}
   635  		sendQ.EnqueueMsg(sId, nextCell, circ.next.conn, circ.conn)
   636  	}
   637  	return nil
   638  }
   639  
   640  // handleMessages reconstructs the full message at the exit node, and sends it
   641  // out to the final destination. The directives are handled in handleConn.
   642  func (r *RouterContext) handleMessage(dest string, circ *Circuit,
   643  	sendQ, respQ *Queue, sId, rId uint64) {
   644  	var conn *Conn = nil
   645  	var netConn net.Conn = nil
   646  	for {
   647  		msg, err := circ.ReceiveMessage()
   648  		if err == io.EOF {
   649  			break
   650  		} else if err != nil {
   651  			if err = r.SendError(respQ, rId, circ.id, err, circ.conn); err != nil {
   652  				r.errs <- err
   653  			}
   654  			continue
   655  		}
   656  
   657  		if conn == nil { // dial when you receive the first message to send
   658  			netConn, err = net.DialTimeout(r.network, dest, r.timeout)
   659  			if err != nil {
   660  				if err = r.SendError(respQ, rId, circ.id, err, circ.conn); err != nil {
   661  					r.errs <- err
   662  				}
   663  				continue
   664  			}
   665  			r.mapLock.Lock()
   666  			conn = &Conn{netConn, 0, r.timeout, make(map[uint64]*Circuit), new(sync.RWMutex), false}
   667  			circ.next.conn = conn
   668  			// Add the circuit to final dest to list of circuits
   669  			conn.AddCircuit(circ.next)
   670  			r.circuits[circ.next.id] = circ.next
   671  			r.mapLock.Unlock()
   672  			// Create handler for responses from the destination
   673  			go r.handleResponse(netConn, circ, respQ, rId)
   674  		}
   675  		sendQ.EnqueueMsg(sId, msg, netConn, circ.conn)
   676  	}
   677  	if conn != nil {
   678  		conn.Close()
   679  		conn.DeleteCircuit(circ.next)
   680  	}
   681  }
   682  
   683  // handleResponse receives a message from the final destination, breaks it down
   684  // into cells, and sends it back to the user
   685  func (r *RouterContext) handleResponse(conn net.Conn, respCirc *Circuit, queue *Queue, queueId uint64) {
   686  	for {
   687  		resp := make([]byte, MaxMsgBytes+1)
   688  		conn.SetDeadline(time.Now().Add(r.timeout))
   689  		n, e := conn.Read(resp)
   690  		if e == io.EOF {
   691  			// the connection closed
   692  			return
   693  		} else if e != nil {
   694  			if strings.Contains(e.Error(), "closed network connection") {
   695  				// TODO(kwonalbert) Currently, this is a hack to
   696  				// avoid sending unnecesary error back to user,
   697  				// since Read returns this error when the conn
   698  				// closes while it's constructing response cells
   699  				return
   700  			} else {
   701  				r.SendError(queue, queueId, respCirc.id, e, respCirc.conn)
   702  				return
   703  			}
   704  		} else if n > MaxMsgBytes {
   705  			r.SendError(queue, queueId, respCirc.id, errors.New("Response message too long"), respCirc.conn)
   706  			return
   707  		}
   708  
   709  		cell := make([]byte, CellBytes)
   710  		binary.LittleEndian.PutUint64(cell[ID:], respCirc.id)
   711  
   712  		cell[TYPE] = msgCell
   713  
   714  		bodies := make(chan []byte)
   715  		go breakMessages(resp[:n], bodies)
   716  		for {
   717  			body, ok := <-bodies
   718  			if !ok {
   719  				break
   720  			}
   721  			boxed := respCirc.Encrypt(body)
   722  			copy(cell[BODY:], boxed)
   723  			queue.EnqueueMsg(queueId, cell, respCirc.conn, nil)
   724  		}
   725  	}
   726  }
   727  
   728  // SendError sends an error message to a client.
   729  func (r *RouterContext) SendError(queue *Queue, queueId, id uint64, err error, c *Conn) error {
   730  	var d Directive
   731  	d.Type = DirectiveType_ERROR.Enum()
   732  	d.Error = proto.String(err.Error())
   733  	cell, err := marshalDirective(id, &d)
   734  	if err != nil {
   735  		return err
   736  	}
   737  	queue.EnqueueMsg(queueId, cell, c, nil)
   738  	return nil
   739  }
   740  
   741  func (r *RouterContext) delete(c *Conn, circuit *Circuit) bool {
   742  	r.mapLock.Lock()
   743  	delete(r.circuits, circuit.id)
   744  	delete(r.circuits, circuit.next.id)
   745  	empty := c.DeleteCircuit(circuit)
   746  	if empty {
   747  		delete(r.conns, c.RemoteAddr().String())
   748  	}
   749  	r.mapLock.Unlock()
   750  	return empty
   751  }