예제 #1
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	log.Println("Waiting for configuration IP...")
	var options *bonjour.ServiceEntry
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			log.Println("Error receiving IP:", err.Error())
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		if err = json.Unmarshal(ip[1], &options); err != nil {
			log.Println("Error decoding options:", err.Error())
			continue
		}
		inPort.Close()
		break
	}

	log.Println("Started...")
	var err error
	bonjourCh, err = bonjour.Register(options.Instance, options.Service, options.Domain, options.Port, options.Text, nil)
	if err != nil {
		log.Println("Error registering service:", err.Error())
		exitCh <- syscall.SIGTERM
		return
	}

	// Block execution
	select {}
}
예제 #2
0
파일: main.go 프로젝트: vishnuvr/cascades
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	waitCh := make(chan bool)
	go func() {
		for {
			v := <-outCh
			if v && waitCh != nil {
				waitCh <- true
			}
			if !v {
				log.Println("OUT port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Output port connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		exitCh <- syscall.SIGTERM
		return
	}

	log.Println("Wait for configuration IP...")
	var interval time.Duration
	for {
		ip, err := intervalPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		interval, err = time.ParseDuration(string(ip[1]))
		if err != nil {
			log.Println("Error parsing duration from IP:", err.Error())
			continue
		}
		break
	}

	ticker := time.NewTicker(interval)
	log.Printf("Configured to tick with interval: %v", interval)

	log.Println("Started...")
	for v := range ticker.C {
		msg := fmt.Sprintf("%v", v.Unix())
		outPort.SendMessage(runtime.NewPacket([]byte(msg)))
	}
}
예제 #3
0
파일: main.go 프로젝트: vishnuvr/cascades
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	// Connections monitoring routine
	waitCh := make(chan bool)
	go func() {
		for {
			v := <-inCh
			if v && waitCh != nil {
				waitCh <- true
			}
			if !v {
				log.Println("IN port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Input port connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		exitCh <- syscall.SIGTERM
		return
	}

	log.Println("Started...")
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}
		switch {
		case runtime.IsPacket(ip):
			fmt.Println("IP:", string(ip[1]))
		case runtime.IsOpenBracket(ip):
			fmt.Println("[")
		case runtime.IsCloseBracket(ip):
			fmt.Println("]")
		}
	}
}
예제 #4
0
func mainLoop() {
	openPorts()
	defer closePorts()

	waitCh := make(chan bool)
	go func() {
		totalIn := 0
		totalOut := 0
		for {
			select {
			case v := <-inCh:
				if !v {
					log.Println("IN port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					totalIn++
				}
			case v := <-outCh:
				if !v {
					log.Println("OUT port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					totalOut++
				}
			}

			if totalIn >= 1 && totalOut >= 1 && waitCh != nil {
				waitCh <- true
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("One of the output ports is connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		os.Exit(1)
	}

	contexts = make(map[string]*caf.Context)
	var ip [][]byte
	for {
		ip, err = tmplPort.RecvMessageBytes(0)
		if err != nil {
			log.Println("Error receiving message:", err.Error())
			continue
		}

		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			log.Println("Received invalid IP")
			continue
		}

		err = json.Unmarshal(ip[1], &ctxTemplate)
		if err != nil {
			log.Println("ERROR: failed to unmarshal template:", err.Error())
			continue
		}
		log.Printf("Template specified: %+v", ctxTemplate)
		break
	}
	log.Println("Started...")

	for {
		results, err := poller.Poll(-1)
		if err != nil {
			log.Println("Error polling ports:", err.Error())
			continue
		}
		for _, r := range results {
			if r.Socket == nil {
				log.Println("ERROR: could not find socket in the polling results")
				continue
			}
			ip, err = r.Socket.RecvMessageBytes(0)
			if err != nil {
				log.Println("Error receiving message:", err.Error())
				continue
			}
			if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
				log.Println("Received invalid IP")
				continue
			}

			// Find the port index
			index, err := getPortIndex(r.Socket)
			if err != nil {
				log.Printf("Error processing IP: %v\n", err.Error())
				continue
			}

			// Update the corresponding context
			ctx, err := updateContext(index, ip[1])
			if err != nil {
				log.Printf("Error updating context: %v\n", err.Error())
				continue
			}

			if ctx.Determined {
				// Evaluate the context
				m1 := ctx.Matching
				m2, err := ctx.Evaluate()
				if err != nil {
					log.Printf("Error evaluating context %s: %v\n", ctx.ID, err.Error())
				} else {
					// Notify if matching status has changed
					if m1 != m2 {
						if matchPort != nil {
							out, _ := json.Marshal(ctx)
							matchPort.SendMessage(runtime.NewPacket(out))
						}
					}
				}
			}

			// Notify about the update (always)
			if updPort != nil {
				out, _ := json.Marshal(ctx)
				updPort.SendMessage(runtime.NewPacket(out))
			}
		}
	}
}
예제 #5
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	waitCh := make(chan bool)
	go func() {
		for {
			v := <-outCh
			if v && waitCh != nil {
				waitCh <- true
			}
			if !v {
				log.Println("OUT port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Output port connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		exitCh <- syscall.SIGTERM
		return
	}

	log.Println("Waiting for configuration IP...")
	var options *bonjour.ServiceRecord
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		if err = json.Unmarshal(ip[1], &options); err != nil {
			log.Println("Error decoding options:", err.Error())
			continue
		}
		inPort.Close()
		break
	}

	resolver, err = bonjour.NewResolver(nil)
	utils.AssertError(err)

	entries := make(chan *bonjour.ServiceEntry)
	err = resolver.Browse(options.Service, options.Domain, entries)
	utils.AssertError(err)

	log.Println("Started...")
	for e := range entries {
		data, err := json.Marshal(e)
		if err != nil {
			log.Println("Error encoding entry:", err.Error())
			continue
		}
		outPort.SendMessage(runtime.NewPacket(data))
	}

}
예제 #6
0
func main() {
	flag.Parse()

	if *jsonFlag {
		doc, _ := registryEntry.JSON()
		fmt.Println(string(doc))
		os.Exit(0)
	}

	log.SetFlags(0)
	if *debug {
		log.SetOutput(os.Stdout)
	} else {
		log.SetOutput(ioutil.Discard)
	}

	validateArgs()

	openPorts()
	defer closePorts()

	exitCh := utils.HandleInterruption()

	// Wait for the configuration on the options port
	var bindAddr string
	for {
		log.Println("Waiting for configuration...")
		ip, err := optionsPort.RecvMultipart(0)
		if err != nil {
			log.Println("Error receiving IP:", err.Error())
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		bindAddr = string(ip[1])
		break
	}
	optionsPort.Close()

	// Data from http handler and data to http handler
	inCh := make(chan httputils.HTTPResponse)
	outCh := make(chan HandlerRequest)

	go func(ctx *zmq.Context, endpoint string) {
		outPort, err = utils.CreateOutputPort(context, endpoint)
		utils.AssertError(err)

		// Map of uuid to requests
		dataMap := make(map[string]chan httputils.HTTPResponse)

		// Start listening in/out channels
		for {
			select {
			case data := <-outCh:
				dataMap[data.Request.Id] = data.ResponseCh
				ip, _ := httputils.Request2IP(data.Request)
				outPort.SendMultipart(ip, 0)
			case resp := <-inCh:
				if respCh, ok := dataMap[resp.Id]; ok {
					log.Println("Resolved channel for response", resp.Id)
					respCh <- resp
					delete(dataMap, resp.Id)
					continue
				}
				log.Println("Didn't find request handler mapping for a given ID", resp.Id)
			}
		}
	}(context, *outputEndpoint)

	// Web server goroutine
	go func() {
		mux := http.NewServeMux()
		mux.HandleFunc("/", Handler(outCh))

		s := &http.Server{
			Handler:        mux,
			ReadTimeout:    10 * time.Second,
			WriteTimeout:   10 * time.Second,
			MaxHeaderBytes: 1 << 20,
		}

		ln, err := net.Listen("tcp", bindAddr)
		if err != nil {
			log.Println(err.Error())
			exitCh <- syscall.SIGTERM
			return
		}

		log.Printf("Starting listening %v", bindAddr)
		err = s.Serve(ln)
		if err != nil {
			log.Println(err.Error())
			exitCh <- syscall.SIGTERM
			return
		}
	}()

	// Process incoming message forever
	for {
		ip, err := inPort.RecvMultipart(0)
		if err != nil {
			log.Println("Error receiving message:", err.Error())
			continue
		}
		if !runtime.IsValidIP(ip) {
			log.Println("Received invalid IP")
			continue
		}

		resp, err := httputils.IP2Response(ip)
		if err != nil {
			log.Printf("Error converting IP to response: %s", err.Error())
			continue
		}
		inCh <- *resp
	}
}
예제 #7
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	waitCh := make(chan bool)
	go func() {
		total := 0
		for {
			v := <-outCh
			if !v {
				log.Println("An OUT port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			} else {
				total++
			}
			// At least one output ports are opened
			if total >= 1 && waitCh != nil {
				waitCh <- true
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Ports connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		os.Exit(1)
	}

	// Setup socket poll items
	poller := zmq.NewPoller()
	poller.Add(intPort, zmq.POLLIN)
	poller.Add(reqPort, zmq.POLLIN)
	poller.Add(tmplPort, zmq.POLLIN)

	// This is obviously dangerous but we need it to deal with our custom CA's
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	client.Timeout = 30 * time.Second

	var (
		interval     time.Duration
		ip           [][]byte
		request      *requestIP
		propTemplate *caf.PropertyTemplate
		httpRequest  *http.Request
	)

	for {
		sockets, err := poller.Poll(-1)
		if err != nil {
			log.Println("Error polling ports:", err.Error())
			continue
		}
		for _, socket := range sockets {
			if socket.Socket == nil {
				log.Println("ERROR: could not find socket in polling items array")
				continue
			}
			ip, err = socket.Socket.RecvMessageBytes(0)
			if err != nil {
				log.Println("Error receiving message:", err.Error())
				continue
			}
			if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
				log.Println("Invalid IP:", ip)
				continue
			}
			switch socket.Socket {
			case intPort:
				interval, err = time.ParseDuration(string(ip[1]))
				log.Println("Interval specified:", interval)
			case reqPort:
				err = json.Unmarshal(ip[1], &request)
				if err != nil {
					log.Println("ERROR: failed to unmarshal request:", err.Error())
					continue
				}
				log.Println("Request specified:", request)
			case tmplPort:
				err = json.Unmarshal(ip[1], &propTemplate)
				if err != nil {
					log.Println("ERROR: failed to unmarshal template:", err.Error())
					continue
				}
				log.Printf("Template specified: %+v", propTemplate)

			default:
				log.Println("ERROR: IP from unhandled socket received!")
				continue
			}
		}
		if interval > 0 && request != nil && propTemplate != nil {
			log.Println("Component configured. Moving on...")
			break
		}
	}

	log.Println("Started...")
	ticker := time.NewTicker(interval)
	for _ = range ticker.C {
		httpRequest, err = http.NewRequest(request.Method, request.URL, nil)
		utils.AssertError(err)

		// Set the accepted Content-Type
		if request.ContentType != "" {
			httpRequest.Header.Add("Content-Type", request.ContentType)
		}

		// Set any additional headers if provided
		for k, v := range request.Headers {
			httpRequest.Header.Add(k, v[0])
		}

		response, err := client.Do(httpRequest)
		if err != nil {
			log.Printf("ERROR performing HTTP %s %s: %s\n", request.Method, request.URL, err.Error())
			if errPort != nil {
				errPort.SendMessageDontwait(runtime.NewPacket([]byte(err.Error())))
			}
			continue
		}

		resp, err := httputils.Response2Response(response)
		if err != nil {
			log.Println("ERROR converting response to reply:", err.Error())
			if errPort != nil {
				errPort.SendMessageDontwait(runtime.NewPacket([]byte(err.Error())))
			}
			continue
		}

		// Property output socket
		if propPort != nil {
			var data interface{}
			if strings.HasSuffix(request.ContentType, "json") {
				err = json.Unmarshal(resp.Body, &data)
				if err != nil {
					log.Println("ERROR unmarshaling the JSON response:", err.Error())
					continue
				}
			} else {
				// TODO: support other content-types
				log.Printf("WARNING processing of %s is not supported", request.ContentType)
				continue
			}

			prop, err := propTemplate.Fill(data)
			if err != nil {
				log.Println("ERROR filling template with data: ", err.Error())
				continue
			}

			out, _ := json.Marshal(prop)
			propPort.SendMessage(runtime.NewPacket(out))
		}

		// Extra output sockets (e.g., for debugging)
		if respPort != nil {
			ip, err = httputils.Response2IP(resp)
			if err != nil {
				log.Println("ERROR converting reply to IP:", err.Error())
				if errPort != nil {
					errPort.SendMessageDontwait(runtime.NewPacket([]byte(err.Error())))
				}
			} else {
				respPort.SendMessage(ip)
			}
		}
		if bodyPort != nil {
			bodyPort.SendMessage(runtime.NewPacket(resp.Body))
		}
	}
}
예제 #8
0
파일: main.go 프로젝트: vishnuvr/cascades
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	waitCh := make(chan bool)
	go func() {
		total := 0
		for {
			select {
			case v := <-inCh:
				if !v {
					log.Println("IN port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			case v := <-outCh:
				if !v {
					log.Println("OUT port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			}
			if total >= 2 && waitCh != nil {
				waitCh <- true
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Ports connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		exitCh <- syscall.SIGTERM
		return
	}

	log.Println("Waiting for configuration IP...")
	var delay time.Duration
	for {
		ip, err := delayPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		delay, err = time.ParseDuration(string(ip[1]))
		if err != nil {
			log.Println("Error parsing duration from IP:", err.Error())
			continue
		}
		break
	}
	delayPort.Close()

	log.Println("Started...")
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}
		time.Sleep(delay)
		outPort.SendMessage(ip)
	}
}
예제 #9
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	service := NewService()

	openPorts()
	defer closePorts()

	go func() {
		outPort, err = utils.CreateOutputPort("tcp/server.out", *outputEndpoint, outCh)
		utils.AssertError(err)
		for data := range service.Output {
			outPort.SendMessage(runtime.NewOpenBracket())
			outPort.SendMessage(runtime.NewPacket(data[0]))
			outPort.SendMessage(runtime.NewPacket(data[1]))
			outPort.SendMessage(runtime.NewCloseBracket())
		}
	}()

	waitCh := make(chan bool)
	go func() {
		total := 0
		for {
			select {
			case v := <-inCh:
				if !v {
					log.Println("IN port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			case v := <-outCh:
				if !v {
					log.Println("OUT port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			}
			if total >= 2 && waitCh != nil {
				waitCh <- true
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Ports connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		exitCh <- syscall.SIGTERM
		return
	}

	// Wait for the configuration on the options port
	log.Println("Waiting for configuration...")
	var bindAddr string
	for {
		ip, err := optionsPort.RecvMessageBytes(0)
		if err != nil {
			log.Println("Error receiving IP:", err.Error())
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		bindAddr = string(ip[1])
		break
	}
	optionsPort.Close()

	// Create binding address listener
	laddr, err := net.ResolveTCPAddr("tcp", bindAddr)
	if err != nil {
		log.Fatalln(err)
	}
	listener, err := net.ListenTCP("tcp", laddr)
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("Listening on", listener.Addr())

	go service.Serve(listener)

	log.Println("Started...")
	var (
		connID string
		data   []byte
	)
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			log.Println("Error receiving message:", err.Error())
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}
		switch {
		case runtime.IsOpenBracket(ip):
			connID = ""
			data = nil
		case runtime.IsPacket(ip):
			if connID == "" {
				connID = string(ip[1])
			} else {
				data = ip[1]
			}
		case runtime.IsCloseBracket(ip):
			service.Dispatch(connID, data)
		}
	}
}
예제 #10
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	// Receiver routine
	go func() {
		inPort, err = utils.CreateInputPort("websocket/server.in", *inputEndpoint, inCh)
		utils.AssertError(err)
		defer inPort.Close()
		for {
			ip, err := inPort.RecvMessageBytes(0)
			if err != nil {
				continue
			}
			if !runtime.IsValidIP(ip) {
				continue
			}
			msg, err := wsutils.IP2Message(ip)
			if err != nil {
				log.Println("Failed to convert IP to Message:", err.Error())
				continue
			}
			log.Printf("Received response: %#v\n", msg)
			DefaultHub.Outgoing <- *msg
		}
	}()

	// Sender routine
	go func() {
		outPort, err = utils.CreateOutputPort("websocket/server.out", *outputEndpoint, outCh)
		utils.AssertError(err)
		defer outPort.Close()
		for msg := range DefaultHub.Incoming {
			log.Printf("Received data from connection: %#v\n", msg)
			ip, err := wsutils.Message2IP(&msg)
			if err != nil {
				log.Println("Failed to convert Message to IP:", err.Error())
				continue
			}
			outPort.SendMessageDontwait(ip)
		}
	}()

	waitCh := make(chan bool)
	go func() {
		total := 0
		for {
			select {
			case v := <-inCh:
				if !v {
					log.Println("IN port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			case v := <-outCh:
				if !v {
					log.Println("OUT port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			}
			if total >= 2 && waitCh != nil {
				waitCh <- true
			}
		}
	}()

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Ports connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		exitCh <- syscall.SIGTERM
		return
	}

	log.Println("Waiting for configuration...")
	var bindAddr string
	for {
		ip, err := optionsPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		bindAddr = string(ip[1])
		break
	}
	optionsPort.Close()

	// Configure & start websocket server
	http.Handle("/", websocket.Handler(WebHandler))
	go DefaultHub.Start()

	// Listen & serve
	log.Printf("Listening %v", bindAddr)
	log.Printf("Web-socket endpoint: ws://%s/", bindAddr)
	if err := http.ListenAndServe(bindAddr, nil); err != nil {
		log.Fatal("ListenAndServe Error:", err)
	}
}
예제 #11
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	waitCh := make(chan bool)
	go func() {
		total := 0
		for {
			v := <-outCh
			if !v {
				log.Println("An OUT port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			} else {
				total++
			}
			// At least one output ports are opened
			if total >= 1 && waitCh != nil {
				waitCh <- true
			}
		}
	}()

	log.Println("Waiting for options to arrive...")
	var (
		ip            [][]byte
		clientOptions *mqtt.ClientOptions
		client        *mqtt.MqttClient
		defaultTopic  string
		qos           mqtt.QoS
	)

	// Setup socket poll items
	poller := zmq.NewPoller()
	poller.Add(optsPort, zmq.POLLIN)
	poller.Add(tmplPort, zmq.POLLIN)

	for {
		sockets, err := poller.Poll(-1)
		if err != nil {
			log.Println("Error polling ports:", err.Error())
			continue
		}
		for _, socket := range sockets {
			if socket.Socket == nil {
				log.Println("ERROR: could not find socket in polling items array")
				continue
			}
			ip, err = socket.Socket.RecvMessageBytes(0)
			if err != nil {
				log.Println("Error receiving message:", err.Error())
				continue
			}
			if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
				log.Println("Invalid IP:", ip)
				continue
			}
			switch socket.Socket {
			case optsPort:
				err = json.Unmarshal(ip[1], &options)
				if err != nil {
					log.Println("ERROR: failed to unmarshal options:", err.Error())
					continue
				}
				clientOptions, defaultTopic, qos, err = helper.ParseOptionsURI(options.OptionsURI)
				if err != nil {
					log.Printf("Failed to parse connection uri. Error: %s", err.Error())
					continue
				}
				log.Println("Options specified:", options)
			case tmplPort:
				err = json.Unmarshal(ip[1], &propTemplate)
				if err != nil {
					log.Println("ERROR: failed to unmarshal template:", err.Error())
					continue
				}
				log.Printf("Template specified: %+v", propTemplate)

			default:
				log.Println("ERROR: IP from unhandled socket received!")
				continue
			}

			if defaultTopic != "" && clientOptions != nil && propTemplate != nil {
				log.Println("Component configured. Moving on...")
				break
			}
		}

		client = mqtt.NewClient(clientOptions)
		if _, err = client.Start(); err != nil {
			log.Printf("Failed to create MQTT client. Error: %s", err.Error())
			continue
		}

		defer client.Disconnect(1e6)

		optsPort.Close()
		tmplPort.Close()
		break
	}

	log.Println("Started...")
	topicFilter, err := mqtt.NewTopicFilter(defaultTopic, byte(qos))
	utils.AssertError(err)
	_, err = client.StartSubscription(messageHandler, topicFilter)
	utils.AssertError(err)

	ticker := time.Tick(1 * time.Second)
	for _ = range ticker {
	}
}
예제 #12
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

	ports := 1
	if errPort != nil {
		ports++
	}

	waitCh := make(chan bool)
	go func(num int) {
		total := 0
		for {
			select {
			case v := <-inCh:
				if !v {
					log.Println("IN port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			case v := <-errCh:
				if !v {
					log.Println("ERR port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			}
			if total >= num && waitCh != nil {
				waitCh <- true
			}
		}
	}(ports)

	log.Println("Waiting for port connections to establish... ")
	select {
	case <-waitCh:
		log.Println("Ports connected")
		waitCh = nil
	case <-time.Tick(30 * time.Second):
		log.Println("Timeout: port connections were not established within provided interval")
		exitCh <- syscall.SIGTERM
		return
	}

	log.Println("Waiting for options to arrive...")
	var (
		influxHost, influxUsername, influxPassword, influxDB, tmpStr string
		parts, kv                                                    []string
		ip                                                           [][]byte
	)
	for {
		ip, err = optionsPort.RecvMessageBytes(0)
		if err != nil {
			log.Println("Error receiving IP:", err.Error())
			continue
		}
		if !runtime.IsValidIP(ip) || !runtime.IsPacket(ip) {
			continue
		}
		tmpStr = string(ip[1])
		parts = strings.Split(tmpStr, ",")
		for _, p := range parts {
			kv = strings.Split(p, "=")
			if len(kv) != 2 {
				continue
			}
			switch kv[0] {
			case "host":
				influxHost = kv[1]
			case "user":
				influxUsername = kv[1]
			case "pass":
				influxPassword = kv[1]
			case "db":
				influxDB = kv[1]
			}
		}
		optionsPort.Close()
		break
	}

	var (
		config *influxdb.ClientConfig
		client *influxdb.Client
	)
	config = &influxdb.ClientConfig{
		Host:     influxHost,
		Username: influxUsername,
		Password: influxPassword,
		Database: influxDB,
	}
	log.Printf("Using ClientConfig = %#v", config)
	client, err := influxdb.NewClient(config)
	if err != nil {
		fmt.Println("Error creating InfluxDB client:", err.Error())
		exitCh <- syscall.SIGTERM
		return
	}

	log.Println("Started...")
	var series *influxdb.Series
	for {
		ip, err = inPort.RecvMessageBytes(0)
		if err != nil {
			log.Println("Error receiving message:", err.Error())
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}
		err = json.Unmarshal(ip[1], &series)
		if err != nil {
			log.Println("Failed to decode incoming series:", err.Error())
			continue
		}

		if err = client.WriteSeries([]*influxdb.Series{series}); err != nil {
			log.Println("Error writing series:", err.Error())
			if errPort != nil {
				errPort.SendMessage(runtime.NewPacket([]byte(err.Error())))
			}
			continue
		}
	}
}