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