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 std::streamsize Fastcgipp::Fcgistream<char, std::char_traits<char> >::Fcgibuf::xsputn(const char_type *s, std::streamsize n);
00105 template std::streamsize Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::Fcgibuf::xsputn(const char_type *s, std::streamsize n);
00106 template <class charT, class traits>
00107 std::streamsize Fastcgipp::Fcgistream<charT, traits>::Fcgibuf::xsputn(const char_type *s, std::streamsize n)
00108 {
00109 std::streamsize remainder=n;
00110 while(remainder)
00111 {
00112 std::streamsize actual=std::min(remainder, this->epptr()-this->pptr());
00113 std::memcpy(this->pptr(), s, actual*sizeof(char_type));
00114 this->pbump(actual);
00115 remainder-=actual;
00116 if(remainder)
00117 {
00118 s+=actual;
00119 emptyBuffer();
00120 }
00121 }
00122
00123 return n;
00124 }
00125
00126 template Fastcgipp::Fcgistream<char, std::char_traits<char> >::Fcgibuf::int_type Fastcgipp::Fcgistream<char, std::char_traits<char> >::Fcgibuf::overflow(Fastcgipp::Fcgistream<char, std::char_traits<char> >::Fcgibuf::int_type c = traits_type::eof());
00127 template Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::Fcgibuf::int_type Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::Fcgibuf::overflow(Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::Fcgibuf::int_type c = traits_type::eof());
00128 template <class charT, class traits>
00129 typename Fastcgipp::Fcgistream<charT, traits>::Fcgibuf::int_type Fastcgipp::Fcgistream<charT, traits>::Fcgibuf::overflow(Fastcgipp::Fcgistream<charT, traits>::Fcgibuf::int_type c)
00130 {
00131 if(emptyBuffer() < 0)
00132 return traits_type::eof();
00133 if(!traits_type::eq_int_type(c, traits_type::eof()))
00134 return sputc(c);
00135 else
00136 return traits_type::not_eof(c);
00137 }
00138
00139 template void Fastcgipp::Request<char>::complete();
00140 template void Fastcgipp::Request<wchar_t>::complete();
00141 template<class charT> void Fastcgipp::Request<charT>::complete()
00142 {
00143 using namespace Protocol;
00144 out.flush();
00145 err.flush();
00146
00147 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
00148
00149 Header& header=*(Header*)buffer.data;
00150 header.setVersion(version);
00151 header.setType(END_REQUEST);
00152 header.setRequestId(id.fcgiId);
00153 header.setContentLength(sizeof(EndRequest));
00154 header.setPaddingLength(0);
00155
00156 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
00157 body.setAppStatus(0);
00158 body.setProtocolStatus(REQUEST_COMPLETE);
00159
00160 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
00161 }
00162
00163 template void Fastcgipp::Fcgistream<char, std::char_traits<char> >::dump(std::basic_istream<char>& stream);
00164 template void Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::dump(std::basic_istream<char>& stream);
00165 template<class charT, class traits > void Fastcgipp::Fcgistream<charT, traits>::dump(std::basic_istream<char>& stream)
00166 {
00167 const size_t bufferSize=32768;
00168 char buffer[bufferSize];
00169
00170 while(stream.good())
00171 {
00172 stream.read(buffer, bufferSize);
00173 dump(buffer, stream.gcount());
00174 }
00175 }
00176
00177 template bool Fastcgipp::Request<char>::handler();
00178 template bool Fastcgipp::Request<wchar_t>::handler();
00179 template<class charT> bool Fastcgipp::Request<charT>::handler()
00180 {
00181 using namespace Protocol;
00182 using namespace std;
00183
00184 try
00185 {
00186 if(role!=RESPONDER)
00187 {
00188 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
00189
00190 Header& header=*(Header*)buffer.data;
00191 header.setVersion(version);
00192 header.setType(END_REQUEST);
00193 header.setRequestId(id.fcgiId);
00194 header.setContentLength(sizeof(EndRequest));
00195 header.setPaddingLength(0);
00196
00197 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
00198 body.setAppStatus(0);
00199 body.setProtocolStatus(UNKNOWN_ROLE);
00200
00201 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
00202 return true;
00203 }
00204
00205 {
00206 boost::lock_guard<boost::mutex> lock(messages);
00207 message=messages.front();
00208 messages.pop();
00209 }
00210
00211 if(!message.type)
00212 {
00213 const Header& header=*(Header*)message.data.get();
00214 const char* body=message.data.get()+sizeof(Header);
00215 switch(header.getType())
00216 {
00217 case PARAMS:
00218 {
00219 if(state!=PARAMS) throw Exceptions::RecordOutOfOrder(id, state, PARAMS);
00220 if(header.getContentLength()==0)
00221 {
00222 state=IN;
00223 break;
00224 }
00225 if(!session.fill(body, header.getContentLength())) throw Exceptions::Param(id);
00226 break;
00227 }
00228
00229 case IN:
00230 {
00231 if(state!=IN) throw Exceptions::RecordOutOfOrder(id, state, IN);
00232 if(header.getContentLength()==0)
00233 {
00234 session.clearPostBuffer();
00235 state=OUT;
00236 if(response())
00237 {
00238 complete();
00239 return true;
00240 }
00241 break;
00242 }
00243 session.fillPosts(body, header.getContentLength());
00244 inHandler(header.getContentLength());
00245 break;
00246 }
00247
00248 case ABORT_REQUEST:
00249 {
00250 return true;
00251 }
00252
00253 default:
00254 {
00255 break;
00256 }
00257 }
00258 }
00259 else if(response())
00260 {
00261 complete();
00262 return true;
00263 }
00264 }
00265 catch(std::exception& e)
00266 {
00267 err << e.what();
00268 err.flush();
00269 complete();
00270 return true;
00271 }
00272 return false;
00273 }
00274
00275 template void Fastcgipp::Request<char>::setloc(std::locale loc_);
00276 template void Fastcgipp::Request<wchar_t>::setloc(std::locale loc_);
00277 template<class charT> void Fastcgipp::Request<charT>::setloc(std::locale loc_)
00278 {
00279 loc=makeLocale<charT>(loc_);
00280 out.imbue(loc);
00281 err.imbue(loc);
00282 }
00283
00284 #include "utf8_codecvt_facet.cpp"