github.com/la5nta/wl2k-go@v0.11.8/transport/url.go (about)

     1  // Copyright 2016 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
     2  // Use of this source code is governed by the MIT-license that can be
     3  // found in the LICENSE file.
     4  
     5  package transport
     6  
     7  import (
     8  	"net/url"
     9  	"path"
    10  	"sort"
    11  	"strings"
    12  )
    13  
    14  // URL contains all information needed to dial a remote node.
    15  type URL struct {
    16  	// TNC/modem/interface/network type.
    17  	Scheme string
    18  
    19  	// The host interface address.
    20  	Host string
    21  
    22  	// Host username (typically the local stations callsign) and password information.
    23  	User *url.Userinfo
    24  
    25  	// Target callsign.
    26  	Target string
    27  
    28  	// List of digipeaters ("path" between origin and target).
    29  	Digis []string
    30  
    31  	// List of query parameters.
    32  	Params url.Values
    33  }
    34  
    35  // ParseURL parses a raw urlstring into an URL.
    36  //
    37  // scheme://(mycall(:password)@)(host)(/digi1/...)/targetcall
    38  // Examples:
    39  //   - ardop:///LA1B                        (Addresses LA1B on ARDOP).
    40  //   - ax25://mycall@myaxport/LD5SK/LA1B-10 (Addresses LA1B-10 via LD5SK using AX.25-port "myaxport" and "MYCALL" as source callsign).
    41  //
    42  // The special query parameter host will override the host part of the path. (E.g. ax25:///LA1B?host=ax0 == ax25://ax0/LA1B).
    43  func ParseURL(rawurl string) (*URL, error) {
    44  	u, err := url.Parse(rawurl)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	// The digis and target should be all upper case
    50  	u.Path = strings.ToUpper(u.Path)
    51  
    52  	via, target := path.Split(u.Path)
    53  	if len(target) < 3 {
    54  		return nil, ErrInvalidTarget
    55  	}
    56  
    57  	url := &URL{
    58  		Scheme: u.Scheme,
    59  		Host:   u.Host,
    60  		User:   u.User,
    61  		Target: target,
    62  		Params: u.Query(),
    63  	}
    64  
    65  	if str := url.Params.Get("host"); str != "" {
    66  		url.Host = str
    67  	}
    68  
    69  	// Digis
    70  	url.Digis = strings.Split(strings.Trim(via, "/"), "/")
    71  	_ = sort.Reverse(sort.StringSlice(url.Digis))
    72  	if len(url.Digis) == 1 && url.Digis[0] == "" {
    73  		url.Digis = []string{}
    74  	}
    75  
    76  	// TODO: This should be up to the specific transport to decide.
    77  	digisUnsupported := url.Scheme == "ardop" || url.Scheme == "telnet"
    78  	if len(url.Digis) > 0 && digisUnsupported {
    79  		return url, ErrDigisUnsupported
    80  	}
    81  
    82  	return url, nil
    83  }
    84  
    85  // Set the URL.User's username (usually the source callsign).
    86  func (u *URL) SetUser(call string) { u.User = url.User(call) }