raw
udp_genesis             1 /*
udp_genesis 2 ------------------------------------------------------------------------------
udp_genesis 3 ------------------------------------------------------------------------------
udp_genesis 4 -- This file is part of 'UDP', a datagram sockets library. --
udp_genesis 5 -- --
udp_genesis 6 -- (C) 2018 Stanislav Datskovskiy ( www.loper-os.org ) --
udp_genesis 7 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html --
udp_genesis 8 -- --
udp_genesis 9 -- You do not have, nor can you ever acquire the right to use, copy or --
udp_genesis 10 -- distribute this software ; Should you use this software for any purpose, --
udp_genesis 11 -- or copy and distribute it to anyone or in any manner, you are breaking --
udp_genesis 12 -- the laws of whatever soi-disant jurisdiction, and you promise to --
udp_genesis 13 -- continue doing so for the indefinite future. In any case, please --
udp_genesis 14 -- always : read and understand any software ; verify any PGP signatures --
udp_genesis 15 -- that you use - for any purpose. --
udp_genesis 16 -- --
udp_genesis 17 -- See also http://trilema.com/2015/a-new-software-licensing-paradigm . --
udp_genesis 18 ------------------------------------------------------------------------------
udp_genesis 19 ------------------------------------------------------------------------------
udp_genesis 20 */
udp_genesis 21
udp_genesis 22 #include <string.h>
udp_genesis 23 #include <unistd.h>
udp_genesis 24 #include <arpa/inet.h>
udp_genesis 25 #include <netinet/in.h>
udp_genesis 26 #include <sys/types.h>
udp_genesis 27 #include <sys/socket.h>
udp_genesis 28
udp_genesis 29
udp_genesis 30 /* Socket state representation: */
udp_genesis 31 typedef struct _UDP_Socket {
udp_genesis 32 struct sockaddr_in sa_local;
udp_genesis 33 int sock;
udp_genesis 34 } UDP_Socket;
udp_genesis 35
udp_genesis 36
udp_genesis 37 /* local-endian ip to string conversion */
udp_genesis 38 void unix_udp_ip_to_string(uint32_t ip, char *buf, uint32_t buf_size) {
udp_genesis 39 struct in_addr addr;
udp_genesis 40 addr.s_addr = htonl(ip);
udp_genesis 41 char *txt = inet_ntoa(addr);
udp_fix_ip_nullchars 42 /* Given IP might be shorter than buf_size so don't copy blindly. */
udp_fix_ip_nullchars 43 int len = strlen(txt);
udp_fix_ip_nullchars 44 /* ONTH don't ever copy more than buf_size either */
udp_fix_ip_nullchars 45 if (len > buf_size)
udp_fix_ip_nullchars 46 len = buf_size;
udp_fix_ip_nullchars 47 strncpy(buf, txt, len);
udp_genesis 48 }
udp_errata_asciil... 49 /* Should be replaced with native routine */
udp_genesis 50
udp_genesis 51
udp_genesis 52 /* string to local-endian ip conversion */
udp_genesis 53 int unix_udp_string_to_ip(char *buf, uint32_t *ip) {
udp_genesis 54 struct in_addr addr;
udp_genesis 55 if (inet_aton(buf, &addr) <= 0)
udp_genesis 56 return -1;
udp_genesis 57 *ip = ntohl(addr.s_addr);
udp_genesis 58 return 0;
udp_genesis 59 }
udp_errata_asciil... 60 /* Should be replaced with native routine */
udp_genesis 61
udp_genesis 62
udp_genesis 63 int unix_udp_socket_open(UDP_Socket *S,
udp_genesis 64 uint32_t local_ip, uint16_t local_port) {
udp_genesis 65 /* Open the socket FD: */
udp_genesis 66 if ((S->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
udp_genesis 67 return -1;
udp_genesis 68 }
udp_genesis 69
udp_genesis 70 memset(&S->sa_local, 0, sizeof(struct sockaddr_in));
udp_genesis 71
udp_genesis 72 /* Set up emitter endpoint, converting from local endianness: */
udp_genesis 73 S->sa_local.sin_family = AF_INET;
udp_genesis 74 S->sa_local.sin_addr.s_addr = htonl(local_ip);
udp_genesis 75 S->sa_local.sin_port = htons(local_port);
udp_genesis 76
udp_genesis 77 /* Cure the asinine linuxism where dead sockets interfere with living: */
udp_genesis 78 int one = 1;
udp_genesis 79 if (setsockopt(S->sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
udp_genesis 80 close(S->sock);
udp_genesis 81 return -2;
udp_genesis 82 }
udp_genesis 83
udp_genesis 84 /* Bind the socket */
udp_genesis 85 if (bind(S->sock,
udp_genesis 86 (struct sockaddr *)&(S->sa_local), sizeof(S->sa_local)) < 0) {
udp_genesis 87 close(S->sock);
udp_genesis 88 return -3;
udp_genesis 89 }
udp_genesis 90
udp_genesis 91 /* ok */
udp_genesis 92 return 0;
udp_genesis 93 }
udp_genesis 94
udp_genesis 95
udp_genesis 96 void unix_udp_socket_close(UDP_Socket *S) {
udp_genesis 97 close(S->sock);
udp_genesis 98 }
udp_genesis 99
udp_genesis 100
udp_genesis 101 int unix_udp_socket_transmit(UDP_Socket *S,
udp_genesis 102 uint32_t remote_ip, uint16_t remote_port,
udp_genesis 103 uint8_t *payload, uint32_t payload_len) {
udp_genesis 104 int bytes_sent = 0;
udp_genesis 105 struct sockaddr_in remote_addr;
udp_genesis 106 memset((char *)&remote_addr, 0, sizeof(remote_addr));
udp_genesis 107
udp_genesis 108 /* Set up dest endpoint, converting from local endianness: */
udp_genesis 109 remote_addr.sin_family = AF_INET;
udp_genesis 110 remote_addr.sin_port = htons(remote_port);
udp_genesis 111 remote_addr.sin_addr.s_addr = htonl(remote_ip);
udp_genesis 112
udp_genesis 113 /* Transmit Datagram */
udp_genesis 114 bytes_sent = sendto(S->sock, payload, payload_len,
udp_genesis 115 0, /* no flags */
udp_genesis 116 (struct sockaddr*)&remote_addr,
udp_genesis 117 sizeof(remote_addr));
udp_genesis 118 if (bytes_sent <= 0)
udp_genesis 119 return -1;
udp_genesis 120
udp_genesis 121 return bytes_sent;
udp_genesis 122 }
udp_genesis 123
udp_genesis 124
udp_genesis 125 int unix_udp_socket_receive(UDP_Socket *S,
udp_genesis 126 uint32_t *origin_ip, uint16_t *origin_port,
udp_genesis 127 uint8_t *payload, uint32_t payload_len) {
udp_genesis 128 int bytes_received = 0;
udp_genesis 129 struct sockaddr_in orig_addr;
udp_genesis 130 socklen_t orig_addr_len = sizeof(orig_addr);
udp_genesis 131 memset((char *)&orig_addr, 0, sizeof(orig_addr));
udp_genesis 132
udp_genesis 133 /* Receive Datagram (blocking!) */
udp_genesis 134 bytes_received = recvfrom(S->sock, payload, payload_len,
udp_genesis 135 0, /* no flags */
udp_genesis 136 (struct sockaddr *)&orig_addr,
udp_genesis 137 &orig_addr_len);
udp_genesis 138
udp_genesis 139 if (bytes_received < 0) return -1;
udp_genesis 140
udp_genesis 141 /* Save the originator's endpoint in ~local~ endianness */
udp_genesis 142 *origin_ip = ntohl(orig_addr.sin_addr.s_addr);
udp_genesis 143 *origin_port = ntohs(orig_addr.sin_port);
udp_genesis 144
udp_genesis 145 return bytes_received;
udp_genesis 146 }