OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "device/bluetooth/bluetooth_socket_experimental_chromeos.h" |
| 6 |
| 7 #include <errno.h> |
| 8 #include <unistd.h> |
| 9 #include <sys/ioctl.h> |
| 10 #include <sys/types.h> |
| 11 #include <sys/socket.h> |
| 12 |
| 13 #include <string> |
| 14 |
| 15 #include "base/logging.h" |
| 16 #include "base/memory/ref_counted.h" |
| 17 #include "base/safe_strerror_posix.h" |
| 18 #include "base/threading/thread_restrictions.h" |
| 19 #include "dbus/file_descriptor.h" |
| 20 #include "device/bluetooth/bluetooth_socket.h" |
| 21 #include "net/base/io_buffer.h" |
| 22 |
| 23 namespace chromeos { |
| 24 |
| 25 BluetoothSocketExperimentalChromeOS::BluetoothSocketExperimentalChromeOS( |
| 26 int fd) |
| 27 : fd_(fd) { |
| 28 // Fetch the socket type so we read from it correctly. |
| 29 int optval; |
| 30 socklen_t opt_len = sizeof optval; |
| 31 if (getsockopt(fd_, SOL_SOCKET, SO_TYPE, &optval, &opt_len) < 0) { |
| 32 // Sequenced packet is the safest assumption since it won't result in |
| 33 // truncated packets. |
| 34 LOG(WARNING) << "Unable to get socket type: " << safe_strerror(errno); |
| 35 optval = SOCK_SEQPACKET; |
| 36 } |
| 37 |
| 38 if (optval == SOCK_DGRAM || optval == SOCK_SEQPACKET) { |
| 39 socket_type_ = L2CAP; |
| 40 } else { |
| 41 socket_type_ = RFCOMM; |
| 42 } |
| 43 } |
| 44 |
| 45 BluetoothSocketExperimentalChromeOS::~BluetoothSocketExperimentalChromeOS() { |
| 46 close(fd_); |
| 47 } |
| 48 |
| 49 bool BluetoothSocketExperimentalChromeOS::Receive( |
| 50 net::GrowableIOBuffer *buffer) { |
| 51 base::ThreadRestrictions::AssertIOAllowed(); |
| 52 |
| 53 if (socket_type_ == L2CAP) { |
| 54 int count; |
| 55 if (ioctl(fd_, FIONREAD, &count) < 0) { |
| 56 LOG(WARNING) << "Unable to get waiting data size: " |
| 57 << safe_strerror(errno); |
| 58 return true; |
| 59 } |
| 60 |
| 61 // TODO(keybuk): verify what happens on a closed socket |
| 62 // read(0) always returns (0) |
| 63 |
| 64 buffer->SetCapacity(count); |
| 65 } else { |
| 66 buffer->SetCapacity(1024); |
| 67 } |
| 68 |
| 69 ssize_t bytes_read; |
| 70 do { |
| 71 if (buffer->RemainingCapacity() == 0) |
| 72 buffer->SetCapacity(buffer->capacity() * 2); |
| 73 bytes_read = read(fd_, buffer->data(), buffer->RemainingCapacity()); |
| 74 if (bytes_read > 0) |
| 75 buffer->set_offset(buffer->offset() + bytes_read); |
| 76 } while (socket_type_ == RFCOMM && bytes_read > 0); |
| 77 |
| 78 if (bytes_read < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { |
| 79 error_message_ = safe_strerror(errno); |
| 80 return false; |
| 81 } |
| 82 return true; |
| 83 } |
| 84 |
| 85 bool BluetoothSocketExperimentalChromeOS::Send( |
| 86 net::DrainableIOBuffer *buffer) { |
| 87 base::ThreadRestrictions::AssertIOAllowed(); |
| 88 |
| 89 ssize_t bytes_written; |
| 90 do { |
| 91 bytes_written = write(fd_, buffer->data(), buffer->BytesRemaining()); |
| 92 if (bytes_written > 0) |
| 93 buffer->DidConsume(bytes_written); |
| 94 } while (buffer->BytesRemaining() > 0 && bytes_written > 0); |
| 95 |
| 96 if (bytes_written < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { |
| 97 error_message_ = safe_strerror(errno); |
| 98 return false; |
| 99 } |
| 100 return true; |
| 101 } |
| 102 |
| 103 std::string BluetoothSocketExperimentalChromeOS::GetLastErrorMessage() const { |
| 104 return error_message_; |
| 105 } |
| 106 |
| 107 // static |
| 108 scoped_refptr<device::BluetoothSocket> |
| 109 BluetoothSocketExperimentalChromeOS::Create(dbus::FileDescriptor* fd) { |
| 110 DCHECK(fd->is_valid()); |
| 111 |
| 112 BluetoothSocketExperimentalChromeOS* bluetooth_socket = |
| 113 new BluetoothSocketExperimentalChromeOS(fd->TakeValue());; |
| 114 return scoped_refptr<BluetoothSocketExperimentalChromeOS>(bluetooth_socket); |
| 115 } |
| 116 |
| 117 } // namespace chromeos |
OLD | NEW |