// Create a new Channel instance with a given service type func NewChannel(service *Service, serviceName string) *Channel { serviceHash_BCrypt, _ := bcrypt.HashBytes([]byte(serviceName)) serviceHash_Base64 := base64.StdEncoding.EncodeToString(serviceHash_BCrypt) channel := &Channel{ serviceName: serviceName, serviceHash: serviceHash_Base64, servicePath: fmt.Sprintf("/%s", serviceName), peers: make([]*Peer, 0), proxies: make([]*Proxy, 0), broadcastBuffer: make(chan *WireMessage, 512), done: make(chan int, 1), } channel.proxyPath = fmt.Sprintf("/%s", GenerateId()) go channel.messageDispatcher() log.Printf("New '%s' channel peer created.", channel.serviceName) service.Channels[channel.servicePath] = channel // Terminate channel when it is closed go func() { <-channel.stopNotify() delete(service.Channels, channel.servicePath) }() // Add TLS-SRP credentials for access to this service to credentials store // TODO isolate this per socket serviceTab[channel.serviceHash] = channel.serviceName go channel.advertise(service.ProxyPort) if service.discoveryBrowser != nil { // Attempt to resolve discovered unknown service hashes with this service name recordsCache := make(map[string]*DNSRecord) for _, cachedRecord := range service.discoveryBrowser.cachedDNSRecords { if bcrypt.Match(channel.serviceName, cachedRecord.Hash_BCrypt) { if dErr := dialProxyFromDNSRecord(cachedRecord, channel); dErr != nil { log.Printf("err: %v", dErr) } } else { // Maintain as an unresolved entry in cache recordsCache[cachedRecord.Hash_Base64] = cachedRecord } } // Replace unresolved DNS-SD service entries cache service.discoveryBrowser.cachedDNSRecords = recordsCache } return channel }
func (ds *DiscoveryBrowser) Browse(service *NetworkWebSocket_Service, intervalSeconds, timeoutSeconds int) { // Don't run two browse processes at the same time if ds.inprogress { return } ds.inprogress = true entries := make(chan *mdns.ServiceEntry, 255) recordsCache := make(map[string]*NetworkWebSocket_DNSRecord) timeout := time.Duration(timeoutSeconds) * time.Second interval := time.Duration(intervalSeconds) * time.Second var targetIPv4 *net.UDPAddr var targetIPv6 *net.UDPAddr targetIPv4 = network_ipv4Addr targetIPv6 = network_ipv6Addr // Only look for Named Web Socket DNS-SD services params := &mdns.QueryParam{ Service: "_nws._tcp", Domain: "local", Timeout: timeout, Entries: entries, IPv4mdns: targetIPv4, IPv6mdns: targetIPv6, } go func() { complete := false timeoutFinish := time.After(timeout) intervalFinish := time.After(interval) // Wait for responses until timeout for !complete { select { case discoveredService, ok := <-entries: if !ok { continue } serviceRecord, err := NewNetworkWebSocketRecordFromDNSRecord(discoveredService) if err != nil { log.Printf("err: %v", err) continue } // Ignore our own NetworkWebSocket services if service.isOwnProxyService(serviceRecord) { continue } // Ignore previously discovered NetworkWebSocket proxy services if service.isActiveProxyService(serviceRecord) { continue } // Resolve discovered service hash provided against available services var sock *NetworkWebSocket for _, knownService := range service.Channels { if bcrypt.Match(knownService.serviceName, serviceRecord.Hash_BCrypt) { sock = knownService break } } if sock != nil { // Create new web socket connection toward discovered proxy if _, dErr := sock.dialFromDNSRecord(serviceRecord); dErr != nil { log.Printf("err: %v", dErr) continue } } else { // Store as an unresolved DNS-SD record recordsCache[serviceRecord.Hash_Base64] = serviceRecord continue } case <-timeoutFinish: // Replace unresolved DNS records cache ds.cachedDNSRecords = recordsCache ds.inprogress = false case <-intervalFinish: complete = true } } }() // Run the mDNS/DNS-SD query err := mdns.Query(params) time.Sleep(interval) // sleep until next loop is scheduled if err != nil { log.Printf("Could not perform mDNS/DNS-SD query. %v", err) return } }
func (ds *DiscoveryBrowser) Browse(service *Service, timeoutSeconds int) { entries := make(chan *mdns.ServiceEntry, 255) recordsCache := make(map[string]*DNSRecord, 255) timeout := time.Duration(timeoutSeconds) * time.Second var targetIPv4 *net.UDPAddr var targetIPv6 *net.UDPAddr targetIPv4 = network_ipv4Addr targetIPv6 = network_ipv6Addr // Only look for Network Web Socket DNS-SD services params := &mdns.QueryParam{ Service: "_nws._tcp", Domain: "local", Timeout: timeout, Entries: entries, IPv4mdns: targetIPv4, IPv6mdns: targetIPv6, } go func() { complete := false timeoutFinish := time.After(timeout) // Wait for responses until timeout for !complete { select { case discoveredService, ok := <-entries: if !ok { continue } serviceRecord, err := NewServiceRecordFromDNSRecord(discoveredService) if err != nil { log.Printf("err: %v", err) continue } // Ignore our own Channel services if service.isOwnProxyService(serviceRecord) { continue } // Ignore previously discovered Channel proxy services if service.isActiveProxyService(serviceRecord) { continue } // Resolve discovered service hash provided against available services var channel *Channel for _, knownService := range service.Channels { if bcrypt.Match(knownService.serviceName, serviceRecord.Hash_BCrypt) { channel = knownService break } } if channel != nil { // Create new web socket connection toward discovered proxy if dErr := dialProxyFromDNSRecord(serviceRecord, channel); dErr != nil { log.Printf("err: %v", dErr) continue } } else { // Store as an unresolved DNS-SD record recordsCache[serviceRecord.Hash_Base64] = serviceRecord continue } case <-timeoutFinish: // Replace unresolved DNS records cache ds.cachedDNSRecords = recordsCache complete = true } } }() // Run the mDNS/DNS-SD query err := mdns.Query(params) if err != nil { log.Printf("Could not perform mDNS/DNS-SD query. %v", err) return } }