1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #pragma once
20 
21 #include "fcgi_protocol.h"
22 #include <atscppapi/noncopyable.h>
23 #include <iterator>
24 #include <map>
25 #include <string>
26 #include <ts/ts.h>
27 #include <cstring> //for memcpy
28 
29 #define BUF_SIZE 5000
30 
31 /* Bytes from LSB to MSB 0..3 */
32 
33 #define BYTE_0(x) ((x)&0xff)
34 #define BYTE_1(x) ((x) >> 8 & 0xff)
35 #define BYTE_2(x) ((x) >> 16 & 0xff)
36 #define BYTE_3(x) ((x) >> 24 | 0x80)
37 
38 typedef unsigned char uchar;
39 
40 #define PRINT_OPAQUE_STRUCT(p) print_mem((p), sizeof(*(p)))
41 
42 #define FCGI_PROCESS_AGAIN 1
43 #define FCGI_PROCESS_DONE 2
44 #define FCGI_PROCESS_ERR 3
45 
46 namespace ats_plugin
47 {
48 using namespace atscppapi;
49 
50 typedef enum {
51   fcgi_state_version = 0,
52   fcgi_state_type,
53   fcgi_state_request_id_hi,
54   fcgi_state_request_id_lo,
55   fcgi_state_content_len_hi,
56   fcgi_state_content_len_lo,
57   fcgi_state_padding_len,
58   fcgi_state_reserved,
59   fcgi_state_content_begin,
60   fcgi_state_content_proc,
61   fcgi_state_padding,
62   fcgi_state_done
63 } FCGI_State;
64 
65 struct FCGIClientState;
66 
67 struct FCGIRecordList {
68   FCGI_Header *header;
69   FCGI_EndRequestBody *endBody;
70   uchar *content;
71   FCGI_State state;
72 
73   size_t length, offset;
74 
FCGIRecordListFCGIRecordList75   FCGIRecordList() : content(nullptr), state(FCGI_State::fcgi_state_version), length(0), offset(0)
76   {
77     header = (FCGI_Header *)TSmalloc(sizeof(FCGI_Header));
78     memset(header, 0, sizeof(FCGI_Header));
79     endBody = (FCGI_EndRequestBody *)TSmalloc(sizeof(FCGI_EndRequestBody));
80     memset(endBody, 0, sizeof(FCGI_EndRequestBody));
81   };
82 
~FCGIRecordListFCGIRecordList83   ~FCGIRecordList()
84   {
85     TSfree(header);
86     TSfree(content);
87   }
88 };
89 
90 class FCGIClientRequest
91 {
92 public:
93   std::string postData;
94   FCGIClientRequest(int request_id, TSHttpTxn txn);
95   ~FCGIClientRequest();
96 
97   std::map<std::string, std::string> GenerateFcgiRequestHeaders();
98   void printFCGIRequestHeaders();
99 
100   // Request Creation
101   FCGI_BeginRequest *createBeginRequest();
102   FCGI_Header *createHeader(unsigned char type);
103   void postBodyChunk();
104   void emptyParam();
105 
106   void serialize(uchar *buffer, void *st, size_t size);
107   void fcgiHeaderSetRequestId(FCGI_Header *h, int request_id);
108   void fcgiHeaderSetContentLen(FCGI_Header *h, uint16_t len);
109   uint32_t fcgiHeaderGetContentLen(FCGI_Header *h);
110   uint32_t serializeNameValue(uchar *buffer, const std::pair<std::string, std::string> &it);
111   unsigned char *addClientRequest(int &);
112 
113   // Response Decoding member functions
114   bool fcgiProcessBuffer(uchar *beg_buf, uchar *end_buf, std::ostringstream &output);
115   FCGIRecordList *fcgiRecordCreate();
116   int fcgiProcessHeader(uchar ch, FCGIRecordList *rec);
117   int fcgiProcessContent(uchar **beg_buf, uchar *end_buf, FCGIRecordList *rec);
118   int fcgiProcessRecord(uchar **beg_buf, uchar *end_buf, FCGIRecordList *rec);
119 
120   bool fcgiDecodeRecordChunk(uchar *beg_buf, size_t remain, std::ostringstream &output);
121 
122   void print_bytes(uchar *buf, int n);
123 
124 protected:
125   struct FCGIClientState *state_;
126 
127 private:
128   bool first_chunk;
129   FCGIRecordList *_headerRecord;
130 };
131 } // namespace ats_plugin
132