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