@@ -114,8 +114,8 @@ class Server {
114
114
private:
115
115
typedef std::vector<std::pair<std::regex, Handler>> Handlers;
116
116
117
- void process_request (FILE* fp_read, FILE* fp_write );
118
- bool read_request_line (FILE* fp , Request& req);
117
+ void process_request (socket_t sock );
118
+ bool read_request_line (socket_t sock , Request& req);
119
119
bool routing (Request& req, Response& res);
120
120
bool handle_file_request (Request& req, Response& res);
121
121
bool dispatch_request (Request& req, Response& res, Handlers& handlers);
@@ -140,7 +140,7 @@ class Client {
140
140
bool send (const Request& req, Response& res);
141
141
142
142
private:
143
- bool read_response_line (FILE* fp , Response& res);
143
+ bool read_response_line (socket_t sock , Response& res);
144
144
145
145
const std::string host_;
146
146
const int port_;
@@ -168,35 +168,59 @@ void split(const char* b, const char* e, char d, Fn fn)
168
168
}
169
169
}
170
170
171
- template <typename T>
172
- inline bool read_and_close_socket (socket_t sock, T callback)
171
+ inline int socket_read (socket_t sock, char * ptr, size_t size)
173
172
{
174
- FILE* fp_read ;
175
- FILE* fp_write;
173
+ return recv (sock, ptr, size, 0 ) ;
174
+ }
176
175
177
- # ifdef _MSC_VER
178
- fp_read = _fdopen ( _open_osfhandle (sock, _O_RDONLY), " rb " );
179
- fp_write = _fdopen ( _open_osfhandle (sock, _O_WRONLY), " wb " );
180
- # else
181
- fp_read = fdopen (sock, " rb " );
182
- fp_write = fdopen (sock, " wb " );
183
- # endif
176
+ inline int socket_write ( socket_t sock, const char * ptr, size_t size = - 1 )
177
+ {
178
+ if (size == - 1 ) {
179
+ size = strlen (ptr);
180
+ }
181
+ return send (sock, ptr, size, 0 );
182
+ }
184
183
185
- auto ret = callback (fp_read, fp_write);
184
+ inline bool socket_gets (socket_t sock, char * buf, int bufsiz)
185
+ {
186
+ // TODO: buffering for better performance
187
+ size_t i = 0 ;
186
188
187
- fclose (fp_read);
188
- fclose (fp_write);
189
+ for (;;) {
190
+ char byte;
191
+ auto n = socket_read (sock, &byte, 1 );
189
192
190
- return ret;
193
+ if (n < 1 ) {
194
+ if (i == 0 ) {
195
+ return false ;
196
+ } else {
197
+ break ;
198
+ }
199
+ }
200
+
201
+ buf[i++] = byte;
202
+
203
+ if (byte == ' \n ' ) {
204
+ break ;
205
+ }
206
+ }
207
+
208
+ buf[i] = ' \0 ' ;
209
+ return true ;
191
210
}
192
211
193
- inline int shutdown_socket (socket_t sock)
212
+ template <typename ...Args>
213
+ inline void socket_printf (socket_t sock, const char * fmt, const Args& ...args)
194
214
{
195
- #ifdef _MSC_VER
196
- return shutdown (sock, SD_BOTH);
197
- #else
198
- return shutdown (sock, SHUT_RDWR);
199
- #endif
215
+ char buf[BUFSIZ];
216
+ auto n = snprintf (buf, BUFSIZ, fmt, args...);
217
+ if (n > 0 ) {
218
+ if (n >= BUFSIZ) {
219
+ // TODO: buffer size is not large enough...
220
+ } else {
221
+ socket_write (sock, buf, n);
222
+ }
223
+ }
200
224
}
201
225
202
226
inline int close_socket (socket_t sock)
@@ -208,6 +232,23 @@ inline int close_socket(socket_t sock)
208
232
#endif
209
233
}
210
234
235
+ template <typename T>
236
+ inline bool read_and_close_socket (socket_t sock, T callback)
237
+ {
238
+ auto ret = callback (sock);
239
+ close_socket (sock);
240
+ return ret;
241
+ }
242
+
243
+ inline int shutdown_socket (socket_t sock)
244
+ {
245
+ #ifdef _MSC_VER
246
+ return shutdown (sock, SD_BOTH);
247
+ #else
248
+ return shutdown (sock, SHUT_RDWR);
249
+ #endif
250
+ }
251
+
211
252
template <typename Fn>
212
253
socket_t create_socket (const char * host, int port, Fn fn)
213
254
{
@@ -297,7 +338,7 @@ inline void read_file(const std::string& path, std::string& out)
297
338
fs.seekg (0 , std::ios_base::end);
298
339
auto size = fs.tellg ();
299
340
fs.seekg (0 );
300
- out.resize (size);
341
+ out.resize (static_cast < size_t >( size) );
301
342
fs.read (&out[0 ], size);
302
343
}
303
344
@@ -350,15 +391,15 @@ inline int get_header_value_int(const MultiMap& map, const char* key, int def)
350
391
return def;
351
392
}
352
393
353
- inline bool read_headers (FILE* fp , MultiMap& headers)
394
+ inline bool read_headers (socket_t sock , MultiMap& headers)
354
395
{
355
396
static std::regex re (" (.+?): (.+?)\r\n " );
356
397
357
398
const auto BUFSIZ_HEADER = 2048 ;
358
399
char buf[BUFSIZ_HEADER];
359
400
360
401
for (;;) {
361
- if (!fgets (buf, BUFSIZ_HEADER, fp )) {
402
+ if (!socket_gets (sock, buf, BUFSIZ_HEADER )) {
362
403
return false ;
363
404
}
364
405
if (!strcmp (buf, " \r\n " )) {
@@ -376,43 +417,43 @@ inline bool read_headers(FILE* fp, MultiMap& headers)
376
417
}
377
418
378
419
template <typename T>
379
- bool read_content (T& x, FILE* fp )
420
+ bool read_content (socket_t sock, T& x )
380
421
{
381
422
auto len = get_header_value_int (x.headers , " Content-Length" , 0 );
382
423
if (len) {
383
424
x.body .assign (len, 0 );
384
- if (!fread ( &x.body [0 ], x.body .size (), 1 , fp )) {
425
+ if (!socket_read (sock, &x.body [0 ], x.body .size ())) {
385
426
return false ;
386
427
}
387
428
}
388
429
return true ;
389
430
}
390
431
391
432
template <typename T>
392
- inline void write_headers (FILE* fp , const T& res)
433
+ inline void write_headers (socket_t sock , const T& res)
393
434
{
394
- fprintf (fp , " Connection: close\r\n " );
435
+ socket_write (sock , " Connection: close\r\n " );
395
436
396
437
for (const auto & x: res.headers ) {
397
438
if (x.first != " Content-Type" && x.first != " Content-Length" ) {
398
- fprintf (fp , " %s: %s\r\n " , x.first .c_str (), x.second .c_str ());
439
+ socket_printf (sock , " %s: %s\r\n " , x.first .c_str (), x.second .c_str ());
399
440
}
400
441
}
401
442
402
443
auto t = get_header_value (res.headers , " Content-Type" , " text/plain" );
403
- fprintf (fp , " Content-Type: %s\r\n " , t);
404
- fprintf (fp , " Content-Length: %ld\r\n " , res.body .size ());
405
- fprintf (fp , " \r\n " );
444
+ socket_printf (sock , " Content-Type: %s\r\n " , t);
445
+ socket_printf (sock , " Content-Length: %ld\r\n " , res.body .size ());
446
+ socket_write (sock , " \r\n " );
406
447
}
407
448
408
- inline void write_response (FILE* fp , const Request& req, const Response& res)
449
+ inline void write_response (socket_t sock , const Request& req, const Response& res)
409
450
{
410
- fprintf (fp , " HTTP/1.0 %d %s\r\n " , res.status , status_message (res.status ));
451
+ socket_printf (sock , " HTTP/1.0 %d %s\r\n " , res.status , status_message (res.status ));
411
452
412
- write_headers (fp , res);
453
+ write_headers (sock , res);
413
454
414
455
if (!res.body .empty () && req.method != " HEAD" ) {
415
- fprintf (fp, " %s " , res.body .c_str ());
456
+ socket_write (sock, res. body . c_str () , res.body .size ());
416
457
}
417
458
}
418
459
@@ -547,18 +588,19 @@ inline std::string decode_url(const std::string& s)
547
588
return result;
548
589
}
549
590
550
- inline void write_request (FILE* fp , const Request& req)
591
+ inline void write_request (socket_t sock , const Request& req)
551
592
{
552
593
auto url = encode_url (req.url );
553
- fprintf (fp , " %s %s HTTP/1.0\r\n " , req.method .c_str (), url.c_str ());
594
+ socket_printf (sock , " %s %s HTTP/1.0\r\n " , req.method .c_str (), url.c_str ());
554
595
555
- write_headers (fp , req);
596
+ write_headers (sock , req);
556
597
557
598
if (!req.body .empty ()) {
558
599
if (req.has_header (" application/x-www-form-urlencoded" )) {
559
- fprintf (fp, " %s" , encode_url (req.body ).c_str ());
600
+ auto str = encode_url (req.body );
601
+ socket_write (sock, str.c_str (), str.size ());
560
602
} else {
561
- fprintf (fp, " %s " , req.body .c_str ());
603
+ socket_write (sock, req. body . c_str () , req.body .size ());
562
604
}
563
605
}
564
606
}
@@ -710,8 +752,8 @@ inline bool Server::listen(const char* host, int port)
710
752
}
711
753
712
754
// TODO: should be async
713
- detail::read_and_close_socket (sock, [this ](FILE* fp_read, FILE* fp_write ) {
714
- process_request (fp_read, fp_write );
755
+ detail::read_and_close_socket (sock, [this ](socket_t sock ) {
756
+ process_request (sock );
715
757
return true ;
716
758
});
717
759
}
@@ -726,11 +768,11 @@ inline void Server::stop()
726
768
svr_sock_ = -1 ;
727
769
}
728
770
729
- inline bool Server::read_request_line (FILE* fp , Request& req)
771
+ inline bool Server::read_request_line (socket_t sock , Request& req)
730
772
{
731
773
const auto BUFSIZ_REQUESTLINE = 2048 ;
732
774
char buf[BUFSIZ_REQUESTLINE];
733
- if (!fgets (buf, BUFSIZ_REQUESTLINE, fp )) {
775
+ if (!detail::socket_gets (sock, buf, BUFSIZ_REQUESTLINE )) {
734
776
return false ;
735
777
}
736
778
@@ -803,18 +845,18 @@ inline bool Server::dispatch_request(Request& req, Response& res, Handlers& hand
803
845
return false ;
804
846
}
805
847
806
- inline void Server::process_request (FILE* fp_read, FILE* fp_write )
848
+ inline void Server::process_request (socket_t sock )
807
849
{
808
850
Request req;
809
851
Response res;
810
852
811
- if (!read_request_line (fp_read , req) ||
812
- !detail::read_headers (fp_read , req.headers )) {
853
+ if (!read_request_line (sock , req) ||
854
+ !detail::read_headers (sock , req.headers )) {
813
855
return ;
814
856
}
815
857
816
858
if (req.method == " POST" ) {
817
- if (!detail::read_content (req, fp_read )) {
859
+ if (!detail::read_content (sock, req )) {
818
860
return ;
819
861
}
820
862
static std::string type = " application/x-www-form-urlencoded" ;
@@ -836,8 +878,7 @@ inline void Server::process_request(FILE* fp_read, FILE* fp_write)
836
878
error_handler_ (req, res);
837
879
}
838
880
839
- detail::write_response (fp_write, req, res);
840
- fflush (fp_write);
881
+ detail::write_response (sock, req, res);
841
882
842
883
if (logger_) {
843
884
logger_ (req, res);
@@ -851,11 +892,11 @@ inline Client::Client(const char* host, int port)
851
892
{
852
893
}
853
894
854
- inline bool Client::read_response_line (FILE* fp , Response& res)
895
+ inline bool Client::read_response_line (socket_t sock , Response& res)
855
896
{
856
897
const auto BUFSIZ_RESPONSELINE = 2048 ;
857
898
char buf[BUFSIZ_RESPONSELINE];
858
- if (!fgets (buf, BUFSIZ_RESPONSELINE, fp )) {
899
+ if (!detail::socket_gets (sock, buf, BUFSIZ_RESPONSELINE )) {
859
900
return false ;
860
901
}
861
902
@@ -876,18 +917,17 @@ inline bool Client::send(const Request& req, Response& res)
876
917
return false ;
877
918
}
878
919
879
- return detail::read_and_close_socket (sock, [&](FILE* fp_read, FILE* fp_write ) {
920
+ return detail::read_and_close_socket (sock, [&](socket_t sock ) {
880
921
// Send request
881
- detail::write_request (fp_write, req);
882
- fflush (fp_write);
922
+ detail::write_request (sock, req);
883
923
884
924
// Receive response
885
- if (!read_response_line (fp_read , res) ||
886
- !detail::read_headers (fp_read , res.headers )) {
925
+ if (!read_response_line (sock , res) ||
926
+ !detail::read_headers (sock , res.headers )) {
887
927
return false ;
888
928
}
889
929
if (req.method != " HEAD" ) {
890
- if (!detail::read_content (res, fp_read )) {
930
+ if (!detail::read_content (sock, res )) {
891
931
return false ;
892
932
}
893
933
}
0 commit comments