1 /*
2 This file is part of libmicrospdy
3 Copyright Copyright (C) 2013 Andrey Uzunov
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * @file io_raw.c
21 * @brief IO for SPDY without TLS.
22 * @author Andrey Uzunov
23 */
24
25 #include "platform.h"
26 #include "internal.h"
27 #include "session.h"
28 #include "io_raw.h"
29 //TODO put in in the right place
30 #include <netinet/tcp.h>
31
32
33 void
SPDYF_raw_global_init()34 SPDYF_raw_global_init()
35 {
36 }
37
38
39 void
SPDYF_raw_global_deinit()40 SPDYF_raw_global_deinit()
41 {
42 }
43
44
45 int
SPDYF_raw_init(struct SPDY_Daemon * daemon)46 SPDYF_raw_init(struct SPDY_Daemon *daemon)
47 {
48 (void)daemon;
49
50 return SPDY_YES;
51 }
52
53
54 void
SPDYF_raw_deinit(struct SPDY_Daemon * daemon)55 SPDYF_raw_deinit(struct SPDY_Daemon *daemon)
56 {
57 (void)daemon;
58 }
59
60
61 int
SPDYF_raw_new_session(struct SPDY_Session * session)62 SPDYF_raw_new_session(struct SPDY_Session *session)
63 {
64 int fd_flags;
65 int val = 1;
66 int ret;
67
68 //setting the socket to be non-blocking
69 fd_flags = fcntl (session->socket_fd, F_GETFL);
70 if ( -1 == fd_flags
71 || 0 != fcntl (session->socket_fd, F_SETFL, fd_flags | O_NONBLOCK))
72 SPDYF_DEBUG("WARNING: Couldn't set the new connection to be non-blocking");
73
74 if(SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags)
75 {
76 ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
77 if(-1 == ret)
78 SPDYF_DEBUG("WARNING: Couldn't set the new connection to TCP_NODELAY");
79 }
80
81 return SPDY_YES;
82 }
83
84
85 void
SPDYF_raw_close_session(struct SPDY_Session * session)86 SPDYF_raw_close_session(struct SPDY_Session *session)
87 {
88 (void)session;
89 }
90
91
92 int
SPDYF_raw_recv(struct SPDY_Session * session,void * buffer,size_t size)93 SPDYF_raw_recv(struct SPDY_Session *session,
94 void * buffer,
95 size_t size)
96 {
97 int n = read(session->socket_fd,
98 buffer,
99 size);
100 //if(n > 0) SPDYF_DEBUG("recvd: %i",n);
101 if (n < 0)
102 {
103 switch(errno)
104 {
105 case EAGAIN:
106 #if EAGAIN != EWOULDBLOCK
107 case EWOULDBLOCK:
108 #endif
109 case EINTR:
110 return SPDY_IO_ERROR_AGAIN;
111
112 default:
113 return SPDY_IO_ERROR_ERROR;
114 }
115 }
116
117 return n;
118 }
119
120
121 int
SPDYF_raw_send(struct SPDY_Session * session,const void * buffer,size_t size)122 SPDYF_raw_send(struct SPDY_Session *session,
123 const void * buffer,
124 size_t size)
125 {
126 int n = write(session->socket_fd,
127 buffer,
128 size);
129 //if(n > 0) SPDYF_DEBUG("sent: %i",n);
130 if (n < 0)
131 {
132 switch(errno)
133 {
134 case EAGAIN:
135 #if EAGAIN != EWOULDBLOCK
136 case EWOULDBLOCK:
137 #endif
138 case EINTR:
139 return SPDY_IO_ERROR_AGAIN;
140
141 default:
142 return SPDY_IO_ERROR_ERROR;
143 }
144 }
145
146 return n;
147 }
148
149
150 int
SPDYF_raw_is_pending(struct SPDY_Session * session)151 SPDYF_raw_is_pending(struct SPDY_Session *session)
152 {
153 (void)session;
154
155 return SPDY_NO;
156 }
157
158
159 int
SPDYF_raw_before_write(struct SPDY_Session * session)160 SPDYF_raw_before_write(struct SPDY_Session *session)
161 {
162 #if HAVE_DECL_TCP_CORK
163 if(0 == (SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags))
164 {
165 int val = 1;
166 int ret;
167
168 ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_CORK, &val, (socklen_t)sizeof(val));
169 if(-1 == ret)
170 SPDYF_DEBUG("WARNING: Couldn't set the new connection to TCP_CORK");
171 }
172 #endif
173
174 return SPDY_YES;
175 }
176
177
178 int
SPDYF_raw_after_write(struct SPDY_Session * session,int was_written)179 SPDYF_raw_after_write(struct SPDY_Session *session, int was_written)
180 {
181 #if HAVE_DECL_TCP_CORK
182 if(SPDY_YES == was_written && 0 == (SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags))
183 {
184 int val = 0;
185 int ret;
186
187 ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_CORK, &val, (socklen_t)sizeof(val));
188 if(-1 == ret)
189 SPDYF_DEBUG("WARNING: Couldn't unset the new connection to TCP_CORK");
190 }
191
192 #endif
193 return was_written;
194 }
195