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