Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: device/bluetooth/bluetooth_socket_chromeos.cc

Issue 267633003: Reimplement BluetoothSocketChromeOS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Got windows compiling, ship it Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « device/bluetooth/bluetooth_socket_chromeos.h ('k') | device/bluetooth/bluetooth_socket_net.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/bluetooth/bluetooth_socket_chromeos.h" 5 #include "device/bluetooth/bluetooth_socket_chromeos.h"
6 6
7 #include <errno.h>
8 #include <poll.h>
9 #include <unistd.h>
10 #include <sys/ioctl.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13
14 #include <string> 7 #include <string>
15 8
16 #include "base/logging.h" 9 #include "base/logging.h"
17 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
18 #include "base/posix/eintr_wrapper.h" 11 #include "base/sequenced_task_runner.h"
19 #include "base/safe_strerror_posix.h"
20 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
21 #include "dbus/file_descriptor.h" 13 #include "dbus/file_descriptor.h"
22 #include "device/bluetooth/bluetooth_socket.h" 14 #include "device/bluetooth/bluetooth_socket.h"
23 #include "net/base/io_buffer.h" 15 #include "device/bluetooth/bluetooth_socket_net.h"
16 #include "device/bluetooth/bluetooth_socket_thread.h"
17 #include "net/base/ip_endpoint.h"
18 #include "net/base/net_errors.h"
19
20 namespace {
21
22 const char kSocketAlreadyConnected[] = "Socket is already connected.";
23
24 } // namespace
24 25
25 namespace chromeos { 26 namespace chromeos {
26 27
27 BluetoothSocketChromeOS::BluetoothSocketChromeOS(int fd) 28 // static
28 : fd_(fd) { 29 scoped_refptr<BluetoothSocketChromeOS>
29 // Fetch the socket type so we read from it correctly. 30 BluetoothSocketChromeOS::CreateBluetoothSocket(
30 int optval; 31 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
31 socklen_t opt_len = sizeof optval; 32 scoped_refptr<device::BluetoothSocketThread> socket_thread,
32 if (getsockopt(fd_, SOL_SOCKET, SO_TYPE, &optval, &opt_len) < 0) { 33 net::NetLog* net_log,
33 // Sequenced packet is the safest assumption since it won't result in 34 const net::NetLog::Source& source) {
34 // truncated packets. 35 DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
35 LOG(WARNING) << "Unable to get socket type: " << safe_strerror(errno);
36 optval = SOCK_SEQPACKET;
37 }
38 36
39 if (optval == SOCK_DGRAM || optval == SOCK_SEQPACKET) { 37 return make_scoped_refptr(
40 socket_type_ = L2CAP; 38 new BluetoothSocketChromeOS(
41 } else { 39 ui_task_runner, socket_thread, net_log, source));
42 socket_type_ = RFCOMM; 40 }
43 } 41
42 BluetoothSocketChromeOS::BluetoothSocketChromeOS(
43 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
44 scoped_refptr<device::BluetoothSocketThread> socket_thread,
45 net::NetLog* net_log,
46 const net::NetLog::Source& source)
47 : BluetoothSocketNet(ui_task_runner, socket_thread, net_log, source) {
44 } 48 }
45 49
46 BluetoothSocketChromeOS::~BluetoothSocketChromeOS() { 50 BluetoothSocketChromeOS::~BluetoothSocketChromeOS() {
47 close(fd_);
48 } 51 }
49 52
50 void BluetoothSocketChromeOS::Close() { NOTIMPLEMENTED(); } 53 void BluetoothSocketChromeOS::Connect(
54 scoped_ptr<dbus::FileDescriptor> fd,
55 const base::Closure& success_callback,
56 const ErrorCompletionCallback& error_callback) {
57 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread());
51 58
52 void BluetoothSocketChromeOS::Disconnect(const base::Closure& callback) { 59 socket_thread()->task_runner()->PostTask(
53 NOTIMPLEMENTED(); 60 FROM_HERE,
61 base::Bind(
62 &BluetoothSocketChromeOS::DoConnect,
63 this,
64 base::Passed(&fd),
65 base::Bind(&BluetoothSocketChromeOS::PostSuccess,
66 this,
67 success_callback),
68 base::Bind(&BluetoothSocketChromeOS::PostErrorCompletion,
69 this,
70 error_callback)));
54 } 71 }
55 72
56 void BluetoothSocketChromeOS::Receive( 73 void BluetoothSocketChromeOS::DoConnect(
57 int buffer_size, 74 scoped_ptr<dbus::FileDescriptor> fd,
58 const ReceiveCompletionCallback& success_callback, 75 const base::Closure& success_callback,
59 const ReceiveErrorCompletionCallback& error_callback) { 76 const ErrorCompletionCallback& error_callback) {
60 NOTIMPLEMENTED(); 77 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread());
61 } 78 base::ThreadRestrictions::AssertIOAllowed();
79 DCHECK(fd->is_valid());
62 80
63 void BluetoothSocketChromeOS::Send( 81 if (tcp_socket()) {
64 scoped_refptr<net::IOBuffer> buffer, 82 error_callback.Run(kSocketAlreadyConnected);
65 int buffer_size, 83 return;
66 const SendCompletionCallback& success_callback,
67 const ErrorCompletionCallback& error_callback) {
68 NOTIMPLEMENTED();
69 }
70
71 #if 0
72 bool BluetoothSocketChromeOS::Receive(net::GrowableIOBuffer *buffer) {
73 base::ThreadRestrictions::AssertIOAllowed();
74
75 if (socket_type_ == L2CAP) {
76 int count;
77 if (ioctl(fd_, FIONREAD, &count) < 0) {
78 error_message_ = safe_strerror(errno);
79 LOG(WARNING) << "Unable to get waiting data size: " << error_message_;
80 return true;
81 }
82
83 // No bytes waiting can mean either nothing to read, or the other end has
84 // been closed, and reading zero bytes always returns zero.
85 //
86 // We can't do a short read for fear of a race where data arrives between
87 // calls and we trunctate it. So use poll() to check for the POLLHUP flag.
88 if (count == 0) {
89 struct pollfd pollfd;
90
91 pollfd.fd = fd_;
92 pollfd.events = 0;
93 pollfd.revents = 0;
94
95 // Timeout parameter set to 0 so this call will not block.
96 if (HANDLE_EINTR(poll(&pollfd, 1, 0)) < 0) {
97 error_message_ = safe_strerror(errno);
98 LOG(WARNING) << "Unable to check whether socket is closed: "
99 << error_message_;
100 return false;
101 }
102
103 if (pollfd.revents & POLLHUP) {
104 // TODO(keybuk, youngki): Agree a common way to flag disconnected.
105 error_message_ = "Disconnected";
106 return false;
107 }
108 }
109
110 buffer->SetCapacity(count);
111 } else {
112 buffer->SetCapacity(1024);
113 } 84 }
114 85
115 ssize_t bytes_read; 86 ResetTCPSocket();
116 do {
117 if (buffer->RemainingCapacity() == 0)
118 buffer->SetCapacity(buffer->capacity() * 2);
119 bytes_read =
120 HANDLE_EINTR(read(fd_, buffer->data(), buffer->RemainingCapacity()));
121 if (bytes_read > 0)
122 buffer->set_offset(buffer->offset() + bytes_read);
123 } while (socket_type_ == RFCOMM && bytes_read > 0);
124 87
125 // Ignore an error if at least one read() call succeeded; it'll be returned 88 // Note: We don't have a meaningful |IPEndPoint|, but that is ok since the
126 // the next read() call. 89 // TCPSocket implementation does not actually require one.
127 if (buffer->offset() > 0) 90 int net_result = tcp_socket()->AdoptConnectedSocket(fd->value(),
128 return true; 91 net::IPEndPoint());
129 92 if (net_result != net::OK) {
130 if (bytes_read < 0) { 93 error_callback.Run("Error connecting to socket: " +
131 if (errno == ECONNRESET || errno == ENOTCONN) { 94 std::string(net::ErrorToString(net_result)));
132 // TODO(keybuk, youngki): Agree a common way to flag disconnected. 95 return;
133 error_message_ = "Disconnected";
134 return false;
135 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
136 error_message_ = safe_strerror(errno);
137 return false;
138 }
139 } 96 }
140 97
141 if (bytes_read == 0 && socket_type_ == RFCOMM) { 98 fd->TakeValue();
142 // TODO(keybuk, youngki): Agree a common way to flag disconnected. 99 success_callback.Run();
143 error_message_ = "Disconnected";
144 return false;
145 }
146
147 return true;
148 }
149
150 bool BluetoothSocketChromeOS::Send(net::DrainableIOBuffer *buffer) {
151 base::ThreadRestrictions::AssertIOAllowed();
152
153 ssize_t bytes_written;
154 do {
155 bytes_written =
156 HANDLE_EINTR(write(fd_, buffer->data(), buffer->BytesRemaining()));
157 if (bytes_written > 0)
158 buffer->DidConsume(bytes_written);
159 } while (buffer->BytesRemaining() > 0 && bytes_written > 0);
160
161 if (bytes_written < 0) {
162 if (errno == EPIPE || errno == ECONNRESET || errno == ENOTCONN) {
163 // TODO(keybuk, youngki): Agree a common way to flag disconnected.
164 error_message_ = "Disconnected";
165 return false;
166 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
167 error_message_ = safe_strerror(errno);
168 return false;
169 }
170 }
171
172 return true;
173 }
174
175 std::string BluetoothSocketChromeOS::GetLastErrorMessage() const {
176 return error_message_;
177 }
178 #endif
179
180 // static
181 scoped_refptr<device::BluetoothSocket> BluetoothSocketChromeOS::Create(
182 dbus::FileDescriptor* fd) {
183 DCHECK(fd->is_valid());
184
185 BluetoothSocketChromeOS* bluetooth_socket =
186 new BluetoothSocketChromeOS(fd->TakeValue());
187 return scoped_refptr<BluetoothSocketChromeOS>(bluetooth_socket);
188 } 100 }
189 101
190 } // namespace chromeos 102 } // namespace chromeos
OLDNEW
« no previous file with comments | « device/bluetooth/bluetooth_socket_chromeos.h ('k') | device/bluetooth/bluetooth_socket_net.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698