<commit_before>// Copyright 2015 <NAME> (LA5NTA). All rights reserved.
// Use of this source code is governed by the MIT-license that can be
// found in the LICENSE file.

package main

import (
	"fmt"
	"log"
	"net"
	"net/url"
	"path"
	"strings"
	"time"

	"github.com/la5nta/wl2k-go/transport"
	"github.com/la5nta/wl2k-go/transport/ax25"
	"github.com/la5nta/wl2k-go/transport/telnet"
)

func connectAny(connectStr ...string) bool {
	for _, str := range connectStr {
		if Connect(str) {
			return true
		}
	}
	return false
}

func Connect(connectStr string) (success bool) {
	if connectStr == "" {
		return false
	}

	if aliased, ok := config.ConnectAliases[connectStr]; ok {
		return Connect(aliased)
	}

	url, err := url.Parse(connectStr)
	if err != nil {
		log.Println(err)
		return false
	}

	targetcall := path.Base(url.Path)

	if len(targetcall) < 3 {
		log.Println("Missing targetcall in connection URL")
		return false
	}

	// QSY
	var revertFreq func()
	if freq := url.Query().Get("freq"); freq != "" {
		revertFreq, err = qsy(url.Scheme, freq)
		if err != nil {
			log.Printf("Unable to QSY: %s", err)
			return
		}
		defer revertFreq()
	}

	var currFreq Frequency
	if vfo, ok := VFOForTransport(url.Scheme); ok {
		f, _ := vfo.GetFreq()
		currFreq = Frequency(f)
	}

	log.Printf("Connecting to %s...", url)

	var conn net.Conn
	switch url.Scheme {
	case MethodWinmor:
		done := handleInterrupt()
		conn, err = connectWinmor(targetcall)
		close(done)
	case MethodArdop:
		done := handleInterrupt()
		conn, err = connectArdop(targetcall)
		close(done)
	case MethodTelnet:
		var user, pass string
		if url.User != nil {
			pass, _ = url.User.Password()
			user = url.User.Username()
		}
		if user == "" {
			user = fOptions.MyCall
		}
		conn, err = telnet.Dial(url.Host, user, pass)
	case MethodAX25:
		axport := url.Host
		if axport == "" {
			axport = config.AX25.Port
		}
		conn, err = ax25.DialAX25Timeout(
			axport,
			fOptions.MyCall,
			targetcall,
			45*time.Second,
		)

	case MethodSerialTNC:
		conn, err = ax25.DialKenwood(
			config.SerialTNC.Path,
			fOptions.MyCall,
			targetcall,
			ax25.NewConfig(ax25.Baudrate(config.SerialTNC.Baudrate)),
			nil,
		)

	default:
		log.Printf("'%s' is not a valid transport scheme.", url.Scheme)
		return
	}

	eventLog.LogConn("connect "+connectStr, currFreq, conn, err)

	if err != nil {
		log.Printf("Unable to establish connection to remote: %s", err)
		return
	}

	err = exchange(conn, targetcall, false)
	if err != nil {
		log.Printf("Exchange failed: %s", err)
	} else {
		log.Println("Disconnected.")
		success = true
	}

	return
}

func qsy(method, addr string) (revert func(), err error) {
	noop := func() {}

	var rigName string
	switch method {
	case MethodWinmor:
		rigName = config.Winmor.Rig
	case MethodArdop:
		rigName = config.Ardop.Rig
	case MethodAX25:
		rigName = config.AX25.Rig
	default:
		return noop, fmt.Errorf("Not supported with transport '%s'", method)
	}

	if rigName == "" {
		return noop, fmt.Errorf("Missing rig reference in config section for %s, don't know which rig to qsy", method)
	}

	var ok bool
	rig, ok := rigs[rigName]
	if !ok {
		return noop, fmt.Errorf("Hamlib rig '%s' not loaded.", rigName)
	}

	log.Printf("QSY %s: %s", method, addr)

	_, oldFreq, err := setFreq(rig, addr)
	if err != nil {
		return noop, err
	}

	time.Sleep(time.Second)

	return func() {
		time.Sleep(time.Second)
		log.Printf("QSX %s: %.3f", method, float64(oldFreq)/1e3)
		rig.SetFreq(oldFreq)
	}, nil
}

func connectWinmor(target string) (net.Conn, error) {
	if wmTNC == nil {
		initWinmorTNC()
	}

	waitBusy(wmTNC)<commit_msg>wl2k: Increase sleep after qsy<commit_after>// Copyright 2015 <NAME> (LA5NTA). All rights reserved.
// Use of this source code is governed by the MIT-license that can be
// found in the LICENSE file.

package main

import (
	"fmt"
	"log"
	"net"
	"net/url"
	"path"
	"strings"
	"time"

	"github.com/la5nta/wl2k-go/transport"
	"github.com/la5nta/wl2k-go/transport/ax25"
	"github.com/la5nta/wl2k-go/transport/telnet"
)

func connectAny(connectStr ...string) bool {
	for _, str := range connectStr {
		if Connect(str) {
			return true
		}
	}
	return false
}

func Connect(connectStr string) (success bool) {
	if connectStr == "" {
		return false
	}

	if aliased, ok := config.ConnectAliases[connectStr]; ok {
		return Connect(aliased)
	}

	url, err := url.Parse(connectStr)
	if err != nil {
		log.Println(err)
		return false
	}

	targetcall := path.Base(url.Path)

	if len(targetcall) < 3 {
		log.Println("Missing targetcall in connection URL")
		return false
	}

	// QSY
	var revertFreq func()
	if freq := url.Query().Get("freq"); freq != "" {
		revertFreq, err = qsy(url.Scheme, freq)
		if err != nil {
			log.Printf("Unable to QSY: %s", err)
			return
		}
		defer revertFreq()
	}

	var currFreq Frequency
	if vfo, ok := VFOForTransport(url.Scheme); ok {
		f, _ := vfo.GetFreq()
		currFreq = Frequency(f)
	}

	log.Printf("Connecting to %s...", url)

	var conn net.Conn
	switch url.Scheme {
	case MethodWinmor:
		done := handleInterrupt()
		conn, err = connectWinmor(targetcall)
		close(done)
	case MethodArdop:
		done := handleInterrupt()
		conn, err = connectArdop(targetcall)
		close(done)
	case MethodTelnet:
		var user, pass string
		if url.User != nil {
			pass, _ = url.User.Password()
			user = url.User.Username()
		}
		if user == "" {
			user = fOptions.MyCall
		}
		conn, err = telnet.Dial(url.Host, user, pass)
	case MethodAX25:
		axport := url.Host
		if axport == "" {
			axport = config.AX25.Port
		}
		conn, err = ax25.DialAX25Timeout(
			axport,
			fOptions.MyCall,
			targetcall,
			45*time.Second,
		)

	case MethodSerialTNC:
		conn, err = ax25.DialKenwood(
			config.SerialTNC.Path,
			fOptions.MyCall,
			targetcall,
			ax25.NewConfig(ax25.Baudrate(config.SerialTNC.Baudrate)),
			nil,
		)

	default:
		log.Printf("'%s' is not a valid transport scheme.", url.Scheme)
		return
	}

	eventLog.LogConn("connect "+connectStr, currFreq, conn, err)

	if err != nil {
		log.Printf("Unable to establish connection to remote: %s", err)
		return
	}

	err = exchange(conn, targetcall, false)
	if err != nil {
		log.Printf("Exchange failed: %s", err)
	} else {
		log.Println("Disconnected.")
		success = true
	}

	return
}

func qsy(method, addr string) (revert func(), err error) {
	noop := func() {}

	var rigName string
	switch method {
	case MethodWinmor:
		rigName = config.Winmor.Rig
	case MethodArdop:
		rigName = config.Ardop.Rig
	case MethodAX25:
		rigName = config.AX25.Rig
	default:
		return noop, fmt.Errorf("Not supported with transport '%s'", method)
	}

	if rigName == "" {
		return noop, fmt.Errorf("Missing rig reference in config section for %s, don't know which rig to qsy", method)
	}

	var ok bool
	rig, ok := rigs[rigName]
	if !ok {
		return noop, fmt.Errorf("Hamlib rig '%s' not loaded.", rigName)
	}

	log.Printf("QSY %s: %s", method, addr)

	_, oldFreq, err := setFreq(rig, addr)
	if err != nil {
		return noop, err
	}

	time.Sleep(3*time.Second)

	return func() {
		time.Sleep(time.Second)
		log.Printf("QSX %s: %.3f", method, float64(oldFreq)/1e3)
		rig.SetFreq(oldFreq)
	}, nil
}

func connectWinmor(target string) (net.Conn, error) {
	if wmTNC == nil {
		initWinmorTNC()
	}

	waitBusy(wmTNC)
{'fraction_non_alphanumeric': 0.13947696139476962, 'fraction_numerical': 0.011069600110696002, 'mean_word_length': 3.458975940777298, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5025436', 'n_tokens_mistral': 3018, 'n_tokens_neox': 2761, 'n_words': 697}