OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "media/audio/async_socket_io_handler.h" | |
6 | |
7 #include <fcntl.h> | |
8 | |
9 #include "base/posix/eintr_wrapper.h" | |
10 | |
11 namespace media { | |
12 | |
13 AsyncSocketIoHandler::AsyncSocketIoHandler() | |
14 : socket_(base::SyncSocket::kInvalidHandle), | |
15 pending_buffer_(NULL), | |
16 pending_buffer_len_(0), | |
17 is_watching_(false) { | |
18 } | |
19 | |
20 AsyncSocketIoHandler::~AsyncSocketIoHandler() { | |
21 DCHECK(CalledOnValidThread()); | |
22 } | |
23 | |
24 void AsyncSocketIoHandler::OnFileCanReadWithoutBlocking(int socket) { | |
25 DCHECK(CalledOnValidThread()); | |
26 DCHECK_EQ(socket, socket_); | |
27 DCHECK(!read_complete_.is_null()); | |
28 | |
29 if (pending_buffer_) { | |
30 int bytes_read = HANDLE_EINTR(read(socket_, pending_buffer_, | |
31 pending_buffer_len_)); | |
32 DCHECK_GE(bytes_read, 0); | |
33 pending_buffer_ = NULL; | |
34 pending_buffer_len_ = 0; | |
35 read_complete_.Run(bytes_read > 0 ? bytes_read : 0); | |
36 } else { | |
37 // We're getting notifications that we can read from the socket while | |
38 // we're not waiting for data. In order to not starve the message loop, | |
39 // let's stop watching the fd and restart the watch when Read() is called. | |
40 is_watching_ = false; | |
41 socket_watcher_.StopWatchingFileDescriptor(); | |
42 } | |
43 } | |
44 | |
45 bool AsyncSocketIoHandler::Read(char* buffer, int buffer_len) { | |
46 DCHECK(CalledOnValidThread()); | |
47 DCHECK(!read_complete_.is_null()); | |
48 DCHECK(!pending_buffer_); | |
49 | |
50 EnsureWatchingSocket(); | |
51 | |
52 int bytes_read = HANDLE_EINTR(read(socket_, buffer, buffer_len)); | |
53 if (bytes_read < 0) { | |
54 if (errno == EAGAIN) { | |
55 pending_buffer_ = buffer; | |
56 pending_buffer_len_ = buffer_len; | |
57 } else { | |
58 NOTREACHED() << "read(): " << errno; | |
59 return false; | |
60 } | |
61 } else { | |
62 read_complete_.Run(bytes_read); | |
63 } | |
64 return true; | |
65 } | |
66 | |
67 bool AsyncSocketIoHandler::Initialize(base::SyncSocket::Handle socket, | |
68 const ReadCompleteCallback& callback) { | |
69 DCHECK_EQ(socket_, base::SyncSocket::kInvalidHandle); | |
70 | |
71 DetachFromThread(); | |
72 | |
73 socket_ = socket; | |
74 read_complete_ = callback; | |
75 | |
76 // SyncSocket is blocking by default, so let's convert it to non-blocking. | |
77 int value = fcntl(socket, F_GETFL); | |
78 if (!(value & O_NONBLOCK)) { | |
79 // Set the socket to be non-blocking so we can do async reads. | |
80 if (fcntl(socket, F_SETFL, O_NONBLOCK) == -1) { | |
81 NOTREACHED(); | |
82 return false; | |
83 } | |
84 } | |
85 | |
86 return true; | |
87 } | |
88 | |
89 void AsyncSocketIoHandler::EnsureWatchingSocket() { | |
90 DCHECK(CalledOnValidThread()); | |
91 if (!is_watching_ && socket_ != base::SyncSocket::kInvalidHandle) { | |
92 is_watching_ = base::MessageLoopForIO::current()->WatchFileDescriptor( | |
93 socket_, true, base::MessageLoopForIO::WATCH_READ, | |
94 &socket_watcher_, this); | |
95 } | |
96 } | |
97 | |
98 } // namespace media. | |
OLD | NEW |