Beispiel #1
0
func NewMaster() *Master {
	address, err := net.ResolveTCPAddr("tcp", config.CORE_HOST+":"+strconv.Itoa(config.CORE_PORT))
	if err != nil {
		utils.Print("Master: Error resolving TCP address:", err)
		return nil
	}
	l, err := net.ListenTCP("tcp", address)
	if err != nil {
		utils.Print("Master: Error listening to the TCP address:", err)
		return nil
	}
	master := &Master{
		address:            address,
		listener:           l,
		quit:               make(chan int),
		newConnections:     make(chan *net.TCPConn),
		deadConnections:    make(chan *net.TCPConn),
		validConnections:   make(map[*net.TCPConn]bool),
		messages:           make(chan *Packet),
		Services:           []*Service{},
		ServiceById:        make(map[uint8]*Service),
		SubscriptionMap:    NewSubscriptionMap(),
		commandInterpreter: NewCommandInterpreter(),
		packetReader:       nil,
		LastPacketId:       make(map[uint8]uint),
	}
	master.packetReader = NewPacketReader(master)
	return master
}
Beispiel #2
0
func (s *Service) Write(packet *Packet) {
	if !s.master.IsValidConnection(s.Connection) {
		return
	}
	if config.DEBUG {
		utils.Debug(s.Connection.LocalAddr(), "->", s.Connection.RemoteAddr(), "Len:", packet.ContentLength, "Packet:", packet)
	} else {
		utils.Print(s.Connection.LocalAddr(), "->", s.Connection.RemoteAddr(), "Len:", packet.ContentLength)
	}
	_, err := s.Connection.Write(packet.Prepare())
	if err != nil {
		netOpError, ok := err.(*net.OpError)
		if err == io.EOF || err.Error()[0:11] == "WSARecv tcp" || (ok && (netOpError.Err.Error() == "use of closed network connection" || netOpError.Err.Error() == "read: connection reset by peer")) {
			s.master.RemoveValidConnection(s.Connection)
		}
	}
}
func (r *PacketReader) Listen(conn *net.TCPConn) {

	for _, connection := range r.connections {
		if connection == conn {
			utils.Debug("PacketReader: Already listening on Connection", conn, ". Skipped enabling another listener.")
			return
		}
	}
	r.connections = append(r.connections, conn)

	utils.Debug("PacketReader: Now listening on Connection:", conn)
	r.recovering[conn] = []byte{}
	defer conn.Close()
LoopListen:
	for r.master.IsValidConnection(conn) {
		select {
		case <-r.quit:
			utils.Debug("PacketReader: LoopListen stopped. (Quit)", conn)
			break LoopListen
		default:
			if len(r.recovering[conn]) > 0 {
				r.Recover(conn)
				if !r.master.IsValidConnection(conn) {
					utils.Debug("PacketReader: LoopListen stopped. (Recovering failed)", conn)
					r.master.deadConnections <- conn
					break LoopListen
				}
			} else {
				packet, err := r.Read(conn)
				if err != nil {
					netOpError, ok := err.(*net.OpError)
					if err == io.EOF || err.Error()[0:11] == "WSARecv tcp" || (ok && netOpError.Err.Error() == "read: connection reset by peer") {
						r.master.SetValidConnection(conn, false)
						r.master.deadConnections <- conn
						utils.Debug("PacketReader: LoopListen stopped. (Client disconnected)", conn)
						break LoopListen
					}
					if ok && netOpError.Err.Error() == "use of closed network connection" {
						r.master.SetValidConnection(conn, false)
						r.master.deadConnections <- conn
						utils.Debug("PacketReader: LoopListen stopped. (Lost Connection)", conn)
						break LoopListen
					}
					utils.Debug("PacketReader: Error reading a packet for Connection", conn, ":", err)
					continue
				}
				if config.DEBUG {
					utils.Debug(conn.RemoteAddr(), "->", conn.LocalAddr(), "Len:", packet.ContentLength, "Packet:", packet)
				} else {
					utils.Print(conn.RemoteAddr(), "->", conn.LocalAddr(), "Len:", packet.ContentLength)
				}
				r.master.NewMessage(packet)
			}
		}
	}
	for index, connection := range r.connections {
		if connection == conn {
			r.connections = append(r.connections[:index], r.connections[index+1:]...)
			break
		}
	}
	delete(r.recovering, conn)
	utils.Debug("PacketReader stopped listening on Connection:", conn)
}
Beispiel #4
0
func main() {

	runtime.GOMAXPROCS(runtime.NumCPU())
	if config.LOG {
		logDirectory := config.LOGDIR
		if len(config.LOGDIR) > 0 && config.LOGDIR[len(config.LOGDIR)-1] != '/' {
			logDirectory = logDirectory + "/"
		}
		f, err := os.OpenFile(logDirectory+"log_"+time.Now().Format("02-01-2006_15-04")+".txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			log.Fatalf("error opening file: %v", err)
		}
		defer f.Close()
		log.SetOutput(f)
	}

	var serviceId uint8 = 1
	serviceName := "ServiceTestName"
	tunnelHost := "core.craftolution.de"
	tunnelService := 1
	tunnelPort := 8123

	p := core.ConstructPacket(nil, serviceId, core.PACKETTYPE_CONNECT, 1, []byte{})
	p.AppendContent(utils.UintToByte(uint(len(serviceName)), 1))
	p.AppendContent([]byte(serviceName))
	p.AppendContent(utils.UintToByte(uint(len(tunnelHost)), 1))
	p.AppendContent([]byte(tunnelHost))
	p.AppendContent(utils.UintToByte(uint(tunnelService), 1))
	p.AppendContent(utils.UintToByte(uint(tunnelPort), 2))
	p.Prepare()

	master := core.NewMaster()
	if master == nil {
		return
	}

	var cmds []commands.Command = []commands.Command{}
	cmds = append(cmds, commands.NewConnectCommand(master))
	cmds = append(cmds, commands.NewDisconnectCommand(master))
	cmds = append(cmds, commands.NewSubscribeCommand(master))
	cmds = append(cmds, commands.NewUnsubscribeCommand(master))
	cmds = append(cmds, commands.NewListServicesCommand(master))
	cmds = append(cmds, commands.NewAskTunnelCommand(master))
	cmds = append(cmds, commands.NewSyncTimeCommand(master))
	cmds = append(cmds, commands.NewNothingCommand(master))

	clients := []*net.TCPConn{}

	go func() {
		if !config.RUN_TEST {
			return
		}

		utils.Print("Running test, program will quit automatically when the test is finished. (ETA: 1 min)")
		address, err := net.ResolveTCPAddr("tcp", config.CORE_HOST+":"+strconv.Itoa(config.CORE_PORT))
		if err != nil {
			utils.Print(err)
		}

		time.Sleep(time.Duration(3) * time.Second)
		for i := 0; i < 100; i++ {
			conn, err := net.DialTCP("tcp", nil, address)
			if err != nil {
				utils.Print(err)
				continue
			}
			serviceName := "Service " + strconv.Itoa(i)
			connectPacket := core.ConstructPacket(nil, uint8(i), core.PACKETTYPE_CONNECT, 1, []byte{})
			connectPacket.AppendContent(utils.UintToByte(uint(len(serviceName)), 1))
			connectPacket.AppendContent([]byte(serviceName))
			connectPacket.AppendContent(utils.UintToByte(uint(len(tunnelHost)), 1))
			connectPacket.AppendContent([]byte(tunnelHost))
			connectPacket.AppendContent(utils.UintToByte(uint(tunnelService), 1))
			connectPacket.AppendContent(utils.UintToByte(uint(tunnelPort), 2))
			conn.Write(connectPacket.Prepare())
			clients = append(clients, conn)
			time.Sleep(time.Duration(10) * time.Millisecond)

			listServicesPacket := core.ConstructPacket(nil, uint8(i), core.PACKETTYPE_LIST_SERVICES, 2, []byte{})
			conn.Write(listServicesPacket.Prepare())
			time.Sleep(time.Duration(10) * time.Millisecond)
		}

		time.Sleep(time.Duration(3) * time.Second)
		for i := 0; i < 100; i++ {
			conn := clients[i]
			disconnectPacket := core.ConstructPacket(nil, uint8(i), core.PACKETTYPE_DISCONNECT, 3, []byte{})
			conn.Write(disconnectPacket.Prepare())
			time.Sleep(time.Duration(10) * time.Millisecond)
		}

		time.Sleep(time.Duration(3) * time.Second)
		for i := 0; i < 100; i++ {
			clients[i].Close()
			time.Sleep(time.Duration(10) * time.Millisecond)
		}

		time.Sleep(time.Duration(3) * time.Second)
		clients := []*net.TCPConn{}
		for i := 1; i < 5; i++ {
			conn, err := net.DialTCP("tcp", nil, address)
			if err != nil {
				utils.Print(err)
				continue
			}
			serviceName := "Service " + strconv.Itoa(i)
			connectPacket := core.ConstructPacket(nil, uint8(i), core.PACKETTYPE_CONNECT, 1, []byte{})
			connectPacket.AppendContent(utils.UintToByte(uint(len(serviceName)), 1))
			connectPacket.AppendContent([]byte(serviceName))
			connectPacket.AppendContent(utils.UintToByte(uint(len(tunnelHost)), 1))
			connectPacket.AppendContent([]byte(tunnelHost))
			connectPacket.AppendContent(utils.UintToByte(uint(4), 1))
			connectPacket.AppendContent(utils.UintToByte(uint(1234), 2))
			connectPacket.AppendContent(utils.UintToByte(uint(2), 1))
			connectPacket.AppendContent(utils.UintToByte(uint(1235), 2))
			conn.Write(connectPacket.Prepare())
			clients = append(clients, conn)
			time.Sleep(time.Duration(10) * time.Millisecond)

			askTunnelPacket := core.ConstructPacket(nil, uint8(i), core.PACKETTYPE_ASK_TUNNEL, 2, []byte{})
			askTunnelPacket.AppendContent(utils.UintToByte(1, 1))
			askTunnelPacket.AppendContent(utils.UintToByte(2, 1))
			askTunnelPacket.AppendContent(utils.UintToByte(3, 1))
			askTunnelPacket.AppendContent(utils.UintToByte(4, 1))
			conn.Write(askTunnelPacket.Prepare())
			time.Sleep(time.Duration(10) * time.Millisecond)
		}

		time.Sleep(time.Duration(3) * time.Second)
		subscribePacket := core.ConstructPacket(nil, uint8(1), core.PACKETTYPE_SUBSCRIBE, 3, []byte{})
		subscribePacket.AppendContent(utils.UintToByte(14, 1))
		clients[0].Write(subscribePacket.Prepare())

		subscribePacket.ServiceId = uint8(4)
		subscribePacket.AppendContent(utils.UintToByte(1, 1))
		subscribePacket.AppendContent(utils.UintToByte(11, 1))
		clients[3].Write(subscribePacket.Prepare())

		time.Sleep(time.Duration(3) * time.Second)
		dataPacket := core.ConstructPacket(nil, uint8(2), uint8(13), 3, []byte{})
		dataPacket.AppendContent([]byte{8, 3, 7})
		for i := 10; i < 15; i++ {
			dataPacket.Next()
			dataPacket.PacketType = uint8(i)
			clients[1].Write(dataPacket.Prepare())
			time.Sleep(time.Duration(10) * time.Millisecond)
		}

		time.Sleep(time.Duration(3) * time.Second)
		disconnectPacket := core.ConstructPacket(nil, uint8(3), core.PACKETTYPE_DISCONNECT, 4, []byte{})
		clients[2].Write(disconnectPacket.Prepare())

		// no disconnect packets for other clients, test master functionality...
		time.Sleep(time.Duration(3) * time.Second)
		for i := 0; i < 4; i++ {
			clients[i].Close()
			time.Sleep(time.Duration(10) * time.Millisecond)
		}

		time.Sleep(time.Duration(3) * time.Second)
		master.Quit()

	}()

	master.Listen()

}
Beispiel #5
0
func (master *Master) Listen() {
	utils.Debug("Master: Now listening for TCP connections.")

	running := true

	// fetch new tcp connections parallel
	go func() {

	LoopConnector:
		for running {
			select {
			case <-master.quit:
				running = false
				break LoopConnector
			default:
				conn, err := master.listener.AcceptTCP()
				if err != nil {
					if err == io.EOF || err.Error()[0:11] != "WSARecv tcp" {
						running = false
						break LoopConnector
					}
					netOpError, ok := err.(*net.OpError)
					if ok && (netOpError.Err.Error() == "use of closed network connection" || netOpError.Err.Error() == "read: connection reset by peer") {
						running = false
						break LoopConnector
					}
					utils.Debug("Master: Error accepting new TCP connection:", err)
					continue
				}
				master.newConnections <- conn
			}
		}
		utils.Debug("Master: LoopConnector stopped.")

	}()

LoopWorker:
	for running {
		select {
		case <-master.quit:
			utils.Debug("Master: LoopWorker stopped.")
			break LoopWorker
		case conn := <-master.newConnections:
			master.AddValidConnection(conn)
			go master.packetReader.Listen(conn)
		case conn := <-master.deadConnections:
			master.RemoveValidConnection(conn)
			services := master.Services
			for _, service := range services {
				if service.Connection == conn {
					master.DisconnectService(service)
				}
			}
		case message := <-master.messages:
			if !message.IsData() {
				service := master.ServiceById[message.ServiceId]
				err := master.GetCommandInterpreter().Handle(message, service)
				if err != nil {
					utils.Debug("Master WARN: CommandInterpreter couldn't handle packet:", err)
				}
			}
			subscribers := master.SubscriptionMap.GetServicesForPacketType(message.PacketType)
			for _, service := range subscribers {
				service.Write(message)
			}
		}
	}
	utils.Print("Master stopped.")
}