Example #1
0
/*
 * Push a new line on to the end of the buffer.
 */
int
add_to_buffer(struct buffer_s *buffptr, unsigned char *data, size_t length)
{
	struct bufline_s *newline;

	assert(buffptr != NULL);
	assert(data != NULL);
	assert(length > 0);

	/*
	 * Sanity check here. A buffer with a non-NULL head pointer must
	 * have a size greater than zero, and vice-versa.
	 */
	if (BUFFER_HEAD(buffptr) == NULL)
		assert(buffptr->size == 0);
	else
		assert(buffptr->size > 0);

	/*
	 * Make a new line so we can add it to the buffer.
	 */
	if (!(newline = makenewline(data, length)))
		return -1;

	if (buffptr->size == 0)
		BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = newline;
	else {
		BUFFER_TAIL(buffptr)->next = newline;
		BUFFER_TAIL(buffptr) = newline;
	}

	buffptr->size += length;

	return 0;
}
Example #2
0
/*
 * Write the bytes in the buffer to the socket.
 * Takes a connection and returns the number of bytes written.
 */
ssize_t
write_buffer(int fd, struct buffer_s * buffptr)
{
	ssize_t bytessent;
	struct bufline_s *line;

	assert(fd >= 0);
	assert(buffptr != NULL);

	if (buffptr->size == 0)
		return 0;

	/* Sanity check. It would be bad to be using a NULL pointer! */
	assert(BUFFER_HEAD(buffptr) != NULL);
	line = BUFFER_HEAD(buffptr);

	bytessent =
	    send(fd, line->string + line->pos, line->length - line->pos, MSG_NOSIGNAL);

	if (bytessent >= 0) {
		/* bytes sent, adjust buffer */
		line->pos += bytessent;
		if (line->pos == line->length)
			free_line(remove_from_buffer(buffptr));
		return bytessent;
	} else {
		switch (errno) {
#ifdef EWOULDBLOCK
		case EWOULDBLOCK:
#else
#  ifdef EAGAIN
		case EAGAIN:
#  endif
#endif
		case EINTR:
			return 0;
		case ENOBUFS:
		case ENOMEM:
			log_message(LOG_ERR,
				    "writebuff: write() error [NOBUFS/NOMEM] \"%s\" on file descriptor %d",
				    strerror(errno), fd);
			return 0;
		default:
			log_message(LOG_ERR,
				    "writebuff: write() error \"%s\" on file descriptor %d",
				    strerror(errno), fd);
			return -1;
		}
	}
}
Example #3
0
/*
 * Remove the first line from the top of the buffer
 */
static struct bufline_s *
remove_from_buffer(struct buffer_s *buffptr)
{
	struct bufline_s *line;

	assert(buffptr != NULL);
	assert(BUFFER_HEAD(buffptr) != NULL);

	line = BUFFER_HEAD(buffptr);
	BUFFER_HEAD(buffptr) = line->next;

	buffptr->size -= line->length;

	return line;
}
Example #4
0
/*
 * Delete all the lines in the buffer and the buffer itself
 */
void
delete_buffer(struct buffer_s *buffptr)
{
	struct bufline_s *next;

	assert(buffptr != NULL);

	while (BUFFER_HEAD(buffptr)) {
		next = BUFFER_HEAD(buffptr)->next;
		free_line(BUFFER_HEAD(buffptr));
		BUFFER_HEAD(buffptr) = next;
	}

	safefree(buffptr);
}
Example #5
0
/*
 * Create a new buffer
 */
struct buffer_s *
new_buffer(void)
{
	struct buffer_s *buffptr;

	if (!(buffptr = safemalloc(sizeof(struct buffer_s))))
		return NULL;

	/*
	 * Since the buffer is initially empty, set the HEAD and TAIL
	 * pointers to NULL since they can't possibly point anywhere at the
	 * moment.
	 */
	BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = NULL;
	buffptr->size = 0;

	return buffptr;
}
Example #6
0
/**
 *	从url中抽取ip和端口,有各种情况需要分析
 *  0表示抽取成功, 
 *  -1表示不包含请求行
 *  -2表示出错(含有HTTP)
 */
int extract_ip_buffer( buffer_t *pbuf, char *ip, size_t size, uint16_t *port ) {
	block_t	*pb;
	int		bytes;
	char	*pE;
	block_t		*pnb;
	pb = BUFFER_HEAD(pbuf);

	//第一个块含有请求行
	if (  NULL != strnstr( BLOCK_SENDADDR(pb), BLOCK_SENDATA(pb), "HTTP", 4 ) ) {
		return __extract_ip( pbuf, pb, ip, size, port );	
	}
	else {

		pnb = pb->next;
		if ( NULL == pnb )
			return -1;
		if ( NULL != (pE=strnstr( BLOCK_SENDADDR(pnb), BLOCK_SENDATA(pnb), "HTTP", 4))){
			char	*p1, *p2;
			p1 = memchr( BLOCK_SENDADDR(pnb), '/', pE - BLOCK_SENDADDR(pnb) );

			//如果vm:port有可能横跨两个block
			if ( NULL == p1 ) {
				goto MERGEBLOCK;
			}
			p2 = memchr( p1, ':', pE-p1 );
			if ( NULL == p2 ) {
				goto MERGEBLOCK;
			}

			//现在可以确定,vm:port在pnb块里面
			return  __extract_ip( pbuf, pnb, ip, size, port );
		}

		int last = pb->end;
		//请求行只可能在第一快或是第二个快间.(1024的大小)
		if ( ( 'H' == pb->data[last-1] && 0 == strncmp( BLOCK_SENDADDR(pnb), "TTP", 3 ) ) 
			|| ( 'H' == pb->data[last-2] && 'T' == pb->data[last-1] && 
				0 == strncmp( BLOCK_SENDADDR(pnb), "TP", 2) )
			|| ( 0 == strncmp( pb->data+last-3, "HTT", 3 ) && 'P' == pnb->data[pnb->pos] )
		   ) {
			return __extract_ip( pbuf, pb, ip, size, port );
		}

		return -1;
	}

MERGEBLOCK:
	log_message( LOG_DEBUG, "in mergeblock" );
	bytes = BLOCK_SENDATA(pb)+ pE - BLOCK_SENDADDR(pnb);
	if ( bytes <= BLOCK_MAXDATA ) {
		block_t		*newb = (block_t*)safemalloc( sizeof(block_t) );
		newb->pos = 0;
		memcpy( newb->data, BLOCK_SENDADDR(pb), BLOCK_SENDATA(pb) );
		newb->end = BLOCK_SENDATA(pb);

		memcpy( BLOCK_READADDR(newb), BLOCK_SENDADDR(pnb), pE-BLOCK_SENDADDR(pnb) );
		newb->end += pE-BLOCK_SENDADDR(pnb);
		pnb->pos += pE-BLOCK_SENDADDR(pnb);
					
		pbuf->head = newb;
		newb->next = pnb;
		safefree( pb );
					
		return __extract_ip( pbuf, newb, ip, size, port );
	}
	else {
		log_message( LOG_ERROR, "vm:port between two block!" );
		return -1;
	}
}
Example #7
0
/**
 * 非阻塞写,从第一个block到pos位置
 * return 发送的总数据量
 */
ssize_t write_buffer( int fd, buffer_t *pbuf ) {
	
	assert(fd >= 0);
	assert( pbuf != NULL);

	block_t		*pb = NULL;
	int			n, total, size;
	
	total = 0;
	g_errno = 1;

NONWRITE:
	if ( 0 == pbuf->size )			//结束发送
		return total;
	pb = BUFFER_HEAD(pbuf);
	if ( NULL == pb ) {
		log_message( LOG_ERROR, "head = NULL, but remain size:%d", pbuf->size );
		return total;		
	}
	if ( 0 == BLOCK_SENDATA(pb) ) {	//块没有数据发了
		delete_head( pbuf );		
		goto NONWRITE;
	}
	size = BLOCK_SENDATA(pb);
	n = send( fd, BLOCK_SENDADDR(pb), size, 0 );
	log_message( LOG_DEBUG, "send %d bytes to fd[%d]", n, fd );

	if ( n >= 0 ) {
		g_errno = 1;
		pbuf->size -= n;
		pb->pos += n;
		total += n;
		
		if ( n == size ) {			//块数据发送完,其实不应该删除,判断有没有满
			delete_head( pbuf );		
			goto NONWRITE;			//et mode
		}
	}
	else {
		switch (errno) {
#ifdef EWOULDBLOCK
		case EWOULDBLOCK:
#else
#  ifdef EAGAIN
		case EAGAIN:
#  endif
#endif
		case EINTR:
			g_errno = 1;			//没有错误,等待下一次事件
			break;

		case ENOBUFS:
		case ENOMEM:
			log_message(LOG_ERROR,  "writebuff: write() error [NOBUFS/NOMEM] \"%s\" on file descriptor %d",  strerror(errno), fd);
		default:
			log_message(LOG_ERROR, "writebuff: write() error \"%s\" on file descriptor %d", strerror(errno), fd); 
			g_errno = -1;
		}
	}

	return total;
}