示例#1
0
文件: socket.c 项目: zhoukk/routine
int socket_udp(const char *host, int port, void *ud) {
	struct socket_req req;
	int fd;
	int family;
	if (port != 0 || host != 0) {
		fd = _socket_bind(host, port, IPPROTO_UDP, &family);
		if (fd < 0) {
			return -1;
		}
	} else {
		family = AF_INET;
		fd = socket(family, SOCK_DGRAM, 0);
		if (fd < 0) {
			return -1;
		}
	}
	socket_nonblocking(fd);
	memset(&req, 0, sizeof req);
	req.req = SOCKET_REQ_UDP;
	req.u.udp.id = socket_next_id();
	req.u.udp.fd = fd;
	req.u.udp.ud = ud;
	req.u.udp.family = family;
	socket_send_req(&req);
	return req.u.udp.id;
}
示例#2
0
文件: socket.c 项目: zhoukk/routine
static int socket_req_bind(struct _bind_req *req, struct socket_message *msg) {
	struct socket *sock;
	msg->id = req->id;
	msg->ud = req->ud;
	msg->size = 0;
	sock = socket_new(req->fd, req->id, PROTOCOL_TCP, req->ud, 1);
	if (sock == 0) {
		msg->data = "socket limit";
		return SOCKET_ERR;
	}
	socket_nonblocking(req->fd);
	sock->type = SOCKET_TYPE_BIND;
	msg->data = "binding";
	return SOCKET_OPEN;
}
示例#3
0
文件: reqs.c 项目: OPSF/uClinux
/*
 * pull_client_data is used to pull across any client data (like in a
 * POST) which needs to be handled before an error can be reported, or
 * server headers can be processed.
 *	- rjkaes
 */
static int
pull_client_data(struct conn_s *connptr, long int length)
{
	char *buffer;
	ssize_t len;

	buffer = safemalloc(min(MAXBUFFSIZE, length));
	if (!buffer)
		return -1;

	do {
		len = safe_read(connptr->client_fd, buffer,
				min(MAXBUFFSIZE, length));
		if (len <= 0)
			goto ERROR_EXIT;

		if (!connptr->error_variables) {
			if (safe_write(connptr->server_fd, buffer, len) < 0)
				goto ERROR_EXIT;
		}

		length -= len;
	} while (length > 0);

	/*
	 * BUG FIX: Internet Explorer will leave two bytes (carriage
	 * return and line feed) at the end of a POST message.  These
	 * need to be eaten for tinyproxy to work correctly.
	 */
	socket_nonblocking(connptr->client_fd);
	len = recv(connptr->client_fd, buffer, 2, MSG_PEEK);
	socket_blocking(connptr->client_fd);

	if (len < 0 && errno != EAGAIN)
		goto ERROR_EXIT;

	if (len == 2 && CHECK_CRLF(buffer, len))
		read(connptr->client_fd, buffer, 2);

	safefree(buffer);
	return 0;

  ERROR_EXIT:
	safefree(buffer);
	return -1;
}
示例#4
0
文件: socket.c 项目: zhoukk/routine
static int socket_try_accept(struct socket *sock, struct socket_message *msg) {
	union sockaddr_all u;
	socklen_t len = sizeof(u);
	struct socket *newsock;
	void * sin_addr;
	int sin_port;
	int client_fd, id;
	client_fd = accept(sock->fd, &u.s, &len);
	if (client_fd < 0) {
		if (errno == EMFILE || errno == ENFILE) {
			msg->id = sock->id;
			msg->ud = sock->ud;
			msg->data = strerror(errno);
			return SOCKET_ERR;
		} else {
			return -1;
		}
	}
	id = socket_next_id();
	if (id < 0) {
		close(client_fd);
		return -1;
	}
	socket_keepalive(client_fd);
	socket_nonblocking(client_fd);
	newsock = socket_new(client_fd, id, PROTOCOL_TCP, sock->ud, 0);
	if (newsock == 0) {
		close(client_fd);
		return -1;
	}
	newsock->type = SOCKET_TYPE_PACCEPT;
	msg->size = newsock->id;
	msg->data = 0;
	sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr;
	sin_port = ntohs((u.s.sa_family == AF_INET) ? u.v4.sin_port : u.v6.sin6_port);
	char tmp[INET6_ADDRSTRLEN];
	if (inet_ntop(u.s.sa_family, sin_addr, tmp, sizeof(tmp))) {
		snprintf(S.buffer, sizeof(S.buffer), "%s:%d", tmp, sin_port);
		msg->data = S.buffer;
	}
	return SOCKET_ACCEPT;
}
示例#5
0
文件: reqs.c 项目: OPSF/uClinux
/*
 * Switch the sockets into nonblocking mode and begin relaying the bytes
 * between the two connections. We continue to use the buffering code
 * since we want to be able to buffer a certain amount for slower
 * connections (as this was the reason why I originally modified
 * tinyproxy oh so long ago...)
 *	- rjkaes
 */
static void
relay_connection(struct conn_s *connptr)
{
	fd_set rset, wset;
	struct timeval tv;
	time_t last_access;
	int ret;
	double tdiff;
	int maxfd = max(connptr->client_fd, connptr->server_fd) + 1;
	ssize_t bytes_received;

	socket_nonblocking(connptr->client_fd);
	socket_nonblocking(connptr->server_fd);

	last_access = time(NULL);

	for (;;) {
		FD_ZERO(&rset);
		FD_ZERO(&wset);

		tv.tv_sec =
		    config.idletimeout - difftime(time(NULL), last_access);
		tv.tv_usec = 0;

		if (buffer_size(connptr->sbuffer) > 0)
			FD_SET(connptr->client_fd, &wset);
		if (buffer_size(connptr->cbuffer) > 0)
			FD_SET(connptr->server_fd, &wset);
		if (buffer_size(connptr->sbuffer) < MAXBUFFSIZE)
			FD_SET(connptr->server_fd, &rset);
		if (buffer_size(connptr->cbuffer) < MAXBUFFSIZE)
			FD_SET(connptr->client_fd, &rset);

		ret = select(maxfd, &rset, &wset, NULL, &tv);

		if (ret == 0) {
			tdiff = difftime(time(NULL), last_access);
			if (tdiff > config.idletimeout) {
				log_message(LOG_INFO,
					    "Idle Timeout (after select) as %g > %u.",
					    tdiff, config.idletimeout);
				return;
			} else {
				continue;
			}
		} else if (ret < 0) {
			log_message(LOG_ERR,
				    "relay_connection: select() error \"%s\". Closing connection (client_fd:%d, server_fd:%d)",
				    strerror(errno), connptr->client_fd,
				    connptr->server_fd);
			return;
		} else {
			/*
			 * All right, something was actually selected so mark it.
			 */
			last_access = time(NULL);
		}

		if (FD_ISSET(connptr->server_fd, &rset)) {
			bytes_received = read_buffer(connptr->server_fd, connptr->sbuffer);
			if (bytes_received < 0)
				break;

			connptr->content_length.server -= bytes_received;
			if (connptr->content_length.server == 0)
				break;
		}
		if (FD_ISSET(connptr->client_fd, &rset)
		    && read_buffer(connptr->client_fd, connptr->cbuffer) < 0) {
			break;
		}
		if (FD_ISSET(connptr->server_fd, &wset)
		    && write_buffer(connptr->server_fd, connptr->cbuffer) < 0) {
			break;
		}
		if (FD_ISSET(connptr->client_fd, &wset)
		    && write_buffer(connptr->client_fd, connptr->sbuffer) < 0) {
			break;
		}
	}

	/*
	 * Here the server has closed the connection... write the
	 * remainder to the client and then exit.
	 */
	socket_blocking(connptr->client_fd);
	while (buffer_size(connptr->sbuffer) > 0) {
		if (write_buffer(connptr->client_fd, connptr->sbuffer) < 0)
			break;
	}
	shutdown(connptr->client_fd, SHUT_WR);

	/*
	 * Try to send any remaining data to the server if we can.
	 */
	socket_blocking(connptr->server_fd);
	while (buffer_size(connptr->cbuffer) > 0) {
		if (write_buffer(connptr->server_fd, connptr->cbuffer) < 0)
			break;
	}

	return;
}
示例#6
0
文件: socket.c 项目: zhoukk/routine
static int socket_req_open(struct _open_req *req, struct socket_message *msg) {
	struct socket *sock;
	int status;
	int fd = -1;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = 0;
	struct addrinfo *ai_ptr = 0;
	char port[16];
	msg->id = req->id;
	msg->ud = req->ud;
	sprintf(port, "%d", req->port);
	memset(&ai_hints, 0, sizeof(ai_hints));
	ai_hints.ai_family = AF_UNSPEC;
	ai_hints.ai_socktype = SOCK_STREAM;
	ai_hints.ai_protocol = IPPROTO_TCP;
	status = getaddrinfo(req->host, port, &ai_hints, &ai_list);
	if (status != 0) {
		msg->data = (void *)gai_strerror(status);
		goto _failed;
	}
	for (ai_ptr = ai_list; ai_ptr != 0; ai_ptr = ai_ptr->ai_next) {
		fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
		if (fd < 0) {
			continue;
		}
		socket_keepalive(fd);
		socket_nonblocking(fd);
		status = connect(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if (status != 0 && errno != EINPROGRESS) {
			close(fd);
			fd = -1;
			continue;
		}
		break;
	}
	if (fd < 0) {
		msg->data = strerror(errno);
		goto _failed;
	}
	sock = socket_new(fd, req->id, PROTOCOL_TCP, req->ud, 1);
	if (sock == 0) {
		close(fd);
		msg->data = "socket limit";
		goto _failed;
	}
	if (status == 0) {
		sock->type = SOCKET_TYPE_OPENED;
		struct sockaddr *addr = ai_ptr->ai_addr;
		void *sin_addr = (ai_ptr->ai_family == AF_INET) ? (void *)&((struct sockaddr_in *)addr)->sin_addr : (void *)&((struct sockaddr_in6 *)addr)->sin6_addr;
		int sin_port = ntohs((ai_ptr->ai_family == AF_INET) ? ((struct sockaddr_in *)addr)->sin_port : ((struct sockaddr_in6 *)addr)->sin6_port);
		char tmp[INET6_ADDRSTRLEN];
		if (inet_ntop(ai_ptr->ai_family, sin_addr, tmp, sizeof(tmp))) {
			snprintf(S.buffer, sizeof(S.buffer), "%s:%d", tmp, sin_port);
			msg->data = S.buffer;
		}
		freeaddrinfo(ai_list);
		return SOCKET_OPEN;
	} else {
		sock->type = SOCKET_TYPE_OPENING;
		event_write(S.event_fd, sock->fd, sock, 1);
	}
	freeaddrinfo(ai_list);
	return -1;
_failed:
	freeaddrinfo(ai_list);
	S.slot[HASH_ID(req->id)].type = SOCKET_TYPE_INVALID;
	return SOCKET_ERR;
}
示例#7
0
/*
 * This is the main (per child) loop.
 */
static void child_main (struct child_s *ptr)
{
    int connfd;
    struct sockaddr *cliaddr;
    socklen_t clilen;
    fd_set rfds;
    int maxfd = 0;
    ssize_t i;
    int ret;

    cliaddr = (struct sockaddr *)
              safemalloc (sizeof(struct sockaddr_storage));
    if (!cliaddr) {
        log_message (LOG_CRIT,
                     "Could not allocate memory for child address.");
        exit (0);
    }

    ptr->connects = 0;

    /*
     * We have to wait for connections on multiple fds,
     * so use select.
     */

    FD_ZERO(&rfds);

    for (i = 0; i < vector_length(listen_fds); i++) {
        int *fd = (int *) vector_getentry(listen_fds, i, NULL);

        ret = socket_nonblocking(*fd);
        if (ret != 0) {
            log_message(LOG_ERR, "Failed to set the listening "
                        "socket %d to non-blocking: %s",
                        fd, strerror(errno));
            exit(1);
        }

        FD_SET(*fd, &rfds);
        maxfd = max(maxfd, *fd);
    }

    while (!config.quit) {
        int listenfd = -1;

        ptr->status = T_WAITING;

        clilen = sizeof(struct sockaddr_storage);

        ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
        if (ret == -1) {
            log_message (LOG_ERR, "error calling select: %s",
                         strerror(errno));
            exit(1);
        } else if (ret == 0) {
            log_message (LOG_WARNING, "Strange: select returned 0 "
                         "but we did not specify a timeout...");
            continue;
        }

        for (i = 0; i < vector_length(listen_fds); i++) {
            int *fd = (int *) vector_getentry(listen_fds, i, NULL);

            if (FD_ISSET(*fd, &rfds)) {
                /*
                 * only accept the connection on the first
                 * fd that we find readable. - fair?
                 */
                listenfd = *fd;
                break;
            }
        }

        if (listenfd == -1) {
            log_message(LOG_WARNING, "Strange: None of our listen "
                        "fds was readable after select");
            continue;
        }

        ret = socket_blocking(listenfd);
        if (ret != 0) {
            log_message(LOG_ERR, "Failed to set listening "
                        "socket %d to blocking for accept: %s",
                        listenfd, strerror(errno));
            exit(1);
        }

        /*
         * We have a socket that is readable.
         * Continue handling this connection.
         */

        connfd = accept (listenfd, cliaddr, &clilen);

#ifndef NDEBUG
        /*
         * Enable the TINYPROXY_DEBUG environment variable if you
         * want to use the GDB debugger.
         */
        if (getenv ("TINYPROXY_DEBUG")) {
            /* Pause for 10 seconds to allow us to connect debugger */
            fprintf (stderr,
                     "Process has accepted connection: %ld\n",
                     (long int) ptr->tid);
            sleep (10);
            fprintf (stderr, "Continuing process: %ld\n",
                     (long int) ptr->tid);
        }
#endif

        /*
         * Make sure no error occurred...
         */
        if (connfd < 0) {
            log_message (LOG_ERR,
                         "Accept returned an error (%s) ... retrying.",
                         strerror (errno));
            continue;
        }

        ptr->status = T_CONNECTED;

        SERVER_DEC ();

        handle_connection (connfd);
        ptr->connects++;

        if (child_config.maxrequestsperchild != 0) {
            DEBUG2 ("%u connections so far...", ptr->connects);

            if (ptr->connects == child_config.maxrequestsperchild) {
                log_message (LOG_NOTICE,
                             "Child has reached MaxRequestsPerChild (%u). "
                             "Killing child.", ptr->connects);
                break;
            }
        }

        SERVER_COUNT_LOCK ();
        if (*servers_waiting > child_config.maxspareservers) {
            /*
             * There are too many spare children, kill ourself
             * off.
             */
            log_message (LOG_NOTICE,
                         "Waiting servers (%d) exceeds MaxSpareServers (%d). "
                         "Killing child.",
                         *servers_waiting,
                         child_config.maxspareservers);
            SERVER_COUNT_UNLOCK ();

            break;
        } else {
            SERVER_COUNT_UNLOCK ();
        }

        SERVER_INC ();
    }

    ptr->status = T_EMPTY;

    safefree (cliaddr);
    exit (0);
}
示例#8
0
/* 
 * 主进程调用
 * hp add 2012/10/18
 */
int open_listening_sockets( config_t *pconfig )
{
	int i, opt=1;
	int fd;
	struct sockaddr_in addr;

	listenfd_cnt = pconfig->bindcnt;
	for ( i = 0; i < listenfd_cnt; ++ i ) {
		if ( strlen( pconfig->ips[i] ) > 15 ) {
			//ipv6
			//...
		}
		else { //ipv4
			fd = socket( AF_INET, SOCK_STREAM, 0 );
			if ( fd < 0 ) {
				log_message( LOG_ERROR, "socket error:%s.", strerror(errno) );
				return -1;
			}
	
			if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int) ) < 0 ) {
				log_message( LOG_ERROR, "setsockopt SO_REUSEADDR error:%s.", strerror(errno) );
				close( fd );
				return -1;
			}
				
			if ( socket_nonblocking(fd) < 0 ) {
				log_message( LOG_ERROR, "socket_nonblocking error." );
				close( fd );
				return -1;
			}
			
			bzero( &addr, sizeof(addr) );
			addr.sin_family = AF_INET;
			addr.sin_port = htons( SHELLINABOXPORT );
			if ( inet_pton( AF_INET, pconfig->ips[i], &addr.sin_addr ) < 1 ) {
				log_message( LOG_ERROR, "inet_pton %s error:%s.", pconfig->ips[i], strerror(errno) );
				close( fd );
				return -1;
			}

			if ( bind( fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 ) {
				log_message( LOG_ERROR, "bind error:%s.", strerror(errno) );
				close( fd );
				return -1;
			}

			if ( listen( fd, MAXLISTEN ) < 0 ) {
				log_message( LOG_ERROR, "listen error:%s.", strerror(errno) );
				close( fd );
				return -1;
			}
			listenfds[i].fd = fd;
			log_message( LOG_DEBUG, "create listen socket:[%s:%d]", pconfig->ips[i], SHELLINABOXPORT );

			//listenfds[i].addr = (struct sockaddr*)safemalloc( sizeof(addr) );
			memcpy( &listenfds[i].addr, &addr, sizeof(addr) ); 
			listenfds[i].addrlen = sizeof(addr);	
		}
	}	
	return TRUE;
}