-
+ 1CE3FCE5802BD1C1DF524A6C3E1C9B2A45C62535D72602BE8C7EF81E47CC543CE4D150AE2F1DCA99D7B77F64209D2F47789AE08DEE79473009F0531DF1B77AA0udp/libudp/unix_udp.c(0 . 0)(1 . 139)
642 /*
643 ------------------------------------------------------------------------------
644 ------------------------------------------------------------------------------
645 -- This file is part of 'UDP', a datagram sockets library. --
646 -- --
647 -- (C) 2018 Stanislav Datskovskiy ( www.loper-os.org ) --
648 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html --
649 -- --
650 -- You do not have, nor can you ever acquire the right to use, copy or --
651 -- distribute this software ; Should you use this software for any purpose, --
652 -- or copy and distribute it to anyone or in any manner, you are breaking --
653 -- the laws of whatever soi-disant jurisdiction, and you promise to --
654 -- continue doing so for the indefinite future. In any case, please --
655 -- always : read and understand any software ; verify any PGP signatures --
656 -- that you use - for any purpose. --
657 -- --
658 -- See also http://trilema.com/2015/a-new-software-licensing-paradigm . --
659 ------------------------------------------------------------------------------
660 ------------------------------------------------------------------------------
661 */
662
663 #include <string.h>
664 #include <unistd.h>
665 #include <arpa/inet.h>
666 #include <netinet/in.h>
667 #include <sys/types.h>
668 #include <sys/socket.h>
669
670
671 /* Socket state representation: */
672 typedef struct _UDP_Socket {
673 struct sockaddr_in sa_local;
674 int sock;
675 } UDP_Socket;
676
677
678 /* local-endian ip to string conversion */
679 void unix_udp_ip_to_string(uint32_t ip, char *buf, uint32_t buf_size) {
680 struct in_addr addr;
681 addr.s_addr = htonl(ip);
682 char *txt = inet_ntoa(addr);
683 strncpy(buf, txt, buf_size);
684 }
685
686
687 /* string to local-endian ip conversion */
688 int unix_udp_string_to_ip(char *buf, uint32_t *ip) {
689 struct in_addr addr;
690 if (inet_aton(buf, &addr) <= 0)
691 return -1;
692 *ip = ntohl(addr.s_addr);
693 return 0;
694 }
695
696
697 int unix_udp_socket_open(UDP_Socket *S,
698 uint32_t local_ip, uint16_t local_port) {
699 /* Open the socket FD: */
700 if ((S->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
701 return -1;
702 }
703
704 memset(&S->sa_local, 0, sizeof(struct sockaddr_in));
705
706 /* Set up emitter endpoint, converting from local endianness: */
707 S->sa_local.sin_family = AF_INET;
708 S->sa_local.sin_addr.s_addr = htonl(local_ip);
709 S->sa_local.sin_port = htons(local_port);
710
711 /* Cure the asinine linuxism where dead sockets interfere with living: */
712 int one = 1;
713 if (setsockopt(S->sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
714 close(S->sock);
715 return -2;
716 }
717
718 /* Bind the socket */
719 if (bind(S->sock,
720 (struct sockaddr *)&(S->sa_local), sizeof(S->sa_local)) < 0) {
721 close(S->sock);
722 return -3;
723 }
724
725 /* ok */
726 return 0;
727 }
728
729
730 void unix_udp_socket_close(UDP_Socket *S) {
731 close(S->sock);
732 }
733
734
735 int unix_udp_socket_transmit(UDP_Socket *S,
736 uint32_t remote_ip, uint16_t remote_port,
737 uint8_t *payload, uint32_t payload_len) {
738 int bytes_sent = 0;
739 struct sockaddr_in remote_addr;
740 memset((char *)&remote_addr, 0, sizeof(remote_addr));
741
742 /* Set up dest endpoint, converting from local endianness: */
743 remote_addr.sin_family = AF_INET;
744 remote_addr.sin_port = htons(remote_port);
745 remote_addr.sin_addr.s_addr = htonl(remote_ip);
746
747 /* Transmit Datagram */
748 bytes_sent = sendto(S->sock, payload, payload_len,
749 0, /* no flags */
750 (struct sockaddr*)&remote_addr,
751 sizeof(remote_addr));
752 if (bytes_sent <= 0)
753 return -1;
754
755 return bytes_sent;
756 }
757
758
759 int unix_udp_socket_receive(UDP_Socket *S,
760 uint32_t *origin_ip, uint16_t *origin_port,
761 uint8_t *payload, uint32_t payload_len) {
762 int bytes_received = 0;
763 struct sockaddr_in orig_addr;
764 socklen_t orig_addr_len = sizeof(orig_addr);
765 memset((char *)&orig_addr, 0, sizeof(orig_addr));
766
767 /* Receive Datagram (blocking!) */
768 bytes_received = recvfrom(S->sock, payload, payload_len,
769 0, /* no flags */
770 (struct sockaddr *)&orig_addr,
771 &orig_addr_len);
772
773 if (bytes_received < 0) return -1;
774
775 /* Save the originator's endpoint in ~local~ endianness */
776 *origin_ip = ntohl(orig_addr.sin_addr.s_addr);
777 *origin_port = ntohs(orig_addr.sin_port);
778
779 return bytes_received;
780 }