00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _PASSENGER_EVENTED_SERVER_H_
00026 #define _PASSENGER_EVENTED_SERVER_H_
00027
00028 #include <ev++.h>
00029 #include <boost/shared_ptr.hpp>
00030 #include <boost/enable_shared_from_this.hpp>
00031 #include <oxt/system_calls.hpp>
00032 #include <oxt/macros.hpp>
00033 #include <algorithm>
00034 #include <string>
00035 #include <set>
00036 #include <sys/types.h>
00037 #include <sys/un.h>
00038 #include <sys/uio.h>
00039 #include <netinet/in.h>
00040 #include <unistd.h>
00041 #include <cerrno>
00042 #include "EventedClient.h"
00043 #include "FileDescriptor.h"
00044 #include "StaticString.h"
00045 #include "Logging.h"
00046 #include "Utils/ScopeGuard.h"
00047 #include "Utils/StrIntUtils.h"
00048
00049 namespace Passenger {
00050
00051 using namespace std;
00052 using namespace boost;
00053 using namespace oxt;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 class EventedServer {
00090 protected:
00091 typedef set<EventedClient *> ClientSet;
00092
00093 const ClientSet &getClients() const {
00094 return clients;
00095 }
00096
00097 string getClientName(const EventedClient *client) const {
00098 return toString(client);
00099 }
00100
00101 void logError(const EventedClient *client, const string &message) {
00102 P_ERROR("Error in client " << getClientName(client) << ": " << message);
00103 }
00104
00105 void logSystemError(const EventedClient *client, const string &message, int errorCode) {
00106 P_ERROR("Error in client " << getClientName(client) << ": " <<
00107 message << ": " << strerror(errorCode) << " (" << errorCode << ")");
00108 }
00109
00110 void logSystemError(const string &message, int errorCode) {
00111 P_ERROR(message << ": " << strerror(errorCode) << " (" << errorCode << ")");
00112 }
00113
00114 virtual EventedClient *createClient(const FileDescriptor &fd) {
00115 return new EventedClient(loop, fd);
00116 }
00117
00118 virtual void onNewClient(EventedClient *client) { }
00119 virtual void onClientReadable(EventedClient *client) { }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 virtual void onClientDisconnected(EventedClient *client) { }
00132
00133 private:
00134 struct ev_loop *loop;
00135 FileDescriptor fd;
00136 ev::io acceptWatcher;
00137 ClientSet clients;
00138
00139 void removeClient(EventedClient *client) {
00140 clients.erase(client);
00141 }
00142
00143 void freeAllClients() {
00144 ClientSet::iterator it;
00145 ClientSet::iterator end = clients.end();
00146
00147 for (it = clients.begin(); it != clients.end(); it++) {
00148 (*it)->unref();
00149 }
00150 clients.clear();
00151 }
00152
00153 static void _onReadable(EventedClient *client) {
00154 EventedServer *server = (EventedServer *) client->userData;
00155 client->ref();
00156 ScopeGuard guard(boost::bind(&EventedClient::unref, client));
00157 server->onClientReadable((EventedClient *) client);
00158 }
00159
00160 static void _onDisconnect(EventedClient *client) {
00161 EventedServer *server = (EventedServer *) client->userData;
00162 ScopeGuard guard1(boost::bind(&EventedClient::unref, client));
00163
00164 client->ref();
00165 ScopeGuard guard2(boost::bind(&EventedClient::unref, client));
00166
00167 server->removeClient(client);
00168 server->onClientDisconnected((EventedClient *) client);
00169 }
00170
00171 static void _onDetach(EventedClient *client) {
00172 EventedServer *server = (EventedServer *) client->userData;
00173 ScopeGuard guard1(boost::bind(&EventedClient::unref, client));
00174
00175 client->ref();
00176 ScopeGuard guard2(boost::bind(&EventedClient::unref, client));
00177
00178 server->removeClient(client);
00179 }
00180
00181 static void _onSystemError(EventedClient *client, const string &message, int code) {
00182 EventedServer *server = (EventedServer *) client->userData;
00183 server->logSystemError(client, message, code);
00184 }
00185
00186 void exceptionThrownWhileInitializingClient(EventedClient *client, ClientSet::iterator it) {
00187 if (!client->ioAllowed()) {
00188
00189
00190 client->unref();
00191 } else {
00192
00193 client->unref();
00194 client->unref();
00195 clients.erase(it);
00196 }
00197
00198 }
00199
00200 void onAcceptable(ev::io &w, int revents) {
00201 this_thread::disable_syscall_interruption dsi;
00202 int i = 0;
00203 bool done = false;
00204
00205
00206
00207 while (i < 10 && !done) {
00208
00209
00210 union {
00211 struct sockaddr_un local;
00212 struct sockaddr_in inet;
00213 } addr;
00214 socklen_t len = sizeof(addr);
00215
00216 int clientfd = syscalls::accept(fd, (struct sockaddr *) &addr, &len);
00217 if (clientfd == -1) {
00218 if (errno != EAGAIN && errno != EWOULDBLOCK) {
00219 int e = errno;
00220 logSystemError("Cannot accept new client", e);
00221 }
00222 done = true;
00223 } else {
00224 FileDescriptor clientfdGuard = clientfd;
00225 int optval = 1;
00226
00227 setNonBlocking(clientfdGuard);
00228 syscalls::setsockopt(clientfd, SOL_SOCKET, SO_KEEPALIVE,
00229 &optval, sizeof(optval));
00230
00231 EventedClient *client = createClient(clientfdGuard);
00232 client->onReadable = _onReadable;
00233 client->onDisconnect = _onDisconnect;
00234 client->onDetach = _onDetach;
00235 client->onSystemError = _onSystemError;
00236 client->userData = this;
00237 client->notifyReads(true);
00238
00239 pair<ClientSet::iterator, bool> p = clients.insert(client);
00240
00241 client->ref();
00242
00243 {
00244 ScopeGuard g(boost::bind(
00245 &EventedServer::exceptionThrownWhileInitializingClient,
00246 this,
00247 client,
00248 p.first));
00249 onNewClient(client);
00250 g.clear();
00251
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 client->unref();
00263 }
00264 i++;
00265 }
00266 }
00267
00268 public:
00269 EventedServer(struct ev_loop *_loop, FileDescriptor serverFd)
00270 : loop(_loop),
00271 acceptWatcher(_loop)
00272 {
00273 fd = serverFd;
00274 setNonBlocking(serverFd);
00275 acceptWatcher.set<EventedServer, &EventedServer::onAcceptable>(this);
00276 acceptWatcher.start(fd, ev::READ);
00277 }
00278
00279 virtual ~EventedServer() {
00280 freeAllClients();
00281 }
00282
00283 struct ev_loop *getLoop() const {
00284 return loop;
00285 }
00286
00287 FileDescriptor getServerFd() const {
00288 return fd;
00289 }
00290 };
00291
00292
00293 }
00294
00295 #endif