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
00024 template int Fastcgipp::Fcgistream<char, std::char_traits<char> >::Fcgibuf::emptyBuffer();
00025 template int Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::Fcgibuf::emptyBuffer();
00026 template <class charT, class traits>
00027 int Fastcgipp::Fcgistream<charT, traits>::Fcgibuf::emptyBuffer()
00028 {
00029 using namespace std;
00030 using namespace Protocol;
00031 char_type const* pStreamPos=this->pbase();
00032 while(1)
00033 {{
00034 size_t count=this->pptr()-pStreamPos;
00035 size_t wantedSize=count*sizeof(char_type)+dumpSize;
00036 if(!wantedSize)
00037 break;
00038
00039 int remainder=wantedSize%chunkSize;
00040 wantedSize+=sizeof(Header)+(remainder?(chunkSize-remainder):remainder);
00041 if(wantedSize>numeric_limits<uint16_t>::max()) wantedSize=numeric_limits<uint16_t>::max();
00042 Block dataBlock(transceiver->requestWrite(wantedSize));
00043 dataBlock.size=(dataBlock.size/chunkSize)*chunkSize;
00044
00045 mbstate_t cs = mbstate_t();
00046 char* toNext=dataBlock.data+sizeof(Header);
00047
00048 locale loc=this->getloc();
00049 if(count)
00050 {
00051 if(sizeof(char_type)!=sizeof(char))
00052 {
00053 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)
00054 {
00055 pbump(-(this->pptr()-this->pbase()));
00056 dumpSize=0;
00057 dumpPtr=0;
00058 throw Exceptions::FastcgiException("Error in streambuf code conversion");
00059 }
00060 }
00061 else
00062 {
00063 size_t cnt=min(dataBlock.size-sizeof(Header), count);
00064 memcpy(dataBlock.data+sizeof(Header), pStreamPos, cnt);
00065 pStreamPos+=cnt;
00066 toNext+=cnt;
00067 }
00068 }
00069
00070 size_t dumpedSize=min(dumpSize, static_cast<size_t>(dataBlock.data+dataBlock.size-toNext));
00071 memcpy(toNext, dumpPtr, dumpedSize);
00072 dumpPtr+=dumpedSize;
00073 dumpSize-=dumpedSize;
00074 uint16_t contentLength=toNext-dataBlock.data+dumpedSize-sizeof(Header);
00075 uint8_t contentRemainder=contentLength%chunkSize;
00076
00077 Header& header=*(Header*)dataBlock.data;
00078 header.setVersion(version);
00079 header.setType(type);
00080 header.setRequestId(id.fcgiId);
00081 header.setContentLength(contentLength);
00082 header.setPaddingLength(contentRemainder?(chunkSize-contentRemainder):contentRemainder);
00083
00084 transceiver->secureWrite(sizeof(Header)+contentLength+header.getPaddingLength(), id, false);
00085 }}
00086 pbump(-(this->pptr()-this->pbase()));
00087 return 0;
00088 }
00089
00090 template void Fastcgipp::Request<char>::complete();
00091 template void Fastcgipp::Request<wchar_t>::complete();
00092 template<class charT> void Fastcgipp::Request<charT>::complete()
00093 {
00094 using namespace Protocol;
00095 out.flush();
00096 err.flush();
00097
00098 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
00099
00100 Header& header=*(Header*)buffer.data;
00101 header.setVersion(version);
00102 header.setType(END_REQUEST);
00103 header.setRequestId(id.fcgiId);
00104 header.setContentLength(sizeof(EndRequest));
00105 header.setPaddingLength(0);
00106
00107 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
00108 body.setAppStatus(0);
00109 body.setProtocolStatus(REQUEST_COMPLETE);
00110
00111 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
00112 }
00113
00114 template void Fastcgipp::Fcgistream<char, std::char_traits<char> >::dump(std::basic_istream<char>& stream);
00115 template void Fastcgipp::Fcgistream<wchar_t, std::char_traits<wchar_t> >::dump(std::basic_istream<char>& stream);
00116 template<class charT, class traits > void Fastcgipp::Fcgistream<charT, traits>::dump(std::basic_istream<char>& stream)
00117 {
00118 const size_t bufferSize=32768;
00119 char buffer[bufferSize];
00120
00121 while(stream.good())
00122 {
00123 stream.read(buffer, bufferSize);
00124 dump(buffer, stream.gcount());
00125 }
00126 }
00127
00128 template bool Fastcgipp::Request<char>::handler();
00129 template bool Fastcgipp::Request<wchar_t>::handler();
00130 template<class charT> bool Fastcgipp::Request<charT>::handler()
00131 {
00132 using namespace Protocol;
00133 using namespace std;
00134
00135 try
00136 {
00137 if(role!=RESPONDER)
00138 {
00139 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
00140
00141 Header& header=*(Header*)buffer.data;
00142 header.setVersion(version);
00143 header.setType(END_REQUEST);
00144 header.setRequestId(id.fcgiId);
00145 header.setContentLength(sizeof(EndRequest));
00146 header.setPaddingLength(0);
00147
00148 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
00149 body.setAppStatus(0);
00150 body.setProtocolStatus(UNKNOWN_ROLE);
00151
00152 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
00153 return true;
00154 }
00155
00156 {
00157 boost::lock_guard<boost::mutex> lock(messages);
00158 message=messages.front();
00159 messages.pop();
00160 }
00161
00162 if(!message.type)
00163 {
00164 const Header& header=*(Header*)message.data.get();
00165 const char* body=message.data.get()+sizeof(Header);
00166 switch(header.getType())
00167 {
00168 case PARAMS:
00169 {
00170 if(status!=PARAMETERS) throw Exceptions::FastcgiException("Parameter data recieved when it should not have been.");
00171 if(header.getContentLength()==0)
00172 {
00173 status=POST;
00174 break;
00175 }
00176 session.fill(body, header.getContentLength());
00177 break;
00178 }
00179
00180 case IN:
00181 {
00182 if(status!=POST) throw Exceptions::FastcgiException("Post data recieved when it should not have been.");
00183 if(header.getContentLength()==0)
00184 {
00185 session.clearPostBuffer();
00186 status=RESPONSE;
00187 if(response())
00188 {
00189 complete();
00190 return true;
00191 }
00192 break;
00193 }
00194 session.fillPosts(body, header.getContentLength());
00195 inHandler(header.getContentLength());
00196 break;
00197 }
00198
00199 case ABORT_REQUEST:
00200 {
00201 return true;
00202 }
00203
00204 default:
00205 {
00206 break;
00207 }
00208 }
00209 }
00210 else if(response())
00211 {
00212 complete();
00213 return true;
00214 }
00215 }
00216 catch(std::exception& e)
00217 {
00218 err << e.what();
00219 err.flush();
00220 complete();
00221 return true;
00222 }
00223 return false;
00224 }
00225