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
33void
34SPDYF_raw_global_init()
35{
36}
37
38
39void
40SPDYF_raw_global_deinit()
41{
42}
43
44
45int
46SPDYF_raw_init(struct SPDY_Daemon *daemon)
47{
48  (void)daemon;
49
50	return SPDY_YES;
51}
52
53
54void
55SPDYF_raw_deinit(struct SPDY_Daemon *daemon)
56{
57  (void)daemon;
58}
59
60
61int
62SPDYF_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
85void
86SPDYF_raw_close_session(struct SPDY_Session *session)
87{
88  (void)session;
89}
90
91
92int
93SPDYF_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
121int
122SPDYF_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
150int
151SPDYF_raw_is_pending(struct SPDY_Session *session)
152{
153  (void)session;
154
155	return SPDY_NO;
156}
157
158
159int
160SPDYF_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
178int
179SPDYF_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