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

Side by Side Diff: libraries/nacl-mounts/net/TcpSocket.cc

Issue 10392070: Socket subsystem implementation (Closed) Base URL: http://naclports.googlecode.com/svn/trunk/src/
Patch Set: Created 8 years, 6 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 | « libraries/nacl-mounts/net/TcpSocket.h ('k') | libraries/nacl-mounts/net/newlib_compat.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium OS 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 "net/TcpSocket.h"
6
7 #include <assert.h>
8 #include <string.h>
9 #include "../net/SocketSubSystem.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/cpp/module.h"
12 #include "../util/DebugPrint.h"
13 #include "../util/PthreadHelpers.h"
14
15 TCPSocket::TCPSocket(SocketSubSystem* sys, int oflag)
16 : ref_(1), oflag_(oflag), factory_(this), socket_(NULL),
17 read_buf_(kBufSize), write_sent_(false), sys_(sys) {
18 }
19
20 TCPSocket::~TCPSocket() {
21 assert(!socket_);
22 assert(!ref_);
23 }
24
25 void TCPSocket::addref() {
26 ++ref_;
27 }
28
29 void TCPSocket::release() {
30 if (!--ref_)
31 delete this;
32 }
33
34 bool TCPSocket::connect(const char* host, uint16_t port) {
35 SimpleAutoLock lock(sys_->mutex());
36 int32_t result = PP_OK_COMPLETIONPENDING;
37 pp::Module::Get()->core()->CallOnMainThread(0,
38 factory_.NewCallback(&TCPSocket::Connect, host, port, &result));
39 while (result == PP_OK_COMPLETIONPENDING) {
40 sys_->cond().wait(sys_->mutex());
41 }
42 return result == PP_OK;
43 }
44
45 bool TCPSocket::acceptFrom(PP_Resource resource) {
46 SimpleAutoLock lock(sys_->mutex());
47 int32_t result = PP_OK_COMPLETIONPENDING;
48 pp::Module::Get()->core()->CallOnMainThread(0,
49 factory_.NewCallback(&TCPSocket::Accept, resource, &result));
50 while (result == PP_OK_COMPLETIONPENDING) {
51 sys_->cond().wait(sys_->mutex());
52 }
53 return result == PP_OK;
54 }
55
56 void TCPSocket::close() {
57 SimpleAutoLock lock(sys_->mutex());
58 if (socket_) {
59 int32_t result = PP_OK_COMPLETIONPENDING;
60 pp::Module::Get()->core()->CallOnMainThread(0,
61 factory_.NewCallback(&TCPSocket::Close, &result));
62 while (result == PP_OK_COMPLETIONPENDING) {
63 sys_->cond().wait(sys_->mutex());
64 }
65 }
66 }
67
68 int TCPSocket::read(char* buf, size_t count, size_t* nread) {
69 SimpleAutoLock lock(sys_->mutex());
70 if (!is_open())
71 return EIO;
72
73 if (is_block()) {
74 while (in_buf_.empty() && is_open())
75 sys_->cond().wait(sys_->mutex());
76 }
77
78 *nread = 0;
79 while (*nread < count) {
80 if (in_buf_.empty())
81 break;
82
83 buf[(*nread)++] = in_buf_.front();
84 in_buf_.pop_front();
85 }
86
87 if (*nread == 0) {
88 if (!is_open()) {
89 return 0;
90 } else {
91 *nread = -1;
92 return EAGAIN;
93 }
94 }
95
96 return 0;
97 }
98
99 int TCPSocket::write(const char* buf, size_t count, size_t* nwrote) {
100 SimpleAutoLock lock(sys_->mutex());
101 if (!is_open())
102 return EIO;
103
104 out_buf_.insert(out_buf_.end(), buf, buf + count);
105 if (is_block()) {
106 int32_t result = PP_OK_COMPLETIONPENDING;
107 pp::Module::Get()->core()->CallOnMainThread(0,
108 factory_.NewCallback(&TCPSocket::Write, &result));
109 while (result == PP_OK_COMPLETIONPENDING)
110 sys_->cond().wait(sys_->mutex());
111 if ((size_t)result != count) {
112 *nwrote = -1;
113 return EIO;
114 } else {
115 *nwrote = count;
116 return 0;
117 }
118 } else {
119 if (!write_sent_) {
120 write_sent_ = true;
121 pp::Module::Get()->core()->CallOnMainThread(0,
122 factory_.NewCallback(&TCPSocket::Write,
123 reinterpret_cast<int32_t*>(NULL)));
124 }
125 *nwrote = count;
126 return 0;
127 }
128 }
129
130 int TCPSocket::fcntl(int cmd, va_list ap) {
131 if (cmd == F_GETFL) {
132 return oflag_;
133 } else if (cmd == F_SETFL) {
134 oflag_ = va_arg(ap, long);
135 return 0;
136 } else {
137 return -1;
138 }
139 }
140
141 bool TCPSocket::is_read_ready() {
142 return !is_open() || !in_buf_.empty();
143 }
144
145 bool TCPSocket::is_write_ready() {
146 return !is_open() || out_buf_.size() < kBufSize;
147 }
148
149 bool TCPSocket::is_exception() {
150 return !is_open();
151 }
152
153 void TCPSocket::Connect(int32_t result, const char* host, uint16_t port,
154 int32_t* pres) {
155 SimpleAutoLock lock(sys_->mutex());
156 assert(!socket_);
157 socket_ = new pp::TCPSocketPrivate(sys_->instance());
158 *pres = socket_->Connect(host, port,
159 factory_.NewCallback(&TCPSocket::OnConnect, pres));
160 if (*pres != PP_OK_COMPLETIONPENDING) {
161 sys_->cond().broadcast();
162 }
163 }
164
165 void TCPSocket::OnConnect(int32_t result, int32_t* pres) {
166 SimpleAutoLock lock(sys_->mutex());
167 if (result == PP_OK) {
168 Read(PP_OK, NULL);
169 } else {
170 delete socket_;
171 socket_ = NULL;
172 }
173 *pres = result;
174 sys_->cond().broadcast();
175 }
176
177 void TCPSocket::Read(int32_t result, int32_t* pres) {
178 SimpleAutoLock lock(sys_->mutex());
179 if (!is_open())
180 return;
181
182 result = socket_->Read(&read_buf_[0], read_buf_.size(),
183 factory_.NewCallback(&TCPSocket::OnRead, pres));
184 if (result != PP_OK_COMPLETIONPENDING) {
185 delete socket_;
186 socket_ = NULL;
187 if (pres)
188 *pres = result;
189 sys_->cond().broadcast();
190 }
191 }
192
193 void TCPSocket::OnRead(int32_t result, int32_t* pres) {
194 SimpleAutoLock lock(sys_->mutex());
195 if (!is_open())
196 return;
197
198 if (result > 0) {
199 in_buf_.insert(in_buf_.end(), &read_buf_[0], &read_buf_[0]+result);
200 Read(PP_OK, NULL);
201 } else {
202 delete socket_;
203 socket_ = NULL;
204 }
205 if (pres)
206 *pres = result;
207 sys_->cond().broadcast();
208 }
209
210 void TCPSocket::Write(int32_t result, int32_t* pres) {
211 SimpleAutoLock lock(sys_->mutex());
212 if (!is_open())
213 return;
214
215 if (write_buf_.size()) {
216 // Previous write operation is in progress.
217 pp::Module::Get()->core()->CallOnMainThread(1,
218 factory_.NewCallback(&TCPSocket::Write, &result));
219 return;
220 }
221 assert(out_buf_.size());
222 write_buf_.swap(out_buf_);
223 result = socket_->Write(&write_buf_[0], write_buf_.size(),
224 factory_.NewCallback(&TCPSocket::OnWrite, pres));
225 if (result != PP_OK_COMPLETIONPENDING) {
226 dbgprintf("TCPSocket::Write: failed %d %d\n", result, write_buf_.size());
227 delete socket_;
228 socket_ = NULL;
229 if (pres)
230 *pres = result;
231 sys_->cond().broadcast();
232 }
233 write_sent_ = false;
234 }
235
236 void TCPSocket::OnWrite(int32_t result, int32_t* pres) {
237 SimpleAutoLock lock(sys_->mutex());
238 if (!is_open())
239 return;
240
241 if (result < 0 || (size_t)result > write_buf_.size()) {
242 // Write error.
243 dbgprintf("TCPSocket::OnWrite: close socket\n");
244 delete socket_;
245 socket_ = NULL;
246 } else if ((size_t)result < write_buf_.size()) {
247 // Partial write. Insert remaining bytes at the beginning of out_buf_.
248 out_buf_.insert(out_buf_.begin(), &write_buf_[result], &*write_buf_.end());
249 }
250 if (pres)
251 *pres = result;
252 write_buf_.clear();
253 sys_->cond().broadcast();
254 }
255
256 void TCPSocket::Close(int32_t result, int32_t* pres) {
257 SimpleAutoLock lock(sys_->mutex());
258 delete socket_;
259 socket_ = NULL;
260 if (pres)
261 *pres = PP_OK;
262 sys_->cond().broadcast();
263 }
264
265 bool TCPSocket::Accept(int32_t result, PP_Resource resource, int32_t* pres) {
266 SimpleAutoLock lock(sys_->mutex());
267 assert(!socket_);
268 socket_ = new pp::TCPSocketPrivate(pp::PassRef(), resource);
269 Read(PP_OK, NULL);
270 *pres = PP_OK;
271 sys_->cond().broadcast();
272 return true;
273 }
274
OLDNEW
« no previous file with comments | « libraries/nacl-mounts/net/TcpSocket.h ('k') | libraries/nacl-mounts/net/newlib_compat.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698