1.提供支持ipv6的udp client和server接口, 可支持ipv6 (#1967)

* 1.提供支持ipv6的udp client和server接口, 可支持ipv6

* remove chinese comments
This commit is contained in:
huojicha
2024-08-08 02:34:15 +08:00
committed by GitHub
parent bcf97ecd1b
commit 839570ce3f
7 changed files with 218 additions and 3 deletions

View File

@@ -180,6 +180,18 @@ skynet_socket_udp(struct skynet_context *ctx, const char * addr, int port) {
return socket_server_udp(SOCKET_SERVER, source, addr, port);
}
int
skynet_socket_udp_dial(struct skynet_context *ctx, const char * addr, int port){
uint32_t source = skynet_context_handle(ctx);
return socket_server_udp_dial(SOCKET_SERVER, source, addr, port);
}
int
skynet_socket_udp_listen(struct skynet_context *ctx, const char * addr, int port){
uint32_t source = skynet_context_handle(ctx);
return socket_server_udp_listen(SOCKET_SERVER, source, addr, port);
}
int
skynet_socket_udp_connect(struct skynet_context *ctx, int id, const char * addr, int port) {
return socket_server_udp_connect(SOCKET_SERVER, id, addr, port);

View File

@@ -40,6 +40,8 @@ void skynet_socket_nodelay(struct skynet_context *ctx, int id);
int skynet_socket_udp(struct skynet_context *ctx, const char * addr, int port);
int skynet_socket_udp_connect(struct skynet_context *ctx, int id, const char * addr, int port);
int skynet_socket_udp_dial(struct skynet_context *ctx, const char * addr, int port);
int skynet_socket_udp_listen(struct skynet_context *ctx, const char * addr, int port);
int skynet_socket_udp_sendbuffer(struct skynet_context *ctx, const char * address, struct socket_sendbuffer *buffer);
const char * skynet_socket_udp_address(struct skynet_socket_message *, int *addrsz);

View File

@@ -190,6 +190,13 @@ struct request_udp {
uintptr_t opaque;
};
struct request_dial_udp {
int id;
int fd;
uintptr_t opaque;
uint8_t address[UDP_ADDRESS_SIZE];
};
/*
The first byte is TYPE
R Resume socket
@@ -204,6 +211,7 @@ struct request_udp {
P Send package (low)
A Send UDP package
C set udp address
N client dial to UDP host port
T Set opt
U Create UDP socket
*/
@@ -222,6 +230,7 @@ struct request_package {
struct request_setopt setopt;
struct request_udp udp;
struct request_setudp set_udp;
struct request_dial_udp dial_udp;
} u;
uint8_t dummy[256];
};
@@ -1329,6 +1338,30 @@ set_udp_address(struct socket_server *ss, struct request_setudp *request, struct
return -1;
}
static int
dial_udp_socket(struct socket_server *ss, struct request_dial_udp *request, struct socket_message *result){
int id = request->id;
int protocol = request->address[0];
struct socket *ns = new_fd(ss, id, request->fd, protocol, request->opaque, true);
if (ns == NULL){
close(request->fd);
ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
return -1;
}
if (protocol == PROTOCOL_UDP){
memcpy(ns->p.udp_address, request->address, 1 + 2 + 4);
} else {
memcpy(ns->p.udp_address, request->address, 1 + 2 + 16);
}
ATOM_STORE(&ns->type , SOCKET_TYPE_CONNECTED);
ATOM_FDEC(&ns->udpconnecting);
return -1;
}
static inline void
inc_sending_ref(struct socket *s, int id) {
if (s->protocol != PROTOCOL_TCP)
@@ -1372,7 +1405,6 @@ ctrl_cmd(struct socket_server *ss, struct socket_message *result) {
int type = header[0];
int len = header[1];
block_readpipe(fd, buffer, len);
// ctrl command only exist in local fd, so don't worry about endian.
switch (type) {
case 'R':
@@ -1409,6 +1441,8 @@ ctrl_cmd(struct socket_server *ss, struct socket_message *result) {
}
case 'C':
return set_udp_address(ss, (struct request_setudp *)buffer, result);
case 'N':
return dial_udp_socket(ss, (struct request_dial_udp *)buffer, result);
case 'T':
setopt_socket(ss, (struct request_setopt *)buffer);
return -1;
@@ -2116,6 +2150,92 @@ socket_server_udp(struct socket_server *ss, uintptr_t opaque, const char * addr,
return id;
}
int
socket_server_udp_listen(struct socket_server *ss, uintptr_t opaque, const char* addr, int port){
int fd;
if (port == 0){
return -1;
}
int family;
// bind
fd = do_bind(addr, port, IPPROTO_UDP, &family);
if (fd < 0) {
return -1;
}
sp_nonblocking(fd);
int id = reserve_id(ss);
if (id < 0) {
close(fd);
return -1;
}
struct request_package request;
request.u.udp.id = id;
request.u.udp.fd = fd;
request.u.udp.opaque = opaque;
request.u.udp.family = family;
send_request(ss, &request, 'U', sizeof(request.u.udp));
return id;
}
int
socket_server_udp_dial(struct socket_server *ss, uintptr_t opaque, const char* addr, int port){
int status;
struct addrinfo ai_hints;
struct addrinfo *ai_list = NULL;
char portstr[16];
sprintf(portstr, "%d", port);
memset( &ai_hints, 0, sizeof( ai_hints ) );
ai_hints.ai_family = AF_UNSPEC;
ai_hints.ai_socktype = SOCK_DGRAM;
ai_hints.ai_protocol = IPPROTO_UDP;
status = getaddrinfo(addr, portstr, &ai_hints, &ai_list );
if ( status != 0 ) {
return -1;
}
int protocol;
if (ai_list->ai_family == AF_INET) {
protocol = PROTOCOL_UDP;
} else if (ai_list->ai_family == AF_INET6) {
protocol = PROTOCOL_UDPv6;
} else {
freeaddrinfo( ai_list );
return -1;
}
int fd = socket(ai_list->ai_family, SOCK_DGRAM, 0);
if (fd < 0){
return -1;
}
sp_nonblocking(fd);
int id = reserve_id(ss);
if (id < 0){
close(fd);
return -1;
}
struct request_package request;
request.u.dial_udp.id = id;
request.u.dial_udp.fd = fd;
request.u.dial_udp.opaque = opaque;
int addrsz = gen_udp_address(protocol, (union sockaddr_all *)ai_list->ai_addr, request.u.dial_udp.address);
freeaddrinfo( ai_list );
send_request(ss, &request, 'N', sizeof(request.u.dial_udp) - sizeof(request.u.dial_udp.address) + addrsz);
return id;
}
int
socket_server_udp_send(struct socket_server *ss, const struct socket_udp_address *addr, struct socket_sendbuffer *buf) {
int id = buf->id;

View File

@@ -57,6 +57,12 @@ struct socket_udp_address;
int socket_server_udp(struct socket_server *, uintptr_t opaque, const char * addr, int port);
// set default dest address, return 0 when success
int socket_server_udp_connect(struct socket_server *, int id, const char * addr, int port);
// create an udp client socket handle, and connect to server addr, return id when success
int socket_server_udp_dial(struct socket_server *ss, uintptr_t opaque, const char* addr, int port);
// create an udp server socket handle, and bind the host port, return id when success
int socket_server_udp_listen(struct socket_server *ss, uintptr_t opaque, const char* addr, int port);
// If the socket_udp_address is NULL, use last call socket_server_udp_connect address instead
// You can also use socket_server_send
int socket_server_udp_send(struct socket_server *, const struct socket_udp_address *, struct socket_sendbuffer *buffer);