Example #1
0
// OnDisconnect event. Terminates MumbleDJ process or retries connection if
// automatic connection retries are enabled.
func (dj *MumbleDJ) OnDisconnect(e *gumble.DisconnectEvent) {
	dj.Queue.Reset()
	if viper.GetBool("connection.retry_enabled") &&
		(e.Type == gumble.DisconnectError || e.Type == gumble.DisconnectKicked) {
		logrus.WithFields(logrus.Fields{
			"interval_secs": fmt.Sprintf("%d", viper.GetInt("connection.retry_interval")),
			"attempts":      fmt.Sprintf("%d", viper.GetInt("connection.retry_attempts")),
		}).Warnln("Disconnected from server. Retrying connection...")

		success := false
		for retries := 0; retries < viper.GetInt("connection.retry_attempts"); retries++ {
			logrus.Infoln("Retrying connection...")
			if client, err := gumble.DialWithDialer(new(net.Dialer), viper.GetString("connection.address")+":"+viper.GetString("connection.port"), dj.GumbleConfig, dj.TLSConfig); err == nil {
				dj.Client = client
				logrus.Infoln("Successfully reconnected to the server!")
				success = true
				break
			}
			time.Sleep(time.Duration(viper.GetInt("connection.retry_interval")) * time.Second)
		}
		if !success {
			dj.KeepAlive <- true
			logrus.Fatalln("Could not reconnect to server. Exiting...")
		}
	} else {
		dj.KeepAlive <- true
		logrus.Fatalln("Disconnected from server. No reconnect attempts will be made.")
	}
}
Example #2
0
// Main aids in the creation of a basic command line gumble bot. It accepts the
// following flag arguments:
//  --server
//  --username
//  --password
//  --insecure,
//  --certificate
//  --key
func Main(listeners ...gumble.EventListener) {
	server := flag.String("server", "localhost:64738", "Mumble server address")
	username := flag.String("username", "gumble-bot", "client username")
	password := flag.String("password", "", "client password")
	insecure := flag.Bool("insecure", false, "skip server certificate verification")
	certificateFile := flag.String("certificate", "", "user certificate file (PEM)")
	keyFile := flag.String("key", "", "user certificate key file (PEM)")

	if !flag.Parsed() {
		flag.Parse()
	}

	host, port, err := net.SplitHostPort(*server)
	if err != nil {
		host = *server
		port = strconv.Itoa(gumble.DefaultPort)
	}

	keepAlive := make(chan bool)

	config := gumble.NewConfig()
	config.Username = *username
	config.Password = *password
	address := net.JoinHostPort(host, port)

	var tlsConfig tls.Config

	if *insecure {
		tlsConfig.InsecureSkipVerify = true
	}
	if *certificateFile != "" {
		if *keyFile == "" {
			keyFile = certificateFile
		}
		if certificate, err := tls.LoadX509KeyPair(*certificateFile, *keyFile); err != nil {
			fmt.Printf("%s: %s\n", os.Args[0], err)
			os.Exit(1)
		} else {
			tlsConfig.Certificates = append(tlsConfig.Certificates, certificate)
		}
	}
	config.Attach(AutoBitrate)
	for _, listener := range listeners {
		config.Attach(listener)
	}
	config.Attach(Listener{
		Disconnect: func(e *gumble.DisconnectEvent) {
			keepAlive <- true
		},
	})
	_, err = gumble.DialWithDialer(new(net.Dialer), address, config, &tlsConfig)
	if err != nil {
		fmt.Printf("%s: %s\n", os.Args[0], err)
		os.Exit(1)
	}

	<-keepAlive
}
Example #3
0
// Connect starts the process for connecting to a Mumble server.
func (dj *MumbleDJ) Connect() error {
	// Perform startup checks before connecting.
	logrus.Infoln("Performing startup checks...")
	PerformStartupChecks()

	// Create Gumble config.
	dj.GumbleConfig = gumble.NewConfig()
	dj.GumbleConfig.Username = viper.GetString("connection.username")
	dj.GumbleConfig.Password = viper.GetString("connection.password")
	dj.GumbleConfig.Tokens = strings.Split(viper.GetString("connection.access_tokens"), ",")

	// Initialize key pair if needed.
	if viper.GetBool("connection.insecure") {
		dj.TLSConfig.InsecureSkipVerify = true
	} else {
		dj.TLSConfig.ServerName = viper.GetString("connection.address")

		if viper.GetString("connection.cert") != "" {
			if viper.GetString("connection.key") == "" {
				viper.Set("connection.key", viper.GetString("connection.cert"))
			}

			if certificate, err := tls.LoadX509KeyPair(viper.GetString("connection.cert"), viper.GetString("connection.key")); err == nil {
				dj.TLSConfig.Certificates = append(dj.TLSConfig.Certificates, certificate)
			} else {
				return err
			}
		}
	}

	// Add user p12 cert if needed.
	if viper.GetString("connection.user_p12") != "" {
		if _, err := os.Stat(viper.GetString("connection.user_p12")); os.IsNotExist(err) {
			return err
		}

		// Create temporary directory for converted p12 file.
		dir, err := ioutil.TempDir("", "mumbledj")
		if err != nil {
			return err
		}
		defer os.RemoveAll(dir)

		// Create temporary mumbledj.crt.pem from p12 file.
		command := exec.Command("openssl", "pkcs12", "-password", "pass:"******"-in", viper.GetString("connection.user_p12"), "-out", dir+"/mumbledj.crt.pem", "-clcerts", "-nokeys")
		if err := command.Run(); err != nil {
			return err
		}

		// Create temporary mumbledj.key.pem from p12 file.
		command = exec.Command("openssl", "pkcs12", "-password", "pass:"******"-in", viper.GetString("connection.user_p12"), "-out", dir+"/mumbledj.key.pem", "-nocerts", "-nodes")
		if err := command.Run(); err != nil {
			return err
		}

		if certificate, err := tls.LoadX509KeyPair(dir+"/mumbledj.crt.pem", dir+"/mumbledj.key.pem"); err == nil {
			dj.TLSConfig.Certificates = append(dj.TLSConfig.Certificates, certificate)
		} else {
			return err
		}
	}

	dj.GumbleConfig.Attach(gumbleutil.Listener{
		Connect:     dj.OnConnect,
		Disconnect:  dj.OnDisconnect,
		TextMessage: dj.OnTextMessage,
		UserChange:  dj.OnUserChange,
	})
	dj.GumbleConfig.Attach(gumbleutil.AutoBitrate)

	var connErr error

	logrus.WithFields(logrus.Fields{
		"address": viper.GetString("connection.address"),
		"port":    viper.GetString("connection.port"),
	}).Infoln("Attempting connection to server...")
	if dj.Client, connErr = gumble.DialWithDialer(new(net.Dialer), viper.GetString("connection.address")+":"+viper.GetString("connection.port"), dj.GumbleConfig, dj.TLSConfig); connErr != nil {
		return connErr
	}

	return nil
}