📄 udp.c
字号:
#include "common.h"#include <stddef.h>#include <netdb.h>#include <pwd.h>#include <errno.h>#include <time.h>#include <unistd.h>#include <fcntl.h>#include <ctype.h>#include <sys/wait.h>#include <sys/mman.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/param.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <string.h>intinternal_realloc(void **ptr,size_t new_size,size_t old_size){ void *orig_ptr; ssize_t clr_len; if (!ptr) return -1; orig_ptr=*ptr; *ptr=realloc(*ptr, new_size); if (!(*ptr)) { *ptr=orig_ptr; return -2; } clr_len=new_size - old_size; if (clr_len > 0) memset( ((*ptr)+old_size),0,clr_len); return 0;}const char *udp_get_peeraddr(const udp_con_t *con){ int rc; struct addrinfo *info; g_assert(con); info=con->server_info; g_assert(info); rc=getnameinfo(info->ai_addr, info->ai_addrlen, (char *)con->peer, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); g_assert (!rc); dbg_out("get peer host:%s (family,type,proto)=(%d,%d,%d)\n", con->peer, info->ai_family, info->ai_socktype, info->ai_protocol); return (const char *)con->peer;}int udp_setup_server(udp_con_t *con,int port,int family){ int rc; int soc; char reuse=1; struct addrinfo *info; if (!con) return -EINVAL; memset(con,0,sizeof(udp_con_t)); rc=setup_addr_info(&info, NULL,port,SOCK_DGRAM,family); if (rc<0) return rc; rc=socket(info->ai_family,info->ai_socktype,info->ai_protocol); if (rc<0) goto err_out; soc=rc;#ifdef IPV6_V6ONLY if (info->ai_family == AF_INET6) { int v6only=1; rc=setsockopt(soc,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&v6only,sizeof(v6only)); if (rc) { goto err_out; } }#endif /* IPV6_V6ONLY */ rc=bind(soc,info->ai_addr,info->ai_addrlen); if (rc<0) goto err_out; con->client_info=info; con->soc=soc; con->family=family; con->port=port; /* *allocate server side */ rc=setup_addr_info(&info, NULL,port,SOCK_DGRAM,family); if (rc<0) goto free_client_out; con->server_info=info; return 0; free_client_out: if (con->client_info) freeaddrinfo(con->client_info); con->client_info=NULL; err_out: err_out("Error:%s (%d)\n",strerror(errno),errno); if (info) freeaddrinfo(info); exit(rc); return rc;}intudp_setup_client(udp_con_t *con,const char *hostname, int port,int family){ int soc; int rc; struct addrinfo *info=NULL; if (!hostname) return -EINVAL; rc=setup_addr_info(&info, hostname,port,SOCK_DGRAM,family); if (rc<0) goto err_out; rc=socket(info->ai_family,info->ai_socktype,info->ai_protocol); if (rc<0) goto free_out; soc=rc;#ifdef IPV6_V6ONLY if (info->ai_family == AF_INET6) { int v6only=1; rc=setsockopt(soc,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&v6only,sizeof(v6only)); if (rc) { goto err_out; } }#endif /* IPV6_V6ONLY */ con->server_info=info; con->soc=soc; con->family=family; con->port=port; return 0; free_out: if (info) freeaddrinfo(info); err_out: err_out("Error: %s (%d)\n",strerror(errno),errno); return rc;}intudp_release_connection(udp_con_t *con) { if (!con) return -EINVAL; dbg_out("Close udp sock:%d\n",con->soc); if (con->client_info) freeaddrinfo(con->client_info); if (con->server_info) freeaddrinfo(con->server_info); con->client_info=NULL; con->server_info=NULL; close(con->soc); return 0;}intudp_send_message(const udp_con_t *con,const char *ipaddr,int port, const char *msg,size_t len){ int rc; struct addrinfo *info=NULL; if ((!con) || (!ipaddr) || (!msg) ) return -EINVAL; dbg_out("send [addr:%s port:%d]:\n %s\n",ipaddr,port,msg); rc=setup_addr_info(&info,ipaddr,port,SOCK_DGRAM,con->family); if (rc<0) goto err_out; rc=sendto(con->soc,msg,len,0,info->ai_addr,info->ai_addrlen); err_out: if (info) freeaddrinfo(info); return rc;}intudp_send_peer(const udp_con_t *con,const char *msg,size_t len){ int rc; struct addrinfo *info; if ((!con) || (!msg) ) return -EINVAL; dbg_out("send peer:%s\n",msg); info=con->server_info; g_assert(info); rc=sendto(con->soc,msg,len,0,info->ai_addr,info->ai_addrlen); return rc;}intudp_send_broadcast_with_addr(const udp_con_t *con,const char *bcast,const char *msg,size_t len){ int rc; struct addrinfo *info=NULL; if ((!con) || (!msg) ) return -EINVAL; udp_enable_broadcast(con); dbg_out("%s\n",msg); if (!bcast) { switch(con->family) { case PF_INET6: rc=setup_addr_info(&info,"ff02::1",con->port,SOCK_DGRAM,con->family); break; default: rc=setup_addr_info(&info,"255.255.255.255",con->port,SOCK_DGRAM,con->family); break; } } else { rc=setup_addr_info(&info,bcast,con->port,SOCK_DGRAM,con->family); } if (rc<0) goto err_out; rc=sendto(con->soc,msg,len,0,info->ai_addr,info->ai_addrlen); err_out: if (info) freeaddrinfo(info); return rc;}intudp_send_broadcast(const udp_con_t *con,const char *msg,size_t len){ return udp_send_broadcast_with_addr(con,NULL,msg,len);}static intudp_set_buffer(const udp_con_t *con){ int rc; int size=0; if (!con) return -EINVAL; return sock_set_buffer(con->soc);;}intudp_enable_broadcast(const udp_con_t *con){ int rc; int flag; int confirm,confirm_len; if (!con) return -EINVAL; dbg_out("Here\n"); flag=1; rc=setsockopt(con->soc, SOL_SOCKET, SO_BROADCAST, (void*)&flag, sizeof(int)); if (rc<0) { err_out("Can not set broad cast:%s(%d)\n",strerror(errno),errno); return -errno; } confirm=0; confirm_len=sizeof(confirm); rc=getsockopt(con->soc, SOL_SOCKET, SO_BROADCAST, (void*)&confirm, &confirm_len); if (rc<0) { err_out("Can not get broad cast:%s(%d)\n",strerror(errno),errno); return -errno; } if (confirm) dbg_out("Broadcat is set\n"); else err_out("Can not set broad cast:%s(%d)\n",strerror(errno),errno); return 0;}intudp_disable_broadcast(const udp_con_t *con){ int rc; int flag; if (!con) return -EINVAL; dbg_out("Here\n"); flag=0; rc=setsockopt(con->soc, SOL_SOCKET, SO_BROADCAST, (void*)&flag, sizeof(int)); if (rc<0) { err_out("Can not unset broad cast:%s(%d)\n",strerror(errno),errno); return -errno; } return 0;}intudp_recv_message(const udp_con_t *con,char **msg,size_t *len){ ssize_t recv_len; char *recv_buf=NULL; int old_fd_flags; int rc; int ret_code=0; struct addrinfo *info; if ( (!con) || (!msg) || (!len) ) return -EINVAL; g_assert(*msg==NULL); recv_buf=malloc(_MSG_BUF_SIZE); if (!recv_buf) return -ENOMEM; rc=udp_set_buffer(con); if (rc<0) goto err_out; rc=udp_enable_broadcast(con); if (rc<0) goto err_out; info=con->server_info; /* * 空読みする */ recv_len=recvfrom(con->soc,recv_buf,_MSG_BUF_SIZE,(MSG_PEEK|MSG_DONTWAIT),info->ai_addr,&(info->ai_addrlen)); if (recv_len<=0) { err_out("%s(errno:%d)\n",strerror(errno),errno); ret_code=-errno; goto err_out; } dbg_out("read:%d %s\n",recv_len,recv_buf); /* * バッファに読み込む */ recv_len=recvfrom(con->soc,recv_buf,recv_len,MSG_DONTWAIT,info->ai_addr,&(info->ai_addrlen)); if (recv_len<0) { err_out("%s(errno:%d)\n",strerror(errno),errno); ret_code=-errno; goto err_out; } /* * バッファ獲得 */ g_assert(*msg==NULL); *msg=malloc(recv_len); if (!(*msg)) goto err_out; dbg_out("copy:%d %s\n",recv_len,recv_buf); *len=recv_len; memmove(*msg,recv_buf,recv_len); /* 内容をコピー */err_out: if (recv_buf) free(recv_buf); return ret_code;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -