예제 #1
1
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
}
예제 #2
0
// addPPDDescriptionToPrinters fetches description, PPD hash, manufacturer, model
// for argument printers, concurrently. These are the fields derived from PPD.
func (c *CUPS) addPPDDescriptionToPrinters(printers []lib.Printer) []lib.Printer {
	var wg sync.WaitGroup
	ch := make(chan *lib.Printer, len(printers))

	for i := range printers {
		wg.Add(1)
		go func(p *lib.Printer) {
			if description, manufacturer, model, err := c.pc.getPPDCacheEntry(p.Name); err == nil {
				p.Description.Absorb(description)
				p.Manufacturer = manufacturer
				p.Model = model
				ch <- p
			} else {
				log.Error(err)
			}
			wg.Done()
		}(&printers[i])
	}

	wg.Wait()
	close(ch)

	result := make([]lib.Printer, 0, len(ch))
	for printer := range ch {
		result = append(result, *printer)
	}

	return result
}
예제 #3
0
// Quit terminates the XMPP conversation so that new jobs stop arriving.
func (x *XMPP) Quit() {
	// Signal to KeepXMPPAlive.
	close(x.quit)
	select {
	case <-x.dead:
		// Wait for XMPP to die.
	case <-time.After(3 * time.Second):
		// But not too long.
		log.Error("XMPP taking a while to close, so giving up")
	}
}
예제 #4
0
// keepXMPPAlive restarts XMPP when it fails.
func (x *XMPP) keepXMPPAlive() {
	for {
		select {
		case <-x.dead:
			log.Error("XMPP conversation died; restarting")
			if err := x.startXMPP(); err != nil {
				for err != nil {
					log.Errorf("XMPP restart failed, will try again in 10s: %s", err)
					time.Sleep(10 * time.Second)
					err = x.startXMPP()
				}
				log.Error("XMPP conversation restarted successfully")
			}

		case <-x.quit:
			// Close XMPP.
			x.ix.Quit()
			return
		}
	}
}
예제 #5
0
func (pm *PrinterManager) syncPrintersPeriodically(interval time.Duration) {
	go func() {
		t := time.NewTimer(interval)
		defer t.Stop()

		for {
			select {
			case <-t.C:
				if err := pm.syncPrinters(false); err != nil {
					log.Error(err)
				}
				t.Reset(interval)

			case <-pm.quit:
				return
			}
		}
	}()
}