OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "mojo/public/bindings/lib/connector.h" | |
6 | |
7 #include <assert.h> | |
8 #include <stdlib.h> | |
9 | |
10 #include "mojo/public/cpp/bindings/error_handler.h" | |
11 | |
12 namespace mojo { | |
13 namespace internal { | |
14 | |
15 // ---------------------------------------------------------------------------- | |
16 | |
17 Connector::Connector(ScopedMessagePipeHandle message_pipe, | |
18 MojoAsyncWaiter* waiter) | |
19 : error_handler_(NULL), | |
20 waiter_(waiter), | |
21 message_pipe_(message_pipe.Pass()), | |
22 incoming_receiver_(NULL), | |
23 async_wait_id_(0), | |
24 error_(false), | |
25 drop_writes_(false) { | |
26 // Even though we don't have an incoming receiver, we still want to monitor | |
27 // the message pipe to know if is closed or encounters an error. | |
28 WaitToReadMore(); | |
29 } | |
30 | |
31 Connector::~Connector() { | |
32 if (async_wait_id_) | |
33 waiter_->CancelWait(waiter_, async_wait_id_); | |
34 } | |
35 | |
36 void Connector::CloseMessagePipe() { | |
37 Close(message_pipe_.Pass()); | |
38 } | |
39 | |
40 bool Connector::Accept(Message* message) { | |
41 if (error_) | |
42 return false; | |
43 | |
44 if (drop_writes_) | |
45 return true; | |
46 | |
47 MojoResult rv = WriteMessageRaw( | |
48 message_pipe_.get(), | |
49 message->data(), | |
50 message->data_num_bytes(), | |
51 message->mutable_handles()->empty() ? NULL : | |
52 reinterpret_cast<const MojoHandle*>( | |
53 &message->mutable_handles()->front()), | |
54 static_cast<uint32_t>(message->mutable_handles()->size()), | |
55 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
56 | |
57 switch (rv) { | |
58 case MOJO_RESULT_OK: | |
59 // The handles were successfully transferred, so we don't need the message | |
60 // to track their lifetime any longer. | |
61 message->mutable_handles()->clear(); | |
62 break; | |
63 case MOJO_RESULT_FAILED_PRECONDITION: | |
64 // There's no point in continuing to write to this pipe since the other | |
65 // end is gone. Avoid writing any future messages. Hide write failures | |
66 // from the caller since we'd like them to continue consuming any backlog | |
67 // of incoming messages before regarding the message pipe as closed. | |
68 drop_writes_ = true; | |
69 break; | |
70 default: | |
71 // This particular write was rejected, presumably because of bad input. | |
72 // The pipe is not necessarily in a bad state. | |
73 return false; | |
74 } | |
75 return true; | |
76 } | |
77 | |
78 bool Connector::AcceptWithResponder(Message* message, | |
79 MessageReceiver* responder) { | |
80 // TODO(darin): Implement this! | |
81 assert(false); | |
82 return false; | |
83 } | |
84 | |
85 // static | |
86 void Connector::CallOnHandleReady(void* closure, MojoResult result) { | |
87 Connector* self = static_cast<Connector*>(closure); | |
88 self->OnHandleReady(result); | |
89 } | |
90 | |
91 void Connector::OnHandleReady(MojoResult result) { | |
92 async_wait_id_ = 0; | |
93 | |
94 if (result == MOJO_RESULT_OK) { | |
95 ReadMore(); | |
96 } else { | |
97 error_ = true; | |
98 } | |
99 | |
100 if (error_ && error_handler_) | |
101 error_handler_->OnError(); | |
102 } | |
103 | |
104 void Connector::WaitToReadMore() { | |
105 async_wait_id_ = waiter_->AsyncWait(waiter_, | |
106 message_pipe_.get().value(), | |
107 MOJO_WAIT_FLAG_READABLE, | |
108 MOJO_DEADLINE_INDEFINITE, | |
109 &Connector::CallOnHandleReady, | |
110 this); | |
111 } | |
112 | |
113 void Connector::ReadMore() { | |
114 while (true) { | |
115 MojoResult rv; | |
116 | |
117 rv = ReadAndDispatchMessage(message_pipe_.get(), incoming_receiver_, NULL); | |
118 if (rv == MOJO_RESULT_SHOULD_WAIT) { | |
119 WaitToReadMore(); | |
120 break; | |
121 } | |
122 if (rv != MOJO_RESULT_OK) { | |
123 error_ = true; | |
124 break; | |
125 } | |
126 } | |
127 } | |
128 | |
129 } // namespace internal | |
130 } // namespace mojo | |
OLD | NEW |