New constructs an exit Server.
(cfg Config)
| 211 | |
| 212 | // New constructs an exit Server. |
| 213 | func New(cfg Config) (*Server, error) { |
| 214 | aead, err := frame.NewCryptoFromHexKey(cfg.AESKeyHex) |
| 215 | if err != nil { |
| 216 | return nil, err |
| 217 | } |
| 218 | dialFn := dialFunc(cfg.UpstreamProxy) |
| 219 | initialResponseCap := cfg.InitialResponseBytesPreEncode |
| 220 | if initialResponseCap <= 0 { |
| 221 | initialResponseCap = initialResponseBytesPreEncode |
| 222 | } |
| 223 | s := &Server{ |
| 224 | cfg: cfg, |
| 225 | aead: aead, |
| 226 | dial: dialFn, |
| 227 | dns: newDNSCache(), |
| 228 | debugTiming: cfg.DebugTiming, |
| 229 | version: cfg.Version, |
| 230 | initialResponseBytesPreEncode: initialResponseCap, |
| 231 | sessions: make(map[[frame.SessionIDLen]byte]*session.Session), |
| 232 | sessionOwners: make(map[[frame.SessionIDLen]byte][frame.ClientIDLen]byte), |
| 233 | txReady: make(map[[frame.SessionIDLen]byte]struct{}), |
| 234 | firstReply: make(map[[frame.SessionIDLen]byte]struct{}), |
| 235 | upstreams: make(map[[frame.SessionIDLen]byte]net.Conn), |
| 236 | lastActivity: make(map[[frame.SessionIDLen]byte]time.Time), |
| 237 | dialFail: make(map[string]time.Time), |
| 238 | pendingRSTs: make(map[[frame.ClientIDLen]byte][]*frame.Frame), |
| 239 | pendingCtrl: make(map[[frame.ClientIDLen]byte][]*frame.Frame), |
| 240 | activity: make(map[[frame.ClientIDLen]byte]chan struct{}), |
| 241 | } |
| 242 | s.upstreamReadPool.New = func() interface{} { |
| 243 | buf := make([]byte, upstreamReadBuf) |
| 244 | return &buf |
| 245 | } |
| 246 | return s, nil |
| 247 | } |
| 248 | |
| 249 | // dialFunc returns a dial function. When proxyAddr is non-empty it routes all |
| 250 | // outbound connections through the SOCKS5 proxy at that address; otherwise it |