/* 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 . */ /** * @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 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; }