00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <fastcgi++/request.hpp>
00023 #include "utf8_codecvt.hpp"
00024
00025 namespace Fastcgipp
00026 {
00027 template<class charT> inline std::locale makeLocale(std::locale& loc)
00028 {
00029 return loc;
00030 }
00031
00032 template<> std::locale inline makeLocale<wchar_t>(std::locale& loc)
00033 {
00034 return std::locale(loc, new utf8CodeCvt::utf8_codecvt_facet);
00035 }
00036 }
00037
00038 template int Fastcgipp::Fcgistream<char, std::char_traits<char> >::Fcgibuf::emptyBuffer();
00039 template int Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::Fcgibuf::emptyBuffer();
00040 template <class charT, class traits>
00041 int Fastcgipp::Fcgistream<charT, traits>::Fcgibuf::emptyBuffer()
00042 {
00043 using namespace std;
00044 using namespace Protocol;
00045 char_type const* pStreamPos=this->pbase();
00046 while(1)
00047 {{
00048 size_t count=this->pptr()-pStreamPos;
00049 size_t wantedSize=count*sizeof(char_type)+dumpSize;
00050 if(!wantedSize)
00051 break;
00052
00053 int remainder=wantedSize%chunkSize;
00054 wantedSize+=sizeof(Header)+(remainder?(chunkSize-remainder):remainder);
00055 if(wantedSize>numeric_limits<uint16_t>::max()) wantedSize=numeric_limits<uint16_t>::max();
00056 Block dataBlock(transceiver->requestWrite(wantedSize));
00057 dataBlock.size=(dataBlock.size/chunkSize)*chunkSize;
00058
00059 mbstate_t cs = mbstate_t();
00060 char* toNext=dataBlock.data+sizeof(Header);
00061
00062 locale loc=this->getloc();
00063 if(count)
00064 {
00065 if(sizeof(char_type)!=sizeof(char))
00066 {
00067 if(use_facet<codecvt<char_type, char, mbstate_t> >(loc).out(cs, pStreamPos, this->pptr(), pStreamPos, toNext, dataBlock.data+dataBlock.size, toNext)==codecvt_base::error)
00068 {
00069 pbump(-(this->pptr()-this->pbase()));
00070 dumpSize=0;
00071 dumpPtr=0;
00072 throw Exceptions::Stream(id);
00073 }
00074 }
00075 else
00076 {
00077 size_t cnt=min(dataBlock.size-sizeof(Header), count);
00078 memcpy(dataBlock.data+sizeof(Header), pStreamPos, cnt);
00079 pStreamPos+=cnt;
00080 toNext+=cnt;
00081 }
00082 }
00083
00084 size_t dumpedSize=min(dumpSize, static_cast<size_t>(dataBlock.data+dataBlock.size-toNext));
00085 memcpy(toNext, dumpPtr, dumpedSize);
00086 dumpPtr+=dumpedSize;
00087 dumpSize-=dumpedSize;
00088 uint16_t contentLength=toNext-dataBlock.data+dumpedSize-sizeof(Header);
00089 uint8_t contentRemainder=contentLength%chunkSize;
00090
00091 Header& header=*(Header*)dataBlock.data;
00092 header.setVersion(version);
00093 header.setType(type);
00094 header.setRequestId(id.fcgiId);
00095 header.setContentLength(contentLength);
00096 header.setPaddingLength(contentRemainder?(chunkSize-contentRemainder):contentRemainder);
00097
00098 transceiver->secureWrite(sizeof(Header)+contentLength+header.getPaddingLength(), id, false);
00099 }}
00100 pbump(-(this->pptr()-this->pbase()));
00101 return 0;
00102 }
00103
00104 template void Fastcgipp::Request<char>::complete();
00105 template void Fastcgipp::Request<wchar_t>::complete();
00106 template<class charT> void Fastcgipp::Request<charT>::complete()
00107 {
00108 using namespace Protocol;
00109 out.flush();
00110 err.flush();
00111
00112 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
00113
00114 Header& header=*(Header*)buffer.data;
00115 header.setVersion(version);
00116 header.setType(END_REQUEST);
00117 header.setRequestId(id.fcgiId);
00118 header.setContentLength(sizeof(EndRequest));
00119 header.setPaddingLength(0);
00120
00121 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
00122 body.setAppStatus(0);
00123 body.setProtocolStatus(REQUEST_COMPLETE);
00124
00125 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
00126 }
00127
00128 template void Fastcgipp::Fcgistream<char, std::char_traits<char> >::dump(std::basic_istream<char>& stream);
00129 template void Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::dump(std::basic_istream<char>& stream);
00130 template<class charT, class traits > void Fastcgipp::Fcgistream<charT, traits>::dump(std::basic_istream<char>& stream)
00131 {
00132 const size_t bufferSize=32768;
00133 char buffer[bufferSize];
00134
00135 while(stream.good())
00136 {
00137 stream.read(buffer, bufferSize);
00138 dump(buffer, stream.gcount());
00139 }
00140 }
00141
00142 template bool Fastcgipp::Request<char>::handler();
00143 template bool Fastcgipp::Request<wchar_t>::handler();
00144 template<class charT> bool Fastcgipp::Request<charT>::handler()
00145 {
00146 using namespace Protocol;
00147 using namespace std;
00148
00149 try
00150 {
00151 if(role!=RESPONDER)
00152 {
00153 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
00154
00155 Header& header=*(Header*)buffer.data;
00156 header.setVersion(version);
00157 header.setType(END_REQUEST);
00158 header.setRequestId(id.fcgiId);
00159 header.setContentLength(sizeof(EndRequest));
00160 header.setPaddingLength(0);
00161
00162 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
00163 body.setAppStatus(0);
00164 body.setProtocolStatus(UNKNOWN_ROLE);
00165
00166 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
00167 return true;
00168 }
00169
00170 {
00171 boost::lock_guard<boost::mutex> lock(messages);
00172 message=messages.front();
00173 messages.pop();
00174 }
00175
00176 if(!message.type)
00177 {
00178 const Header& header=*(Header*)message.data.get();
00179 const char* body=message.data.get()+sizeof(Header);
00180 switch(header.getType())
00181 {
00182 case PARAMS:
00183 {
00184 if(state!=PARAMS) throw Exceptions::RecordOutOfOrder(id, state, PARAMS);
00185 if(header.getContentLength()==0)
00186 {
00187 state=IN;
00188 break;
00189 }
00190 if(!session.fill(body, header.getContentLength())) throw Exceptions::Param(id);
00191 break;
00192 }
00193
00194 case IN:
00195 {
00196 if(state!=IN) throw Exceptions::RecordOutOfOrder(id, state, IN);
00197 if(header.getContentLength()==0)
00198 {
00199 session.clearPostBuffer();
00200 state=OUT;
00201 if(response())
00202 {
00203 complete();
00204 return true;
00205 }
00206 break;
00207 }
00208 session.fillPosts(body, header.getContentLength());
00209 inHandler(header.getContentLength());
00210 break;
00211 }
00212
00213 case ABORT_REQUEST:
00214 {
00215 return true;
00216 }
00217
00218 default:
00219 {
00220 break;
00221 }
00222 }
00223 }
00224 else if(response())
00225 {
00226 complete();
00227 return true;
00228 }
00229 }
00230 catch(std::exception& e)
00231 {
00232 err << e.what();
00233 err.flush();
00234 complete();
00235 return true;
00236 }
00237 return false;
00238 }
00239
00240 template void Fastcgipp::Request<char>::setloc(std::locale loc_);
00241 template void Fastcgipp::Request<wchar_t>::setloc(std::locale loc_);
00242 template<class charT> void Fastcgipp::Request<charT>::setloc(std::locale loc_)
00243 {
00244 loc=makeLocale<charT>(loc_);
00245 out.imbue(loc);
00246 err.imbue(loc);
00247 }
00248
00249 #include "utf8_codecvt_facet.cpp"