Пример #1
0
static int
report_connect(struct socket_server *ss, struct socket *s, struct socket_message *result) {
	int error;
	socklen_t len = sizeof(error);  
	int code = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &error, &len);  
	if (code < 0 || error) {  
		force_close(ss,s, result);
		return SOCKET_ERROR;
	} else {
		s->type = SOCKET_TYPE_CONNECTED;
		result->opaque = s->opaque;
		result->id = s->id;
		result->ud = 0;
		if (send_buffer_empty(s)) {
			sp_write(ss->event_fd, s->fd, s, false);
		}
		union sockaddr_all u;
		socklen_t slen = sizeof(u);
		if (getpeername(s->fd, &u.s, &slen) == 0) {
			void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr;
			if (inet_ntop(u.s.sa_family, sin_addr, ss->buffer, sizeof(ss->buffer))) {
				result->data = ss->buffer;
				return SOCKET_OPEN;
			}
		}
		result->data = NULL;
		return SOCKET_OPEN;
	}
}
Пример #2
0
static int
send_buffer(struct socket_server *ss, struct socket *s, union socket_message *result) {
	while (s->head) {
		struct write_buffer * tmp = s->head;
		for (;;) {
			int sz = write(s->fd, tmp->ptr, tmp->sz);
			if (sz < 0) {
				switch(errno) {
				case EINTR:
					continue;
				case EAGAIN:
					return 0;
				}
				result->close.id = s->id;
				force_close(ss,s);
				return SOCKET_CLOSE;
			}
			if (sz != tmp->sz) {
				tmp->ptr += sz;
				tmp->sz -= sz;
				return -1;
			}
			break;
		}
		s->head = tmp->next;
		FREE(tmp->buffer);
		FREE(tmp);
	}
	s->tail = NULL;
	sp_write(ss->event_fd, s->fd, s, false);

	return -1;
}
Пример #3
0
/*
	Each socket has two write buffer list, high priority and low priority.

	1. send high list as far as possible.
	2. If high list is empty, try to send low list.
	3. If low list head is uncomplete (send a part before), move the head of low list to empty high list (call raise_uncomplete) .
	4. If two lists are both empty, turn off the event. (call check_close)
 */
static int
send_buffer(struct socket_server *ss, struct socket *s, struct socket_message *result) {
	assert(!list_uncomplete(&s->low));
	// step 1
	if (send_list(ss,s,&s->high,result) == SOCKET_CLOSE) {
		return SOCKET_CLOSE;
	}
	if (s->high.head == NULL) {
		// step 2
		if (s->low.head != NULL) {
			if (send_list(ss,s,&s->low,result) == SOCKET_CLOSE) {
				return SOCKET_CLOSE;
			}
			// step 3
			if (list_uncomplete(&s->low)) {
				raise_uncomplete(s);
			}
		} else {
			// step 4
			sp_write(ss->event_fd, s->fd, s, false);

			if (s->type == SOCKET_TYPE_HALFCLOSE) {
				force_close(ss, s, result);
				return SOCKET_CLOSE;
			}
		}
	}

	return -1;
}
Пример #4
0
/**
 * Write a number of bytes to the specified serial port.
 *
 * @param serial Previously initialized serial port structure.
 * @param buf Buffer containing the bytes to write.
 * @param count Number of bytes to write.
 *
 * @return The number of bytes written, or a negative error code upon failure.
 */
SR_PRIV int serial_write(struct sr_serial_dev_inst *serial,
		const void *buf, size_t count)
{
	ssize_t ret;
	char *error;

	if (!serial) {
		sr_dbg("Invalid serial port.");
		return SR_ERR;
	}

	if (serial->fd == -1) {
		sr_dbg("Cannot use unopened serial port %s (fd %d).",
				serial->port, serial->fd);
		return SR_ERR;
	}

	ret = sp_write(serial->data, buf, count);

	switch (ret) {
	case SP_ERR_ARG:
		sr_err("Attempted serial port write with invalid arguments.");
		return SR_ERR_ARG;
	case SP_ERR_FAIL:
		error = sp_last_error_message();
		sr_err("Write error: %s.", error);
		sp_free_error_message(error);
		return SR_ERR;
	}

	sr_spew("Wrote %d/%d bytes (fd %d).", ret, count, serial->fd);

	return ret;
}
Пример #5
0
// 尝试连接中的套接字可写事件发生,可能是连接成功,也可能是连接出错
int socket_proxy::report_connect()
{
	int error;
	socklen_t len = sizeof(error);
	int code = getsockopt(this->fd, SOL_SOCKET, SO_ERROR, &error, &len);
	if (code < 0 || error)
    {
		force_close();
		return SOCKET_ERROR;
	}
    else
    {
		this->type = SOCKET_TYPE_CONNECTED;

		sp_write(this->ss->event_fd, this->fd, this, false);    // 连接成功,取消关注可写事件
		union sockaddr_all u;
		socklen_t slen = sizeof(u);
		if (getpeername(this->fd, &u.s, &slen) == 0)
        {
			void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr;
			if (inet_ntop(u.s.sa_family, sin_addr, this->ss->buffer, sizeof(this->ss->buffer)))
            {
				this->data = this->ss->buffer;
				return SOCKET_CONNECTION;
			}
		}
		this->data = NULL;
		return SOCKET_CONNECTION;
	}
}
Пример #6
0
static int
send_socket(struct socket_server *ss, struct request_send * request, struct socket_message *result) {
	int id = request->id;
	struct socket * s = &ss->slot[id % MAX_SOCKET];
	if (s->type == SOCKET_TYPE_INVALID || s->id != id 
		|| s->type == SOCKET_TYPE_HALFCLOSE
		|| s->type == SOCKET_TYPE_PACCEPT) {
		FREE(request->buffer);
		return -1;
	}
	assert(s->type != SOCKET_TYPE_PLISTEN && s->type != SOCKET_TYPE_LISTEN);
	if (s->head == NULL) {
		int n = write(s->fd, request->buffer, request->sz);
		if (n<0) {
			switch(errno) {
			case EINTR:
			case EAGAIN:
				n = 0;
				break;
			default:
				fprintf(stderr, "socket-server: write to %d (fd=%d) error.",id,s->fd);
				force_close(ss,s,result);
				return SOCKET_CLOSE;
			}
		}
		if (n == request->sz) {
			FREE(request->buffer);
			return -1;
		}

		struct write_buffer * buf = MALLOC(sizeof(*buf));
		buf->next = NULL;
		buf->ptr = request->buffer+n;
		buf->sz = request->sz - n;
		buf->buffer = request->buffer;
		s->head = s->tail = buf;

		sp_write(ss->event_fd, s->fd, s, true);
	} else {
		struct write_buffer * buf = MALLOC(sizeof(*buf));
		buf->ptr = request->buffer;
		buf->buffer = request->buffer;
		buf->sz = request->sz;
		assert(s->tail != NULL);
		assert(s->tail->next == NULL);
		buf->next = s->tail->next;
		s->tail->next = buf;
		s->tail = buf;
	}
	return -1;
}
Пример #7
0
/*
When send a package , we can assign the priority : PRIORITY_HIGH or PRIORITY_LOW

If socket buffer is empty, write to fd directly.
If write a part, append the rest part to high list. (Even priority is PRIORITY_LOW)
Else append package to high (PRIORITY_HIGH) or low (PRIORITY_LOW) list.
*/
static int
send_socket(struct socket_server *ss, struct request_send * request, struct socket_message *result, int priority)
{
	int id = request->id;
	struct socket * s = &ss->slot[id % MAX_SOCKET];
	if (s->type == SOCKET_TYPE_INVALID || s->id != id
		|| s->type == SOCKET_TYPE_HALFCLOSE
		|| s->type == SOCKET_TYPE_PACCEPT)
	{
		FREE(request->buffer);
		return -1;
	}
	assert(s->type != SOCKET_TYPE_PLISTEN && s->type != SOCKET_TYPE_LISTEN);
	if (send_buffer_empty(s))
	{
		int n = write(s->fd, request->buffer, request->sz);
		if (n < 0)
		{
			switch (errno)
			{
				case EINTR:
				case EAGAIN:
					n = 0;
					break;
				default:
					fprintf(stderr, "socket-server: write to %d (fd=%d) error.", id, s->fd);
					force_close(ss, s, result);
					return SOCKET_CLOSE;
			}
		}
		if (n == request->sz)
		{
			FREE(request->buffer);
			return -1;
		}
		append_sendbuffer(s, request, n);	// add to high priority list, even priority == PRIORITY_LOW
		sp_write(ss->event_fd, s->fd, s, true);
	}
	else
	{
		if (priority == PRIORITY_LOW)
		{
			append_sendbuffer_low(s, request);
		}
		else
		{
			append_sendbuffer(s, request, 0);
		}
	}
	return -1;
}
Пример #8
0
//执行send事件
int socket_proxy::send_socket(char *buffer, int sz)
{
	if (this->type == SOCKET_TYPE_INVALID
		|| this->type == SOCKET_TYPE_HALFCLOSE
		|| this->type == SOCKET_TYPE_PACCEPT )
    {
		//FREE(buffer);
		return -1;
	}
	assert(this->type != SOCKET_TYPE_PLISTEN && this->type != SOCKET_TYPE_LISTEN);
    char * buf = (char *)malloc(sz);
    memcpy(buf, buffer, sz);
	if (this->head == NULL)
    {
		int n = write(this->fd, buf, sz);
        //printf("n=%d, errno = %d", n, errno);
		if (n<0)
        {
			switch(errno)
            {
                case EINTR:
                case EAGAIN:
                    n = 0;
                    break;
                default:
                    //fprintf(stderr, "socket-server: write to %d (fd=%d) error.",id,s->fd);
                    force_close();
                    return SOCKET_CLOSE;
			}
		}
		if (n == sz)
        {
			FREE(buf);
			return -1;
		}
		this->append_sendbuffer(buf, sz, n);
		sp_write(this->ss->event_fd, this->fd, this, true);
	}
    else
    {
        printf("append");
		this->append_sendbuffer(buf, sz, 0);
        
	}
	return -1;
}
Пример #9
0
// 可写事件到来,从应用层发送缓冲区取数据发送
int socket_proxy::send_buffer()
{
	while (this->head)
    {
		struct write_buffer * tmp = this->head;
		for (;;)
        {
			int sz = write(this->fd, tmp->ptr, tmp->sz);
			if (sz < 0)
            {
				switch(errno)
                {
                    case EINTR:
                        continue;
                    case EAGAIN:    // 内核发送缓冲区已满
                        return -1;
				}
				force_close();
				return SOCKET_CLOSE;
			}
			this->wb_size -= sz;   //发送缓冲区未发的字节数需要更新
			if (sz != tmp->sz)
            {    // 未将该块缓冲区完全发送出去
				tmp->ptr += sz; // 该块缓冲区未发送数据首地址更新
				tmp->sz -= sz;  // 当前块未发送字节数更新
				return -1;
			}
			break;
		}
		this->head = tmp->next;
		FREE(tmp->buffer);
		FREE(tmp);
	}
	this->tail = NULL;
	sp_write(this->ss->event_fd,this->fd, this, false);
    
	if (this->type == SOCKET_TYPE_HALFCLOSE)
    {
		force_close();
		return SOCKET_CLOSE;
	}
    
	return -1;
}
Пример #10
0
static int
send_socket(struct socket_server *ss, struct request_send * request, struct socket_message *result) {
	int id = request->id;
	struct socket * s = &ss->slot[id % MAX_SOCKET];
	if (s->type == SOCKET_TYPE_INVALID || s->id != id 
		|| s->type == SOCKET_TYPE_HALFCLOSE
		|| s->type == SOCKET_TYPE_PACCEPT) {
		FREE(request->buffer);
		return -1;
	}
	assert(s->type != SOCKET_TYPE_PLISTEN && s->type != SOCKET_TYPE_LISTEN);
	// 应用层缓冲区 没有数据直接发送
	if (s->head == NULL) {
		int n = write(s->fd, request->buffer, request->sz);
		if (n<0) {
			switch(errno) {
			case EINTR:
			case EAGAIN: // 内核缓冲区满了
				n = 0;
				break;
			default:
				fprintf(stderr, "socket-server: write to %d (fd=%d) error.",id,s->fd);
				force_close(ss,s,result);
				return SOCKET_CLOSE;
			}
		}
		// 可以把数据拷贝到内核缓冲区中
		if (n == request->sz) {
			FREE(request->buffer);
			return -1;
		}
		// 将未发送的部分添加到应用层缓冲区中 关注可写事件
		append_sendbuffer(s, request, n);
		sp_write(ss->event_fd, s->fd, s, true);
	} else { // 将未发送的数据添加到应用层缓冲区 应用层缓冲区已经有数据了
		append_sendbuffer(s, request, 0);
	}
	return -1;
}
Пример #11
0
static int
send_buffer(struct socket_server *ss, struct socket *s, struct socket_message *result) {
	while (s->head) {
		struct write_buffer * tmp = s->head;
		for (;;) {
			int sz = write(s->fd, tmp->ptr, tmp->sz);
			if (sz < 0) {
				switch(errno) {
				case EINTR:
					continue;
				case EAGAIN:
					return -1;
				}
				force_close(ss,s, result);
				return SOCKET_CLOSE;
			}
			s->wb_size -= sz;
			if (sz != tmp->sz) {
				tmp->ptr += sz;
				tmp->sz -= sz;
				return -1;
			}
			break;
		}
		s->head = tmp->next;
		FREE(tmp->buffer);
		FREE(tmp);
	}
	s->tail = NULL;
	sp_write(ss->event_fd, s->fd, s, false); // 取消关注

	// 这里 在关闭的时候 处理不够完善 因为第二次发送的时候直接关闭了socket 没有继续发送完毕 所以skynet不适合大流量的网络应用
	if (s->type == SOCKET_TYPE_HALFCLOSE) {
		force_close(ss, s, result);
		return SOCKET_CLOSE;
	}

	return -1;
}
Пример #12
0
// return -1 when connecting
static int
open_socket(struct socket_server *ss, struct request_open * request, struct socket_message *result) {
	int id = request->id;
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = NULL;
	struct socket *ns;
	int status;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = NULL;
	struct addrinfo *ai_ptr = NULL;
	char port[16];
	sprintf(port, "%d", request->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( request->host, port, &ai_hints, &ai_list );
	if ( status != 0 ) {
		goto _failed;
	}
	int sock= -1;
	for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) {
		sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
		if ( sock < 0 ) {
			continue;
		}
		socket_keepalive(sock);
		sp_nonblocking(sock);
		status = connect( sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if ( status != 0 && errno != EINPROGRESS) {
			close(sock);
			sock = -1;
			continue;
		}
		break;
	}

	if (sock < 0) {
		goto _failed;
	}

	ns = new_fd(ss, id, sock, request->opaque, true);
	if (ns == NULL) {
		close(sock);
		goto _failed;
	}

	if(status == 0) {
		ns->type = SOCKET_TYPE_CONNECTED;
		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;
		if (inet_ntop(ai_ptr->ai_family, sin_addr, ss->buffer, sizeof(ss->buffer))) {
			result->data = ss->buffer;
		}
		freeaddrinfo( ai_list );
		return SOCKET_OPEN;
	} else {
		ns->type = SOCKET_TYPE_CONNECTING;
		sp_write(ss->event_fd, ns->fd, ns, true);
	}

	freeaddrinfo( ai_list );
	return -1;
_failed:
	freeaddrinfo( ai_list );
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
	return SOCKET_ERROR;
}
Пример #13
0
/*
	When send a package , we can assign the priority : PRIORITY_HIGH or PRIORITY_LOW

	If socket buffer is empty, write to fd directly.
		If write a part, append the rest part to high list. (Even priority is PRIORITY_LOW)
	Else append package to high (PRIORITY_HIGH) or low (PRIORITY_LOW) list.
 */
static int
send_socket(struct socket_server *ss, struct request_send * request, struct socket_message *result, int priority, const uint8_t *udp_address) {
	int id = request->id;
	struct socket * s = &ss->slot[HASH_ID(id)];
	struct send_object so;
	send_object_init(ss, &so, request->buffer, request->sz);
	if (s->type == SOCKET_TYPE_INVALID || s->id != id 
		|| s->type == SOCKET_TYPE_HALFCLOSE
		|| s->type == SOCKET_TYPE_PACCEPT) {
		so.free_func(request->buffer);
		return -1;
	}
	if (s->type == SOCKET_TYPE_PLISTEN || s->type == SOCKET_TYPE_LISTEN) {
		fprintf(stderr, "socket-server: write to listen fd %d.\n", id);
		so.free_func(request->buffer);
		return -1;
	}
	if (send_buffer_empty(s) && s->type == SOCKET_TYPE_CONNECTED) {
		// 如果已连接且发送缓冲区为空
		if (s->protocol == PROTOCOL_TCP) {
			// 直接写入套接字
			int n = write(s->fd, so.buffer, so.sz);
			if (n<0) {
				switch(errno) {
				case EINTR:
				case AGAIN_WOULDBLOCK:
					// 信号中断或者缓冲区写满
					n = 0;
					break;
				default:
					fprintf(stderr, "socket-server: write to %d (fd=%d) error :%s.\n",id,s->fd,strerror(errno));
					force_close(ss,s,result);
					so.free_func(request->buffer);
					return SOCKET_CLOSE;
				}
			}
			if (n == so.sz) {
				// 如果全部发送完,释放数据缓冲区,返回-1
				so.free_func(request->buffer);
				return -1;
			}
			// 如果没有发送完,剩余数据放到高优先级写缓冲区链表
			append_sendbuffer(ss, s, request, n);	// add to high priority list, even priority == PRIORITY_LOW
		} else {
			// udp
			if (udp_address == NULL) {
				udp_address = s->p.udp_address;
			}
			union sockaddr_all sa;
			socklen_t sasz = udp_socket_address(s, udp_address, &sa);
			int n = sendto(s->fd, so.buffer, so.sz, 0, &sa.s, sasz);
			if (n != so.sz) {
				append_sendbuffer_udp(ss,s,priority,request,udp_address);
			} else {
				so.free_func(request->buffer);
				return -1;
			}
		}
		// 打开事件循环中fd的可写权限
		sp_write(ss->event_fd, s->fd, s, true);
	} else {
		if (s->protocol == PROTOCOL_TCP) {
			if (priority == PRIORITY_LOW) {
				append_sendbuffer_low(ss, s, request);
			} else {
				append_sendbuffer(ss, s, request, 0);
			}
		} else {
			if (udp_address == NULL) {
				udp_address = s->p.udp_address;
			}
			append_sendbuffer_udp(ss,s,priority,request,udp_address);
		}
	}
	return -1;
}
Пример #14
0
// return -1 when connecting
// 打开套接字
// 正常返回 SOCKET_OPEN
// 其他返回 -1,包括 连接中 的情况
static int
open_socket(struct socket_server *ss, struct request_open * request, struct socket_message *result) {
	int id = request->id;
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = NULL;
	struct socket *ns;
	int status;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = NULL;
	struct addrinfo *ai_ptr = NULL;
	char port[16];
	sprintf(port, "%d", request->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;

	// host和port获取地址,支持ipv4和ipv6
	status = getaddrinfo( request->host, port, &ai_hints, &ai_list );
	if ( status != 0 ) {
		result->data = (void *)gai_strerror(status);
		goto _failed;
	}
	int sock= -1;
	for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) {
		// 创建socket套接字
		sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
		if ( sock < 0 ) {
			continue;
		}
		// 设置keepalive和非阻塞
		socket_keepalive(sock);
		sp_nonblocking(sock);
		// 连接套接字
		status = connect( sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if ( status != 0 && errno != EINPROGRESS) {
			// O_NONBLOCK is set for the file descriptor for the socket and the connection cannot be immediately established; the connection shall be established asynchronously.
			// 当套接字被设置为非阻塞后,连接不会被立即建立,所以errno会返回EINPROGRESS
			close(sock);
			sock = -1;
			continue;
		}
		break;
	}

	if (sock < 0) {
		result->data = strerror(errno);
		goto _failed;
	}

	// 创建socket实例
	ns = new_fd(ss, id, sock, PROTOCOL_TCP, request->opaque, true);
	if (ns == NULL) {
		close(sock);
		result->data = "reach skynet socket number limit";
		goto _failed;
	}

	if(status == 0) {
		// socket修改为已连接类型
		ns->type = SOCKET_TYPE_CONNECTED;
		struct sockaddr * addr = ai_ptr->ai_addr;
 		// 区分ipv4和ipv6,ip地址放入result->data
		void * sin_addr = (ai_ptr->ai_family == AF_INET) ? (void*)&((struct sockaddr_in *)addr)->sin_addr : (void*)&((struct sockaddr_in6 *)addr)->sin6_addr;
		if (inet_ntop(ai_ptr->ai_family, sin_addr, ss->buffer, sizeof(ss->buffer))) {
			result->data = ss->buffer;
		}
		freeaddrinfo( ai_list );
		return SOCKET_OPEN;
	} else {
		// socket修改为连接中类型,在socket_server_poll方法中调用report_connect方法修改为SOCKET_TYPE_CONNECTED,并返回SOCKET_OPEN
		ns->type = SOCKET_TYPE_CONNECTING;
		// 打开事件循环中fd的可写权限
		sp_write(ss->event_fd, ns->fd, ns, true);
	}

	freeaddrinfo( ai_list );
	return -1;
_failed:
	freeaddrinfo( ai_list );
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
	return SOCKET_ERROR;
}
Пример #15
0
void bsplit (char *file, char *split_spec) {
  char *ibuf, *obuf;
  struct stat64 statbuf;
  loff_t size = 0, skip_length;
  int in = 0;
  FILE *fin, *fout = NULL;
  loff_t pos = 0, opos = 0, i = 0, ipos = 0, read_len = 0;
  int file_part = 1;
  char ofilename[1024];
  loff_t positions[1024];
  char *split;
  
  if (! (ibuf = (char *) malloc (BUFFER_SIZE))) {
    perror ("bsplit");
    exit (-1);
  }
      
  if (! (obuf = (char *) malloc (BUFFER_SIZE))) {
    perror ("bsplit");
    exit (-1);
  }
  
  if (! (in = open64(file, O_RDONLY))) {
    perror ("bsplit open");
    exit (-1);
  }

  if (fstat64 (in, &statbuf) < 0) {
    perror ("bsplit stat");
    exit (-1);
  }

  size = statbuf.st_size;

  fin = fdopen(in, "r");
  
  positions[i++] = 0;
  split = (char*)strtok(split_spec, ":");
  positions[i++] = atoll(split);
  while ((split = strtok(NULL, ":")) != NULL) 
    positions[i++] = atoll(split);

  positions[i++] = size;
  
  i = 0;
  
  while (pos < size) {
    if (pos == positions[i]) {
      if (fout) {
	sp_write(fout, obuf, opos);
	fclose(fout);
      }
      sprintf(ofilename, name, file_part++);
      fprintf(stderr, "Opening %s\n", ofilename);
      if ((fout = fopen64(ofilename, "w")) == NULL) {
	perror("bsplit");
	exit(0);
      }
      i++;
      opos = 0;
    }

    if (ipos == read_len) {
      read_len = fread(ibuf, 1, min(BUFFER_SIZE, size - pos), fin);
      ipos = 0;
    }

    if (opos == BUFFER_SIZE) {
      sp_write(fout, obuf, BUFFER_SIZE);
      opos = 0;
    }

    skip_length = min(min(read_len - ipos, BUFFER_SIZE - opos),
		      positions[i] - pos);

    memcpy(obuf + opos, ibuf + ipos, skip_length);
    opos += skip_length;
    ipos += skip_length;
    pos += skip_length;
  }

  printf("%llu %llu\n", pos, size);

  if (fout) {
    sp_write(fout, obuf, opos);
    fclose(fout);
  }
    
}
Пример #16
0
int socket_proxy::_connect(bool blocking)
{
    bool ret;
    int status;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = NULL;
	struct addrinfo *ai_ptr = NULL;
	char port[16];
	sprintf(port, "%d", this->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;
    int sock= -1;

    // 获取地址列表,(不用gethostbyname、gethostbyadd,这两个函数仅支持IPV4)
    // 第一个参数是IP地址或主机名称,第二个参数是服务名(可以是端口或服务名称,如ftp、http等)
	status = getaddrinfo( this->host, port, &ai_hints, &ai_list );
	if ( status != 0 )
    {
		goto _failed;
	}
	for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next )
    {
		sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
		if ( sock < 0 )
        {
			continue;
		}
		socket_keepalive(sock);
		if (!blocking)
        {
			sp_nonblocking(sock);   // blocking为false,设置为非阻塞模式,即用非阻塞connect
		}
		status = ::connect( sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if ( status != 0 && errno != EINPROGRESS)
        {
			close(sock);
			sock = -1;
			continue;   // 连接出错,跳过本循环,连接下一个地址
		}
		if (blocking)
        {
			sp_nonblocking(sock);   //到此为止,不管blocking是真是假,都设置为非阻塞模式,即IO模型使用的是non blocking
		}
		break;
	}
    
	if (sock < 0)
    {
		goto _failed;
	}
    
    this->fd = sock;

	ret = ss->new_fd(this, true);   // 加入epoll管理
    if (!ret)
    {
        close(sock);
        goto _failed;
    }
	if(status == 0)
    {   //说明connect已连接成功
		this->type = SOCKET_TYPE_CONNECTED;
		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;
		if (inet_ntop(ai_ptr->ai_family, sin_addr, ss->buffer, sizeof(ss->buffer)))
        {
			//result->data = ss->buffer;
		}
		freeaddrinfo( ai_list );
		return SOCKET_OPEN;
	}
    else
    {    // 说明非阻塞套接字尝试连接中
		this->type = SOCKET_TYPE_CONNECTING;
		sp_write(ss->event_fd, this->fd, this, true);   // 非阻塞字尝试连接中,必需将关注其可写事件,稍后epoll触发才可以捕捉到已连接
	}
    
	freeaddrinfo( ai_list );
	return -1;
_failed:
	freeaddrinfo( ai_list );
	//ss->slot[id % MAX_SOCKET].type = SOCKET_TYPE_INVALID;
    this->type = SOCKET_TYPE_INVALID;
	return 0;
}