func connector(context *cli.Context) int { config, configFilename, err := lib.GetConfig(context) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read config file: %s", err) return 1 } logFileMaxBytes := config.LogFileMaxMegabytes * 1024 * 1024 var logWriter io.Writer logWriter, err = log.NewLogRoller(config.LogFileName, logFileMaxBytes, config.LogMaxFiles) if err != nil { fmt.Fprintf(os.Stderr, "Failed to start log roller: %s", err) return 1 } if context.Bool("log-to-console") { logWriter = io.MultiWriter(logWriter, os.Stderr) } logLevel, ok := log.LevelFromString(config.LogLevel) if !ok { fmt.Fprintf(os.Stderr, "Log level %s is not recognized", config.LogLevel) return 1 } log.SetLevel(logLevel) log.SetWriter(logWriter) if configFilename == "" { log.Info("No config file was found, so using defaults") } log.Error(lib.FullName) fmt.Println(lib.FullName) if !config.CloudPrintingEnable && !config.LocalPrintingEnable { log.Error("Cannot run connector with both local_printing_enable and cloud_printing_enable set to false") return 1 } if _, err := os.Stat(config.MonitorSocketFilename); !os.IsNotExist(err) { if err != nil { log.Errorf("Failed to stat monitor socket: %s", err) } else { log.Errorf( "A connector is already running, or the monitoring socket %s wasn't cleaned up properly", config.MonitorSocketFilename) } return 1 } jobs := make(chan *lib.Job, 10) xmppNotifications := make(chan xmpp.PrinterNotification, 5) var g *gcp.GoogleCloudPrint var x *xmpp.XMPP if config.CloudPrintingEnable { xmppPingTimeout, err := time.ParseDuration(config.XMPPPingTimeout) if err != nil { log.Fatalf("Failed to parse xmpp ping timeout: %s", err) return 1 } xmppPingInterval, err := time.ParseDuration(config.XMPPPingInterval) if err != nil { log.Fatalf("Failed to parse xmpp ping interval default: %s", err) return 1 } g, err = gcp.NewGoogleCloudPrint(config.GCPBaseURL, config.RobotRefreshToken, config.UserRefreshToken, config.ProxyName, config.GCPOAuthClientID, config.GCPOAuthClientSecret, config.GCPOAuthAuthURL, config.GCPOAuthTokenURL, config.GCPMaxConcurrentDownloads, jobs) if err != nil { log.Error(err) return 1 } x, err = xmpp.NewXMPP(config.XMPPJID, config.ProxyName, config.XMPPServer, config.XMPPPort, xmppPingTimeout, xmppPingInterval, g.GetRobotAccessToken, xmppNotifications) if err != nil { log.Error(err) return 1 } defer x.Quit() } cupsConnectTimeout, err := time.ParseDuration(config.CUPSConnectTimeout) if err != nil { log.Fatalf("Failed to parse CUPS connect timeout: %s", err) return 1 } c, err := cups.NewCUPS(config.CopyPrinterInfoToDisplayName, config.PrefixJobIDToJobTitle, config.DisplayNamePrefix, config.CUPSPrinterAttributes, config.CUPSMaxConnections, cupsConnectTimeout) if err != nil { log.Fatal(err) return 1 } defer c.Quit() var s *snmp.SNMPManager if config.SNMPEnable { log.Info("SNMP enabled") s, err = snmp.NewSNMPManager(config.SNMPCommunity, config.SNMPMaxConnections) if err != nil { log.Error(err) return 1 } defer s.Quit() } var priv *privet.Privet if config.LocalPrintingEnable { if g == nil { priv, err = privet.NewPrivet(jobs, config.GCPBaseURL, nil) } else { priv, err = privet.NewPrivet(jobs, config.GCPBaseURL, g.ProximityToken) } if err != nil { log.Error(err) return 1 } defer priv.Quit() } cupsPrinterPollInterval, err := time.ParseDuration(config.CUPSPrinterPollInterval) if err != nil { log.Fatalf("Failed to parse CUPS printer poll interval: %s", err) return 1 } pm, err := manager.NewPrinterManager(c, g, priv, s, cupsPrinterPollInterval, config.CUPSJobQueueSize, config.CUPSJobFullUsername, config.CUPSIgnoreRawPrinters, config.ShareScope, jobs, xmppNotifications) if err != nil { log.Error(err) return 1 } defer pm.Quit() m, err := monitor.NewMonitor(c, g, priv, pm, config.MonitorSocketFilename) if err != nil { log.Error(err) return 1 } defer m.Quit() if config.CloudPrintingEnable { if config.LocalPrintingEnable { log.Errorf("Ready to rock as proxy '%s' and in local mode", config.ProxyName) fmt.Printf("Ready to rock as proxy '%s' and in local mode\n", config.ProxyName) } else { log.Errorf("Ready to rock as proxy '%s'", config.ProxyName) fmt.Printf("Ready to rock as proxy '%s'\n", config.ProxyName) } } else { log.Error("Ready to rock in local-only mode") fmt.Println("Ready to rock in local-only mode") } waitIndefinitely() log.Error("Shutting down") fmt.Println("") fmt.Println("Shutting down") return 0 }
func testXMPP_reconnect(t *testing.T) { cfg := configureTLS(t) waiting := make(chan struct{}) ts := &testXMPPServer{handler: &testXMPPHandler{T: t, cfg: cfg, waiting: waiting}} ts.Start() defer ts.Close() orig := http.DefaultTransport http.DefaultTransport = &http.Transport{ TLSClientConfig: cfg, } defer func() { http.DefaultTransport = orig }() ch := make(chan<- xmpp.PrinterNotification) x, err := xmpp.NewXMPP("*****@*****.**", "proxyName", "127.0.0.1", ts.port, time.Minute, time.Minute, func() (string, error) { return "accessToken", nil }, ch) if err != nil { t.Fatal(err) } waiting <- struct{}{} // signal testXMPPHandler to reconnect waiting <- struct{}{} go func() { waiting <- struct{}{} }() // make crossing condition Quit and reconnect. note that this goroutine may leak x.Quit() }
func TestXMPP_proxyauth(t *testing.T) { cfg := configureTLS(t) ts := httptest.NewServer(&testXMPPHandler{T: t, cfg: cfg, wantProxyAuth: "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="}) defer ts.Close() u, err := url.Parse(ts.URL) if err != nil { t.Fatal("failed to parse URL", ts.URL) } u.User = url.UserPassword("Aladdin", "open sesame") orig := http.DefaultTransport http.DefaultTransport = &http.Transport{ Proxy: http.ProxyURL(u), TLSClientConfig: cfg, } defer func() { http.DefaultTransport = orig }() strs := strings.Split(u.Host, ":") port, err := strconv.Atoi(strs[1]) if err != nil { t.Fatal(err) } ch := make(chan<- xmpp.PrinterNotification) x, err := xmpp.NewXMPP("*****@*****.**", "proxyName", strs[0], uint16(port), time.Minute, time.Minute, func() (string, error) { return "accessToken", nil }, ch) if err != nil { t.Fatal(err) } x.Quit() }
func testXMPP_pingtimeout(t *testing.T) { cfg := configureTLS(t) ts := &testXMPPServer{handler: &testXMPPHandler{T: t, cfg: cfg}} ts.Start() defer ts.Close() orig := http.DefaultTransport http.DefaultTransport = &http.Transport{ TLSClientConfig: cfg, } defer func() { http.DefaultTransport = orig }() ch := make(chan<- xmpp.PrinterNotification) x, err := xmpp.NewXMPP("*****@*****.**", "proxyName", "127.0.0.1", ts.port, time.Millisecond, time.Millisecond, func() (string, error) { return "accessToken", nil }, ch) if err != nil { if strings.Contains(err.Error(), "initial ping failed") { // ignore initial ping failed due to short timeout duration t.Log(err) return } t.Fatal(err) } time.Sleep(time.Millisecond * 100) // make ping timeout x.Quit() ts.Close() if ts.count <= 1 { t.Fatal("want: multiple connection counts by reconnecting but:", ts.count) } }
func TestXMPP_ping(t *testing.T) { cfg := configureTLS(t) waiting := make(chan struct{}) ts := &testXMPPServer{handler: &testXMPPHandler{T: t, cfg: cfg, waiting: waiting, wantPing: 2}} ts.Start() defer ts.Close() orig := http.DefaultTransport http.DefaultTransport = &http.Transport{ TLSClientConfig: cfg, } defer func() { http.DefaultTransport = orig }() ch := make(chan<- xmpp.PrinterNotification) x, err := xmpp.NewXMPP("*****@*****.**", "proxyName", "127.0.0.1", ts.port, time.Second, time.Second, func() (string, error) { return "accessToken", nil }, ch) if err != nil { t.Fatal(err) } waiting <- struct{}{} // sync pings received x.Quit() }
func main() { flag.Parse() defer glog.Flush() glog.Error(lib.FullName) fmt.Println(lib.FullName) config, err := lib.ConfigFromFile() if err != nil { glog.Fatal(err) } if _, err := os.Stat(config.MonitorSocketFilename); !os.IsNotExist(err) { if err != nil { glog.Fatal(err) } glog.Fatalf( "A connector is already running, or the monitoring socket %s wasn't cleaned up properly", config.MonitorSocketFilename) } cupsConnectTimeout, err := time.ParseDuration(config.CUPSConnectTimeout) if err != nil { glog.Fatalf("Failed to parse cups connect timeout: %s", err) } gcpXMPPPingTimeout, err := time.ParseDuration(config.XMPPPingTimeout) if err != nil { glog.Fatalf("Failed to parse xmpp ping timeout: %s", err) } gcpXMPPPingIntervalDefault, err := time.ParseDuration(config.XMPPPingIntervalDefault) if err != nil { glog.Fatalf("Failed to parse xmpp ping interval default: %s", err) } gcp, err := gcp.NewGoogleCloudPrint(config.GCPBaseURL, config.RobotRefreshToken, config.UserRefreshToken, config.ProxyName, config.GCPOAuthClientID, config.GCPOAuthClientSecret, config.GCPOAuthAuthURL, config.GCPOAuthTokenURL, gcpXMPPPingIntervalDefault) if err != nil { glog.Fatal(err) } xmpp, err := xmpp.NewXMPP(config.XMPPJID, config.ProxyName, config.XMPPServer, config.XMPPPort, gcpXMPPPingTimeout, gcpXMPPPingIntervalDefault, gcp.GetRobotAccessToken) if err != nil { glog.Fatal(err) } defer xmpp.Quit() cups, err := cups.NewCUPS(config.CopyPrinterInfoToDisplayName, config.CUPSPrinterAttributes, config.CUPSMaxConnections, cupsConnectTimeout, gcp.Translate) if err != nil { glog.Fatal(err) } defer cups.Quit() var snmpManager *snmp.SNMPManager if config.SNMPEnable { glog.Info("SNMP enabled") snmpManager, err = snmp.NewSNMPManager(config.SNMPCommunity, config.SNMPMaxConnections) if err != nil { glog.Fatal(err) } defer snmpManager.Quit() } pm, err := manager.NewPrinterManager(cups, gcp, xmpp, snmpManager, config.CUPSPrinterPollInterval, config.GCPMaxConcurrentDownloads, config.CUPSJobQueueSize, config.CUPSJobFullUsername, config.CUPSIgnoreRawPrinters, config.ShareScope) if err != nil { glog.Fatal(err) } defer pm.Quit() m, err := monitor.NewMonitor(cups, gcp, pm, config.MonitorSocketFilename) if err != nil { glog.Fatal(err) } defer m.Quit() glog.Errorf("Ready to rock as proxy '%s'\n", config.ProxyName) fmt.Printf("Ready to rock as proxy '%s'\n", config.ProxyName) waitIndefinitely() glog.Error("Shutting down") fmt.Println("") fmt.Println("Shutting down") }
func main() { flag.Parse() defer glog.Flush() glog.Error(lib.FullName) fmt.Println(lib.FullName) var config *lib.Config if lib.ConfigFileExists() { var err error config, err = lib.ConfigFromFile() if err != nil { glog.Fatal(err) } } else { config = &lib.DefaultConfig glog.Info("No config file was found, so using defaults") } if !config.CloudPrintingEnable && !config.LocalPrintingEnable { glog.Fatal("Cannot run connector with both local_printing_enable and cloud_printing_enable set to false") } if _, err := os.Stat(config.MonitorSocketFilename); !os.IsNotExist(err) { if err != nil { glog.Fatal(err) } glog.Fatalf( "A connector is already running, or the monitoring socket %s wasn't cleaned up properly", config.MonitorSocketFilename) } cupsConnectTimeout, err := time.ParseDuration(config.CUPSConnectTimeout) if err != nil { glog.Fatalf("Failed to parse cups connect timeout: %s", err) } gcpXMPPPingTimeout, err := time.ParseDuration(config.XMPPPingTimeout) if err != nil { glog.Fatalf("Failed to parse xmpp ping timeout: %s", err) } gcpXMPPPingIntervalDefault, err := time.ParseDuration(config.XMPPPingIntervalDefault) if err != nil { glog.Fatalf("Failed to parse xmpp ping interval default: %s", err) } jobs := make(chan *lib.Job, 10) xmppNotifications := make(chan xmpp.PrinterNotification, 5) var g *gcp.GoogleCloudPrint var x *xmpp.XMPP if config.CloudPrintingEnable { g, err = gcp.NewGoogleCloudPrint(config.GCPBaseURL, config.RobotRefreshToken, config.UserRefreshToken, config.ProxyName, config.GCPOAuthClientID, config.GCPOAuthClientSecret, config.GCPOAuthAuthURL, config.GCPOAuthTokenURL, gcpXMPPPingIntervalDefault, config.GCPMaxConcurrentDownloads, jobs) if err != nil { glog.Fatal(err) } x, err = xmpp.NewXMPP(config.XMPPJID, config.ProxyName, config.XMPPServer, config.XMPPPort, gcpXMPPPingTimeout, gcpXMPPPingIntervalDefault, g.GetRobotAccessToken, xmppNotifications) if err != nil { glog.Fatal(err) } defer x.Quit() } c, err := cups.NewCUPS(config.CopyPrinterInfoToDisplayName, config.CUPSPrinterAttributes, config.CUPSMaxConnections, cupsConnectTimeout) if err != nil { glog.Fatal(err) } defer c.Quit() var s *snmp.SNMPManager if config.SNMPEnable { glog.Info("SNMP enabled") s, err = snmp.NewSNMPManager(config.SNMPCommunity, config.SNMPMaxConnections) if err != nil { glog.Fatal(err) } defer s.Quit() } var priv *privet.Privet if config.LocalPrintingEnable { if g == nil { priv, err = privet.NewPrivet(jobs, config.GCPBaseURL, nil) } else { priv, err = privet.NewPrivet(jobs, config.GCPBaseURL, g.ProximityToken) } if err != nil { glog.Fatal(err) } defer priv.Quit() } pm, err := manager.NewPrinterManager(c, g, priv, s, config.CUPSPrinterPollInterval, config.CUPSJobQueueSize, config.CUPSJobFullUsername, config.CUPSIgnoreRawPrinters, config.ShareScope, jobs, xmppNotifications) if err != nil { glog.Fatal(err) } defer pm.Quit() m, err := monitor.NewMonitor(c, g, pm, config.MonitorSocketFilename) if err != nil { glog.Fatal(err) } defer m.Quit() if config.CloudPrintingEnable { if config.LocalPrintingEnable { glog.Errorf("Ready to rock as proxy '%s' and in local mode", config.ProxyName) fmt.Printf("Ready to rock as proxy '%s' and in local mode\n", config.ProxyName) } else { glog.Errorf("Ready to rock as proxy '%s'", config.ProxyName) fmt.Printf("Ready to rock as proxy '%s'\n", config.ProxyName) } } else { glog.Error("Ready to rock in local-only mode") fmt.Println("Ready to rock in local-only mode") } waitIndefinitely() glog.Error("Shutting down") fmt.Println("") fmt.Println("Shutting down") }
func connector(context *cli.Context) int { config, configFilename, err := lib.GetConfig(context) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read config file: %s", err) return 1 } log.SetLogToConsole(context.Bool("log-to-console")) logLevel, ok := log.LevelFromString(config.LogLevel) if !ok { fmt.Fprintf(os.Stderr, "Log level %s is not recognized", config.LogLevel) return 1 } log.SetLevel(logLevel) if configFilename == "" { log.Info("No config file was found, so using defaults") } log.Info(lib.FullName) fmt.Println(lib.FullName) if !config.CloudPrintingEnable && !config.LocalPrintingEnable { log.Fatal("Cannot run connector with both local_printing_enable and cloud_printing_enable set to false") return 1 } else if config.LocalPrintingEnable { log.Fatal("Local printing has not been implemented in this version of the Windows connector.") return 1 } jobs := make(chan *lib.Job, 10) xmppNotifications := make(chan xmpp.PrinterNotification, 5) var g *gcp.GoogleCloudPrint var x *xmpp.XMPP if config.CloudPrintingEnable { xmppPingTimeout, err := time.ParseDuration(config.XMPPPingTimeout) if err != nil { log.Fatalf("Failed to parse xmpp ping timeout: %s", err) return 1 } xmppPingInterval, err := time.ParseDuration(config.XMPPPingInterval) if err != nil { log.Fatalf("Failed to parse xmpp ping interval default: %s", err) return 1 } g, err = gcp.NewGoogleCloudPrint(config.GCPBaseURL, config.RobotRefreshToken, config.UserRefreshToken, config.ProxyName, config.GCPOAuthClientID, config.GCPOAuthClientSecret, config.GCPOAuthAuthURL, config.GCPOAuthTokenURL, config.GCPMaxConcurrentDownloads, jobs) if err != nil { log.Fatal(err) return 1 } x, err = xmpp.NewXMPP(config.XMPPJID, config.ProxyName, config.XMPPServer, config.XMPPPort, xmppPingTimeout, xmppPingInterval, g.GetRobotAccessToken, xmppNotifications) if err != nil { log.Fatal(err) return 1 } defer x.Quit() } ws, err := winspool.NewWinSpool(config.PrefixJobIDToJobTitle, config.DisplayNamePrefix, config.PrinterBlacklist) if err != nil { log.Fatal(err) return 1 } nativePrinterPollInterval, err := time.ParseDuration(config.NativePrinterPollInterval) if err != nil { log.Fatalf("Failed to parse printer poll interval: %s", err) return 1 } pm, err := manager.NewPrinterManager(ws, g, nil, nil, nativePrinterPollInterval, config.NativeJobQueueSize, false, false, config.ShareScope, jobs, xmppNotifications) if err != nil { log.Fatal(err) return 1 } defer pm.Quit() if config.CloudPrintingEnable { if config.LocalPrintingEnable { log.Infof("Ready to rock as proxy '%s' and in local mode", config.ProxyName) fmt.Printf("Ready to rock as proxy '%s' and in local mode\n", config.ProxyName) } else { log.Infof("Ready to rock as proxy '%s'", config.ProxyName) fmt.Printf("Ready to rock as proxy '%s'\n", config.ProxyName) } } else { log.Info("Ready to rock in local-only mode") fmt.Println("Ready to rock in local-only mode") } waitIndefinitely() log.Info("Shutting down") fmt.Println("") fmt.Println("Shutting down") return 0 }