Пример #1
0
func (c *Client) initialConnect() (tun *Conn) {
	var theParam = new(tunParams)
	var man = &d5cman{connectionInfo: c.connInfo}
	var err error
	tun, err = man.Connect(theParam)
	if err != nil {
		log.Errorf("Failed to connect to %s %s Retry after %s",
			c.connInfo.RemoteName(), ex.Detail(err), RETRY_INTERVAL)
		return nil
	} else {
		log.Infof("Login to server %s with %s successfully",
			c.connInfo.RemoteName(), c.connInfo.user)
		c.params = theParam
		c.token = theParam.token
		return
	}
}
Пример #2
0
// return header=1 + TKSZ*many
func (s *SessionMgr) createTokens(session *Session, many int) []byte {
	s.lock.Lock()
	defer s.lock.Unlock()

	// issue #35
	// clearTokens() invoked prior to createTokens()
	if session == nil || session.tokens == nil {
		return nil
	}

	var (
		tokens  = make([]byte, 1+many*TKSZ)
		i64buf  = make([]byte, 8)
		_tokens = tokens[1:]
		sha     = sha1.New()
	)
	rand.Seed(time.Now().UnixNano())
	sha.Write([]byte(session.uid))
	for i := 0; i < many; i++ {
		binary.BigEndian.PutUint64(i64buf, uint64(rand.Int63()))
		sha.Write(i64buf)
		binary.BigEndian.PutUint64(i64buf, uint64(time.Now().UnixNano()))
		sha.Write(i64buf)
		pos := i * TKSZ
		sha.Sum(_tokens[pos:pos])
		token := _tokens[pos : pos+TKSZ]
		key := fmt.Sprintf("%x", token)
		if _, y := s.container[key]; y {
			i--
			continue
		}
		s.container[key] = session
		session.tokens[key] = true
	}
	if log.V(log.LV_SESSION) {
		log.Errorf("SessionMap created=%d len=%d\n", many, len(s.container))
	}
	return tokens
}
Пример #3
0
func (p *multiplexer) relay(edge *edgeConn, tun *Conn, sid uint16) {
	var (
		buf  = bytePool.Get(FRAME_MAX_LEN)
		code byte
		src  = edge.conn
	)
	defer func() {
		// actively close then notify peer
		if edge.bitwiseCompareAndSet(TCP_CLOSE_R) && code != FRAME_ACTION_OPEN_DENIED {
			pack(buf, FRAME_ACTION_CLOSE_W, sid, nil)
			go func() {
				// tell peer to closeW
				frameWriteBuffer(tun, buf[:FRAME_HEADER_LEN])
				bytePool.Put(buf)
			}()
		} else {
			bytePool.Put(buf)
		}
		if code == FRAME_ACTION_OPEN_Y {
			closeR(src)
		} else { // remote open failed
			SafeClose(src)
			if log.V(log.LV_REQ) {
				switch code {
				case FRAME_ACTION_OPEN_N:
					log.Infof("Remote open %s failed", edge.dest)
				case FRAME_ACTION_OPEN_DENIED:
					log.Infof("Request %s was denied by remote", edge.dest)
				}
			}
		}
	}()
	if edge.active { // for client
		_len := pack(buf, FRAME_ACTION_OPEN, sid, []byte(edge.dest[2:])) // dest with a leading mark
		if frameWriteBuffer(tun, buf[:_len]) != nil {
			SafeClose(tun)
			return
		}
	}

	var (
		tn         int // total
		nr         int
		er         error
		_fast_open = p.isClient
	)
	for {
		if _fast_open {
			// In fastOpening, the timeout will give rise to recheck fastopen state
			src.SetReadDeadline(time.Now().Add(READ_TMO_IN_FASTOPEN))
			received := false
			select {
			case code = <-edge.ready:
				received = true
			default:
			}
			if received {
				if code == FRAME_ACTION_OPEN_Y {
					_fast_open = false // fastopen finished
				} else {
					return
				}
			} else { // ready-chan was not ready
				if tn >= FAST_OPEN_BUF_MAX_SIZE { // must waiting for signal
					select {
					case code = <-edge.ready:
					case <-time.After(WAITING_OPEN_TIMEOUT):
						log.Errorf("Waiting open-signal sid=%d timeout for %s\n", sid, edge.dest)
					}
					// timeout or open-signal received
					if code == FRAME_ACTION_OPEN_Y {
						_fast_open = false // fastopen finished
					} else {
						return
					}
				}
			}
			// Received signal-y then finish fastopen
			if !_fast_open {
				// read forever
				src.SetReadDeadline(ZERO_TIME)
			}
		}

		nr, er = src.Read(buf[FRAME_HEADER_LEN:])
		if nr > 0 {
			tn += nr
			pack(buf, FRAME_ACTION_DATA, sid, uint16(nr))
			if frameWriteBuffer(tun, buf[:nr+FRAME_HEADER_LEN]) != nil {
				SafeClose(tun)
				return
			}
		}
		// timeout to recheck open signal
		if er != nil && !(_fast_open && IsTimeout(er)) {
			if er != io.EOF && DEBUG {
				log.Infof("Read to the end of edge total=%d err=(%v)", tn, er)
			}
			return
		}
	}
}
Пример #4
0
func (c *Client) StartTun(mustRestart bool) {
	var (
		tun  *Conn
		wait bool
		rn   = atomic.LoadInt32(&c.round)
	)
	for {
		if wait {
			time.Sleep(RETRY_INTERVAL)
		}
		if rn < atomic.LoadInt32(&c.round) {
			return
		}
		if mustRestart {
			// clear mustRestart
			mustRestart = false
			// prevent concurrently
			if atomic.CompareAndSwapInt32(&c.state, CLT_WORKING, CLT_PENDING) {
				tun, rn = c.restart()
			} else {
				return
			}
		}
		if atomic.LoadInt32(&c.state) == CLT_WORKING {
			var dtcnt int32
			var err error

			// not restarting, ordinary data tun
			if tun == nil {
				tun, err = c.createDataTun()
				if err != nil {
					log.Errorf("Connection failed %s Reconnect after %s",
						ex.Detail(err), RETRY_INTERVAL)
					wait = true
					continue
				}
			}

			if log.V(log.LV_CLT_CONNECT) {
				log.Infof("Tun %s is established\n", tun.identifier)
			}

			dtcnt = atomic.AddInt32(&c.dtCnt, 1)
			err = c.mux.Listen(tun, c.eventHandler, c.params.pingInterval+int(dtcnt))
			dtcnt = atomic.AddInt32(&c.dtCnt, -1)

			if log.V(log.LV_CLT_CONNECT) {
				log.Errorf("Tun %s was disconnected %s Reconnect after %s\n",
					tun.identifier, ex.Detail(err), RETRY_INTERVAL)
			}
			// reset
			tun, wait = nil, true

			// received ping count
			if atomic.LoadInt32(&c.mux.pingCnt) <= 0 {
				// dirty tokens: used abandoned tokens
				c.clearTokens()
			}

			// restart: all connections were disconnected
			if dtcnt <= 0 {
				log.Errorf("Currently offline, all connections %s were lost\n", c.connInfo.RemoteName())
				go c.StartTun(true)
				return
			}
		} else {
			// now is restarting then exit
			return
		}
	}
}