Ejemplo n.º 1
0
static int
send_list_udp(struct socket_server *ss, struct socket *s, struct wb_list *list, struct socket_message *result) {
	while (list->head) {
		struct write_buffer * tmp = list->head;
		union sockaddr_all sa;
		socklen_t sasz = udp_socket_address(s, tmp->udp_address, &sa);
		int err = sendto(s->fd, tmp->ptr, tmp->sz, 0, &sa.s, sasz);
		if (err < 0) {
			switch(errno) {
			case EINTR:
			case AGAIN_WOULDBLOCK:
				return -1;
			}
			fprintf(stderr, "socket-server : udp (%d) sendto error %s.\n",s->id, strerror(errno));
			return -1;
/*			// ignore udp sendto error
			
			result->opaque = s->opaque;
			result->id = s->id;
			result->ud = 0;
			result->data = NULL;

			return SOCKET_ERROR;
*/
		}

		s->wb_size -= tmp->sz;
		list->head = tmp->next;
		write_buffer_free(ss,tmp);
	}
	list->tail = NULL;

	return -1;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
static int socket_req_send(struct _send_req *req, struct socket_message *msg, const uint8_t *udp_address) {
	struct socket * sock = &S.slot[HASH_ID(req->id)];
	struct socket_send_object so;
	socket_send_object_init(&so, req->data, req->size);
	if (sock->type == SOCKET_TYPE_INVALID || sock->id != req->id || sock->type == SOCKET_TYPE_HALFCLOSE
		|| sock->type == SOCKET_TYPE_PACCEPT) {
		so.free(req->data);
		return -1;
	}
	if (sock->type == SOCKET_TYPE_PLISTEN || sock->type == SOCKET_TYPE_LISTEN) {
		fprintf(stderr, "socket_req_send: write to listen fd:%d\n", sock->id);
		so.free(req->data);
		return -1;
	}
	if (sock->high.head == 0 && sock->low.head == 0 && sock->type == SOCKET_TYPE_OPENED) {
		if (sock->protocol == PROTOCOL_TCP) {
			int n = write(sock->fd, so.data, so.size);
			if (n < 0) {
				switch (errno) {
				case EINTR:
				case EAGAIN:
					n = 0;
					break;
				default:
					fprintf(stderr, "socket_req_send: write to %d (fd=%d) error:%d\n", sock->id, sock->fd, errno);
					socket_force_close(sock, msg);
					so.free(req->data);
					return SOCKET_CLOSE;
				}
			}
			if (n == so.size) {
				so.free(req->data);
				return -1;
			}
			socket_append_sendbuffer(sock, req, n);
		} else {
			int n;
			union sockaddr_all sa;
			socklen_t sa_size;
			if (!udp_address) {
				udp_address = sock->p.udp_address;
			}
			sa_size = udp_socket_address(sock, udp_address, &sa);
			n = sendto(sock->fd, so.data, so.size, 0, &sa.s, sa_size);
			if (n != req->size) {
				socket_append_udp_sendbuffer(sock, req, udp_address);
			} else {
				so.free(req->data);
				return -1;
			}
		}
		event_write(S.event_fd, sock->fd, sock, 1);
	} else {
		if (sock->protocol == PROTOCOL_TCP) {
			socket_append_sendbuffer(sock, req, 0);
		} else {
			if (!udp_address) {
				udp_address = sock->p.udp_address;
			}
			socket_append_udp_sendbuffer(sock, req, udp_address);
		}
	}
	if (sock->wb_size > 1024 * 1024) {
		msg->id = sock->id;
		msg->size = (int)(sock->wb_size / 1024);
		msg->data = 0;
		msg->ud = sock->ud;
		return SOCKET_WARNING;
	}
	return -1;
}