3

I have a scanner class to scan list of all bonjour services available with an option for the user to search for all the devices in a certain bonjour service name.

Everything works great! except when I remove my iphone from the cable then I can't see all the bonjour services.

Any ideas y?

Note: My iphone any my laptop connected via wifi at the same network. But it seems that the iphone detects the bonjour services through my laptop.

here is my Class though I am sure its not about my class implementation.

class ScannerViewController: UIViewController {

@IBOutlet weak var serviceTextField: UITextField!
@IBOutlet weak var transportLayerTextField: UITextField!
@IBOutlet weak var domainTextField: UITextField!

@IBOutlet weak var tableView: UITableView!

@IBOutlet weak var allBonjourBtn: UIButton!
@IBOutlet weak var searchBtn: UIButton!

let searchForAllString = "_services._dns-sd._udp."

var services = [NetService](){
    didSet{
        self.tableView.reloadData()
    }
}

private lazy var serviceBrowser = NetServiceBrowser()

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.estimatedRowHeight = 150
    self.tableView.rowHeight = UITableViewAutomaticDimension

    self.serviceBrowser.delegate = self
    self.searchBtn.makeCircularEdges()
    self.allBonjourBtn.makeCircularEdges()
}

@IBAction func allBonjourPressed(_ sender: UIButton) {
    self.startBrowsing(all: true)
}

@IBAction func searchPressed(_ sender: UIButton) {
    self.startBrowsing(all: false)
}

func setBrowserObj() -> (serviceName: String, transportLayer: String, domain: String){

    let sName = (self.serviceTextField?.text ?? "").trim
    let tl = (self.transportLayerTextField?.text ?? "").trim

    let text = (self.domainTextField?.text ?? "").trim
    let domain = (text == "" ? text: "\(text).")
    print("\(sName).\(tl).", domain)
    return (serviceName: "_\(sName)", transportLayer: "_\(tl)", domain: "\(domain)")
}

func startBrowsing(all: Bool){
    self.hideKeyboard()
    self.serviceBrowser.stop()
    self.services = []
    let result = self.setBrowserObj()
    self.serviceBrowser.delegate = self
    if all {
        self.serviceBrowser.searchForServices(ofType: searchForAllString, inDomain: "\(result.domain)")
    }else{
        self.serviceBrowser.searchForServices(ofType: "\(result.serviceName).\(result.transportLayer).", inDomain: "\(result.domain)")
    }
}
}

extension ScannerViewController: UITableViewDelegate, UITableViewDataSource {

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.services.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") else{
        return UITableViewCell()
    }

    guard self.services.count > 0 else{
        return cell
    }
    let service = self.services[indexPath.row]
    cell.textLabel?.text = "Name: \(service.name)\nDomain: \(service.domain)\nPort: \(service.port)"
    return cell
}
}

extension ScannerViewController: UITextFieldDelegate {

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    let nextTag = textField.tag + 1
    if let nextTextField = textField.superview?.viewWithTag(nextTag) {
        nextTextField.becomeFirstResponder()
    }else{
        self.hideKeyboard()
    }
    return false
}

func hideKeyboard() {
    self.serviceTextField?.resignFirstResponder()
    self.transportLayerTextField?.resignFirstResponder()
    self.domainTextField?.resignFirstResponder()
}
}

extension ScannerViewController: NetServiceBrowserDelegate, NetServiceDelegate {

func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) {
    print("Error serching for service")
    print("Errors: \(errorDict.keys)\n")
}

func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
    service.delegate = self
    self.services.append(service)
}

func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
    service.delegate = nil
    self.removeServiceFromList(serviceObj: service)
}

///Removes the service from the current list.
func removeServiceFromList(serviceObj: NetService){
    for (index, sev) in self.services.enumerated() {
        if sev == serviceObj {
            self.services.remove(at: index)
        }
    }
}

}

enter image description here

Update:

I am using the command line to check the available bonjour services and I have noticed:

  1. Running dns-sd -B _services._dns-sd._udp local. will list couple of services that I believe is brodcasted from my machine only.

  2. Running dns-sd -B _ipp._tcp local. or dns-sd -B _http._tcp local. will list all things uses the ipp/http services.

The real question why the ipp or http service types did not appear when I used the command dns-sd -B _services._dns-sd._udp local. ??? based on all my readings online everybody saying that this command should list all bonjour services availble and active on the network! But thats not what is happening with me.

Note: I am connected to the network via wifi and I can't use a cable since I do not have an adapter.

Attached a snapshot of the result.

enter image description here


Update 2

Finally I figured it out. I guess the issue was with the wifi network at work that was blocking the list of services. because when I tried it home I was able to see all the bonjour services with no issues.

Ehab Saifan
  • 290
  • 2
  • 13
  • "But it seems that the iphone detects the bonjour services through my laptop" Is it the _connection_ between the iPhone and the laptop that matters, or the fact that you run your app _from Xcode_ rather than from the device? In other words, what if you are connected but you launch the app by tapping in the springboard rather than by telling Xcode to run it? – matt Nov 14 '17 at 18:53
  • If I am not using xcode and run the app normally then i can't see the list of all bonjour services! But if I hocked the cable just like if you are charging your phone then I can detect all the services. Actually even if both my laptop and my iphone connected to a different wifi I still can see all the services as long as there is a cable connection between the iphone and the laptop – Ehab Saifan Nov 14 '17 at 19:34
  • Are all the radios working on the device? You didn't turn off your bluetooth, by any chance? You're not in airplane mode or anything? Grasping at straws here: I'm not a Bonjour expert by any means. – matt Nov 14 '17 at 19:41
  • I tried all possibilities of turning on/of bluetooth, wireless airplane mode. The only thing is for sure that I can't get a list of all bonjour services unless I am connected through a wire to my laptop. And that make things weird! – Ehab Saifan Nov 14 '17 at 19:48
  • 1
    Are the bonjour services coming *from* your laptop? Many home routers have problems with multicast forwarding so the multicast bonjour packets may be only being delivered over the virtual network established between your Mac and your phone. You may need to check your router to see if it had n option for multicast forwarding. – Paulw11 Nov 14 '17 at 20:13
  • I can't check the router since I am work! Thought I tried multiple network I have at work. But still the same result. Basically If I am searching for "_ipp._tcp." service for printer on domain "local." then I can detect all the machines using that bonjour service. But when trying to list all the bonjour services I can't detect them unless I am connected to my laptop. – Ehab Saifan Nov 14 '17 at 20:40
  • @Paulw11 You are right I can see the bonjour services only running by my laptop. I guess what you are suggesting is true. But I can't verify it. – Ehab Saifan Nov 14 '17 at 21:04
  • I ran the command `dns-sd -B _services._dns-sd._udp local.` on my terminal and listed 5 services not including any 'ipp' services. After that I ran the command `dns-sd -B _ipp._tcp local.` and I could see 4 printers available.... My question is why I am not seeing the ipp services when I run the first command?? – Ehab Saifan Nov 14 '17 at 21:31
  • Finally I figured it out. I guess the issue was with the wifi network at work that was blocking the list services. because when I tried it home I was able to see all the bonjour services. @Paulw11 Thanks – Ehab Saifan Nov 15 '17 at 00:55

1 Answers1

0

Finally I was able to figure it out and it was the wifi network at my work who was blocking this. When I tried it at home everything is working as expected.

Thanks for everyone helped me figure this out

Ehab Saifan
  • 290
  • 2
  • 13