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