fastcgi++  3.1alpha
A C++ FastCGI/Web API
fcgistreambuf.cpp
Go to the documentation of this file.
1 
9 /*******************************************************************************
10 * Copyright (C) 2020 Eddie Carle [eddie@isatec.ca] *
11 * *
12 * This file is part of fastcgi++. *
13 * *
14 * fastcgi++ is free software: you can redistribute it and/or modify it under *
15 * the terms of the GNU Lesser General Public License as published by the Free *
16 * Software Foundation, either version 3 of the License, or (at your option) *
17 * any later version. *
18 * *
19 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT ANY *
20 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
21 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
22 * more details. *
23 * *
24 * You should have received a copy of the GNU Lesser General Public License *
25 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. *
26 *******************************************************************************/
27 
29 #include "fastcgi++/log.hpp"
30 
31 #include <codecvt>
32 #include <algorithm>
33 
34 namespace Fastcgipp
35 {
36  template <> bool
38  {
39  const std::codecvt_utf8<wchar_t> converter;
40  std::codecvt_base::result result;
41  Block record;
42  size_t count;
43  mbstate_t state = mbstate_t();
44  char* toNext;
45  const wchar_t* from = this->pbase();
46  const wchar_t* const fromEnd = this->pptr();
47 
48  while((count = fromEnd - from) != 0)
49  {
50  record.reserve(
51  Protocol::getRecordSize(count*converter.max_length()));
52 
54  = *reinterpret_cast<Protocol::Header*>(record.begin());
55 
56  result = converter.out(
57  state,
58  from,
59  fromEnd,
60  from,
61  record.begin()+sizeof(Protocol::Header),
62  &*record.end(),
63  toNext);
64 
65  if(result == std::codecvt_base::error
66  || result == std::codecvt_base::noconv)
67  {
68  ERROR_LOG("FcgiStreambuf code conversion failed")
69  pbump(-count);
70  return false;
71  }
72  header.contentLength = std::distance(
73  record.begin()+sizeof(Protocol::Header),
74  toNext);
75  record.size(Protocol::getRecordSize(header.contentLength));
76 
77  header.version = Protocol::version;
78  header.type = m_type;
79  header.fcgiId = m_id.m_id;
80  header.paddingLength =
81  record.size()-header.contentLength-sizeof(Protocol::Header);
82 
83  send(m_id.m_socket, std::move(record));
84  }
85 
86  this->setp(m_buffer, m_buffer+s_buffSize);
87  return true;
88  }
89 
90  template <>
92  {
93  Block record;
94  size_t count;
95 
96  const char* from = this->pbase();
97  const char* const fromEnd = this->pptr();
98 
99  while((count = fromEnd - from) != 0)
100  {
101  record.size(Protocol::getRecordSize(count));
102 
103  Protocol::Header& header
104  = *reinterpret_cast<Protocol::Header*>(record.begin());
105  header.contentLength = std::min(
106  count,
107  static_cast<size_t>(0xffffU));
108 
109  std::copy(
110  from,
111  from+header.contentLength,
112  record.begin()+sizeof(Protocol::Header));
113 
114  from += header.contentLength;
115 
116  header.version = Protocol::version;
117  header.type = m_type;
118  header.fcgiId = m_id.m_id;
119  header.paddingLength =
120  record.size()-header.contentLength-sizeof(Protocol::Header);
121 
122  send(m_id.m_socket, std::move(record));
123  }
124 
125  this->setp(m_buffer, m_buffer+s_buffSize);
126  return true;
127  }
128 }
129 
130 template <class charT, class traits>
132  const char* data,
133  size_t size)
134 {
135  emptyBuffer();
136  Block record;
137 
138  while(size != 0)
139  {
140  record.size(Protocol::getRecordSize(size));
141 
143  = *reinterpret_cast<Protocol::Header*>(record.begin());
144  header.contentLength = std::min(size, static_cast<size_t>(0xffffU));
145 
146  std::copy(
147  data,
148  data+header.contentLength,
149  record.begin()+sizeof(Protocol::Header));
150 
151  size -= header.contentLength;
152  data += header.contentLength;
153 
154  header.version = Protocol::version;
155  header.type = m_type;
156  header.fcgiId = m_id.m_id;
157  header.paddingLength =
158  record.size()-header.contentLength-sizeof(Protocol::Header);
159 
160  send(m_id.m_socket, std::move(record));
161  }
162 }
163 
164 template <class charT, class traits>
166  std::basic_istream<char>& stream)
167 {
168  const size_t maxContentLength = 0xffffU;
169  emptyBuffer();
170  Block record;
171 
172  while(true)
173  {
174  record.reserve(Protocol::getRecordSize(maxContentLength));
175 
177  = *reinterpret_cast<Protocol::Header*>(record.begin());
178 
179  stream.read(record.begin()+sizeof(Protocol::Header), maxContentLength);
180  header.contentLength = stream.gcount();
181  if(header.contentLength == 0)
182  break;
183 
184  record.size(Protocol::getRecordSize(header.contentLength));
185 
186  header.version = Protocol::version;
187  header.type = m_type;
188  header.fcgiId = m_id.m_id;
189  header.paddingLength =
190  record.size()-header.contentLength-sizeof(Protocol::Header);
191 
192  send(m_id.m_socket, std::move(record));
193  }
194 }
195 
Fastcgipp::Block::size
size_t size() const
See the relevant data size.
Definition: block.hpp:128
Fastcgipp::Block::end
char * end()
Pointer to 1+ the last element.
Definition: block.hpp:149
Fastcgipp::version
const char version[]
Defines the fastcgi++ version.
Definition: protocol.cpp:91
Fastcgipp::Block
Data structure to hold a block of raw data.
Definition: block.hpp:61
Fastcgipp::Block::begin
char * begin()
Pointer to the first element.
Definition: block.hpp:137
Fastcgipp::Protocol::getRecordSize
size_t getRecordSize(size_t contentLength)
Determine the optimal record size given a requested content length.
Definition: protocol.cpp:93
fcgistreambuf.hpp
Declares the FcgiStreambuf class.
Fastcgipp::Protocol::Header
Data structure used as the header for FastCGI records.
Definition: protocol.hpp:205
ERROR_LOG
#define ERROR_LOG(data)
Log any "errors" that can be recovered from.
Definition: log.hpp:107
Fastcgipp::Block::reserve
size_t reserve() const
See the reserve size.
Definition: block.hpp:114
Fastcgipp::FcgiStreambuf::dump
void dump(const char *data, size_t size)
Dumps raw data directly into the FastCGI protocol.
Definition: fcgistreambuf.cpp:131
Fastcgipp
Topmost namespace for the fastcgi++ library.
Definition: fcgistreambuf.cpp:34
log.hpp
Declares the Fastcgipp debugging/logging facilities.
Fastcgipp::Protocol::version
static constexpr int version
The version of the FastCGI protocol that this adheres to.
Definition: protocol.hpp:174
Fastcgipp::FcgiStreambuf
Stream buffer class for output of client data through FastCGI.
Definition: fcgistreambuf.hpp:72
Fastcgipp::Logging::header
void header(Level level)
Send a log header to logstream.
Definition: log.cpp:107