rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (c) 2014 Brian Swetland |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining |
| 5 | * a copy of this software and associated documentation files |
| 6 | * (the "Software"), to deal in the Software without restriction, |
| 7 | * including without limitation the rights to use, copy, modify, merge, |
| 8 | * publish, distribute, sublicense, and/or sell copies of the Software, |
| 9 | * and to permit persons to whom the Software is furnished to do so, |
| 10 | * subject to the following conditions: |
| 11 | * |
| 12 | * The above copyright notice and this permission notice shall be |
| 13 | * included in all copies or substantial portions of the Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 22 | */ |
| 23 | |
| 24 | #include <stdio.h> |
| 25 | #include <stdlib.h> |
| 26 | #include <string.h> |
| 27 | #include <unistd.h> |
| 28 | |
| 29 | #include "network.h" |
| 30 | |
| 31 | in_addr_t lookup_hostname(const char *hostname) { |
| 32 | int err; |
| 33 | struct addrinfo *info, *temp; |
| 34 | in_addr_t addr = 0; |
| 35 | |
| 36 | struct addrinfo hints; |
| 37 | memset(&hints, 0, sizeof(hints)); |
| 38 | hints.ai_family = AF_INET; |
| 39 | hints.ai_socktype = SOCK_STREAM; |
| 40 | |
| 41 | err = getaddrinfo(hostname, NULL, &hints, &info); |
| 42 | if (err < 0) { |
| 43 | printf("getaddrinfo() returns %d, error '%s'\n", err, gai_strerror(err)); |
| 44 | return 0; |
| 45 | } |
| 46 | |
| 47 | for (temp = info; temp; temp = temp->ai_next) { |
| 48 | // printf("flags 0x%x, family %d, socktype %d, protocol %d, addrlen %d\n", |
| 49 | // temp->ai_flags, temp->ai_family, temp->ai_socktype, temp->ai_protocol, temp->ai_addrlen); |
| 50 | |
| 51 | if (temp->ai_family == AF_INET && temp->ai_protocol == IPPROTO_TCP) { |
| 52 | struct sockaddr_in *sa = (struct sockaddr_in *)temp->ai_addr; |
| 53 | // printf("port %d, addr 0x%x\n", sa->sin_port, sa->sin_addr.s_addr); |
| 54 | addr = sa->sin_addr.s_addr; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | freeaddrinfo(info); |
| 59 | |
| 60 | return addr; |
| 61 | } |
| 62 | |
| 63 | static int inet_listen(in_addr_t addr, int type, unsigned port, int shared) { |
| 64 | struct sockaddr_in sa; |
| 65 | int s; |
| 66 | if ((s = socket(AF_INET, type, 0)) < 0) { |
| 67 | return -1; |
| 68 | } |
| 69 | if (shared) { |
| 70 | int opt = 1; |
| 71 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); |
| 72 | //setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)); |
| 73 | } |
| 74 | memset(&sa, 0, sizeof(sa)); |
| 75 | sa.sin_family = AF_INET; |
| 76 | sa.sin_port = htons(port); |
| 77 | sa.sin_addr.s_addr = addr; |
| 78 | if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { |
| 79 | close(s); |
| 80 | return -1; |
| 81 | } |
| 82 | return s; |
| 83 | } |
| 84 | |
| 85 | static int inet_connect(in_addr_t addr, int type, unsigned port) { |
| 86 | struct sockaddr_in sa; |
| 87 | int s; |
| 88 | if ((s = socket(AF_INET, type, 0)) < 0) { |
| 89 | return -1; |
| 90 | } |
| 91 | if (addr == 0xFFFFFFFF) { |
| 92 | int opt = 1; |
| 93 | setsockopt(s, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)); |
| 94 | } |
| 95 | memset(&sa, 0, sizeof(sa)); |
| 96 | sa.sin_family = AF_INET; |
| 97 | sa.sin_port = htons(port); |
| 98 | sa.sin_addr.s_addr = addr; |
| 99 | if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { |
| 100 | close(s); |
| 101 | return -1; |
| 102 | } |
| 103 | return s; |
| 104 | } |
| 105 | |
| 106 | int udp_listen(in_addr_t addr, unsigned port, int shared) { |
| 107 | return inet_listen(addr, SOCK_DGRAM, port, shared); |
| 108 | } |
| 109 | |
| 110 | int udp_connect(in_addr_t addr, unsigned port) { |
| 111 | return inet_connect(addr, SOCK_DGRAM, port); |
| 112 | } |
| 113 | |
| 114 | int tcp_listen(in_addr_t addr, unsigned port) { |
| 115 | return inet_listen(addr, SOCK_STREAM, port, 0); |
| 116 | } |
| 117 | |
| 118 | int tcp_connect(in_addr_t addr, unsigned port) { |
| 119 | return inet_connect(addr, SOCK_STREAM, port); |
| 120 | } |
| 121 | |
| 122 | // vim: noexpandtab |