1 |
/* |
2 |
* Copyright (C) 2002 Nikos Mavroyanopoulos |
3 |
* |
4 |
* This file is part of Hydra webserver. |
5 |
* |
6 |
* Hydra is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* Hydra is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
19 |
*/ |
20 |
|
21 |
#include "boa.h" |
22 |
#include "ssl.h" |
23 |
|
24 |
ssize_t socket_recv( request* req, void* buf, size_t buf_size) |
25 |
{ |
26 |
ssize_t bytes; |
27 |
|
28 |
#ifdef ENABLE_SSL |
29 |
if ( req->secure) { |
30 |
bytes = gnutls_record_recv(req->ssl_state, |
31 |
buf, buf_size); |
32 |
|
33 |
if (bytes < 0) { |
34 |
if (bytes == GNUTLS_E_INTERRUPTED) |
35 |
return BOA_E_INTR; |
36 |
if (bytes == GNUTLS_E_AGAIN) /* request blocked */ |
37 |
return BOA_E_AGAIN; |
38 |
if (bytes==GNUTLS_E_UNEXPECTED_PACKET_LENGTH) /* abnormal termination */ |
39 |
return 0; |
40 |
|
41 |
log_error_doc(req); |
42 |
fprintf(stderr, "TLS receiving error \"%s\"\n", gnutls_strerror( bytes)); |
43 |
check_ssl_alert( req, bytes); |
44 |
return BOA_E_UNKNOWN; |
45 |
} |
46 |
} else { |
47 |
#endif |
48 |
bytes = |
49 |
recv(req->fd, buf, buf_size, 0); |
50 |
|
51 |
if (bytes == -1) { |
52 |
if (errno == EINTR) |
53 |
return BOA_E_INTR; |
54 |
if (errno == EAGAIN || errno == EWOULDBLOCK) /* request blocked */ |
55 |
return BOA_E_AGAIN; |
56 |
|
57 |
log_error_doc(req); |
58 |
perror("header read"); /* don't need to save errno because log_error_doc does */ |
59 |
return BOA_E_UNKNOWN; |
60 |
} |
61 |
|
62 |
#ifdef ENABLE_SSL |
63 |
} |
64 |
#endif |
65 |
|
66 |
return bytes; |
67 |
} |
68 |
|
69 |
ssize_t socket_send( request* req, const void* buf, size_t buf_size) |
70 |
{ |
71 |
ssize_t bytes; |
72 |
|
73 |
#ifdef ENABLE_SSL |
74 |
if ( req->secure) { |
75 |
bytes = gnutls_record_send(req->ssl_state, |
76 |
buf, buf_size); |
77 |
|
78 |
if (bytes < 0) { |
79 |
if (bytes == GNUTLS_E_INTERRUPTED) |
80 |
return BOA_E_INTR; |
81 |
if (bytes == GNUTLS_E_AGAIN) /* request blocked */ |
82 |
return BOA_E_AGAIN; |
83 |
|
84 |
log_error_doc(req); |
85 |
fprintf(stderr, "TLS sending error \"%s\"\n", gnutls_strerror( bytes)); |
86 |
return BOA_E_UNKNOWN; |
87 |
} |
88 |
} else { |
89 |
#endif |
90 |
bytes = |
91 |
send(req->fd, buf, buf_size, 0); |
92 |
|
93 |
if (bytes == -1) { |
94 |
if (errno == EINTR) |
95 |
return BOA_E_INTR; |
96 |
if (errno == EPIPE) |
97 |
return BOA_E_PIPE; |
98 |
if (errno == EAGAIN || errno == EWOULDBLOCK) /* request blocked */ |
99 |
return BOA_E_AGAIN; |
100 |
|
101 |
log_error_doc(req); |
102 |
perror("header read"); /* don't need to save errno because log_error_doc does */ |
103 |
return BOA_E_UNKNOWN; |
104 |
} |
105 |
|
106 |
#ifdef ENABLE_SSL |
107 |
} |
108 |
#endif |
109 |
|
110 |
return bytes; |
111 |
} |
112 |
|
113 |
#ifdef HAVE_TCP_CORK |
114 |
void socket_flush( int fd) |
115 |
{ |
116 |
int zero = 0; |
117 |
|
118 |
/* This is to flush output buffers. |
119 |
*/ |
120 |
if (setsockopt( fd, IPPROTO_TCP, TCP_CORK, |
121 |
(void *) &zero, sizeof (zero)) == -1) { |
122 |
WARN("setsockopt: unable to set TCP_CORK"); |
123 |
} |
124 |
} |
125 |
#endif |
126 |
|
127 |
void socket_set_options( int fd) { |
128 |
#ifdef HAVE_TCP_CORK /* Linux */ |
129 |
int one = 1; |
130 |
|
131 |
if (setsockopt(fd, IPPROTO_TCP, TCP_CORK, |
132 |
(void *) &one, sizeof (one)) == -1) |
133 |
{ |
134 |
WARN("setsockopt: unable to set TCP_CORK"); |
135 |
} |
136 |
#endif /* TCP_CORK */ |
137 |
} |