]>
git.saurik.com Git - apple/security.git/blob - Network/netmanager.cpp
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // manager - network protocol core manager class
22 #include "netmanager.h"
25 #include "netconnection.h"
33 Manager::Manager() : mActiveTransfers(0), mRetainConnections(true), mObserver(NULL
)
39 //@@@ cleanup, s'il vous plait:
40 //@@@ abort transfers and destroy them
41 //@@@ notify any observers
42 //@@@ destroy protocol objects
47 // Add a new Transfer to this Manager.
48 // This does not start it; it'll just sit around until started.
50 void Manager::add(Transfer
*xfer
)
52 assert(xfer
->state() == Transfer::cold
);
53 mTransfers
.insert(xfer
);
54 xfer
->mState
= Transfer::warm
;
59 // Remove a Transfer from this Manager.
60 // You can remove a pre-active Transfer, or one that has finished or failed.
61 // You can't remove an active Transfer - abort it first.
63 void Manager::remove(Transfer
*xfer
)
65 assert(mTransfers
.find(xfer
) != mTransfers
.end()); // is ours
66 assert(xfer
->state() != Transfer::active
);
67 mTransfers
.erase(xfer
);
72 // Start a Transfer. It must already have been added, and must be in a pre-active state.
74 void Manager::start(Transfer
*xfer
)
76 assert(mTransfers
.find(xfer
) != mTransfers
.end()); // is ours
77 assert(xfer
->state() == Transfer::warm
);
80 xfer
->mState
= Transfer::active
;
81 xfer
->observe(Observer::transferStarting
);
83 debug("netmanager", "%ld active transfers", mActiveTransfers
);
85 xfer
->mState
= Transfer::failed
;
86 debug("netmanager", "Transfer %p failed to start", xfer
);
94 // If it is active, try to make it stop as soon as it's safe. This may return while
95 // the Transfer's state is still active; it will eventually switch to failed unless it
96 // happened to succeed before we got to it (in which case it'll be finished).
97 // You can't abort a Transfer that isn't active.
98 //@@@ Phasing problem? Perhaps aborting non-active Transfers should be
99 //@@@ allowed (and ignored or flagged).
101 void Manager::abort(Transfer
*xfer
)
103 assert(mTransfers
.find(xfer
) != mTransfers
.end()); // is ours
104 switch (xfer
->state()) {
105 case Transfer::active
:
107 debug("netmanager", "xfer %p request abort", xfer
);
110 debug("netmanager", "xfer %p failed to abort; forcing the issue", xfer
);
111 xfer
->Transfer::abort();
114 case Transfer::finished
:
115 case Transfer::failed
:
116 // no longer running; ignore cancel request
117 debug("netmanager", "xfer %p abort ignored (already done)", xfer
);
120 assert(false); // mustn't call in this state
126 // Do bookkeeping for a Transfer that wants to be done.
127 // This method can only be called from a Transfer that belongs
128 // to this Manager and was started.
130 void Manager::done(Transfer
*xfer
)
132 assert(mTransfers
.find(xfer
) != mTransfers
.end()); // is ours
133 assert(xfer
->state() == Transfer::finished
|| xfer
->state() == Transfer::failed
);
134 assert(mActiveTransfers
> 0);
136 debug("netmanager", "%ld active transfers", mActiveTransfers
);
141 // Manage engine clients on behalf of active Transfers.
142 //@@@ Currently the API doesn't specify which Transfer these belong to.
143 //@@@ Perhaps it should.
145 void Manager::addIO(TransferEngine::Client
*client
)
150 void Manager::removeIO(TransferEngine::Client
*client
)
152 mEngine
.remove(client
);
157 // Manage Connections on behalf of Transfers (and perhaps Protocols)
159 void Manager::retainConnection(Connection
*connection
)
161 if (mRetainConnections
)
162 mConnections
.retain(connection
);
164 closeConnection(connection
);
167 void Manager::closeConnection(Connection
*connection
)
169 mConnections
.remove(connection
);
170 mMorgue
.insert(connection
);
175 // Try to find a live retained Connection for a HostTarget and return it.
177 Connection
*Manager::pickConnection(const HostTarget
&host
)
179 while (Connection
*connection
= mConnections
.get(host
)) {
180 if (connection
->validate()) {
181 connection
->restarting(true); // mark restarting
182 return connection
; // good to go
184 // if validate returned false, the connection has self-destructed (so ignore it)
185 debug("netmanager", "%p connection %p failed to validate",
188 return NULL
; // no joy, caller must make a new one
193 // Handle the global Connection cache
195 void Manager::reuseConnections(bool retain
)
197 mRetainConnections
= retain
;
201 void Manager::flushConnections()
203 mConnections
.purge();
210 void Manager::setTimer(Timer
*timer
, Time::Absolute when
)
212 mTimers
.schedule(timer
, when
);
215 void Manager::clearTimer(Timer
*timer
)
217 if (timer
->scheduled())
218 mTimers
.unschedule(timer
);
222 void Manager::runTimers()
224 while (Timer
*top
= static_cast<Timer
*>(mTimers
.pop(Time::now()))) {
225 debug("netmanager", "%p timer %p executing at %.3f",
226 this, top
, Time::now().internalForm());
229 debug("machsrvtime", "%p timer %p done", this, top
);
232 "%p server timer %p failed with exception", this, top
);
239 // Perform a (small) incremental operations step.
244 if (!mEngine
.isEmpty()) {
245 debug("mgrstep", "operations step");
252 // Run in this thread until a particular time (or until no more Transfers are active).
254 void Manager::run(Time::Absolute stopTime
)
257 "starting run with %ld active transfers", mActiveTransfers
);
258 while (mActiveTransfers
> 0) {
260 Time::Absolute limit
= mTimers
.empty() ? stopTime
: min(stopTime
, mTimers
.next());
261 mEngine(limit
- Time::now());
262 if (Time::now() > stopTime
)
265 debug("netmanager", "ending run");
270 run(Time::heatDeath());
277 void Manager::prepare()
280 if (!mMorgue
.empty()) {
282 "clearing morgue of %ld connections", mMorgue
.size());
283 for (set
<Connection
*>::iterator it
= mMorgue
.begin(); it
!= mMorgue
.end(); it
++)
285 mMorgue
.erase(mMorgue
.begin(), mMorgue
.end());
288 // run pending timers
293 } // end namespace Network
294 } // end namespace Security