/*
This file is part of libmicrospdy
Copyright Copyright (C) 2013 Andrey Uzunov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file io_raw.c
* @brief IO for SPDY without TLS.
* @author Andrey Uzunov
*/
#include "platform.h"
#include "internal.h"
#include "session.h"
#include "io_raw.h"
//TODO put in in the right place
#include <netinet/tcp.h>
void
SPDYF_raw_global_init()
{
}
void
SPDYF_raw_global_deinit()
{
}
int
SPDYF_raw_init(struct SPDY_Daemon *daemon)
{
(void)daemon;
return SPDY_YES;
}
void
SPDYF_raw_deinit(struct SPDY_Daemon *daemon)
{
(void)daemon;
}
int
SPDYF_raw_new_session(struct SPDY_Session *session)
{
int fd_flags;
int val = 1;
int ret;
//setting the socket to be non-blocking
fd_flags = fcntl (session->socket_fd, F_GETFL);
if ( -1 == fd_flags
|| 0 != fcntl (session->socket_fd, F_SETFL, fd_flags | O_NONBLOCK))
SPDYF_DEBUG("WARNING: Couldn't set the new connection to be non-blocking");
if(SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags)
{
ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
if(-1 == ret)
SPDYF_DEBUG("WARNING: Couldn't set the new connection to TCP_NODELAY");
}
return SPDY_YES;
}
void
SPDYF_raw_close_session(struct SPDY_Session *session)
{
(void)session;
}
int
SPDYF_raw_recv(struct SPDY_Session *session,
void * buffer,
size_t size)
{
int n = read(session->socket_fd,
buffer,
size);
//if(n > 0) SPDYF_DEBUG("recvd: %i",n);
if (n < 0)
{
switch(errno)
{
case EAGAIN:
#if EAGAIN != EWOULDBLOCK
case EWOULDBLOCK:
#endif
case EINTR:
return SPDY_IO_ERROR_AGAIN;
default:
return SPDY_IO_ERROR_ERROR;
}
}
return n;
}
int
SPDYF_raw_send(struct SPDY_Session *session,
const void * buffer,
size_t size)
{
int n = write(session->socket_fd,
buffer,
size);
//if(n > 0) SPDYF_DEBUG("sent: %i",n);
if (n < 0)
{
switch(errno)
{
case EAGAIN:
#if EAGAIN != EWOULDBLOCK
case EWOULDBLOCK:
#endif
case EINTR:
return SPDY_IO_ERROR_AGAIN;
default:
return SPDY_IO_ERROR_ERROR;
}
}
return n;
}
int
SPDYF_raw_is_pending(struct SPDY_Session *session)
{
(void)session;
return SPDY_NO;
}
int
SPDYF_raw_before_write(struct SPDY_Session *session)
{
#if HAVE_DECL_TCP_CORK
if(0 == (SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags))
{
int val = 1;
int ret;
ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_CORK, &val, (socklen_t)sizeof(val));
if(-1 == ret)
SPDYF_DEBUG("WARNING: Couldn't set the new connection to TCP_CORK");
}
#endif
return SPDY_YES;
}
int
SPDYF_raw_after_write(struct SPDY_Session *session, int was_written)
{
#if HAVE_DECL_TCP_CORK
if(SPDY_YES == was_written && 0 == (SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags))
{
int val = 0;
int ret;
ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_CORK, &val, (socklen_t)sizeof(val));
if(-1 == ret)
SPDYF_DEBUG("WARNING: Couldn't unset the new connection to TCP_CORK");
}
#endif
return was_written;
}