// 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) } } }
// 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 {} }
// 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))) } }
// 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("]") } } }
// 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())) } }
// 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) } } }
// 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) } }
// 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 } } }
// 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 } }
// 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)) } }
// 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)) } } }
// 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()) } } }
// 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) } }
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 } }
// 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) } } }
// 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 } } }
// 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) } }
// 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()) } }
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 } }
// 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 } } }
// 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 } } }
// 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 { } }
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)) } } } }
// 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)) } }