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_MESSAGE_CLIENT_H_
00026 #define _PASSENGER_MESSAGE_CLIENT_H_
00027
00028 #include <boost/shared_ptr.hpp>
00029 #include <string>
00030
00031 #include "StaticString.h"
00032 #include "MessageChannel.h"
00033 #include "Exceptions.h"
00034 #include "Utils.h"
00035
00036
00037 namespace Passenger {
00038
00039 using namespace std;
00040 using namespace boost;
00041
00042 class MessageClient {
00043 protected:
00044 FileDescriptor fd;
00045 MessageChannel channel;
00046
00047
00048
00049 virtual void sendUsername(MessageChannel &channel, const string &username) {
00050 channel.writeScalar(username);
00051 }
00052
00053 virtual void sendPassword(MessageChannel &channel, const StaticString &userSuppliedPassword) {
00054 channel.writeScalar(userSuppliedPassword.c_str(), userSuppliedPassword.size());
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 void authenticate(const string &username, const StaticString &userSuppliedPassword) {
00067 vector<string> args;
00068
00069 sendUsername(channel, username);
00070 sendPassword(channel, userSuppliedPassword);
00071
00072 if (!channel.read(args)) {
00073 throw IOException("The ApplicationPool server did not send an authentication response.");
00074 } else if (args.size() != 1) {
00075 throw IOException("The authentication response that the ApplicationPool server sent is not valid.");
00076 } else if (args[0] != "ok") {
00077 throw SecurityException("The ApplicationPool server denied authentication: " + args[0]);
00078 }
00079 }
00080
00081
00082 void silentDisconnect() {
00083 fd = FileDescriptor();
00084 channel = MessageChannel();
00085 }
00086
00087 public:
00088
00089
00090
00091
00092 MessageClient() {
00093
00094
00095
00096
00097 }
00098
00099 virtual ~MessageClient() { }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 MessageClient *connect(const string &socketFilename, const string &username, const StaticString &userSuppliedPassword) {
00121 try {
00122 fd = connectToUnixServer(socketFilename.c_str());
00123 channel = MessageChannel(fd);
00124 authenticate(username, userSuppliedPassword);
00125 return this;
00126 } catch (const RuntimeException &) {
00127 silentDisconnect();
00128 throw;
00129 } catch (const SystemException &) {
00130 silentDisconnect();
00131 throw;
00132 } catch (const IOException &) {
00133 silentDisconnect();
00134 throw;
00135 } catch (const boost::thread_interrupted &) {
00136 silentDisconnect();
00137 throw;
00138 }
00139 }
00140
00141 void disconnect() {
00142 if (fd != -1) {
00143 fd.close();
00144 fd = FileDescriptor();
00145 channel = MessageChannel();
00146 }
00147 }
00148
00149 bool connected() const {
00150 return fd != -1;
00151 }
00152
00153
00154
00155
00156
00157 bool read(vector<string> &args) {
00158 try {
00159 return channel.read(args);
00160 } catch (const SystemException &e) {
00161 silentDisconnect();
00162 throw;
00163 }
00164 }
00165
00166
00167
00168
00169
00170
00171
00172 bool readScalar(string &output, unsigned int maxSize = 0, unsigned long long *timeout = NULL) {
00173 try {
00174 return channel.readScalar(output, maxSize, timeout);
00175 } catch (const SystemException &) {
00176 silentDisconnect();
00177 throw;
00178 } catch (const SecurityException &) {
00179 silentDisconnect();
00180 throw;
00181 } catch (const TimeoutException &) {
00182 silentDisconnect();
00183 throw;
00184 }
00185 }
00186
00187
00188
00189
00190
00191
00192 int readFileDescriptor(bool negotiate = true) {
00193 try {
00194 return channel.readFileDescriptor(negotiate);
00195 } catch (const SystemException &) {
00196 silentDisconnect();
00197 throw;
00198 } catch (const IOException &) {
00199 silentDisconnect();
00200 throw;
00201 }
00202 }
00203
00204
00205
00206
00207
00208 void write(const char *name, ...) {
00209 va_list ap;
00210 va_start(ap, name);
00211 try {
00212 try {
00213 channel.write(name, ap);
00214 } catch (const SystemException &) {
00215 silentDisconnect();
00216 throw;
00217 }
00218 va_end(ap);
00219 } catch (...) {
00220 va_end(ap);
00221 throw;
00222 }
00223 }
00224
00225
00226
00227
00228
00229 void writeScalar(const char *data, unsigned int size) {
00230 try {
00231 channel.writeScalar(data, size);
00232 } catch (const SystemException &) {
00233 silentDisconnect();
00234 throw;
00235 }
00236 }
00237
00238
00239
00240
00241
00242 void writeScalar(const StaticString &data) {
00243 try {
00244 channel.writeScalar(data.c_str(), data.size());
00245 } catch (const SystemException &) {
00246 silentDisconnect();
00247 throw;
00248 }
00249 }
00250
00251
00252
00253
00254
00255 void writeFileDescriptor(int fileDescriptor, bool negotiate = true) {
00256 try {
00257 channel.writeFileDescriptor(fileDescriptor, negotiate);
00258 } catch (const SystemException &) {
00259 silentDisconnect();
00260 throw;
00261 }
00262 }
00263 };
00264
00265 typedef shared_ptr<MessageClient> MessageClientPtr;
00266
00267 }
00268
00269 #endif