// // rhctl // // Copyright (C) 2009-2016 Christian Pointner // // This file is part of rhctl. // // rhctl is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // rhctl is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with rhctl. If not, see . // package main import ( "net" ) const ( CLIENT_MAX_DATA_BYTES = 64 * 1024 // close connection if the client sends more then 64k of data ) type NopTCPInterface struct { ln net.Listener ctrl *SwitchControl } type Close bool func readData(con net.Conn, ch chan<- interface{}) { defer func() { ch <- Close(false) }() bytesRead := 0 for { var null [1024]byte n, err := con.Read(null[:]) if err != nil { return } bytesRead = bytesRead + n if bytesRead > CLIENT_MAX_DATA_BYTES { rhdl.Printf("NopTCP: client(%s) sent too many bytes", con.RemoteAddr()) return } } } func handleClient(con net.Conn, ctrl *SwitchControl) { defer func() { con.Close() rhdl.Printf("NopTCP: client(%s) disconnected", con.RemoteAddr()) }() var ch = ctrl.Updates.Sub() defer ctrl.Updates.Unsub(ch) go readData(con, ch) ctrl.Updates.AddSub(ch, "state") ctrl.Commands <- &Command{Type: CmdState, Response: ch} for { data, ok := <-ch if !ok { return } switch data.(type) { case State: state := data.(State) if state.ActiveServer == "" { state.ActiveServer = "none" } if _, err := con.Write([]byte(state.ActiveServer + "\n")); err != nil { break } case Close: return } } } func (nop *NopTCPInterface) Run() { rhdl.Printf("NopTCP: handler running...") for { con, err := nop.ln.Accept() if err != nil { switch err.(type) { case *net.OpError: if !err.(*net.OpError).Temporary() { rhl.Printf("NopTCP: server exiting: %s", err) return } default: rhl.Printf("NopTCP: server exiting: %s", err) return } } rhdl.Printf("NopTCP: client(%s) connected", con.RemoteAddr()) go handleClient(con, nop.ctrl) } } func NopTCPInit(conf *Config, ctrl *SwitchControl) (nop *NopTCPInterface, err error) { nop = &NopTCPInterface{} nop.ctrl = ctrl if nop.ln, err = net.Listen("tcp", conf.Clients.Noptcp.Address); err != nil { return } rhdl.Printf("NopTCP: listening on %s", nop.ln.Addr()) return }