Merge branch 'srvlookup'

This commit is contained in:
Martin Dosch 2021-03-03 11:40:41 +01:00
commit b74e921c13
3 changed files with 115 additions and 39 deletions

View File

@ -36,12 +36,10 @@ The account data is expected at `~/.sendxmpprc` if no other configuration file l
```plain
username: <your_jid>
jserver: <jabber_server>
port: <jabber_port>
password: <your_jabber_password>
```
`jserver` and `port` might not be necessary depending on the used server. It is also possible to
If this is not sufficient to connect you might also specify `jserver` and `port`. It is also possible to
use a password manager. In this case the `password` setting should be replaced by the `eval_password`
setting:

101
connect.go Normal file
View File

@ -0,0 +1,101 @@
// Copyright 2018 - 2021 Martin Dosch.
// Use of this source code is governed by the BSD-2-clause
// license that can be found in the LICENSE file.package main
package main
import (
"fmt"
"net"
"sort"
"strings"
"github.com/mattn/go-xmpp" // BSD-3-Clause
)
type srv struct {
host string
xmpps bool
port uint16
priority uint16
weight uint16
}
type srvMixed []srv
type byPriority []srv
func (o byPriority) Len() int { return len(o) }
func (o byPriority) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
func (o byPriority) Less(i, j int) bool {
if o[i].priority == o[j].priority {
return o[i].weight > o[j].weight
} else {
return o[i].priority < o[j].priority
}
}
func connect(options xmpp.Options, directTLS bool) (*xmpp.Client, error) {
// Look up SRV records if server is not specified manually.
srvMixed := srvMixed{}
if options.Host == "" {
server := options.User[strings.LastIndex(options.User, "@")+1:]
// Look up xmpp-client SRV records.
if _, addrs, err := net.LookupSRV("xmpp-client", "tcp", server); err == nil {
if len(addrs) > 0 {
for _, adr := range addrs {
srvMixed = append(srvMixed, srv{adr.Target, false,
adr.Port, adr.Priority, adr.Weight})
}
}
}
// Look up xmpps-client SRV records.
if _, addrs, err := net.LookupSRV("xmpps-client", "tcp", server); err == nil {
if len(addrs) > 0 {
for _, adr := range addrs {
srvMixed = append(srvMixed, srv{adr.Target, true,
adr.Port, adr.Priority, adr.Weight})
}
}
}
if len(srvMixed) > 0 {
// Sort xmpp- and xmpps-client SRV records according to the priority
// and wight.
sort.Sort(byPriority(srvMixed))
for _, adr := range srvMixed {
if !directTLS && !adr.xmpps {
// Use StartTLS
options.NoTLS = true
options.StartTLS = true
options.Host = fmt.Sprintf("%s:%d", adr.host, adr.port)
// Connect to server
client, err := options.NewClient()
if err == nil {
return client, err
}
} else if adr.xmpps {
// Use direct TLS
options.NoTLS = false
options.StartTLS = false
options.Host = fmt.Sprintf("%s:%d", adr.host, adr.port)
// Connect to server
client, err := options.NewClient()
if err == nil {
return client, err
}
}
}
}
// Try port 5222 if no xmpp-client SRV records are provided.
options.NoTLS = true
options.StartTLS = true
options.Host = fmt.Sprintf("%s:%d", server, 5222)
// Connect to server
client, err := options.NewClient()
return client, err
}
// Connect to server
client, err := options.NewClient()
return client, err
}

View File

@ -8,10 +8,8 @@ import (
"bufio"
"crypto/tls"
"errors"
"fmt"
"io"
"log"
"net"
"os"
"os/exec"
"os/user"
@ -292,30 +290,6 @@ func main() {
server = *flagServer
}
// Determine server part if no server is specified.
if server == "" {
server = strings.Split(user, "@")[1]
// Lookup SRV record for xmpps-client if direct TLS is requested
if *flagTLS {
if _, addrs, err := net.LookupSRV("xmpps-client", "tcp", server); err == nil {
if len(addrs) > 0 {
// Default to first record
server = fmt.Sprintf("%s:%d", addrs[0].Target, addrs[0].Port)
defP := addrs[0].Priority
for _, adr := range addrs {
if adr.Priority < defP {
server = fmt.Sprintf("%s:%d", adr.Target, adr.Port)
defP = adr.Priority
}
}
}
}
}
}
// Overwrite password if specified via command line flag.
if *flagPassword != "" {
password = *flagPassword
@ -334,20 +308,23 @@ func main() {
// Use ALPN
var tlsConfig tls.Config
tlsConfig.ServerName = strings.Split(user, "@")[1]
tlsConfig.ServerName = user[strings.LastIndex(user, "@")+1:]
tlsConfig.NextProtos = append(tlsConfig.NextProtos, "xmpp-client")
tlsConfig.InsecureSkipVerify = *flagSkipVerify
// Set XMPP connection options.
options := xmpp.Options{
Host: server,
User: user,
Resource: *flagResource,
Password: password,
NoTLS: !*flagTLS,
StartTLS: !*flagTLS,
Debug: *flagDebug,
TLSConfig: &tlsConfig,
Host: server,
User: user,
// TODO: Check whether the timeout is reasonable or maybe make
// it configurable
DialTimeout: 1 * time.Second,
Resource: *flagResource,
Password: password,
NoTLS: !*flagTLS,
StartTLS: !*flagTLS,
Debug: *flagDebug,
TLSConfig: &tlsConfig,
}
// Read message from file.
@ -359,7 +336,7 @@ func main() {
}
// Connect to server.
client, err := options.NewClient()
client, err := connect(options, *flagTLS)
if err != nil {
log.Fatal(err)
}