15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/notify_watcher_mac.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <notify.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotifyWatcherMac::NotifyWatcherMac() : notify_fd_(-1), notify_token_(-1) {}
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotifyWatcherMac::~NotifyWatcherMac() {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cancel();
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotifyWatcherMac::Watch(const char* key, const CallbackType& callback) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(key);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cancel();
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t status = notify_register_file_descriptor(
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key, &notify_fd_, 0, &notify_token_);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status != NOTIFY_STATUS_OK)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(notify_fd_, 0);
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          notify_fd_,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          true,
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          base::MessageLoopForIO::WATCH_READ,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &watcher_,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this)) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_ = callback;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotifyWatcherMac::Cancel() {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (notify_fd_ >= 0) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notify_cancel(notify_token_);  // Also closes |notify_fd_|.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notify_fd_ = -1;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Reset();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watcher_.StopWatchingFileDescriptor();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotifyWatcherMac::OnFileCanReadWithoutBlocking(int fd) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int token;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int status = HANDLE_EINTR(read(notify_fd_, &token, sizeof(token)));
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status != sizeof(token)) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Run(false);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignoring |token| value to avoid possible endianness mismatch:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://openradar.appspot.com/8821081
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(true);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
65