Example #1
0
// 启动socket,加入事件循环
// 成功时返回SOCKET_OPEN
static int
start_socket(struct socket_server *ss, struct request_start *request, struct socket_message *result) {
	int id = request->id;
	result->id = id;
	result->opaque = request->opaque;
	result->ud = 0;
	result->data = NULL;
	struct socket *s = &ss->slot[HASH_ID(id)];
	if (s->type == SOCKET_TYPE_INVALID || s->id !=id) {
		result->data = "invalid socket";
		return SOCKET_ERROR;
	}
	if (s->type == SOCKET_TYPE_PACCEPT || s->type == SOCKET_TYPE_PLISTEN) {
		// 套接字加入事件循环
		if (sp_add(ss->event_fd, s->fd, s)) {
			force_close(ss, s, result);
			result->data = strerror(errno);
			return SOCKET_ERROR;
		}
		// SOCKET_TYPE_PACCEPT -> SOCKET_TYPE_CONNECTED
		// SOCKET_TYPE_PLISTEN -> SOCKET_TYPE_LISTEN
		s->type = (s->type == SOCKET_TYPE_PACCEPT) ? SOCKET_TYPE_CONNECTED : SOCKET_TYPE_LISTEN;
		s->opaque = request->opaque;
		result->data = "start";
		return SOCKET_OPEN;
	} else if (s->type == SOCKET_TYPE_CONNECTED) {
		// todo: maybe we should send a message SOCKET_TRANSFER to s->opaque
		s->opaque = request->opaque;
		result->data = "transfer";
		return SOCKET_OPEN;
	}
	// if s->type == SOCKET_TYPE_HALFCLOSE , SOCKET_CLOSE message will send later
	return -1;
}
Example #2
0
int64_t 
socket_server_udp_send(struct socket_server *ss, int id, const struct socket_udp_address *addr, const void *buffer, int sz) {
	struct socket * s = &ss->slot[HASH_ID(id)];
	if (s->id != id || s->type == SOCKET_TYPE_INVALID) {
		free_buffer(ss, buffer, sz);
		return -1;
	}

	struct request_package request;
	request.u.send_udp.send.id = id;
	request.u.send_udp.send.sz = sz;
	request.u.send_udp.send.buffer = (char *)buffer;

	const uint8_t *udp_address = (const uint8_t *)addr;
	int addrsz;
	switch (udp_address[0]) {
	case PROTOCOL_UDP:
		addrsz = 1+2+4;		// 1 type, 2 port, 4 ipv4
		break;
	case PROTOCOL_UDPv6:
		addrsz = 1+2+16;	// 1 type, 2 port, 16 ipv6
		break;
	default:
		free_buffer(ss, buffer, sz);
		return -1;
	}

	memcpy(request.u.send_udp.address, udp_address, addrsz);	

	send_request(ss, &request, 'A', sizeof(request.u.send_udp.send)+addrsz);
	return s->wb_size;
}
Example #3
0
// 创建新的socket实例
// id,通过reserve_id分配的alloc_id
// fd, 通过socket创建的套接字
// add, true则加入事件循环
static struct socket *
new_fd(struct socket_server *ss, int id, int fd, int protocol, uintptr_t opaque, bool add) {
	struct socket * s = &ss->slot[HASH_ID(id)];
	// 正常情况下,socket已在reserve_id中赋值为保留类型
	assert(s->type == SOCKET_TYPE_RESERVE);

	if (add) {
		// 加入事件循环
		if (sp_add(ss->event_fd, fd, s)) {
			// 如果加入失败,socket重置为初始类型	
			s->type = SOCKET_TYPE_INVALID;
			return NULL;
		}
	}

	// 初始化变量
	s->id = id;
	s->fd = fd;
	s->protocol = protocol;
	s->p.size = MIN_READ_BUFFER;
	s->opaque = opaque;
	s->wb_size = 0;
	check_wb_list(&s->high);
	check_wb_list(&s->low);
	return s;
}
Example #4
0
static int socket_req_start(struct _start_req *req, struct socket_message *msg) {
	struct socket *sock;
	msg->id = req->id;
	msg->ud = req->ud;
	sock = &S.slot[HASH_ID(req->id)];
	if (sock->type == SOCKET_TYPE_INVALID || sock->id != req->id) {
		msg->data = "socket invalid id";
		return SOCKET_ERR;
	}
	if (sock->type == SOCKET_TYPE_PACCEPT || sock->type == SOCKET_TYPE_PLISTEN) {
		if (event_add(S.event_fd, sock->fd, sock)) {
			sock->type = SOCKET_TYPE_INVALID;
			msg->data = strerror(errno);		
			return SOCKET_ERR;
		}
		sock->type = (sock->type == SOCKET_TYPE_PACCEPT) ? SOCKET_TYPE_OPENED : SOCKET_TYPE_LISTEN;
		sock->ud = req->ud;
		msg->data = "start";
		return SOCKET_OPEN;
	} else if (sock->type == SOCKET_TYPE_OPENED) {
		sock->ud = req->ud;
		msg->data = "transfer";
		return SOCKET_OPEN;
	}
	return -1;
}
Example #5
0
// 递增分配id进行hash,并返回匹配的socket
static int
reserve_id(struct socket_server *ss) {
	int i;
	for (i=0;i<MAX_SOCKET;i++) {
		// 递增
		int id = ATOM_INC(&(ss->alloc_id));
		if (id < 0) {
			// 回绕
			id = ATOM_AND(&(ss->alloc_id), 0x7fffffff);
		}
		// 哈希匹配
		struct socket *s = &ss->slot[HASH_ID(id)];
		if (s->type == SOCKET_TYPE_INVALID) {
			// 如果是初始类型,修改为保留类型
			if (ATOM_CAS(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
				s->id = id;
				s->fd = -1;
				return id;
			} else {
				// 否则,重试
				// retry
				--i;
			}
		}
	}
	return -1;
}
Example #6
0
long socket_udpsend(int id, const struct socket_udp_address *address, const void *data, int size) {
	const uint8_t *udp_address;
	int addrsize;
	struct socket_req req;
	struct socket * sock = &S.slot[HASH_ID(id)];
	if (sock->id != id || sock->type == SOCKET_TYPE_INVALID) {
		freebuffer((void *)data, size);
		return -1;
	}
	memset(&req, 0, sizeof req);
	req.req = SOCKET_REQ_SENDUDP;
	req.u.send.id = id;
	req.u.send.data = (char *)data;
	req.u.send.size = size;
	udp_address = (const uint8_t *)address;
	switch (udp_address[0]) {
	case PROTOCOL_UDP:
		addrsize = 1 + 2 + 4;
		break;
	case PROTOCOL_UDPv6:
		addrsize = 1 + 2 + 16;
		break;
	default:
		freebuffer((void *)data, size);
		return -1;
	}
	memcpy(req.u.sendudp.address, udp_address, addrsize);
	socket_send_req(&req);
	return sock->wb_size;
}
Example #7
0
static int
close_socket(struct socket_server *ss, struct request_close *request, struct socket_message *result) {
	int id = request->id;
	struct socket * s = &ss->slot[HASH_ID(id)];
	if (s->type == SOCKET_TYPE_INVALID || s->id != id) {
		result->id = id;
		result->opaque = request->opaque;
		result->ud = 0;
		result->data = NULL;
		return SOCKET_CLOSE;
	}
	if (!send_buffer_empty(s)) { 
		int type = send_buffer(ss,s,result);
		if (type != -1)
			return type;
	}
	if (send_buffer_empty(s)) {
		force_close(ss,s,result);
		result->id = id;
		result->opaque = request->opaque;
		return SOCKET_CLOSE;
	}
	s->type = SOCKET_TYPE_HALFCLOSE;

	return -1;
}
Example #8
0
static int
start_socket(struct socket_server *ss, struct request_start *request, struct socket_message *result) {
	int id = request->id;
	result->id = id;
	result->opaque = request->opaque;
	result->ud = 0;
	result->data = NULL;
	struct socket *s = &ss->slot[HASH_ID(id)];
	if (s->type == SOCKET_TYPE_INVALID || s->id !=id) {
		return SOCKET_ERROR;
	}
	if (s->type == SOCKET_TYPE_PACCEPT || s->type == SOCKET_TYPE_PLISTEN) {
		if (sp_add(ss->event_fd, s->fd, s)) {
			s->type = SOCKET_TYPE_INVALID;
			return SOCKET_ERROR;
		}
		s->type = (s->type == SOCKET_TYPE_PACCEPT) ? SOCKET_TYPE_CONNECTED : SOCKET_TYPE_LISTEN;
		s->opaque = request->opaque;
		result->data = "start";
		return SOCKET_OPEN;
	} else if (s->type == SOCKET_TYPE_CONNECTED) {
		s->opaque = request->opaque;
		result->data = "transfer";
		return SOCKET_OPEN;
	}
	return -1;
}
Example #9
0
static int socket_req_opt(struct _opt_req *req, struct socket_message *msg) {
	struct socket *sock;
	sock = &S.slot[HASH_ID(req->id)];
	if (sock->type == SOCKET_TYPE_INVALID || sock->id != req->id) {
		return -1;
	}
	setsockopt(sock->fd, IPPROTO_TCP, req->what, (const char *)&req->value, sizeof(req->value));
	return -1;
}
Example #10
0
static void
setopt_socket(struct socket_server *ss, struct request_setopt *request) {
	int id = request->id;
	struct socket *s = &ss->slot[HASH_ID(id)];
	if (s->type == SOCKET_TYPE_INVALID || s->id !=id) {
		return;
	}
	int v = request->value;
	setsockopt(s->fd, IPPROTO_TCP, request->what, &v, sizeof(v));
}
Example #11
0
void 
socket_server_send_lowpriority(struct socket_server *ss, int id, const void * buffer, int sz) {
	struct socket * s = &ss->slot[HASH_ID(id)];
	if (s->id != id || s->type == SOCKET_TYPE_INVALID) {
		return;
	}

	struct request_package request;
	request.u.send.id = id;
	request.u.send.sz = sz;
	request.u.send.buffer = (char *)buffer;

	send_request(ss, &request, 'P', sizeof(request.u.send));
}
Example #12
0
static int socket_req_listen(struct _listen_req *req, struct socket_message *msg) {
	struct socket *sock = socket_new(req->fd, req->id, PROTOCOL_TCP, req->ud, 0);
	if (sock == 0) {
		goto _failed;
	}
	sock->type = SOCKET_TYPE_PLISTEN;
	return -1;
_failed:
	close(req->fd);
	msg->ud = req->ud;
	msg->id = req->id;
	msg->data = "socket limit";
	S.slot[HASH_ID(req->id)].type = SOCKET_TYPE_INVALID;
	return SOCKET_ERR;
}
Example #13
0
// return -1 when error
// send_socket HIGH
int64_t 
socket_server_send(struct socket_server *ss, int id, const void * buffer, int sz) {
	struct socket * s = &ss->slot[HASH_ID(id)];
	if (s->id != id || s->type == SOCKET_TYPE_INVALID) {
		free_buffer(ss, buffer, sz);
		return -1;
	}

	struct request_package request;
	request.u.send.id = id;
	request.u.send.sz = sz;
	request.u.send.buffer = (char *)buffer;

	send_request(ss, &request, 'D', sizeof(request.u.send));
	return s->wb_size;
}
Example #14
0
long socket_send(int id, const void *data, int size, int priority) {
	struct socket_req req;
	struct socket * sock = &S.slot[HASH_ID(id)];
	if (sock->id != id || sock->type == SOCKET_TYPE_INVALID) {
		freebuffer((void *)data, size);
		return -1;
	}
	memset(&req, 0, sizeof req);
	req.req = SOCKET_REQ_SEND;
	req.u.send.id = id;
	req.u.send.data = (char *)data;
	req.u.send.size = size;
	req.u.send.priority = priority;
	socket_send_req(&req);
	return sock->wb_size;
}
Example #15
0
static void
add_udp_socket(struct socket_server *ss, struct request_udp *udp) {
    int id = udp->id;
    int protocol;
    if (udp->family == AF_INET6) {
        protocol = PROTOCOL_UDPv6;
    } else {
        protocol = PROTOCOL_UDP;
    }
    struct socket *ns = new_fd(ss, id, udp->fd, protocol, udp->opaque, true);
    if (ns == NULL) {
        close(udp->fd);
        ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
        return;
    }
    ns->type = SOCKET_TYPE_CONNECTED;
    memset(ns->p.udp_address, 0, sizeof(ns->p.udp_address));
}
Example #16
0
static int socket_req_udp(struct _udp_req *req, struct socket_message *msg) {
	int id = req->id;
	int protocol;
	struct socket *sock;
	if (req->family == AF_INET6) {
		protocol = PROTOCOL_UDPv6;
	} else {
		protocol = PROTOCOL_UDP;
	}
	sock = socket_new(req->fd, id, protocol, req->ud, 1);
	if (!sock) {
		close(req->fd);
		S.slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
		return -1;
	}
	sock->type = SOCKET_TYPE_OPENED;
	memset(sock->p.udp_address, 0, sizeof(sock->p.udp_address));
	return -1;
}
Example #17
0
int socket_server::listen_socket(struct request_listen * request, struct socket_message * result)
{
    int id = request->id;
    int listen_fd = request->fd;
    struct socket * s = new_socket(id, listen_fd, PROTOCOL_TCP, request->opaque, false);
    if (s == nullptr) {
        goto _failed;
    }
    s->type = SOCKET_TYPE_PLISTEN;
    return -1;
_failed:
    close(listen_fd);
    result->opaque = request->opaque;
    result->id = id;
    result->ud = 0;
    result->data = nullptr;
    slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
     
    return SOCKET_ERROR;
}
Example #18
0
static int socket_next_id(void) {
	int i;
	for (i = 0; i < MAX_SOCKET; i++) {
		struct socket *sock;
		int id = atom_inc(&(S.next_id));
		if (id < 0) {
			id = atom_and(&(S.next_id), 0x7fffffff);
		}
		sock = &S.slot[HASH_ID(id)];
		if (sock->type == SOCKET_TYPE_INVALID) {
			if (atom_cas(&(sock->type), SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
				sock->id = id;
				sock->fd = -1;
				return id;
			}
			--i;
		}
	}
	return -1;
}
Example #19
0
struct socket * socket_server::new_socket(int id, int fd, int protocol, uintptr_t opaque, bool add)
{
    struct socket * s = &slot[HASH_ID(id)];
    assert(s->type == SOCKET_TYPE_RESERVE);

    if (add) {
        if (event_fd.add(fd, s)) {
            s->type = SOCKET_TYPE_INVALID;
            return nullptr;
        }
    }

    s->id = id;
    s->fd = fd;
    s->protocol = protocol;

    s->opaque = opaque;

    return s;
}
Example #20
0
static int
listen_socket(struct socket_server *ss, struct request_listen * request, struct socket_message *result) {
	int id = request->id;
	int listen_fd = request->fd;
	struct socket *s = new_fd(ss, id, listen_fd, request->opaque, false);
	if (s == NULL) {
		goto _failed;
	}
	s->type = SOCKET_TYPE_PLISTEN;
	return -1;
_failed:
	close(listen_fd);
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = NULL;
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;

	return SOCKET_ERROR;
}
Example #21
0
int socket_server::reserve_id()
{
    for (int i = 0; i < MAX_SOCKET; i++) {
        int id = __sync_add_and_fetch(&alloc_id, 1);
        if (id < 0) {
            id = __sync_and_and_fetch(&alloc_id, 0x7fffffff);
        }
        struct socket *s = &slot[HASH_ID(id)];

        if (s->type == SOCKET_TYPE_INVALID) {
            if (__sync_bool_compare_and_swap(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
                s->id = id;
                s->fd = -1;
                return id;
            } else {
                --i;
            }
        }
    }
    return -1;
}
Example #22
0
static struct socket *socket_new(int fd, int id, int protocol, void *ud, int add) {
	struct socket *sock;
	sock = &S.slot[HASH_ID(id)];
	assert(sock->type == SOCKET_TYPE_RESERVE);
	sock->id = id;
	sock->fd = fd;
	sock->ud = ud;
	sock->p.size = MIN_SOCK_BUFF;
	sock->wb_size = 0;
	sock->protocol = protocol;
	sock->high.head = sock->high.tail = 0;
	sock->low.head = sock->low.tail = 0;
	if (add) {
		if (event_add(S.event_fd, fd, sock)) {
			sock->type = SOCKET_TYPE_INVALID;
			fprintf(stderr, "event_add error:%d.\n", errno);
			return 0;
		}
	}
	return sock;
}
Example #23
0
static struct socket *
new_fd(struct socket_server *ss, int id, int fd, uintptr_t opaque, bool add) {
	struct socket * s = &ss->slot[HASH_ID(id)];
	assert(s->type == SOCKET_TYPE_RESERVE);

	if (add) {
		if (sp_add(ss->event_fd, fd, s)) {
			s->type = SOCKET_TYPE_INVALID;
			return NULL;
		}
	}

	s->id = id;
	s->fd = fd;
	s->size = MIN_READ_BUFFER;
	s->opaque = opaque;
	s->wb_size = 0;
	check_wb_list(&s->high);
	check_wb_list(&s->low);
	return s;
}
Example #24
0
// 监听套接字
static int
listen_socket(struct socket_server *ss, struct request_listen * request, struct socket_message *result) {
	int id = request->id;
	int listen_fd = request->fd;
	// 创建socket实例,并修改为PListen类型
	struct socket *s = new_fd(ss, id, listen_fd, PROTOCOL_TCP, request->opaque, false);
	if (s == NULL) {
		goto _failed;
	}
	s->type = SOCKET_TYPE_PLISTEN;
	return -1;
_failed:
	close(listen_fd);
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = "reach skynet socket number limit";
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;

	return SOCKET_ERROR;
}
Example #25
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[HASH_ID(id)];
	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) && s->type == SOCKET_TYPE_CONNECTED) {
		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;
}
Example #26
0
static int
reserve_id(struct socket_server *ss) {
	int i;
	for (i=0;i<MAX_SOCKET;i++) {
		int id = __sync_add_and_fetch(&(ss->alloc_id), 1);
		if (id < 0) {
			id = __sync_and_and_fetch(&(ss->alloc_id), 0x7fffffff);
		}
		struct socket *s = &ss->slot[HASH_ID(id)];
		if (s->type == SOCKET_TYPE_INVALID) {
			if (__sync_bool_compare_and_swap(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) {
				s->id = id;
				s->fd = -1;
				return id;
			} else {
				// retry
				--i;
			}
		}
	}
	return -1;
}
Example #27
0
static int socket_req_setudp(struct _setudp_req *req, struct socket_message *msg) {
	int id = req->id;
	int type;
	struct socket *sock;
	sock = &S.slot[HASH_ID(req->id)];
	if (sock->type == SOCKET_TYPE_INVALID || sock->id != id) {
		return -1;
	}
	type = req->address[0];
	if (type != sock->protocol) {
		msg->ud = sock->ud;
		msg->id = id;
		msg->data = "socket protocol mismatch";
		return SOCKET_ERR;
	}
	if (type == PROTOCOL_UDP) {
		memcpy(sock->p.udp_address, req->address, 1 + 2 + 4);
	} else {
		memcpy(sock->p.udp_address, req->address, 1 + 2 + 16);
	}
	return -1;
}
Example #28
0
static int socket_req_close(struct _close_req *req, struct socket_message *msg) {
	struct socket * sock = &S.slot[HASH_ID(req->id)];
	if (sock->type == SOCKET_TYPE_INVALID || sock->id != req->id) {
		msg->id = req->id;
		msg->ud = req->ud;
		msg->data = "closed";
		return SOCKET_CLOSE;
	}
	if (sock->high.head != 0 || sock->low.head != 0) {
		int type = socket_send_buffer(sock, msg);
		if (type != -1) return type;
	}
	if (sock->high.head == 0 && sock->low.head == 0) {
		socket_force_close(sock, msg);
		msg->id = req->id;
		msg->ud = req->ud;
		msg->data = "closed";
		msg->size = 0;
		return SOCKET_CLOSE;
	}
	sock->type = SOCKET_TYPE_HALFCLOSE;
	return -1;
}
Example #29
0
static int
set_udp_address(struct socket_server *ss, struct request_setudp *request, struct socket_message *result) {
	int id = request->id;
	struct socket *s = &ss->slot[HASH_ID(id)];
	if (s->type == SOCKET_TYPE_INVALID || s->id !=id) {
		return -1;
	}
	int type = request->address[0];
	if (type != s->protocol) {
		// protocol mismatch
		result->opaque = s->opaque;
		result->id = s->id;
		result->ud = 0;
		result->data = "protocol mismatch";

		return SOCKET_ERROR;
	}
	if (type == PROTOCOL_UDP) {
		memcpy(s->p.udp_address, request->address, 1+2+4);	// 1 type, 2 port, 4 ipv4
	} else {
		memcpy(s->p.udp_address, request->address, 1+2+16);	// 1 type, 2 port, 16 ipv6
	}
	return -1;
}
Example #30
0
int socket_server::send_socket(struct request_send * request, struct socket_message * result, int priority)
{
    int id = request->id;
    struct socket *s = &slot[HASH_ID(id)];
    if (s->type == SOCKET_TYPE_INVALID
            || s->id != id
            || s->type == SOCKET_TYPE_HALFCLOSE
            || s->type == SOCKET_TYPE_PACCEPT) {
        return -1;
    }
    assert(s->type != SOCKET_TYPE_PLISTEN && s->type != SOCKET_TYPE_LISTEN);
    if (send_buffer_empty(s) && s->type == SOCKET_TYPE_CONNECTED) {
        if (s->protocol == PROTOCOL_TCP) {
            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: %s.\n", id, s->fd, strerror(errno));
                        force_close(s, result);
                        return SOCKET_CLOSE;
                }
            }
            if (n == request->sz)
            {
                return -1;
            }
            event_fd.write(s->fd, s, true);
        }
    }

    return -1;
}