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

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

	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("Started...")
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			log.Println("Received invalid IP")
			continue
		}
		for _, port = range outPortArray {
			port.SendMessage(ip)
		}
	}
}
Example #2
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 {}
}
Example #3
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("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)))
	}
}
Example #4
0
// 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("]")
		}
	}
}
Example #5
0
// 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 template...")
	var (
		t  *template.Template
		ip [][]byte
	)
	for {
		ip, err = tplPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			log.Println("Invalid IP:", ip)
			continue
		}
		t = template.New("Current template")
		t, err = t.Parse(string(ip[1]))
		if err != nil {
			log.Println("Failed to configure component:", err.Error())
			continue
		}
		break
	}
	tplPort.Close()

	log.Println("Started...")
	var (
		buf  *bytes.Buffer
		data map[string]interface{}
	)
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}

		err = json.Unmarshal(ip[1], &data)
		if err != nil {
			log.Println(err.Error())
			continue
		}

		buf = bytes.NewBufferString("")
		err = t.Execute(buf, data)
		if err != nil {
			log.Println(err.Error())
			continue
		}

		outPort.SendMessage(runtime.NewPacket(buf.Bytes()))
	}
}
Example #6
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)
		}
	}
}
Example #7
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)
	}
}
Example #8
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

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

	waitCh := make(chan bool)
	inExitCh := make(chan bool, 1)
	go func(num int) {
		total := 0
		for {
			select {
			case v := <-inCh:
				if v {
					total++
				} else {
					inExitCh <- true
				}
			case v := <-outCh:
				if !v {
					log.Println("OUT 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
		break
	}

	log.Println("Started...")
	for {
		ip, err := inPort.RecvMessageBytes(zmq.DONTWAIT)
		if err != nil {
			select {
			case <-inExitCh:
				log.Println("DIR port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			default:
				// IN port is still open
			}
			time.Sleep(2 * time.Second)
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}
		dir := string(ip[1])
		err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !info.IsDir() {
				outPort.SendMessage(runtime.NewPacket([]byte(path)))
			}
			return nil
		})
		if err != nil {
			log.Printf("ERROR openning file %s: %s", dir, err.Error())
			if errPort != nil {
				errPort.SendMessage(runtime.NewPacket([]byte(err.Error())))
			}
			continue
		}

		select {
		case <-inCh:
			log.Println("IN port is closed. Interrupting execution")
			exitCh <- syscall.SIGTERM
			break
		default:
			// IN port is still open
		}
	}
}
Example #9
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

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

	waitCh := make(chan bool)
	reqExitCh := make(chan bool, 1)
	go func(num int) {
		total := 0
		for {
			select {
			case v := <-reqCh:
				if v {
					total++
				} else {
					reqExitCh <- true
				}
			case v := <-bodyCh:
				if !v {
					log.Println("BODY port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				} else {
					total++
				}
			case v := <-respCh:
				if !v {
					log.Println("RESP 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
	}

	// 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

	// Main loop
	var (
		ip            [][]byte
		clientOptions *httputils.HTTPClientOptions
		request       *http.Request
	)

	log.Println("Started")

	for {
		ip, err = reqPort.RecvMessageBytes(zmq.DONTWAIT)
		if err != nil {
			select {
			case <-reqExitCh:
				log.Println("REQ port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			default:
				// IN port is still open
			}
			time.Sleep(2 * time.Second)
			continue
		}
		if !runtime.IsValidIP(ip) {
			log.Println("Invalid IP:", ip)
			continue
		}

		err = json.Unmarshal(ip[1], &clientOptions)
		if err != nil {
			log.Println("ERROR: failed to unmarshal request options:", err.Error())
			continue
		}
		if clientOptions == nil {
			log.Println("ERROR: received nil request options")
			continue
		}

		if clientOptions.Form != nil {
			request, err = http.NewRequest(clientOptions.Method, clientOptions.URL, strings.NewReader(clientOptions.Form.Encode()))
		} else {
			request, err = http.NewRequest(clientOptions.Method, clientOptions.URL, nil)
		}
		utils.AssertError(err)

		if clientOptions.ContentType != "" {
			request.Header.Add("Content-Type", clientOptions.ContentType)
		}

		for k, v := range clientOptions.Headers {
			request.Header.Add(k, v[0])
		}

		response, err := client.Do(request)
		if err != nil {
			log.Printf("ERROR performing HTTP %s %s: %s", request.Method, request.URL, err.Error())
			if errPort != nil {
				errPort.SendMessageDontwait(runtime.NewPacket([]byte(err.Error())))
			}
			clientOptions = nil
			continue
		}
		resp, err := httputils.Response2Response(response)
		if err != nil {
			log.Printf("ERROR converting response to reply: %s", err.Error())
			if errPort != nil {
				errPort.SendMessageDontwait(runtime.NewPacket([]byte(err.Error())))
			}
			clientOptions = nil
			continue
		}
		ip, err = httputils.Response2IP(resp)
		if err != nil {
			log.Printf("ERROR converting reply to IP: %s", err.Error())
			if errPort != nil {
				errPort.SendMessageDontwait(runtime.NewPacket([]byte(err.Error())))
			}
			clientOptions = nil
			continue
		}

		if respPort != nil {
			respPort.SendMessage(ip)
		}
		if bodyPort != nil {
			bodyPort.SendMessage(runtime.NewPacket(resp.Body))
		}

		select {
		case <-reqCh:
			log.Println("REQ port is closed. Interrupting execution")
			exitCh <- syscall.SIGTERM
			break
		default:
			// file port is still open
		}

		clientOptions = nil
		continue
	}
}
Example #10
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))
	}

}
Example #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 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))
		}
	}
}
Example #12
0
// 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 options...")
	var (
		ip [][]byte
	)
	for {
		ip, err = optionsPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			log.Println("Invalid IP:", ip)
			continue
		}
		err = json.Unmarshal(ip[1], &opts)
		if err != nil {
			log.Println("Failed to resolve options:", err.Error())
			continue
		}
		log.Printf("Using options: %#v", opts)
		break
	}
	optionsPort.Close()

	/*
		if err = opts.Validate(); err != nil {
			log.Println("ERROR: Invalid options:", err.Error())
			ch <- syscall.SIGTERM
			return
		}
	*/

	localCache = NewCache(time.Duration(opts.DefaultExpiration)*time.Second, time.Duration(opts.CleanupInterval)*time.Second)
	if opts.IsPersistent() {
		log.Println("Cache is persistent. Using file", opts.File)
		err = localCache.LoadFile(opts.File)
		if err != nil {
			log.Println("WARNING: Failed to load cache from file", opts.File)
		}
	}

	log.Println("Started...")
loop:
	for {
		ip, err = inPort.RecvMessageBytes(zmq.DONTWAIT)
		if err != nil {
			select {
			case <-loopCh:
				log.Println("Main loop shutdown requested")
				break loop
			default:
			}
			time.Sleep(2 * time.Second)
			continue
		}

		if !runtime.IsValidIP(ip) {
			log.Println("Invalid IP:", ip)
			continue
		}

		key := fmt.Sprintf("%x", md5.Sum(ip[1]))
		if _, found := localCache.Get(key); found {
			log.Println("Cache HIT. Not forwarding this IP")
			continue
		}

		log.Println("Cache MISS. Forwarding")

		outPort.SendMessage(ip)

		localCache.Add(key, 1, 0)
	}

	if opts.IsPersistent() {
		log.Println("Saving current cache to", opts.File)
		err = localCache.SaveFile(opts.File)
		if err != nil {
			log.Println("ERROR saving cache to file:", err.Error())
		}
	}
}
Example #13
0
// 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
	}

	go func() {
		log.Println("Started crashing goroutine...")
		time.Sleep(7 * time.Second)
		os.Exit(1)
	}()

	log.Println("Started...")
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}
		outPort.SendMessage(ip)
	}
}
Example #14
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()

	poller.Add(requestPort, zmq.POLLIN)

	exitCh := utils.HandleInterruption()
	err = runtime.SetupShutdownByDisconnect(requestPort, "http-router.in", exitCh)
	utils.AssertError(err)

	// Main loop
	var (
		index       int = -1
		outputIndex int = -1
		params      url.Values
		ip          [][]byte
		pLength     int     = len(pollItems)
		router      *Router = NewRouter()
	)
	for {
		// Poll sockets
		log.Println("Polling sockets...")

		sockets, err := poller.Poll(-1)
		if err != nil {
			log.Println("Error polling ports:", err.Error())
			os.Exit(1)
		}

		for index, s := range sockets {
			ip, err = s.Socket.RecvMessageBytes(0)
			if err != nil {
				log.Printf("Failed to receive data. Error: %s", err.Error())
				continue
			}
			if !runtime.IsValidIP(ip) {
				log.Println("Received invalid IP")
				continue
			}
		}

		// Pattern arrived

		if index < pLength-1 {
			// Close pattern socket
			port = pollItems[index].Socket
			port.Close()

			// Resolve corresponding output socket index
			outputIndex = -1
			for i, s := range patternPorts {
				if s == port {
					outputIndex = i
				}
			}
			if outputIndex == -1 {
				log.Printf("Failed to resolve output socket index")
				continue
			}

			// Remove closed socket from polling items
			pollItems = append(pollItems[:index], pollItems[index+1:]...)
			pLength -= 1

			// Add pattern to router
			parts := strings.Split(string(ip[1]), " ")
			method := strings.ToUpper(strings.TrimSpace(parts[0]))
			pattern := strings.TrimSpace(parts[1])
			switch method {
			case "GET":
				router.Get(pattern, outputIndex)
			case "POST":
				router.Post(pattern, outputIndex)
			case "PUT":
				router.Put(pattern, outputIndex)
			case "DELETE":
				router.Del(pattern, outputIndex)
			case "HEAD":
				router.Head(pattern, outputIndex)
			case "OPTIONS":
				router.Options(pattern, outputIndex)
			default:
				log.Printf("Unsupported HTTP method %s in pattern %s", method, pattern)
			}
			continue
		}

		// Request arrive
		req, err := httputils.IP2Request(ip)
		if err != nil {
			log.Printf("Failed to convert IP to request. Error: %s", err.Error())
			continue
		}

		outputIndex, params = router.Route(req.Method, req.URI)
		log.Printf("Output index for %s %s: %v (params=%#v)", req.Method, req.URI, outputIndex, params)

		switch outputIndex {
		case NotFound:
			log.Println("Sending Not Found response to FAIL output")
			resp := &httputils.HTTPResponse{
				Id:         req.Id,
				StatusCode: http.StatusNotFound,
			}
			ip, _ = httputils.Response2IP(resp)
			failPort.SendMultipart(ip, 0)
		case MethodNotAllowed:
			log.Println("Sending Method Not Allowed response to FAIL output")
			resp := &httputils.HTTPResponse{
				Id:         req.Id,
				StatusCode: http.StatusMethodNotAllowed,
			}
			ip, _ = httputils.Response2IP(resp)
			failPort.SendMultipart(ip, 0)
		default:
			for k, values := range params {
				req.Form[k] = values
			}
			ip, _ = httputils.Request2IP(req)
			successPorts[outputIndex].SendMultipart(ip, 0)
		}

		index = -1
	}
}
Example #15
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

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

	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("Started...")
	var ip [][]byte

	for {
		results, err := poller.Poll(-1)
		if err != nil {
			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 {
				continue
			}
			if !runtime.IsValidIP(ip) {
				log.Println("Received invalid IP")
				continue
			}

			if *debug {
				for i, s := range inPortArray {
					if s == r.Socket {
						log.Printf("Data from port IN[%v]: %#v", i, string(ip[1]))
					}
				}
			}

			outPort.SendMessage(ip)
		}
	}
}
Example #16
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
		}
	}
}
Example #17
0
// 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)
	}
}
Example #18
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

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

	waitCh := make(chan bool)
	fileExitCh := make(chan bool, 1)
	go func(num int) {
		total := 0
		for {
			select {
			case v := <-fileCh:
				if v {
					total++
				} else {
					fileExitCh <- true
				}
			case v := <-outCh:
				if !v {
					log.Println("OUT 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("Started...")
	for {
		ip, err := filePort.RecvMessageBytes(zmq.DONTWAIT)
		if err != nil {
			select {
			case <-fileExitCh:
				log.Println("FILE port is closed. Interrupting execution")
				exitCh <- syscall.SIGTERM
				break
			default:
				// IN port is still open
			}
			time.Sleep(2 * time.Second)
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}

		filepath := string(ip[1])
		f, err := os.Open(filepath)
		if err != nil {
			log.Printf("ERROR openning file %s: %s", filepath, err.Error())
			if errPort != nil {
				errPort.SendMessage(runtime.NewPacket([]byte(err.Error())))
			}
			continue
		}

		outPort.SendMessage(runtime.NewOpenBracket())
		outPort.SendMessage(ip)

		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			outPort.SendMessage(runtime.NewPacket(scanner.Bytes()))
		}
		if err = scanner.Err(); err != nil && errPort != nil {
			errPort.SendMessage(runtime.NewPacket([]byte(err.Error())))
		}
		f.Close()

		outPort.SendMessage(runtime.NewCloseBracket())
	}
}
Example #19
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
	}
}
Example #20
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	// Setup watcher
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		exitCh <- syscall.SIGTERM
		return
	}
	defer watcher.Close()

	openPorts()
	defer closePorts()

	// Process events
	go func() {
		//  Socket to send messages to task sink
		outPort, err = utils.CreateOutputPort("fs/watchdog.out", *outputEndpoint, errCh)
		if err != nil {
			exitCh <- syscall.SIGTERM
			return
		}
		for {
			select {
			case ev := <-watcher.Event:
				log.Println("Event:", ev)
				if ev.IsCreate() {
					if isDir(ev.Name) {
						err = filepath.Walk(ev.Name, func(path string, info os.FileInfo, err error) error {
							if err != nil {
								return err
							}
							if info.IsDir() {
								// we need to watch every subdirectory explicitely
								watcher.Watch(path)
								log.Println("Added to watch:", path)
							} else {
								// Consider every file found in the created directory as just created
								outPort.SendMessage(runtime.NewPacket([]byte(path)))
							}
							return nil
						})
						if err != nil {
							log.Println("Error walking directory:", err.Error())
						}
					} else {
						outPort.SendMessage(runtime.NewPacket([]byte(ev.Name)))
					}
				} else if ev.IsDelete() && isDir(ev.Name) {
					watcher.RemoveWatch(ev.Name)
					log.Println("Removed from watch:", ev.Name)
				}
			case err := <-watcher.Error:
				log.Println("Error:", err)
			}
		}
	}()

	go func() {
		for {
			select {
			case v := <-outCh:
				if !v {
					log.Println("CREATED port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				}
			case v := <-errCh:
				if !v {
					log.Println("ERR port is closed. Interrupting execution")
					exitCh <- syscall.SIGTERM
					break
				}
			}
		}
	}()

	// Main loop
	log.Println("Started")
	for {
		ip, err := inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}

		dir := string(ip[1])
		err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if info.IsDir() {
				watcher.Watch(path)
				log.Println("Added to watch:", path)
			}
			return nil
		})
		if err != nil {
			log.Printf("ERROR opening file %s: %s", dir, err.Error())
			if errPort != nil {
				errPort.SendMessage(runtime.NewPacket([]byte(err.Error())))
			}
			continue
		}
	}
}
Example #21
0
// mainLoop initiates all ports and handles the traffic
func mainLoop() {
	openPorts()
	defer closePorts()

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

	waitCh := make(chan bool)
	cmdExitCh := make(chan bool, 1)
	go func(num int) {
		total := 0
		for {
			select {
			case v := <-cmdCh:
				if v {
					total++
				} else {
					cmdExitCh <- true
					break
				}
			case v := <-outCh:
				if !v {
					log.Println("OUT 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("Started...")
	for {
		ip, err := cmdPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			continue
		}
		out, err := executeCommand(string(ip[1]))
		if err != nil {
			log.Println(err.Error())
			if errPort != nil {
				errPort.SendMessage(runtime.NewPacket([]byte(err.Error())))
			}
			continue
		}
		out = bytes.Replace(out, []byte("\n"), []byte(""), -1)
		log.Println(string(out))
		if outPort != nil {
			outPort.SendMessage(runtime.NewPacket(out))
		}

		select {
		case <-cmdExitCh:
			log.Println("CMD port is closed. Interrupting execution")
			exitCh <- syscall.SIGTERM
			break
		default:
			// IN port is still open
		}
	}
}
Example #22
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 {
	}
}
Example #23
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))
			}
		}
	}
}
Example #24
0
// 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 := <-mapCh:
				if !v {
					log.Println("MAP 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 pattern...")
	var (
		pattern mainRegexp
		ip      [][]byte
	)
	for {
		ip, err = patternPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			log.Println("Invalid IP:", ip)
			continue
		}
		log.Println("Using pattern:", string(ip[1]))
		pattern = mainRegexp{regexp.MustCompile(string(ip[1]))}
		break
	}
	patternPort.Close()

	log.Println("Started...")
	for {
		ip, err = inPort.RecvMessageBytes(0)
		if err != nil {
			continue
		}
		if !runtime.IsValidIP(ip) {
			log.Println("Invalid IP:", ip)
			continue
		}

		matches := pattern.FindStringSubmatchMap(string(ip[1]))
		log.Printf("Matches: %#v\n", matches)

		data, err := json.Marshal(matches)
		if err != nil {
			log.Println(err.Error())
		}

		mapPort.SendMessage(runtime.NewPacket(data))
	}
}