97 if(content_length > 0) { |
101 if(content_length > 0) { |
98 ssize_t n = 0; |
102 ssize_t n = 0; |
99 while(n < content_length) { |
103 while(n < content_length) { |
100 r = netbuf_getbytes(sn->inbuf, buf, 4096); |
104 r = netbuf_getbytes(sn->inbuf, buf, 4096); |
101 if(r <= 0) { |
105 if(r <= 0) { |
102 // TODO: handleerror |
106 // TODO: handle error |
|
107 log_ereport( |
|
108 LOG_FAILURE, |
|
109 "send-cgi: script: %s: cannot read request body", |
|
110 path); |
|
111 kill(cgip.pid, SIGTERM); |
103 cgi_close(&cgip); |
112 cgi_close(&cgip); |
104 return REQ_ABORTED; |
113 return REQ_ABORTED; |
105 } |
114 } |
106 write(cgip.in[1], buf, r); |
115 ssize_t w = write(cgip.in[1], buf, r); |
|
116 if(w <= 0) { |
|
117 // TODO: handle error |
|
118 log_ereport( |
|
119 LOG_FAILURE, |
|
120 "send-cgi: script: %s: cannot send request body to cgi process", |
|
121 path); |
|
122 kill(cgip.pid, SIGKILL); |
|
123 cgi_close(&cgip); |
|
124 return REQ_ABORTED; |
|
125 } |
107 n += r; |
126 n += r; |
108 } |
127 } |
109 } |
128 } |
110 close(cgip.in[1]); |
129 close(cgip.in[1]); |
111 cgip.in[1] = -1; |
130 cgip.in[1] = -1; |
112 |
131 |
113 // read from child |
132 // read from child |
114 CGIResponseParser *parser = cgi_parser_new(sn, rq); |
133 CGIResponseParser *parser = cgi_parser_new(sn, rq); |
115 WSBool cgiheader = TRUE; |
134 WSBool cgiheader = TRUE; |
116 ssize_t wr = 0; |
135 ssize_t wr = 0; |
117 int result = REQ_PROCEED; |
136 int result = REQ_PROCEED; |
|
137 size_t response_length = 0; |
118 while((r = read(cgip.out[0], buf, 4096)) > 0) { |
138 while((r = read(cgip.out[0], buf, 4096)) > 0) { |
119 if(cgiheader) { |
139 if(cgiheader) { |
120 size_t pos; |
140 size_t pos; |
121 ret = cgi_parse_response(parser, buf, r, &pos); |
141 ret = cgi_parse_response(parser, buf, r, &pos); |
122 if(ret == -1) { |
142 if(ret == -1) { |
|
143 log_ereport( |
|
144 LOG_FAILURE, |
|
145 "broken cgi script response: path: %s", path); |
123 protocol_status(sn, rq, 500, NULL); |
146 protocol_status(sn, rq, 500, NULL); |
124 result = REQ_ABORTED; |
147 result = REQ_ABORTED; |
125 break; |
148 break; |
126 } else if(ret == 0) { |
|
127 |
|
128 } else if(ret == 1) { |
149 } else if(ret == 1) { |
129 cgiheader = FALSE; |
150 cgiheader = FALSE; |
130 if(parser->status > 0) { |
151 if(parser->status > 0) { |
131 protocol_status(sn, rq, parser->status, parser->msg); |
152 protocol_status(sn, rq, parser->status, parser->msg); |
132 } |
153 } |
133 http_start_response(sn, rq); |
154 http_start_response(sn, rq); |
134 if(pos < r) { |
155 if(pos < r) { |
|
156 response_length += r-pos; |
135 wr = net_write(sn->csd, &buf[pos], r-pos); |
157 wr = net_write(sn->csd, &buf[pos], r-pos); |
136 if(wr <= 0) { |
158 if(wr <= 0) { |
137 result = REQ_ABORTED; |
159 result = REQ_ABORTED; |
138 break; |
160 break; |
139 } |
161 } |
140 } |
162 } |
141 } |
163 } |
142 } else { |
164 } else { |
|
165 response_length = r; |
143 wr = net_write(sn->csd, buf, r); |
166 wr = net_write(sn->csd, buf, r); |
144 if(wr <= 0) { |
167 if(wr <= 0) { |
145 result = REQ_ABORTED; |
168 result = REQ_ABORTED; |
146 break; |
169 break; |
147 } |
170 } |
148 } |
171 } |
149 } |
172 } |
150 |
173 |
151 cgi_close(&cgip); |
174 char *ctlen_header = pblock_findkeyval(pb_key_content_length, rq->srvhdrs); |
|
175 if(ctlen_header) { |
|
176 int64_t ctlenhdr; |
|
177 if(util_strtoint(ctlen_header, &ctlenhdr)) { |
|
178 if(ctlenhdr != response_length) { |
|
179 log_ereport( |
|
180 LOG_FAILURE, |
|
181 "cgi-send: script: %s: content length mismatch", |
|
182 path); |
|
183 rq->rq_attr.keep_alive = 0; |
|
184 result = REQ_ABORTED; |
|
185 } |
|
186 } |
|
187 } |
|
188 |
|
189 if(result == REQ_ABORTED) { |
|
190 log_ereport(LOG_FAILURE, "cgi-send: kill script: %s", path); |
|
191 kill(cgip.pid, SIGKILL); |
|
192 } |
|
193 cgi_close(&cgip); // TODO: check return value |
152 |
194 |
153 cgi_parser_free(parser); |
195 cgi_parser_free(parser); |
154 return result; |
196 return result; |
155 } |
197 } |
156 |
198 |