1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* 2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat This file is part of libmicrospdy 3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat Copyright Copyright (C) 2013 Andrey Uzunov 4748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 5748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat This program is free software: you can redistribute it and/or modify 6748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat it under the terms of the GNU General Public License as published by 7748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat the Free Software Foundation, either version 3 of the License, or 8748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat (at your option) any later version. 9748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 10748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat This program is distributed in the hope that it will be useful, 11748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat but WITHOUT ANY WARRANTY; without even the implied warranty of 12748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat GNU General Public License for more details. 14748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 15748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat You should have received a copy of the GNU General Public License 16748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat along with this program. If not, see <http://www.gnu.org/licenses/>. 17748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat*/ 18748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 19748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 20748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @file io_raw.c 21748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief IO for SPDY without TLS. 22748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Andrey Uzunov 23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "platform.h" 26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "internal.h" 27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "session.h" 28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "io_raw.h" 29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat//TODO put in in the right place 30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <netinet/tcp.h> 31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid 34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_global_init() 35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid 40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_global_deinit() 41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint 46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_init(struct SPDY_Daemon *daemon) 47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat (void)daemon; 49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_YES; 51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid 55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_deinit(struct SPDY_Daemon *daemon) 56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat (void)daemon; 58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint 62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_new_session(struct SPDY_Session *session) 63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int fd_flags; 65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int val = 1; 66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int ret; 67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat //setting the socket to be non-blocking 69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat fd_flags = fcntl (session->socket_fd, F_GETFL); 70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ( -1 == fd_flags 71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat || 0 != fcntl (session->socket_fd, F_SETFL, fd_flags | O_NONBLOCK)) 72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat SPDYF_DEBUG("WARNING: Couldn't set the new connection to be non-blocking"); 73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if(SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags) 75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)); 77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if(-1 == ret) 78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat SPDYF_DEBUG("WARNING: Couldn't set the new connection to TCP_NODELAY"); 79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_YES; 82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid 86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_close_session(struct SPDY_Session *session) 87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat (void)session; 89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint 93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_recv(struct SPDY_Session *session, 94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat void * buffer, 95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t size) 96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int n = read(session->socket_fd, 98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat buffer, 99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size); 100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat //if(n > 0) SPDYF_DEBUG("recvd: %i",n); 101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (n < 0) 102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat switch(errno) 104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat case EAGAIN: 106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if EAGAIN != EWOULDBLOCK 107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat case EWOULDBLOCK: 108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat case EINTR: 110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_IO_ERROR_AGAIN; 111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat default: 113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_IO_ERROR_ERROR; 114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return n; 118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint 122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_send(struct SPDY_Session *session, 123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat const void * buffer, 124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t size) 125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int n = write(session->socket_fd, 127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat buffer, 128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size); 129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat //if(n > 0) SPDYF_DEBUG("sent: %i",n); 130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (n < 0) 131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat switch(errno) 133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat case EAGAIN: 135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if EAGAIN != EWOULDBLOCK 136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat case EWOULDBLOCK: 137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat case EINTR: 139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_IO_ERROR_AGAIN; 140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat default: 142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_IO_ERROR_ERROR; 143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return n; 147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint 151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_is_pending(struct SPDY_Session *session) 152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat (void)session; 154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_NO; 156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint 160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_before_write(struct SPDY_Session *session) 161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if HAVE_DECL_TCP_CORK 163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if(0 == (SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags)) 164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int val = 1; 166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int ret; 167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_CORK, &val, (socklen_t)sizeof(val)); 169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if(-1 == ret) 170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat SPDYF_DEBUG("WARNING: Couldn't set the new connection to TCP_CORK"); 171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return SPDY_YES; 175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint 179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratSPDYF_raw_after_write(struct SPDY_Session *session, int was_written) 180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if HAVE_DECL_TCP_CORK 182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if(SPDY_YES == was_written && 0 == (SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags)) 183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int val = 0; 185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int ret; 186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat ret = setsockopt(session->socket_fd, IPPROTO_TCP, TCP_CORK, &val, (socklen_t)sizeof(val)); 188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if(-1 == ret) 189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat SPDYF_DEBUG("WARNING: Couldn't unset the new connection to TCP_CORK"); 190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return was_written; 194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 195