From b156cdbf515008ca087ce931e55e9766a6b3a096 Mon Sep 17 00:00:00 2001 From: fanasina Date: Tue, 15 Apr 2025 07:41:30 +0200 Subject: [PATCH] y_socket_t: debug udp chat server --- y_socket_t/include/y_socket_t/y_socket_t.h | 10 +- y_socket_t/src/y_socket_t/y_node_t.c | 12 +- y_socket_t/src/y_socket_t/y_socket_t.c | 377 +++++++++++++++++++-- y_socket_t/test/is_good.c | 43 +++ 4 files changed, 410 insertions(+), 32 deletions(-) diff --git a/y_socket_t/include/y_socket_t/y_socket_t.h b/y_socket_t/include/y_socket_t/y_socket_t.h index 4d8e63d..c4e9371 100644 --- a/y_socket_t/include/y_socket_t/y_socket_t.h +++ b/y_socket_t/include/y_socket_t/y_socket_t.h @@ -33,16 +33,24 @@ enum ipVersions{ extern const int af_array[nbIpVersion];//={AF_INET, AF_INET6}; struct y_socket_t{ - struct pollfd fds[nbIpVersion]; + struct pollfd *fds; char * port; struct main_list_y_NODE_T *nodes; + pthread_mutex_t mut_nodes; +}; +struct argdst { + char *port; + char *addrStr; }; struct y_socket_t * y_socket_create(char * port); void y_socket_free(struct y_socket_t *socket); +void *y_pollSocketsFunc(void *arg); +void *threadFuncSend(void *arg); + // type = nothing if v4, 6 if v6 #define GET_IN_type_ADDR(PointerSockAddr,type) \ ((struct sockaddr_in##type *)(PointerSockAddr))->sin##type##_addr.s##type##_addr diff --git a/y_socket_t/src/y_socket_t/y_node_t.c b/y_socket_t/src/y_socket_t/y_node_t.c index b325cfc..40fc72e 100644 --- a/y_socket_t/src/y_socket_t/y_node_t.c +++ b/y_socket_t/src/y_socket_t/y_node_t.c @@ -11,6 +11,7 @@ GEN_LIST_ALL(y_NODE_T) void init_len_y_NODE_T(y_NODE_T *node){ node->addr_len=sizeof(struct sockaddr_storage); } + void init_len_list_y_NODE_T(struct main_list_y_NODE_T *listNodes){ FOR_LIST_FORM_BEGIN(y_NODE_T, listNodes){ init_len_y_NODE_T(&(listNodes->current_list->value)); @@ -23,17 +24,24 @@ int y_NODE_T_cmp(y_NODE_T nodeA, y_NODE_T nodeB){ ret = nodeA.addr.ss_family - nodeB.addr.ss_family; if(ret == 0){ if(nodeA.addr.ss_family == AF_INET){ + //ret = memcmp((struct sockaddr_in*)&(nodeA.addr), (struct sockaddr_in*)&(nodeB.addr), sizeof(struct sockaddr_in)); + ret = ((struct sockaddr_in*)&(nodeA.addr))->sin_port - ((struct sockaddr_in*)&(nodeB.addr))->sin_port; + if(ret==0) + ret = GET_IN_type_ADDR(&(nodeA.addr),) - GET_IN_type_ADDR(&(nodeB.addr),); //ret = ((struct sockaddr_in*)&(nodeA.addr))->sin_addr.s_addr - ((struct sockaddr_in*)&(nodeB.addr))->sin_addr.s_addr; - ret = GET_IN_type_ADDR(&(nodeA.addr),) - GET_IN_type_ADDR(&(nodeB.addr),); }else if(nodeA.addr.ss_family == AF_INET6){ - ret = memcmp(GET_IN_type_ADDR(&(nodeA.addr),6), GET_IN_type_ADDR(&(nodeB.addr),6), 8); + ret = ((struct sockaddr_in6*)&(nodeA.addr))->sin6_port - ((struct sockaddr_in6*)&(nodeB.addr))->sin6_port; + if(ret ==0) + //ret = memcmp((struct sockaddr_in6*)&(nodeA.addr), (struct sockaddr_in6*)&(nodeB.addr), sizeof(struct sockaddr_in6)); + ret = memcmp(GET_IN_type_ADDR(&(nodeA.addr),6), GET_IN_type_ADDR(&(nodeB.addr),6), 8); //ret = memcmp(((struct sockaddr_in6*)&(nodeA.addr))->sin6_addr.s6_addr , ((struct sockaddr_in6*)&(nodeB.addr))->sin6_addr.s6_addr, 8); } } } return ret; } + struct list_y_NODE_T * search_node_in_list_y_NODE_T(struct main_list_y_NODE_T *listNodes, y_NODE_T node){ /* FOR_LIST_FORM_BEGIN(y_NODE_T, listNodes){ if(y_NODE_T_cmp(node, listNodes->current_list->value) == 0){ diff --git a/y_socket_t/src/y_socket_t/y_socket_t.c b/y_socket_t/src/y_socket_t/y_socket_t.c index a2faea9..a99601d 100644 --- a/y_socket_t/src/y_socket_t/y_socket_t.c +++ b/y_socket_t/src/y_socket_t/y_socket_t.c @@ -4,48 +4,367 @@ const int af_array[nbIpVersion]={AF_INET, AF_INET6}; struct y_socket_t * y_socket_create(char *port){ struct y_socket_t *sock_temp=malloc(sizeof(struct y_socket_t)); + sock_temp->fds = malloc(nbIpVersion * sizeof(struct pollfd)); + sock_temp->port=port; sock_temp->nodes = create_var_list_y_NODE_T(); + pthread_mutex_init(&(sock_temp->mut_nodes), NULL); return sock_temp; } void y_socket_free(struct y_socket_t *socket){ - + free(socket->fds); free_all_var_list_y_NODE_T(socket->nodes); - + pthread_mutex_destroy(&(socket->mut_nodes)); free(socket); } - -#if 0 -struct y_server_t server; - -void close_server(struct y_server_t server){ - char *message ="HTTP/1.1 201 OK\r\n" - "Connection: close"; - - for(int i=0; iai_next){ + for(af=v4; af<=v6; ++af){ + if((rp->ai_family == af_array[af]) && (fds[af].fd ==-1)){ + fds[af].fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if(fds[af].fd == -1) + continue; + + if(node == NULL){ +// android +#ifdef IPV6_V6ONLY + if(af == v6){ + if(setsockopt(fds[af].fd, IPPROTO_IPV6, IPV6_V6ONLY, + &optValueV6, sizeof(optValueV6)) == -1){ + perror("error setsockopt v6 :"); + close(fds[af].fd); + fds[af].fd = -1; + continue; + } + } #endif + if(bind(fds[af].fd, rp->ai_addr, rp->ai_addrlen)==-1){ + close(fds[af].fd); + fds[af].fd=-1; + } + } + } + } + } + freeaddrinfo(result); + + if((fds[v4].fd == -1) && (fds[v6].fd == -1)){ + fprintf(stderr, " v4 or v6 not listening, we leave!"); + return 3; + } + if((fds[v4].fd != -1) && (fds[v6].fd == -1)){ + fprintf(stderr, " only v4 listening!"); + return 1; + } + if((fds[v4].fd == -1) && (fds[v6].fd != -1)){ + fprintf(stderr, " only v6 listening!"); + return 2; + } + + return 0; + + +} + +void *y_pollSocketsFunc(void *arg){ + struct y_socket_t * argSock = (struct y_socket_t*)arg; + struct pollfd *fds = argSock->fds; + fds[v4].fd=-1; fds[v4].events = POLLIN; + fds[v6].fd=-1; fds[v6].events = POLLIN; + + struct addrinfo hints, *result, *rp; + int status; + ssize_t nread; + char buf[BUF_SIZE]; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; // Allow all IPv4 and IPv6 + hints.ai_socktype = SOCK_DGRAM; // udp + hints.ai_flags = AI_PASSIVE; // anyIP + // + hints.ai_protocol = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + status = getaddrinfo(NULL, argSock->port, &hints, &result); + if(status != 0){ + fprintf(stderr, "getaddrinfo :%s\n", gai_strerror(status)); + return NULL; + } + int af, optValueV6 = 1; + + for(rp = result; rp != NULL; rp=rp->ai_next){ + for(af=v4; af<=v6; ++af){ + if((rp->ai_family == af_array[af]) && (fds[af].fd ==-1)){ + fds[af].fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if(fds[af].fd == -1) + continue; +// android +#ifdef IPV6_V6ONLY + if(af == v6){ + if(setsockopt(fds[af].fd, IPPROTO_IPV6, IPV6_V6ONLY, + &optValueV6, sizeof(optValueV6)) == -1){ + perror("error setsockopt v6 :"); + close(fds[af].fd); + fds[af].fd = -1; + continue; + } + } +#endif + if(bind(fds[af].fd, rp->ai_addr, rp->ai_addrlen)==-1){ + close(fds[af].fd); + fds[af].fd=-1; + } + } + } + } + + freeaddrinfo(result); + +// ssize_t nread; +// char buf[BUF_SIZE]; + +// int status, af; +// status = get_fds_with_getaddrinfo(argSock->port, NULL, fds); + +// if(status != 0) + /* + if(status == 1) + fprintf(stderr, " v4 or v6 not listening, we leave!"); + else + fprintf(stderr, " not enough allocatation for fds, we leave!"); + */ + + if((fds[v4].fd==-1) || (fds[v6].fd==-1)){ + fprintf(stderr, " v4 or v6 not listening, we leave!"); + return NULL; + } + //struct sockaddr_storage peer_addr; + //socklen_t len_peer_addr; + y_NODE_T node; + char tempAddr[BUF_SIZE]; + int c_af; + char host[NI_MAXHOST], service[NI_MAXSERV]; +// char msgRet[BUF_SIZE + NI_MAXHOST + NI_MAXSERV + 100]; +// int len_msgRet; + for(;;){ + status = poll(fds, nbIpVersion, -1); + if(status <= 0){ + if(status == -1 && errno != EINTR){ + perror("poll"); + return NULL; + } + continue; + } + node.addr_len = sizeof(struct sockaddr_storage); + for(af = v4; af<=v6;++af){ + if(fds[af].revents && POLLIN){ + memset(buf, 0, BUF_SIZE); + nread = recvfrom(fds[af].fd, buf, BUF_SIZE, 0, + (struct sockaddr *)&(node.addr), &(node.addr_len)); + if(nread == -1) + continue; + +printf("msg : %s\n",buf); + + status = getnameinfo((struct sockaddr*)&(node.addr), node.addr_len, host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICHOST); + if(status == 0) + printf("Received %ld bytes from %s:%s\n",(long)nread, host,service); + else + fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status)); + + + if(NULL == search_node_in_list_y_NODE_T(argSock->nodes, node)) + push_back_list_y_NODE_T(argSock->nodes, node); + + //UPPER + for(int i=0; i='a') && (buf[i]<='z')) + buf[i]=buf[i]+'A'-'a'; + + //memset(msgRet, 0, BUF_SIZE + NI_MAXHOST + NI_MAXSERV + 100); +// sprintf(msgRet, "from %s:%s =%s",host, service, buf); + +// len_msgRet = strlen(msgRet); + printf("sending response %s :\n",buf); + FOR_LIST_FORM_BEGIN(y_NODE_T, argSock->nodes){ + c_af=(argSock->nodes->current_list->value).addr.ss_family; + //memset(tempAddr, 0, BUF_SIZE); + if(c_af==AF_INET){ + if(NULL == inet_ntop(c_af, + &(GET_IN_type_ADDR(&(argSock->nodes->current_list->value),)), + tempAddr, BUF_SIZE/*(argSock->nodes->current_list->value).addr_len*/)){ + fprintf(stderr, "error inet_ntop v4\n"); + } + }else if(c_af==AF_INET6){ + if(NULL == inet_ntop(c_af, + &(GET_IN_type_ADDR(&(argSock->nodes->current_list->value),6)), + tempAddr, BUF_SIZE /*(argSock->nodes->current_list->value).addr_len*/)){ + fprintf(stderr, "error inet_ntop v6 :errno=%d\n",errno); + } + } + + if(sendto(fds[(c_af==AF_INET6)].fd, + buf, nread, + /*msgRet, len_msgRet,*/ + 0, + (struct sockaddr*)&((argSock->nodes->current_list->value).addr), + (argSock->nodes->current_list->value).addr_len) != + nread + /*len_msgRet*/ + ){ + fprintf(stderr, "Error sending response to %s\n",tempAddr); + }else + printf("sending response to %s\n",tempAddr); + } + } + } +// printf("nread = %ld: buf=%s\nlen_buf=%ld\ncmp=%d\n",nread,buf,strlen(buf),strncmp(buf,"SHUTDOWN SERVER",15)); + if(strncmp(buf,"SHUTDOWN SERVER",15) == 0){ + printf("leave poll thread, bye!\n"); + return NULL; + } + } +} +#define str(x) # x +#define xstr(x) str(x) + + +void *threadFuncSend(void *arg){ + struct argdst * dstarg = (struct argdst*)arg; + + int socketDescriptor, status; + unsigned int msgLength; + struct addrinfo hints, *serverInfo, *p; + struct timeval timeValue; + fd_set readSetFD; + char msg[BUF_SIZE];//, serverPort[PORT_ARRAY_SIZE]; + bool sockSuccess = false; + + /* + puts("Entrez le nom du serveur ou son adresse IP : "); + memset(msg, 0, sizeof msg); + scanf("%s"xstr(BUF_SIZE)"s",msg); + + puts("Entrez le numéro de port du serveur : "); + memset(serverPort, 0, sizeof serverPort); + scanf("%s"xstr(MAX_PORT)"s",serverPort); + */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + + if((status = getaddrinfo(dstarg->addrStr, dstarg->port, &hints, &serverInfo)) != 0){ + fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(status)); + exit(EXIT_FAILURE); + } + + p = serverInfo; + while((p!=NULL) && !sockSuccess){ + if(p->ai_family == AF_INET) + puts("Open IPv4 socket"); + else + puts("Open IPv6 socket"); + + if((socketDescriptor = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){ + perror("socket:"); + sockSuccess = false; // echec ouverture du socket + p = p->ai_next; + } + else + sockSuccess = true; + } + + freeaddrinfo(serverInfo); + + if(p==NULL){ + fputs("Creation de socket impossible", stderr); + return NULL; + } + + puts("\n Entrez quelques caractères au clavier."); + puts("Le serveur les modifiera et les renvera."); + puts("Pour sortir, entrez une ligne avec le caractère '.' uniquement."); + + puts("Saisie du message : "); + memset(msg, 0, sizeof msg); + scanf(" %"xstr(BUF_SIZE)"[^\n]%*c", msg); + + while(strcmp(msg, ".")){ + if((msgLength = strlen(msg)) > 0 ){ + if(sendto(socketDescriptor, msg, msgLength, 0, + p->ai_addr, p->ai_addrlen) == -1){ + perror("sendto:"); + close(socketDescriptor); + exit(EXIT_FAILURE); + } + + FD_ZERO(&readSetFD); + FD_SET(socketDescriptor, &readSetFD); + timeValue.tv_sec = 1; + timeValue.tv_usec = 0; + + if(select(socketDescriptor +1, &readSetFD, NULL,NULL, &timeValue)){ + memset(msg, 0, sizeof msg); + if(recv(socketDescriptor, msg, sizeof msg, 0) == -1){ + perror("recv:"); + close(socketDescriptor); + exit(EXIT_FAILURE); + } + + printf("Message traité : %s\n", msg); + if(strcmp(msg,"SHUTDOWN SERVER")==0) + break; + } + else{ + puts("Pas de réponse dans la seconde."); + } + + } + puts("Saisie du message : "); + memset(msg, 0, sizeof msg); + scanf(" %"xstr(BUF_SIZE)"[^\n]%*c", msg); + } + + close(socketDescriptor); + + + + + return NULL; + +} diff --git a/y_socket_t/test/is_good.c b/y_socket_t/test/is_good.c index 71d41bf..a9dd927 100644 --- a/y_socket_t/test/is_good.c +++ b/y_socket_t/test/is_good.c @@ -75,6 +75,28 @@ TEST(equalNode){ } +TEST(equalNode6){ + y_NODE_T nA, nB; + init_len_y_NODE_T(&nA); + init_len_y_NODE_T(&nB); + + nA.addr.ss_family=AF_INET6; + nB.addr.ss_family=AF_INET6; + + //((struct sockaddr_in*)&(nA.addr))->sin_addr.s_addr = inet_addr("192.168.1.2"); + //((struct sockaddr_in*)&(nB.addr))->sin_addr.s_addr = inet_addr("192.168.1.2"); + + inet_pton(AF_INET6, "::1", &(GET_IN_type_ADDR(&(nA.addr),6))); + inet_pton(AF_INET6, "::1", &(GET_IN_type_ADDR(&(nB.addr),6))); + + + EXPECT_EQ(0, y_NODE_T_cmp(nA,nB)); + inet_pton(AF_INET6, "::", &(GET_IN_type_ADDR(&(nB.addr),6))); + LOG("diff = %d\n", y_NODE_T_cmp(nA,nB)); + + +} + TEST(searchNode){ @@ -125,7 +147,28 @@ TEST(searchNode){ } +TEST(pollThread){ + struct y_socket_t *argS=y_socket_create("1600"); + pthread_t pollTh; + pthread_create(&pollTh, NULL, y_pollSocketsFunc, (void*)argS); + +/* + struct argdst dstarg={ + .port="1600", + .addrStr="::1", + }; + pthread_t cliTh; + pthread_create(&cliTh, NULL, threadFuncSend, (void*)&dstarg); + + pthread_join(cliTh, NULL); +*/ + + pthread_join(pollTh, NULL); + + y_socket_free(argS); + +} int main(int argc, char **argv){