C++程序  |  195行  |  3.67 KB

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