diff --git a/cmd/telebit/telebit.go b/cmd/telebit/telebit.go index 4a8470c..79c4aa1 100644 --- a/cmd/telebit/telebit.go +++ b/cmd/telebit/telebit.go @@ -40,70 +40,103 @@ type proxy struct { port int } -func addLocals(proxies []proxy, location string) []proxy { +func addLocals(proxies []proxy, location string) ([]proxy, error) { parts := strings.Split(location, ":") - if len(parts) > 3 { - panic(fmt.Sprintf("provided invalid location %q", location)) + if len(parts) > 3 || "" == parts[0] { + return nil, fmt.Errorf("provided invalid --locals %q", location) } - // If all that was provided as a "local" is the domain name we assume that domain - // has HTTP and HTTPS handlers on the default ports. - if len(parts) == 1 { - proxies = append(proxies, proxy{"http", parts[0], 80}) - proxies = append(proxies, proxy{"https", parts[0], 443}) - return proxies - } + // Format can be any of + // or or : or :: - // Make everything lower case and trim any slashes in something like https://john.example.com - parts[0] = strings.ToLower(parts[0]) - parts[1] = strings.ToLower(strings.Trim(parts[1], "/")) + n := len(parts) + i := n - 1 + last := parts[i] - if len(parts) == 2 { - if strings.Contains(parts[1], ".") { - if parts[0] == "http" { - parts = append(parts, "80") - } else if parts[0] == "https" { - parts = append(parts, "443") - } else { - panic(fmt.Sprintf("port must be specified for %q", location)) - } - } else { - // https:3443 -> https:*:3443 - parts = []string{parts[0], "*", parts[1]} + port, err := strconv.Atoi(last) + if nil != err { + // The last item is the hostname, + // which means it should be the only item + if n > 1 { + return nil, fmt.Errorf("provided invalid --locals %q", location) } + // accepting all defaults + // If all that was provided as a "local" is the domain name we assume that domain + last = strings.ToLower(strings.Trim(last, "/")) + proxies = append(proxies, proxy{"http", last, 80}) + proxies = append(proxies, proxy{"https", last, 443}) + return proxies, nil } - if port, err := strconv.Atoi(parts[2]); err != nil { - panic(fmt.Sprintf("port must be a valid number, not %q: %v", parts[2], err)) - } else if port <= 0 || port > 65535 { - panic(fmt.Sprintf("%d is an invalid port for local services", port)) - } else { - proxies = append(proxies, proxy{parts[0], parts[1], port}) + // the last item is the port, and it must be a valid port + if port <= 0 || port > 65535 { + return nil, fmt.Errorf("local port forward must be between 1 and 65535, not %d", port) } - return proxies + + switch n { + case 1: + // + proxies = append(proxies, proxy{"http", "*", port}) + proxies = append(proxies, proxy{"https", "*", port}) + case 2: + // : + // : + parts[0] = strings.ToLower(strings.Trim(parts[0], "/")) + if strings.Contains(parts[0], ".") { + hostname := parts[0] + proxies = append(proxies, proxy{"http", hostname, port}) + proxies = append(proxies, proxy{"https", hostname, port}) + } else { + scheme := parts[0] + proxies = append(proxies, proxy{scheme, "*", port}) + } + case 3: + // :: + scheme := strings.ToLower(strings.Trim(parts[0], "/")) + hostname := strings.ToLower(strings.Trim(parts[1], "/")) + proxies = append(proxies, proxy{scheme, hostname, port}) + } + return proxies, nil } -func addDomains(proxies []proxy, location string) []proxy { +func addDomains(proxies []proxy, location string) ([]proxy, error) { parts := strings.Split(location, ":") - if len(parts) > 3 { - panic(fmt.Sprintf("provided invalid location %q", location)) - } else if len(parts) == 2 { - panic("invalid argument for --domains, use format or ::") + if len(parts) > 3 || "" == parts[0] { + return nil, fmt.Errorf("provided invalid --domains %q", location) } - // If the scheme and port weren't provided use the zero values - if len(parts) == 1 { - return append(proxies, proxy{"", parts[0], 0}) + // Format is limited to + // or :: + + err := fmt.Errorf("invalid argument for --domains, use format or ::") + switch len(parts) { + case 1: + // TODO test that it's a valid pattern for a domain + hostname := parts[0] + if !strings.Contains(hostname, ".") { + return nil, err + } + proxies = append(proxies, proxy{"http", hostname, 80}) + proxies = append(proxies, proxy{"https", hostname, 443}) + case 2: + return nil, err + case 3: + scheme := parts[0] + hostname := parts[1] + if "" == scheme { + return nil, err + } + if !strings.Contains(hostname, ".") { + return nil, err + } + port, _ := strconv.Atoi(parts[2]) + if port <= 0 || port > 65535 { + return nil, err + } + proxies = append(proxies, proxy{scheme, hostname, port}) } - if port, err := strconv.Atoi(parts[2]); err != nil { - panic(fmt.Sprintf("port must be a valid number, not %q: %v", parts[2], err)) - } else if port <= 0 || port > 65535 { - panic(fmt.Sprintf("%d is an invalid port for local services", port)) - } else { - proxies = append(proxies, proxy{parts[0], parts[1], port}) - } - return proxies + return proxies, nil } func extractServicePorts(proxies []proxy) map[string]map[string]int { @@ -150,15 +183,25 @@ func extractServicePorts(proxies []proxy) map[string]map[string]int { func main() { flag.Parse() + var err error proxies := make([]proxy, 0) for _, option := range viper.GetStringSlice("locals") { for _, location := range strings.Split(option, ",") { - proxies = addLocals(proxies, location) + //fmt.Println("locals", location) + proxies, err = addLocals(proxies, location) + if nil != err { + panic(err) + } } } + //fmt.Println("proxies:") + //fmt.Printf("%+v\n\n", proxies) for _, option := range viper.GetStringSlice("domains") { for _, location := range strings.Split(option, ",") { - proxies = addDomains(proxies, location) + proxies, err = addDomains(proxies, location) + if nil != err { + panic(err) + } } } diff --git a/relay/api/connection.go b/relay/api/connection.go index b15d0e9..0d44a3a 100755 --- a/relay/api/connection.go +++ b/relay/api/connection.go @@ -320,7 +320,7 @@ func (c *Connection) Writer() { log.Println("adding ", messageLen, " to ", message.domain) } else { log.Println("attempting to add bytes to ", message.domain, "it does not exist") - log.Println(c.DomainTrack) + log.Println("dt", c.DomainTrack) } log.Println(c) } diff --git a/relay/api/table.go b/relay/api/table.go index e23f8b8..ea50a7d 100755 --- a/relay/api/table.go +++ b/relay/api/table.go @@ -50,10 +50,10 @@ func (c *Table) Connections() map[*Connection][]string { //back to the WSS connections func (c *Table) ConnByDomain(domain string) (*Connection, bool) { for dn := range c.Domains { - log.Println(dn, domain) + log.Println("[table]", dn, domain) } if domainsLB, ok := c.Domains[domain]; ok { - log.Println("found") + log.Println("[table] found") conn := domainsLB.NextMember() return conn, ok } @@ -64,14 +64,14 @@ func (c *Table) ConnByDomain(domain string) (*Connection, bool) { func (c *Table) reaper(delay int, idle int) { _ = "breakpoint" for { - log.Println("Reaper waiting for ", delay, " seconds") + log.Println("[table] Reaper waiting for ", delay, " seconds") time.Sleep(time.Duration(delay) * time.Second) - log.Println("Running scanning ", len(c.connections)) + log.Println("[table] Running scanning ", len(c.connections)) for d := range c.connections { if !d.State() { if time.Since(d.lastUpdate).Seconds() > float64(idle) { - log.Println("reaper removing ", d.lastUpdate, time.Since(d.lastUpdate).Seconds()) + log.Println("[table] reaper removing ", d.lastUpdate, time.Since(d.lastUpdate).Seconds()) delete(c.connections, d) } } @@ -92,7 +92,7 @@ func (c *Table) GetConnection(serverID int64) (*Connection, error) { //Run -- Execute func (c *Table) Run(ctx context.Context) { - log.Println("ConnectionTable starting") + log.Println("[table] ConnectionTable starting") go c.reaper(c.dwell, c.idle) @@ -100,11 +100,11 @@ func (c *Table) Run(ctx context.Context) { select { case <-ctx.Done(): - log.Println("Cancel signal hit") + log.Println("[table] Cancel signal hit") return case registration := <-c.register: - log.Println("register fired") + log.Println("[table] register fired") connection := NewConnection(c, registration.conn, registration.source, registration.initialDomains, registration.connectionTrack, registration.serverName) @@ -116,7 +116,7 @@ func (c *Table) Run(ctx context.Context) { // add to the domains regirstation newDomain := domain - log.Println("adding domain ", newDomain, " to connection ", connection.conn.RemoteAddr().String()) + log.Println("[table] adding domain ", newDomain, " to connection ", connection.conn.RemoteAddr().String()) //check to see if domain is already present. if _, ok := c.Domains[newDomain]; ok { @@ -137,14 +137,14 @@ func (c *Table) Run(ctx context.Context) { go connection.Reader(ctx) case connection := <-c.unregister: - log.Println("closing connection ", connection.conn.RemoteAddr().String()) + log.Println("[table] closing connection ", connection.conn.RemoteAddr().String()) //does connection exist in the connection table -- should never be an issue if _, ok := c.connections[connection]; ok { //iterate over the connections for the domain for _, domain := range c.connections[connection] { - log.Println("remove domain", domain) + log.Println("[table] remove domain", domain) //removing domain, make sure it is present (should never be a problem) if _, ok := c.Domains[domain]; ok { @@ -166,7 +166,7 @@ func (c *Table) Run(ctx context.Context) { } case domainMapping := <-c.domainAnnounce: - log.Println("domainMapping fired ", domainMapping) + log.Println("[table] domainMapping fired ", domainMapping) //check to make sure connection is already regiered, you can no register a domain without an apporved connection //if connection, ok := connections[domainMapping.connection]; ok { diff --git a/relay/api/tracking.go b/relay/api/tracking.go index e20adf5..6e4b127 100644 --- a/relay/api/tracking.go +++ b/relay/api/tracking.go @@ -41,19 +41,19 @@ func NewTracking() (p *Tracking) { //Run - func (p *Tracking) Run(ctx context.Context) { - log.Println("Tracking Running") + log.Println("[track] Tracking Running") for { select { case <-ctx.Done(): - log.Println("Cancel signal hit") + log.Println("[track] Cancel signal hit") return case connection := <-p.register: p.mutex.Lock() key := connection.conn.RemoteAddr().String() - log.Println("register fired", key) + log.Println("[track] register fired", key) p.connections[key] = connection p.list() p.mutex.Unlock() @@ -61,7 +61,7 @@ func (p *Tracking) Run(ctx context.Context) { case connection := <-p.unregister: p.mutex.Lock() key := connection.RemoteAddr().String() - log.Println("unregister fired", key) + log.Println("[track] unregister fired", key) if _, ok := p.connections[key]; ok { delete(p.connections, key) } @@ -73,7 +73,7 @@ func (p *Tracking) Run(ctx context.Context) { func (p *Tracking) list() { for c := range p.connections { - log.Println(c) + log.Println("[track] list", c) } } diff --git a/relay/mplexy/mplexy.go b/relay/mplexy/mplexy.go index 92660bf..db577d5 100644 --- a/relay/mplexy/mplexy.go +++ b/relay/mplexy/mplexy.go @@ -124,9 +124,9 @@ func (mx *MPlexy) AdminDomain() string { // - execute the GenericLister // - pass initial port, we'll announce that func (mx *MPlexy) Run() error { - loginfo.Println("ConnectionTable starting") + loginfo.Println("[mplexy] ConnectionTable starting") - loginfo.Println(mx.connectionTracking) + loginfo.Println("[mplexy] ct ", mx.connectionTracking) ctx := mx.ctx @@ -145,30 +145,30 @@ func (mx *MPlexy) Run() error { select { case <-ctx.Done(): - loginfo.Println("Cancel signal hit") + loginfo.Println("[mplexy] Cancel signal hit") return nil case registration := <-mx.register: - loginfo.Println("register fired", registration.port) + loginfo.Println("[mplexy] register fired", registration.port) // check to see if port is already running for listener := range mx.listeners { if mx.listeners[listener] == registration.port { - loginfo.Println("listener already running", registration.port) + loginfo.Println("[mplexy] listener already running", registration.port) registration.status = listenerExists registration.commCh <- registration } } - loginfo.Println("listener starting up ", registration.port) - loginfo.Println("[track]", ctx.Value(ctxConnectionTrack).(*api.Tracking)) + loginfo.Println("[mplexy] listener starting up ", registration.port) + loginfo.Println("[mplexy]", ctx.Value(ctxConnectionTrack).(*api.Tracking)) go mx.multiListenAndServe(ctx, registration) status := <-registration.commCh if status.status == listenerAdded { mx.listeners[status.listener] = status.port } else if status.status == listenerFault { - loginfo.Println("Unable to create a new listerer", registration.port) + loginfo.Println("[mplexy] Unable to create a new listerer", registration.port) } } }