Пример #1
0
func (peer Peer) downloadFile(file File, conn *net.TCPConn) {
	if f, ok := status.status["local"].files[file.FileName]; ok {
		if f.Chunks[file.Chunks[1]] == 1 {
			return
		}
	} else {
		chunks := make([]int, file.Chunks[0])
		for chunk := range chunks {
			chunks[chunk] = 0
		}
		chunks[file.Chunks[1]] = 1
		status.status["local"].files[file.FileName] = File{
			FileName: file.FileName,
			Chunks:   chunks,
		}
	}
	status.status["local"].files[file.FileName].Chunks[file.Chunks[1]] = 1
	incrementChunkReplication(file.FileName, file.Chunks[1], file.Chunks[0])

	err := conn.SetReadBuffer(ChunkSize)
	checkError(err)

	readBuffer := make([]byte, ChunkSize)
	_, err = conn.Read(readBuffer)
	checkError(err)
	conn.Close()

	status.mu.Lock()
	basepath := path.Dir(file.FileName)
	fileName := path.Base(file.FileName)
	err = os.MkdirAll(basepath, 0777)
	checkError(err)

	filePath := path.Join(basepath, fileName)

	localFile, err := os.OpenFile(filePath, os.O_CREATE|os.O_RDWR, 0777)
	if err != nil {
		for {
			localFile, err = os.OpenFile(filePath, os.O_CREATE|os.O_RDWR, 0777)
			if err == nil {
				break
			}
		}
	}

	writeOffset := int64(file.Chunks[1] * ChunkSize)
	_, err = localFile.WriteAt(bytes.TrimRight(readBuffer, "\x00"), writeOffset)
	checkError(err)

	err = localFile.Close()
	checkError(err)

	status.mu.Unlock()
	fmt.Printf("Downloaded file %s:%d \n\n", file.FileName, file.Chunks[1])

	fileList := []File{file}
	haveMessage := encodeMessage(peer.host, peer.port, Have, fileList)
	sendToAll(haveMessage)
	return
}
Пример #2
0
func (server *TcpServer) Start() (err error) {
	for {
		var conn *net.TCPConn
		if conn, err = server.TCPListener.AcceptTCP(); err != nil {
			return err
		}
		if server.keepAlive != nil {
			if err := conn.SetKeepAlive(server.keepAlive.(bool)); err != nil {
				return err
			}
		}
		if server.keepAlivePeriod != nil {
			if kap, ok := (net.Conn(conn)).(iKeepAlivePeriod); ok {
				if err := kap.SetKeepAlivePeriod(server.keepAlivePeriod.(time.Duration)); err != nil {
					return err
				}
			}
		}
		if server.linger != nil {
			if err := conn.SetLinger(server.linger.(int)); err != nil {
				return err
			}
		}
		if server.noDelay != nil {
			if err := conn.SetNoDelay(server.noDelay.(bool)); err != nil {
				return err
			}
		}
		if server.readBuffer != nil {
			if err := conn.SetReadBuffer(server.readBuffer.(int)); err != nil {
				return err
			}
		}
		if server.writerBuffer != nil {
			if err := conn.SetWriteBuffer(server.writerBuffer.(int)); err != nil {
				return err
			}
		}
		if server.deadline != nil {
			if err := conn.SetDeadline(server.deadline.(time.Time)); err != nil {
				return err
			}
		}
		if server.readDeadline != nil {
			if err := conn.SetReadDeadline(server.readDeadline.(time.Time)); err != nil {
				return err
			}
		}
		if server.writerDeadline != nil {
			if err := conn.SetWriteDeadline(server.writerDeadline.(time.Time)); err != nil {
				return err
			}
		}
		if server.config != nil {
			server.ServeTCP(tls.Client(conn, server.config))
		} else {
			server.ServeTCP(conn)
		}
	}
}
Пример #3
0
// NewConn creates a new connection for the sio. It generates the session id and
// prepares the internal structure for usage.
func newConn(serv *Server, fd uint32, nc *net.TCPConn) (c *Conn, err error) {
	host, _, err := net.SplitHostPort(nc.RemoteAddr().String())
	if err != nil {
		serv.Log("mudoo/newConn: GetRemoteAddr:", err)
		return
	}

	c = &Conn{
		serv:          serv,
		fd:            fd,
		nc:            nc,
		raddr:         host,
		online:        true,
		lastConnected: time.Now().UnixNano(),
		wakeupFlusher: make(chan byte),
		wakeupReader:  make(chan byte),
		numConns:      0,
		numHeartbeats: 0,
		decBuf:        new(Buffer),
	}

	nc.SetReadBuffer(serv.config.ReadBufferSize)
	nc.SetWriteBuffer(serv.config.WriteBufferSize)

	go c.keepalive()
	// go c.flusher()
	go c.reader()

	return
}
Пример #4
0
func (peers *Peers) connectPeer(hostName string, portNumber int, conn *net.TCPConn) {
	peer, err := peers.getPeer(hostName, portNumber)
	checkError(err)

	err = conn.SetReadBuffer(ChunkSize)
	checkError(err)

	readBuffer := make([]byte, ChunkSize)
	_, err = conn.Read(readBuffer)
	checkError(err)

	var fileList FileList
	readBuffer = bytes.TrimRight(readBuffer, "\x00")

	err = json.Unmarshal(readBuffer, &fileList)
	checkError(err)

	if peer.currentState != Connected {
		updateStatus(hostName, portNumber, fileList.Files)
		peers.numPeers += 1
	}

	peer.currentState = Connected
	return
}
Пример #5
0
// Accept accepts connections on the listener and serves requests
// for each incoming connection.  Accept blocks; the caller typically
// invokes it in a go statement.
func (server *Server) AcceptTCP(lis *net.TCPListener, i int) {
	var (
		conn *net.TCPConn
		err  error
	)
	for {
		log.Debug("server: accept round: %d", i)
		if conn, err = lis.AcceptTCP(); err != nil {
			// if listener close then return
			log.Error("listener.Accept(\"%s\") error(%v)", lis.Addr().String(), err)
			return
		}
		if err = conn.SetKeepAlive(Conf.TCPKeepalive); err != nil {
			log.Error("conn.SetKeepAlive() error(%v)", err)
			return
		}
		if err = conn.SetReadBuffer(Conf.TCPSndbuf); err != nil {
			log.Error("conn.SetReadBuffer() error(%v)", err)
			return
		}
		if err = conn.SetWriteBuffer(Conf.TCPRcvbuf); err != nil {
			log.Error("conn.SetWriteBuffer() error(%v)", err)
			return
		}
		go server.serveConn(conn, i)
		if i++; i == maxInt {
			i = 0
		}
	}
}
Пример #6
0
//处理连接请求
func (this *server) handlerConnection(conn *net.TCPConn) {

	defer logger.CatchException()

	logger.Infof("New connection coming ... IP=%s ", conn.RemoteAddr())

	conn.SetNoDelay(true)                                        //无延迟
	conn.SetKeepAlive(true)                                      //保持激活
	conn.SetReadBuffer(64 * 1024)                                //设置读缓冲区大小
	conn.SetWriteBuffer(64 * 1024)                               //设置写缓冲区大小
	conn.SetReadDeadline(time.Now().Add(30000000 * time.Second)) //设置读超时

	session := network.NewSession(conn)
	defer session.Close()

	for {
		msg, err := session.RecvMSG()
		if err != nil {
			logger.Infof("RecvMsgs IP=%s err=%v", conn.RemoteAddr(), err.Error())
			return
		}

		ret := this.ProcessMessage(session, msg)
		if ret == false {
			return
		}
	}
}
Пример #7
0
// Accept accepts connections on the listener and serves requests
// for each incoming connection.  Accept blocks; the caller typically
// invokes it in a go statement.
func acceptTCP(server *Server, lis *net.TCPListener) {
	var (
		conn *net.TCPConn
		err  error
		r    int
	)
	for {
		if conn, err = lis.AcceptTCP(); err != nil {
			// if listener close then return
			log.Error("listener.Accept(\"%s\") error(%v)", lis.Addr().String(), err)
			return
		}
		if err = conn.SetKeepAlive(Conf.TCPKeepalive); err != nil {
			log.Error("conn.SetKeepAlive() error(%v)", err)
			return
		}
		if err = conn.SetReadBuffer(Conf.TCPSndbuf); err != nil {
			log.Error("conn.SetReadBuffer() error(%v)", err)
			return
		}
		if err = conn.SetWriteBuffer(Conf.TCPRcvbuf); err != nil {
			log.Error("conn.SetWriteBuffer() error(%v)", err)
			return
		}
		go serveTCP(server, conn, r)
		if r++; r == maxInt {
			r = 0
		}
	}
}
Пример #8
0
func configureConn (conn *net.TCPConn, spec *ConnectionSpec) {
	// these two -- the most important -- are causing problems on my osx/64
	// where a "service unavailable" pops up in the async reads 
	// but we absolutely need to be able to use timeouts.
//			conn.SetReadTimeout(spec.rTimeout);	
//			conn.SetWriteTimeout(spec.wTimeout);	
	conn.SetLinger(spec.lingerspec);
	conn.SetKeepAlive(spec.keepalive);
	conn.SetReadBuffer(spec.rBufSize);
	conn.SetWriteBuffer(spec.wBufSize);
}
Пример #9
0
// 每个连接在此函数中完成所有事情,不再启动多个协程
func handle_logic(clientConn *net.TCPConn) {
	defer func() { // 必须要先声明defer,否则不能捕获到panic异常
		if err := recover(); err != nil {
			jlog.Critical("!!!!!!!!!!!!! LOGIC FANIC error: ", err)
			//fmt.Println("!!!!!!!!!!!!! LOGIC FANIC error: ", err)
			clientConn.Close()
			runtime.Goexit()
		}
	}()

	tcpBuffer := make([]byte, nfconst.LEN_TCP_BUFFER)
	clientConn.SetReadBuffer(nfconst.LEN_TCP_BUFFER)
	var handle *nfnet.OrgStreamHandler = nfnet.NewOrgStreamHandler()
	nullmsg := make([]byte, 0)
	var msg []byte
	for {
		n, err := clientConn.Read(tcpBuffer[0:])
		if err != nil {
			if err.Error() == "EOF" {
				// 跳出循环, 并处理已经接收到的数据
				jlog.Infof("%s close, tcp read end, break read loop", clientConn.RemoteAddr().String())
			} else {
				jlog.Errorf("%s tcp read error %s, break read loop", clientConn.RemoteAddr().String(), err.Error())
			}

			//jlog.Tracef("---------- D_%s, read err: %s", clientConn.RemoteAddr().String(), err.Error())
			clientConn.Close()
			jlog.Infof("==================== goroutine exit\n")
			runtime.Goexit()
			break
		}

		done, buf, err1 := handle.AddStream(tcpBuffer[0:n])
		msg = buf
		if err1 != nil {
			jlog.Error("data add stream error, ", err1.Error())
		} else if done {
			// 处理消息
			msgHandler(clientConn, msg)
			msg = nullmsg
		}
	}

	// 如果执行到了这里, 那么就是 read的时候发生错误到了此处
	// 一个完整的包具备的最小长度为 头2字节,cmd 1字节, 负载长度2字节,校验1字节,尾2字节 = 8字节
	/*
		n_msg := len(msg)
		if n_msg >= nfconst.LEN_MIN_PACKAGE && msg[0] == nfconst.SOCK_PACK_HEADER_L && msg[1] == nfconst.SOCK_PACK_HEADER_H &&
			msg[n_msg-2] == nfconst.SOCK_PACK_ENDER_L && msg[n_msg-1] == nfconst.SOCK_PACK_ENDER_H {
			msgHandler(clientConn, msg)
		}
	*/
}
Пример #10
0
func (server *Server) setupSocket(conn *net.TCPConn) (err error) {
	if err = conn.SetLinger(0); err != nil {
		return
	}
	if server.ConfigReadBuffer != 0 {
		if err = conn.SetReadBuffer(int(server.ConfigReadBuffer)); err != nil {
			return
		}
	}
	if err = conn.SetKeepAlive(true); err != nil {
		return
	}
	if err = conn.SetReadDeadline(time.Now().Add(server.ConfigIdleTimeout)); err != nil {
		return
	}
	return
}
Пример #11
0
func TCPConnRead(c *net.TCPConn) error {
	c.SetReadBuffer(*packetsize)
	for {
		_, err := c.Read(b)
		if err != nil {
			if err == io.EOF {
				log.Println("Client ", c.RemoteAddr(), " disconnected")
				c.Close()
				return nil
			} else {
				log.Println("Failed reading bytes from conn: ", c, " with error ", err)
				c.Close()
				return err
			}
		}
	}
	return nil
}
Пример #12
0
func (p *proxy) pipe(src, dst *net.TCPConn) {
	//data direction
	var f, h string
	islocal := src == p.lconn
	if *verbose {
		if islocal {
			f = ">>> %d bytes sent%s"
		} else {
			f = "<<< %d bytes recieved%s"
		}
	}
	h = "%s"

	//directional copy
	buff := make([]byte, 0xffff)
	src.SetReadBuffer(len(buff))
	for {
		n, err := src.Read(buff)
		if err != nil {
			p.err("Read failed '%s'\n", err)
			return
		}

		b := buff[:n]

		//show output
		if *veryverbose {
			p.log(fmt.Sprintf(f, n, "\n"+fmt.Sprintf(h, b)))
		} else if *verbose {
			p.log(fmt.Sprintf(f, n, ""))
		}
		//write out result
		n, err = dst.Write(b)
		if err != nil {
			p.err("Write failed '%s'\n", err)
			return
		}
		if islocal {
			p.sentBytes += uint64(n)
		} else {
			p.receivedBytes += uint64(n)
		}
	}
}
Пример #13
0
func handleConnection(conn *net.TCPConn) {
	defer conn.Close()
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
			return
		}
	}()

	conn.SetKeepAlive(true)
	conn.SetReadBuffer(4096)
	conn.SetWriteBuffer(4096)
	handler := NewHandler(conn)

	accu := lendecoder.NewAccumulator(handler, 2, 1200)
	err := accu.ReadFrom(conn)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
}
Пример #14
0
func NewSession(conn *net.TCPConn, rc *turbo.RemotingConfig) *Session {

	conn.SetKeepAlive(true)
	conn.SetKeepAlivePeriod(rc.IdleTime * 2)
	//禁用nagle
	conn.SetNoDelay(true)
	conn.SetReadBuffer(rc.ReadBufferSize)
	conn.SetWriteBuffer(rc.WriteBufferSize)

	session := &Session{
		conn:         conn,
		br:           bufio.NewReaderSize(conn, rc.ReadBufferSize),
		bw:           bufio.NewWriterSize(conn, rc.WriteBufferSize),
		ReadChannel:  make(chan *packet.Packet, rc.ReadChannelSize),
		WriteChannel: make(chan *packet.Packet, rc.WriteChannelSize),
		isClose:      false,
		remoteAddr:   conn.RemoteAddr().String(),
		rc:           rc}
	return session
}
Пример #15
0
func handleConnection(listenConn *net.TCPConn) {
	listenConn.SetReadBuffer(INBUFSIZE)
	listenConn.SetTimeout(TIMEOUT)

	bufioReader := bufio.NewReader(listenConn)
	bufioWriter := bufio.NewWriter(listenConn)

	addr := listenConn.RemoteAddr()
	fmt.Printf("\nnetwork: %s\n", addr.Network())
	fmt.Printf("\naddr: %s\n", addr.String())

	for {
		fmt.Printf("\nSCHLEIFE\n")
		request, e := bufioReader.ReadBytes('!')
		if e != nil {
			break
		}
		requestLines := strings.Split(string(request), ";", 0)
		length := len(requestLines)
		if length > 0 {
			length--
		}
		requestLines = requestLines[0:length]
		for i, k := range requestLines {
			fmt.Printf("requestLines[%d]: \"%s\"\n", i, k)
		}
		infos := parseCommand(len(requestLines), requestLines)
		fmt.Printf("\nINFOS:\n")
		for i, k := range infos {
			fmt.Printf("\ninfos[%d]\"%s\"\n", i, k)
		}
		answer := strings.Join(infos, ";")
		answer = requestLines[0] + ";" + answer + ";!"
		fmt.Printf("\nSending: \"%s\"\n", answer)
		bufioWriter.WriteString(answer)
		bufioWriter.Flush()
		fmt.Printf("\nSENT\n")
	}
	listenConn.Close()
}
Пример #16
0
// ServeTCP ...
func (service *TcpService) ServeTCP(conn *net.TCPConn) (err error) {
	if service.keepAlive != nil {
		if err = conn.SetKeepAlive(service.keepAlive.(bool)); err != nil {
			return err
		}
	}
	if service.keepAlivePeriod != nil {
		if kap, ok := (net.Conn(conn)).(iKeepAlivePeriod); ok {
			if err = kap.SetKeepAlivePeriod(service.keepAlivePeriod.(time.Duration)); err != nil {
				return err
			}
		}
	}
	if service.linger != nil {
		if err = conn.SetLinger(service.linger.(int)); err != nil {
			return err
		}
	}
	if service.noDelay != nil {
		if err = conn.SetNoDelay(service.noDelay.(bool)); err != nil {
			return err
		}
	}
	if service.readBuffer != nil {
		if err = conn.SetReadBuffer(service.readBuffer.(int)); err != nil {
			return err
		}
	}
	if service.writeBuffer != nil {
		if err = conn.SetWriteBuffer(service.writeBuffer.(int)); err != nil {
			return err
		}
	}
	if service.config != nil {
		tlsConn := tls.Server(conn, service.config)
		tlsConn.Handshake()
		return service.Serve(tlsConn)
	}
	return service.Serve(conn)
}
Пример #17
0
// handle GET request. if value is there, return value, otherwise 'not found'
func handleGet(header []byte, conn *net.TCPConn) {
	var keylen uint16
	keylen = binary.BigEndian.Uint16(header[2:4])
	keybuf := make([]byte, int(keylen))
	conn.SetReadBuffer(int(keylen))
	conn.Read(keybuf)
	key := string(keybuf)

	// ===============
	rwmutex.RLock()
	val := kvmap[key].val
	kind := kvmap[key].kind

	var msg []byte
	if val != nil {
		msg = constructPacket(GET, kind, SUCCESS, val)
	} else {
		var empty []byte
		msg = constructPacket(GET, empty, NOTFOUND, []byte("Not found"))
	}
	conn.Write(msg)
	rwmutex.RUnlock()

}
Пример #18
0
// Handles incoming GET, SET, and UNKNOWN requests based on the packet header.
func handleRequest(conn *net.TCPConn) {

	header := make([]byte, 24)
	conn.SetReadBuffer(24)
	n, err := conn.Read(header)
	if err != nil || n != 24 {
		return
	}

	magic := header[0]
	if magic != REQUEST || n < HEADER_SIZE {
		handleUnknown(conn)
		return
	}

	opcode := header[1]
	if opcode == GET {
		handleGet(header, conn)
	} else if opcode == SET {
		handleSet(header, conn)
	} else {
		handleUnknown(conn)
	}
}
Пример #19
0
// Set the requested key to the requested value and respond with success
func handleSet(header []byte, conn *net.TCPConn) {
	var keylen uint16
	var extralen uint8
	var bodylen uint32
	keylen = binary.BigEndian.Uint16(header[2:4])
	extralen = header[4]
	bodylen = binary.BigEndian.Uint32(header[8:12])

	if bodylen < uint32(keylen)+uint32(extralen) {
		fmt.Printf("Error! Body length not long enough. Header: %X\n", header)
		fmt.Println("BodyLength = ", bodylen)
		return
	}

	body := make([]byte, bodylen)
	if bodylen <= MAX_INT {
		conn.SetReadBuffer(int(bodylen))
		conn.Read(body)
	} else { //size of body is larger than max ReadBuffer size
		restlen := int(bodylen - MAX_INT)
		rest := make([]byte, restlen)
		conn.SetReadBuffer(MAX_INT)
		conn.Read(body)
		conn.SetReadBuffer(restlen)
		conn.Read(rest)
		body = append(body, rest...)
	}

	extras := body[:extralen-4]
	key := string(body[extralen:(keylen + uint16(extralen))])
	val := body[(uint16(extralen) + keylen):bodylen]
	rwmutex.Lock()
	kvmap[key] = data{val, extras}

	var empty []byte
	msg := constructPacket(SET, empty, SUCCESS, empty)

	conn.Write(msg)
	rwmutex.Unlock()

}
Пример #20
0
// start a goroutine when a new connection is accepted
func handleClient(conn *net.TCPConn) {
	defer utils.PrintPanicStack()
	// set per-connection socket buffer
	//设置conn连接接受缓存的大小, 当超过缓存时, 会进入阻塞状态,等待被读取
	conn.SetReadBuffer(SO_RCVBUF)

	// set initial socket buffer
	//设置conn连接发送缓存的大小, 当超过缓存时, 会进入阻塞状态,等待被发送成功
	conn.SetWriteBuffer(SO_SNDBUF)

	// initial network control struct
	// 初始化2个字节数组, 用于存储header长度, 既后面要读取的文件长度
	header := make([]byte, 2)
	// 输入流通道, 解析后的数据将放入,等待被处理
	in := make(chan []byte)

	//设置延迟函数,当玩家断开连接时, 函数退出之前,关闭输入流
	defer func() {
		close(in) // session will close
	}()

	// create a new session object for the connection
	//创建session对象, 用于封装客户端和服务器的信息交换
	var sess Session
	host, port, err := net.SplitHostPort(conn.RemoteAddr().String())
	if err != nil {
		log.Error("cannot get remote address:", err)
		return
	}
	//存储用户ip
	sess.IP = net.ParseIP(host)
	//打印用户的ip和端口, 用户可能会双开?
	log.Infof("new connection from:%v port:%v", host, port)

	// session die signal
	sess_die := make(chan bool)

	//SESSION_DIE 监控有问题.................

	// create a write buffer
	// 创建写入buffer对象
	out := new_buffer(conn, sess_die)
	go out.start()

	// start one agent for handling packet
	//记录goroutine个数,让系统接收到关闭命令后,会阻塞主线程,至少所有agent线程退出,已保证数据落地
	wg.Add(1)
	go agent(&sess, in, out, sess_die)

	//network loop
	for {
		// solve dead line problem
		// 设置读超时时间, 如果在任意一次执行Read syscall 返回的时候,超过这个时间点, 则算超时
		conn.SetReadDeadline(time.Now().Add(TCP_READ_DEADLINE * time.Second))
		//先读取2个字节头文件长度
		n, err := io.ReadFull(conn, header)
		if err != nil {
			log.Warningf("read header failed, ip:%v reason:%v size:%v", sess.IP, err, n)
			return
		}
		//将2个字节数组转成int16类型, 不丢失精度
		size := binary.BigEndian.Uint16(header)

		// alloc a byte slice for reading
		// 创建一个指定长度的切片,用于存放具体内容
		payload := make([]byte, size)
		//read msg
		n, err = io.ReadFull(conn, payload)
		if err != nil {
			log.Warningf("read payload failed, ip:%v reason:%v size:%v", sess.IP, err, n)
			return
		}

		select {
		//接收的数据,转入in通道
		case in <- payload: //payload queued
			//监听sess_die 通道
		case <-sess_die:
			log.Warning("connection closed by logic, flag:%v ip:%v", sess.Flag, sess.IP)
			return
		}
	}

	// 好像没有处理连接超时, 如果玩家连上游戏后,一直未操作,再次链接时,会是新的连接?难道客户端在许久没有操作的情况下,先发一次ping, 如果有响应,继续操作,如果没响应,则执行重连?

	// 如果玩家已经退出了游戏,但是通过非正常途径退出的,这时,服务器还保留着该session, 当玩家再次登陆时, 原先的连接何时删除

}
Пример #21
0
// PIPELINE #1: handleClient
// the goroutine is used for reading incoming PACKETS
// each packet is defined as :
// | 2B size |     DATA       |
//
func handleClient(conn *net.TCPConn) {
	defer utils.PrintPanicStack()
	// set socket read buffer
	conn.SetReadBuffer(SO_RCVBUF)
	// set socket write buffer
	conn.SetWriteBuffer(SO_SNDBUF)

	// for reading the 2-Byte header
	header := make([]byte, 2)
	// the input channel for agent()
	in := make(chan []byte)
	defer func() {
		close(in) // session will close
	}()

	// create a new session object for the connection
	// and record it's IP address
	var sess Session
	host, port, err := net.SplitHostPort(conn.RemoteAddr().String())
	if err != nil {
		log.Error("cannot get remote address:", err)
		return
	}
	sess.IP = net.ParseIP(host)
	log.Infof("new connection from:%v port:%v", host, port)

	// session die signal, will be triggered by agent()
	sess.Die = make(chan struct{})

	// create a write buffer
	out := new_buffer(conn, sess.Die)
	go out.start()

	// start agent for PACKET processing
	wg.Add(1)
	go agent(&sess, in, out)

	// read loop
	for {
		// solve dead link problem:
		// physical disconnection without any communcation between client and server
		// will cause the read to block FOREVER, so a timeout is a rescue.
		conn.SetReadDeadline(time.Now().Add(TCP_READ_DEADLINE * time.Second))

		// read 2B header
		n, err := io.ReadFull(conn, header)
		if err != nil {
			log.Warningf("read header failed, ip:%v reason:%v size:%v", sess.IP, err, n)
			return
		}
		size := binary.BigEndian.Uint16(header)

		// alloc a byte slice of the size defined in the header for reading data
		payload := make([]byte, size)
		n, err = io.ReadFull(conn, payload)
		if err != nil {
			log.Warningf("read payload failed, ip:%v reason:%v size:%v", sess.IP, err, n)
			return
		}

		// deliver the data to the input queue of agent()
		select {
		case in <- payload: // payload queued
		case <-sess.Die:
			log.Warningf("connection closed by logic, flag:%v ip:%v", sess.Flag, sess.IP)
			return
		}
	}
}
Пример #22
0
// start a goroutine when a new connection is accepted
func handleClient(conn *net.TCPConn) {
	defer utils.PrintPanicStack()
	// set per-connection socket buffer
	conn.SetReadBuffer(SO_RCVBUF)

	// set initial socket buffer
	conn.SetWriteBuffer(SO_SNDBUF)

	// initial network control struct
	header := make([]byte, 2)
	in := make(chan []byte)
	defer func() {
		close(in) // session will close
	}()

	// create a new session object for the connection
	var sess Session
	host, port, err := net.SplitHostPort(conn.RemoteAddr().String())
	if err != nil {
		log.Error("cannot get remote address:", err)
		return
	}
	sess.IP = net.ParseIP(host)
	log.Infof("new connection from:%v port:%v", host, port)

	// session die signal
	sess.Die = make(chan struct{})

	// create a write buffer
	out := new_buffer(conn, sess.Die)
	go out.start()

	// start one agent for handling packet
	wg.Add(1)
	go agent(&sess, in, out)

	// network loop
	for {
		// solve dead link problem
		conn.SetReadDeadline(time.Now().Add(TCP_READ_DEADLINE * time.Second))
		n, err := io.ReadFull(conn, header)
		if err != nil {
			log.Warningf("read header failed, ip:%v reason:%v size:%v", sess.IP, err, n)
			return
		}
		size := binary.BigEndian.Uint16(header)

		// alloc a byte slice for reading
		payload := make([]byte, size)
		// read msg
		n, err = io.ReadFull(conn, payload)
		if err != nil {
			log.Warningf("read payload failed, ip:%v reason:%v size:%v", sess.IP, err, n)
			return
		}

		select {
		case in <- payload: // payload queued
		case <-sess.Die:
			log.Warningf("connection closed by logic, flag:%v ip:%v", sess.Flag, sess.IP)
			return
		}
	}
}
Пример #23
0
func (service *TcpService) ServeTCP(conn *net.TCPConn) (err error) {
	if service.keepAlive != nil {
		if err = conn.SetKeepAlive(service.keepAlive.(bool)); err != nil {
			return err
		}
	}
	if service.keepAlivePeriod != nil {
		if kap, ok := (net.Conn(conn)).(iKeepAlivePeriod); ok {
			if err = kap.SetKeepAlivePeriod(service.keepAlivePeriod.(time.Duration)); err != nil {
				return err
			}
		}
	}
	if service.linger != nil {
		if err = conn.SetLinger(service.linger.(int)); err != nil {
			return err
		}
	}
	if service.noDelay != nil {
		if err = conn.SetNoDelay(service.noDelay.(bool)); err != nil {
			return err
		}
	}
	if service.readBuffer != nil {
		if err = conn.SetReadBuffer(service.readBuffer.(int)); err != nil {
			return err
		}
	}
	if service.writeBuffer != nil {
		if err = conn.SetWriteBuffer(service.writeBuffer.(int)); err != nil {
			return err
		}
	}
	if service.timeout != nil {
		if err = conn.SetDeadline(time.Now().Add(service.timeout.(time.Duration))); err != nil {
			return err
		}
	}
	go func(conn net.Conn) {
		if service.config != nil {
			tlsConn := tls.Server(conn, service.config)
			tlsConn.Handshake()
			conn = tlsConn
		}
		var data []byte
		var err error
		for {
			if service.readTimeout != nil {
				err = conn.SetReadDeadline(time.Now().Add(service.readTimeout.(time.Duration)))
			}
			if err == nil {
				data, err = receiveDataOverTcp(conn)
			}
			if err == nil {
				data = service.Handle(data, conn)
				if service.writeTimeout != nil {
					err = conn.SetWriteDeadline(time.Now().Add(service.writeTimeout.(time.Duration)))
				}
				if err == nil {
					err = sendDataOverTcp(conn, data)
				}
			}
			if err != nil {
				conn.Close()
				break
			}
		}
	}(conn)
	return nil
}
Пример #24
0
func (server *TcpServer) handle() (err error) {
	defer func() {
		if e := recover(); e != nil && err == nil {
			err = fmt.Errorf("%v", e)
		}
	}()
	if server.listener == nil {
		return nil
	}
	var conn *net.TCPConn
	if conn, err = server.listener.AcceptTCP(); err != nil {
		return err
	}
	if server.keepAlive != nil {
		if err = conn.SetKeepAlive(server.keepAlive.(bool)); err != nil {
			return err
		}
	}
	if server.keepAlivePeriod != nil {
		if kap, ok := (net.Conn(conn)).(iKeepAlivePeriod); ok {
			if err = kap.SetKeepAlivePeriod(server.keepAlivePeriod.(time.Duration)); err != nil {
				return err
			}
		}
	}
	if server.linger != nil {
		if err = conn.SetLinger(server.linger.(int)); err != nil {
			return err
		}
	}
	if server.noDelay != nil {
		if err = conn.SetNoDelay(server.noDelay.(bool)); err != nil {
			return err
		}
	}
	if server.readBuffer != nil {
		if err = conn.SetReadBuffer(server.readBuffer.(int)); err != nil {
			return err
		}
	}
	if server.writerBuffer != nil {
		if err = conn.SetWriteBuffer(server.writerBuffer.(int)); err != nil {
			return err
		}
	}
	if server.deadline != nil {
		if err = conn.SetDeadline(server.deadline.(time.Time)); err != nil {
			return err
		}
	}
	if server.readDeadline != nil {
		if err = conn.SetReadDeadline(server.readDeadline.(time.Time)); err != nil {
			return err
		}
	}
	if server.writerDeadline != nil {
		if err = conn.SetWriteDeadline(server.writerDeadline.(time.Time)); err != nil {
			return err
		}
	}
	if server.config != nil {
		server.ServeTCP(tls.Client(conn, server.config))
	} else {
		server.ServeTCP(conn)
	}
	return nil
}
Пример #25
-1
func read_tcp_conn(tcpConn *net.TCPConn, connChan chan []byte) {

	buffer := make([]byte, 2048)

	tcpConn.SetReadBuffer(2048)

	for {

		n, err := tcpConn.Read(buffer[0:])

		if err != nil {

			log.Println("one tcp connection read function failed!")

			log.Println("one tcp connection close now!")

			tcpConn.Close()

			runtime.Goexit()

		} else {

			connChan <- buffer[0 : n-1]

		}

	}

}