udp.c

来自「飞鸽传书的linux源代码」· C语言 代码 · 共 373 行

C
373
字号
#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);}intudp_enable_broadcast(const udp_con_t *con){  int rc;  int flag;  if (!con)     return -EINVAL;  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;  }  return 0;}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_disable_broadcast(const udp_con_t *con){  int rc;  int flag;  if (!con)     return -EINVAL;  flag=0;  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;  }  return 0;}intudp_recv_message(const udp_con_t *con,char **msg,size_t *len){  ssize_t recv_len;  char recv_buf[_MSG_BUF_SIZE];  int old_fd_flags;  int rc;  int ret_code=0;  struct addrinfo *info;  if ( (!con) || (!msg) || (!len) )    return -EINVAL;  g_assert(*msg==NULL);    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:  return ret_code;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?