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_genesis 42 strncpy(buf, txt, buf_size);
udp_genesis 43 }
udp_errata_asciil... 44 /* Should be replaced with native routine */
udp_genesis 45
udp_genesis 46
udp_genesis 47 /* string to local-endian ip conversion */
udp_genesis 48 int unix_udp_string_to_ip(char *buf, uint32_t *ip) {
udp_genesis 49 struct in_addr addr;
udp_genesis 50 if (inet_aton(buf, &addr) <= 0)
udp_genesis 51 return -1;
udp_genesis 52 *ip = ntohl(addr.s_addr);
udp_genesis 53 return 0;
udp_genesis 54 }
udp_errata_asciil... 55 /* Should be replaced with native routine */
udp_genesis 56
udp_genesis 57
udp_genesis 58 int unix_udp_socket_open(UDP_Socket *S,
udp_genesis 59 uint32_t local_ip, uint16_t local_port) {
udp_genesis 60 /* Open the socket FD: */
udp_genesis 61 if ((S->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
udp_genesis 62 return -1;
udp_genesis 63 }
udp_genesis 64
udp_genesis 65 memset(&S->sa_local, 0, sizeof(struct sockaddr_in));
udp_genesis 66
udp_genesis 67 /* Set up emitter endpoint, converting from local endianness: */
udp_genesis 68 S->sa_local.sin_family = AF_INET;
udp_genesis 69 S->sa_local.sin_addr.s_addr = htonl(local_ip);
udp_genesis 70 S->sa_local.sin_port = htons(local_port);
udp_genesis 71
udp_genesis 72 /* Cure the asinine linuxism where dead sockets interfere with living: */
udp_genesis 73 int one = 1;
udp_genesis 74 if (setsockopt(S->sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
udp_genesis 75 close(S->sock);
udp_genesis 76 return -2;
udp_genesis 77 }
udp_genesis 78
udp_genesis 79 /* Bind the socket */
udp_genesis 80 if (bind(S->sock,
udp_genesis 81 (struct sockaddr *)&(S->sa_local), sizeof(S->sa_local)) < 0) {
udp_genesis 82 close(S->sock);
udp_genesis 83 return -3;
udp_genesis 84 }
udp_genesis 85
udp_genesis 86 /* ok */
udp_genesis 87 return 0;
udp_genesis 88 }
udp_genesis 89
udp_genesis 90
udp_genesis 91 void unix_udp_socket_close(UDP_Socket *S) {
udp_genesis 92 close(S->sock);
udp_genesis 93 }
udp_genesis 94
udp_genesis 95
udp_genesis 96 int unix_udp_socket_transmit(UDP_Socket *S,
udp_genesis 97 uint32_t remote_ip, uint16_t remote_port,
udp_genesis 98 uint8_t *payload, uint32_t payload_len) {
udp_genesis 99 int bytes_sent = 0;
udp_genesis 100 struct sockaddr_in remote_addr;
udp_genesis 101 memset((char *)&remote_addr, 0, sizeof(remote_addr));
udp_genesis 102
udp_genesis 103 /* Set up dest endpoint, converting from local endianness: */
udp_genesis 104 remote_addr.sin_family = AF_INET;
udp_genesis 105 remote_addr.sin_port = htons(remote_port);
udp_genesis 106 remote_addr.sin_addr.s_addr = htonl(remote_ip);
udp_genesis 107
udp_genesis 108 /* Transmit Datagram */
udp_genesis 109 bytes_sent = sendto(S->sock, payload, payload_len,
udp_genesis 110 0, /* no flags */
udp_genesis 111 (struct sockaddr*)&remote_addr,
udp_genesis 112 sizeof(remote_addr));
udp_genesis 113 if (bytes_sent <= 0)
udp_genesis 114 return -1;
udp_genesis 115
udp_genesis 116 return bytes_sent;
udp_genesis 117 }
udp_genesis 118
udp_genesis 119
udp_genesis 120 int unix_udp_socket_receive(UDP_Socket *S,
udp_genesis 121 uint32_t *origin_ip, uint16_t *origin_port,
udp_genesis 122 uint8_t *payload, uint32_t payload_len) {
udp_genesis 123 int bytes_received = 0;
udp_genesis 124 struct sockaddr_in orig_addr;
udp_genesis 125 socklen_t orig_addr_len = sizeof(orig_addr);
udp_genesis 126 memset((char *)&orig_addr, 0, sizeof(orig_addr));
udp_genesis 127
udp_genesis 128 /* Receive Datagram (blocking!) */
udp_genesis 129 bytes_received = recvfrom(S->sock, payload, payload_len,
udp_genesis 130 0, /* no flags */
udp_genesis 131 (struct sockaddr *)&orig_addr,
udp_genesis 132 &orig_addr_len);
udp_genesis 133
udp_genesis 134 if (bytes_received < 0) return -1;
udp_genesis 135
udp_genesis 136 /* Save the originator's endpoint in ~local~ endianness */
udp_genesis 137 *origin_ip = ntohl(orig_addr.sin_addr.s_addr);
udp_genesis 138 *origin_port = ntohs(orig_addr.sin_port);
udp_genesis 139
udp_genesis 140 return bytes_received;
udp_genesis 141 }