void forwarder_deinit(forwarder_t *f) { su_root_unregister(f->f_pr->pr_root, f->f_wait, NULL, f); su_wait_destroy(f->f_wait); su_root_unregister(f->f_pr->pr_root, f->f_wait + 1, NULL, f); su_wait_destroy(f->f_wait + 1); if (f->f_socket != INVALID_SOCKET) su_close(f->f_socket), f->f_socket = INVALID_SOCKET; if (f->f_buf) su_free(f->f_pr->pr_home, f->f_buf), f->f_buf = NULL; }
int tport_ws_init_secondary(tport_t *self, int socket, int accepted, char const **return_reason) { int one = 1; tport_ws_primary_t *wspri = (tport_ws_primary_t *)self->tp_pri; tport_ws_t *wstp = (tport_ws_t *)self; self->tp_has_connection = 1; if (setsockopt(socket, SOL_TCP, TCP_NODELAY, (void *)&one, sizeof one) == -1) return *return_reason = "TCP_NODELAY", -1; #if defined(SO_KEEPALIVE) setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof one); #endif one = 30; #if defined(TCP_KEEPIDLE) setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, (void *)&one, sizeof one); #endif #if defined(TCP_KEEPINTVL) setsockopt(socket, SOL_TCP, TCP_KEEPINTVL, (void *)&one, sizeof one); #endif if (!accepted) tport_ws_setsndbuf(socket, 64 * 1024); if ( wspri->ws_secure ) wstp->ws_secure = 1; memset(&wstp->ws, 0, sizeof(wstp->ws)); if (ws_init(&wstp->ws, socket, wstp->ws_secure ? wspri->ssl_ctx : NULL, 0) < 0) { ws_destroy(&wstp->ws); su_close(socket); wstp->ws_initialized = -1; return *return_reason = "WS_INIT", -1; } wstp->ws_initialized = 1; self->tp_pre_framed = 1; return 0; }
/** Initialize logging. */ int tport_open_log(tport_master_t *mr, tagi_t *tags) { int n; int log_msg = mr->mr_log != 0; char const *dump = NULL; char const *capt = NULL;; if(mr->mr_capt_name) capt = mr->mr_capt_name; n = tl_gets(tags, TPTAG_LOG_REF(log_msg), TPTAG_DUMP_REF(dump), TPTAG_CAPT_REF(capt), TAG_END()); if (getenv("MSG_STREAM_LOG") != NULL || getenv("TPORT_LOG") != NULL) log_msg = 1; mr->mr_log = log_msg ? MSG_DO_EXTRACT_COPY : 0; if (getenv("TPORT_CAPT")) capt = getenv("TPORT_CAPT"); if (getenv("MSG_DUMP")) dump = getenv("MSG_DUMP"); if (getenv("TPORT_DUMP")) dump = getenv("TPORT_DUMP"); if(capt) { char *captname, *p, *host_s; char port[10]; su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }}; unsigned len =0; if (mr->mr_capt_name && mr->mr_capt_sock && strcmp(capt, mr->mr_capt_name) == 0) return n; captname = su_strdup(mr->mr_home, capt); if (captname == NULL) return n; if(strncmp(captname, "udp:",4) != 0) { su_log("tport_open_log: capturing. Only udp protocol supported [%s]\n", captname); return n; } /* separate proto and host */ p = captname+4; if( (*(p)) == '\0') { su_log("malformed ip address\n"); return n; } host_s = p; if( (p = strrchr(p+1, ':')) == 0 ) { su_log("no host or port specified\n"); return n; } /*the address contains a port number*/ *p = '\0'; p++; if (atoi(p) <1024 || atoi(p)>65536) { su_log("invalid port number; must be in [1024,65536]\n"); return n; } strncpy(port, p, sizeof(port)); *p = '\0'; /* check if we have [] */ if (host_s[0] == '[') { len = strlen(host_s + 1) - 1; if(host_s[len+1] != ']') { su_log("bracket not closed\n"); return n; } memmove(host_s, host_s + 1, len); host_s[len] = '\0'; } /* and again */ captname = su_strdup(mr->mr_home, capt); if (captname == NULL) return n; su_free(mr->mr_home, mr->mr_capt_name); mr->mr_capt_name = captname; if (mr->mr_capt_sock) su_close(mr->mr_capt_sock), mr->mr_capt_sock = 0; /* HINTS && getaddrinfo */ hints->ai_flags = AI_NUMERICSERV; hints->ai_family = AF_UNSPEC; hints->ai_socktype = SOCK_DGRAM; hints->ai_protocol = IPPROTO_UDP; if (su_getaddrinfo(host_s, port, hints, &ai)) { su_perror("capture: su_getaddrinfo()"); return n; } mr->mr_capt_sock = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (mr->mr_capt_sock == INVALID_SOCKET) { su_perror("capture: invalid socket"); return n; } su_setblocking(mr->mr_capt_sock, 0); /* Don't block */ if (connect(mr->mr_capt_sock, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == -1) { if (errno != EINPROGRESS) { su_perror("capture: socket connect"); return n; } } su_freeaddrinfo(ai); } else if(mr->mr_capt_sock) { /* close capture server*/ su_close(mr->mr_capt_sock); mr->mr_capt_sock = 0; } if (dump) { time_t now; char *dumpname; if (mr->mr_dump && strcmp(dump, mr->mr_dump) == 0) return n; dumpname = su_strdup(mr->mr_home, dump); if (dumpname == NULL) return n; su_free(mr->mr_home, mr->mr_dump); mr->mr_dump = dumpname; if (mr->mr_dump_file && mr->mr_dump_file != stdout) fclose(mr->mr_dump_file), mr->mr_dump_file = NULL; if (strcmp(dumpname, "-")) mr->mr_dump_file = fopen(dumpname, "ab"); /* XXX */ else mr->mr_dump_file = stdout; if (mr->mr_dump_file) { time(&now); fprintf(mr->mr_dump_file, "dump started at %s\n\n", ctime(&now)); } } return n; }
/** Build a list of local IPv4 addresses and append it to *rresult. */ static int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult) { su_localinfo_t *tbf = NULL, **lli = &tbf; su_localinfo_t *li = NULL, *li_first = NULL; su_sockaddr_t *su; int error = ELI_NOADDRESS; char *canonname = NULL; su_socket_t s; #if SU_HAVE_IN6 int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0; #else int const su_xtra = 0; #endif struct ifconf ifc; int numifs; char *buffer; struct ifreq *ifr, *ifr_next; #if HAVE_OPEN_C su_sockaddr_t *sa; socklen_t salen = sizeof(*sa); #endif s = su_socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) { SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n", su_strerror(su_errno()))); return ELI_SYSTEM; } # if HAVE_IFNUM /* Get the list of known IP address from the kernel */ if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) { /* can't get number of interfaces -- fall back */ SU_DEBUG_1(("su_localinfo: SIOCGIFNUM failed: %s\n", su_strerror(su_errno()))); error = ELI_SYSTEM; goto err; } SU_DEBUG_9(("su_localinfo: %d active interfaces according to SIOCGIFNUM\n", numifs)); if (numifs < 0) # endif /* Default to 64 interfaces. Enough? */ numifs = 64; if (numifs == 0) return 0; /* * Allocate memory for SIOCGIFCONF ioctl buffer. This memory block is also * used as li_first, first localinfo struct that is returned, so it can be * freed by freelocalinfo() without any complications. */ ifc.ifc_len = numifs * sizeof (struct ifreq); buffer = malloc(sizeof(su_localinfo_t) + ifc.ifc_len + su_xtra); if (!buffer) { SU_DEBUG_1(("su_localinfo: memory exhausted\n")); error = ELI_MEMORY; goto err; } li_first = (su_localinfo_t *)buffer; memset(li_first, 0, sizeof(su_localinfo_t) + su_xtra); ifc.ifc_buf = buffer + sizeof(su_localinfo_t) + su_xtra; #if HAVE_OPEN_C if (ioctl(s, SIOCGIFACTIVECONF, (char *)&ifc) < 0) { SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n", su_strerror(su_errno()))); error = ELI_SYSTEM; goto err; } #else if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n", su_strerror(su_errno()))); error = ELI_SYSTEM; goto err; } #endif buffer = ifc.ifc_buf + ifc.ifc_len; for (ifr = ifc.ifc_req; (void *)ifr < (void *)buffer; ifr = ifr_next) { struct ifreq ifreq[1]; int scope, if_index, flags = 0, gni_flags = 0; char *if_name; #if SU_HAVE_IN6 su_sockaddr_t su2[1]; #endif #if SA_LEN if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr)) ifr_next = (struct ifreq *) (ifr->ifr_addr.sa_len + (char *)(&ifr->ifr_addr)); else #else ifr_next = ifr + 1; #endif if_name = ifr->ifr_name; #if defined(SIOCGIFINDEX) ifreq[0] = *ifr; if (ioctl(s, SIOCGIFINDEX, ifreq) < 0) { SU_DEBUG_1(("su_localinfo: SIOCGIFINDEX failed: %s\n", su_strerror(su_errno()))); error = ELI_SYSTEM; goto err; } #if HAVE_IFR_INDEX if_index = ifreq->ifr_index; #elif HAVE_IFR_IFINDEX if_index = ifreq->ifr_ifindex; #else #error Unknown index field in struct ifreq #endif #else #warning su_localinfo() cannot map interface name to number if_index = 0; #endif SU_DEBUG_9(("su_localinfo: if %s with index %d\n", if_name, if_index)); #if HAVE_OPEN_C su_close(s); li = calloc(1, sizeof(su_localinfo_t)); sa = calloc(1, sizeof(su_sockaddr_t)); if (su_get_local_ip_addr(sa) < 0) goto err; li->li_family = sa->su_family; li->li_scope = LI_SCOPE_GLOBAL /* scope */; li->li_index = if_index; li->li_addrlen = su_sockaddr_size(sa); li->li_addr = sa; if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0) goto err; if (canonname) { if (strchr(canonname, ':') || strspn(canonname, "0123456789.") == strlen(canonname)) li->li_flags |= LI_NUMERIC; } else li->li_flags = 0; li->li_canonname = canonname; canonname = NULL; *rresult = li; return 0; #endif #if defined(SIOCGIFFLAGS) ifreq[0] = *ifr; if (ioctl(s, SIOCGIFFLAGS, ifreq) < 0) { SU_DEBUG_1(("su_localinfo: SIOCGIFFLAGS failed: %s\n", su_strerror(su_errno()))); error = ELI_SYSTEM; goto err; } /* Do not include interfaces that are down unless explicitly asked */ if ((ifreq->ifr_flags & IFF_UP) == 0 && (hints->li_flags & LI_DOWN) == 0) { SU_DEBUG_9(("su_localinfo: if %s with index %d is down\n", if_name, if_index)); continue; } #elif defined(SIOCGIFACTIVECONF) /* Handled above in SIOCGIFACTIVECONF vs. SIOCGIFCONF*/ #else #error su_localinfo() cannot determine interface status #endif #if 0 *ifreq = *ifr; ifreq->ifr_addr.sa_family = AF_INET; if (ioctl(s, SIOCGIFADDR, ifreq) < 0) { SU_DEBUG_1(("su_localinfo: SIOCGIFADDR failed: %s\n", su_strerror(su_errno()))); error = ELI_SYSTEM; goto err; } ifr->ifr_addr = ifreq->ifr_addr; #endif su = (su_sockaddr_t *)&ifr->ifr_addr; if (SU_HAS_INADDR_ANY(su)) continue; scope = li_scope4(su->su_sin.sin_addr.s_addr); if ((hints->li_scope && (hints->li_scope & scope) == 0) || (hints->li_ifname && strcmp(hints->li_ifname, if_name) != 0) || (hints->li_index && hints->li_index != if_index)) continue; #if SU_HAVE_IN6 if (su_xtra) { /* Map IPv4 address to IPv6 address */ memset(su2, 0, sizeof(*su2)); su2->su_family = AF_INET6; ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff); ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr; su = su2; } #endif if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK) gni_flags = NI_NUMERICHOST; if ((error = li_name(hints, gni_flags, su, &canonname)) < 0) goto err; else if (error > 0) continue; if (canonname) if (strchr(canonname, ':') || strspn(canonname, "0123456789.") == strlen(canonname)) flags |= LI_NUMERIC; if (li_first) li = li_first; /* Use li_first with all ifr structs to be freed */ else if (!(li = calloc(1, (sizeof *li) + su_xtra))) { error = ELI_MEMORY; goto err; } if (!tbf) tbf = li; *lli = li; lli = &li->li_next; if (su_xtra) su = (su_sockaddr_t *)memcpy(li + 1, su, su_xtra); li->li_flags = flags; li->li_family = su->su_family; li->li_scope = scope; li->li_index = if_index; li->li_addrlen = su_sockaddr_size(su); li->li_addr = su; li->li_canonname = canonname; li->li_ifname = if_name; canonname = NULL; li_first = NULL; } if (canonname) free(canonname); if (li_first) free(li_first); su_close(s); if (tbf) *rresult = tbf; return 0; err: if (canonname) free(canonname); if (li_first) free(li_first); su_freelocalinfo(tbf); su_close(s); return error; }
/** Build a list of local IPv4 addresses and append it to *rresult. */ static int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult) { su_localinfo_t *li = NULL; su_sockaddr_t *su; int error = ELI_NOADDRESS; char *canonname = NULL; su_socket_t s; #if SU_HAVE_IN6 int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0; #else int const su_xtra = 0; #endif struct ifconf ifc; int numifs; char *buffer; struct ifreq *ifr, *ifr_next; su_sockaddr_t *sa; socklen_t salen = sizeof(*sa); int scope = 0, gni_flags = 0; s = su_socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) { SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n", su_strerror(su_errno()))); return ELI_SYSTEM; } li = calloc(1, (sizeof *li) + (sizeof *sa)); sa = (void *)(li + 1); error = getsockname(s, (struct sockaddr *) sa, &salen); if (error < 0 && errno == SOCKET_ERROR) { SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__, su_strerror(su_errno()))); } error = bind(s, (struct sockaddr *) sa, salen); if (error < 0) { SU_DEBUG_1(("%s: bind() failed: %s\n", __func__, su_strerror(su_errno()))); goto err; } su_close(s); scope = li_scope4(sa->su_sin.sin_addr.s_addr); if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK) gni_flags = NI_NUMERICHOST; if (su_xtra) { /* Map IPv4 address to IPv6 address */ memset(sa, 0, sizeof(*sa)); sa->su_family = AF_INET6; ((int32_t*)&sa->su_sin6.sin6_addr)[3] = sa->su_sin.sin_addr.s_addr; ((int32_t*)&sa->su_sin6.sin6_addr)[2] = htonl(0xffff); } li->li_family = sa->su_family; li->li_scope = scope; li->li_index = 0; li->li_addrlen = su_sockaddr_size(sa); li->li_addr = sa; if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0) goto err; if (canonname) { if (strchr(canonname, ':') || strspn(canonname, "0123456789.") == strlen(canonname)) li->li_flags |= LI_NUMERIC; } else li->li_flags = 0; li->li_canonname = canonname; canonname = NULL; *rresult = li; return 0; err: if (canonname) free(canonname); if (li) free(li); su_close(s); return error; }
static int localinfo0(su_localinfo_t const *hints, su_localinfo_t **rresult) { /* This is Windows IPv4 code */ short family = AF_INET; su_socket_t s; union { SOCKET_ADDRESS_LIST sal[1]; #if HAVE_INTERFACE_INFO_EX INTERFACE_INFO_EX ii[1]; #else INTERFACE_INFO ii[1]; #endif char buffer[2048]; } b = {{ 1 }}; DWORD salen = sizeof(b); int i, error = -1; #if SU_HAVE_IN6 int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0; #endif su_localinfo_t *li, *head = NULL, **next = &head; char *canonname = NULL, *if_name = NULL; *rresult = NULL; s = su_socket(family, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) { SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "su_socket", su_strerror(su_errno()))); return -1; } /* get the list of known IP address (NT5 and up) */ if (WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, &b, sizeof(b), &salen, NULL, NULL) == SOCKET_ERROR) { SU_DEBUG_1(("su_getlocalinfo: %s: %s\n", "SIO_ADDRESS_LIST_QUERY", su_strerror(su_errno()))); error = -1; goto err; } if (b.sal->iAddressCount < 1) { SU_DEBUG_1(("su_getlocalinfo: no local addresses\n")); error = -1; goto err; } for (i = 0; i < b.sal->iAddressCount; i++) { su_sockaddr_t *su = (su_sockaddr_t *)b.sal->Address[i].lpSockaddr; #if SU_HAVE_IN6 socklen_t sulen = v4_mapped ? sizeof(*su) : b.sal->Address[i].iSockaddrLength; su_sockaddr_t su2[1]; #else socklen_t sulen = b.sal->Address[i].iSockaddrLength; #endif int scope, flags = 0, gni_flags = 0; scope = li_scope4(su->su_sin.sin_addr.s_addr); if (hints->li_scope && (hints->li_scope & scope) == 0) continue; if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK) gni_flags = NI_NUMERICHOST; if (!(li = calloc(1, sizeof(*li) + sulen))) { SU_DEBUG_1(("su_getlocalinfo: memory exhausted\n")); error = -1; goto err; } *next = li, next = &li->li_next; #if SU_HAVE_IN6 if (v4_mapped) { /* Map IPv4 address to IPv6 address */ memset(su2, 0, sizeof(*su2)); su2->su_family = AF_INET6; ((int32_t*)&su2->su_sin6.sin6_addr)[2] = htonl(0xffff); ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr; su = su2; } #endif if ((error = li_name(hints, gni_flags, su, &canonname)) < 0) goto err; else if (error > 0) continue; if (canonname) if (strchr(canonname, ':') || strspn(canonname, "0123456789.") == strlen(canonname)) flags |= LI_NUMERIC; li->li_flags = flags; li->li_family = su->su_family; li->li_scope = scope; li->li_index = i; li->li_addrlen = su_sockaddr_size(su); li->li_addr = su; li->li_canonname = canonname, canonname = NULL; if (hints->li_flags & LI_IFNAME) li->li_ifname = if_name; li->li_addr = (su_sockaddr_t *)(li + 1); li->li_addrlen = sulen; memcpy(li->li_addr, su, sulen); } *rresult = head; su_close(s); return 0; err: if (canonname) free(canonname); su_freelocalinfo(head); su_close(s); return error; }
/* Use HOSTADDR6 */ static int localinfo6(su_localinfo_t const *hints, su_localinfo_t **rresult) { char *addr, *ifname; int flags, error; su_localinfo_t *li = NULL; su_sockaddr_t *su; int const su_sockaddr_size = sizeof(*su); error = ELI_NOADDRESS; #if defined(__APPLE_CC__) { su_sockaddr_t *sa; int salen = sizeof(*sa); int s; if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) { if ((addr = getenv("HOSTADDR6"))) { li = calloc(1, sizeof(su_localinfo_t)); sa = calloc(1, sizeof(su_sockaddr_t)); sa->su_family = AF_INET6; if (su_inet_pton(AF_INET6, addr, &sa->su_sin6.sin6_addr) <= 0) goto err; s = su_socket(AF_INET6, SOCK_DGRAM, 0); if (s == -1) { SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n", su_strerror(su_errno()))); return ELI_SYSTEM; } error = getsockname(s, (struct sockaddr *) sa, &salen); if (error < 0 && errno == SOCKET_ERROR) { SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__, su_strerror(su_errno()))); } error = bind(s, (struct sockaddr *) sa, salen); if (error < 0) { SU_DEBUG_1(("%s: bind() failed: %s\n", __func__, su_strerror(su_errno()))); goto err; } su_close(s); li->li_family = sa->su_family; li->li_scope = LI_SCOPE_GLOBAL; li->li_index = 0; li->li_addrlen = su_sockaddr_size(sa); li->li_addr = sa; if ((error = li_name(hints, NI_NUMERICHOST, sa, &li->li_canonname)) < 0) goto err; li->li_flags = NI_NUMERICHOST; } } *rresult = li; return 0; } #endif if (hints->li_scope == 0 || (hints->li_scope & LI_SCOPE_GLOBAL)) { if ((addr = getenv("HOSTADDR6"))) { flags = hints->li_flags & (LI_CANONNAME|LI_NUMERIC|LI_IFNAME); if ((li = calloc(1, sizeof(*li) + su_sockaddr_size)) == NULL) { error = ELI_MEMORY; goto err; } li->li_flags = flags; li->li_scope = LI_SCOPE_GLOBAL, li->li_index = 2, ifname = "eth"; li->li_addrlen = sizeof(*su); li->li_addr = su = (su_sockaddr_t *)(li + 1); su->su_family = li->li_family = AF_INET6; if (su_inet_pton(AF_INET6, addr, &su->su_sin6.sin6_addr) <= 0) goto err; if (li->li_flags & LI_IFNAME) li->li_ifname = ifname; if ((error = li_name(hints, NI_NUMERICHOST, su, &li->li_canonname)) < 0) goto err; else if (error > 0) { free(li); li = NULL; } } } *rresult = li; return 0; err: if (li) su_freelocalinfo(li); return error; }
int su_close_wrp(lua_State *L) { su_state *s = (su_state*)lua_touserdata(L, -1); su_close(s); return 0; }
static int test_sockaddr(void) { su_localinfo_t hints[1] = {{ LI_CANONNAME }}; su_localinfo_t *li, *res = NULL; int s; su_sockaddr_t su[1], a[1], b[1]; BEGIN(); hints->li_family = AF_INET; TEST(su_getlocalinfo(hints, &res), 0); for (li = res; li; li = li->li_next) { if (li->li_addrlen != res->li_addrlen || memcmp(li->li_addr, res->li_addr, li->li_addrlen) != 0) TEST_1(su_cmp_sockaddr(li->li_addr, res->li_addr) != 0); else TEST_1(su_cmp_sockaddr(li->li_addr, res->li_addr) == 0); } memset(su, 0, sizeof su); TEST(su_getlocalip(su), 0); if (res->li_family == AF_INET) TEST(su_cmp_sockaddr(res->li_addr, su), 0); TEST_1(su_gli_strerror(ELI_NOERROR)); TEST_1(su_gli_strerror(ELI_NOADDRESS)); TEST_1(su_gli_strerror(ELI_FAMILY)); TEST_1(su_gli_strerror(ELI_MEMORY)); TEST_1(su_gli_strerror(ELI_RESOLVER)); TEST_1(su_gli_strerror(ELI_SYSTEM)); TEST_1(su_gli_strerror(-100)); li = su_copylocalinfo(res); TEST_1(li); su_freelocalinfo(li); s = su_socket(res->li_family, SOCK_DGRAM, 0); TEST_1(s != -1); TEST(su_setblocking(s, 0), 0); TEST(su_setblocking(s, 1), 0); TEST(su_close(s), 0); su_freelocalinfo(res), res = NULL; #if SU_HAVE_IN6 hints->li_family = AF_INET6; hints->li_flags &= ~LI_CANONNAME; hints->li_flags |= LI_V4MAPPED; TEST(su_getlocalinfo(hints, &res), 0); for (li = res; li; li = li->li_next) TEST(li->li_family, AF_INET6); su_freelocalinfo(res), res = NULL; #endif hints->li_flags |= LI_NUMERIC; TEST(su_getlocalinfo(hints, &res), 0); su_freelocalinfo(res), res = NULL; res = NULL; hints->li_flags |= LI_NAMEREQD; su_getlocalinfo(hints, &res); su_freelocalinfo(res), res = NULL; memset(a, 0, sizeof *a); memset(b, 0, sizeof *b); TEST_1(su_match_sockaddr(a, b)); b->su_family = AF_INET; TEST_1(su_match_sockaddr(a, b)); a->su_port = htons(12); TEST_1(!su_match_sockaddr(a, b)); b->su_port = htons(12); TEST_1(su_match_sockaddr(a, b)); a->su_sin.sin_addr.s_addr = htonl(0x7f000001); TEST_1(su_match_sockaddr(a, b)); a->su_family = AF_INET; TEST_1(!su_match_sockaddr(a, b)); b->su_sin.sin_addr.s_addr = htonl(0x7f000001); TEST_1(su_match_sockaddr(a, b)); a->su_sin.sin_addr.s_addr = 0; TEST_1(su_match_sockaddr(a, b)); #if SU_HAVE_IN6 a->su_family = AF_INET6; TEST_1(!su_match_sockaddr(a, b)); b->su_family = AF_INET6; TEST_1(su_match_sockaddr(a, b)); b->su_sin6.sin6_addr.s6_addr[15] = 1; TEST_1(su_match_sockaddr(a, b)); TEST_1(!su_match_sockaddr(b, a)); a->su_sin6.sin6_addr.s6_addr[15] = 2; TEST_1(!su_match_sockaddr(a, b)); a->su_family = 0; TEST_1(su_match_sockaddr(a, b)); TEST_1(!su_match_sockaddr(b, a)); #endif END(); }
/* Test assumptions in su_select_port implementation */ int test_select(void) { su_socket_t s; su_sockaddr_t su; socklen_t sulen = sizeof su.su_sin; size_t bytes; fd_set *rset, *wset; struct timeval tv; BEGIN(); s = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(s != -1); memset(&su, 0, sulen); su.su_len = sulen; su.su_family = AF_INET; TEST(su_inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1); TEST(bind(s, &su.su_sa, sulen), 0); TEST(getsockname(s, &su.su_sa, &sulen), 0); tv.tv_sec = 0; tv.tv_usec = 1000; TEST(select(0, NULL, NULL, NULL, &tv), 0); bytes = howmany(s); TEST_1(rset = malloc(bytes)); TEST_1(wset = malloc(bytes)); FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, wset); tv.tv_sec = 0, tv.tv_usec = 1000; TEST(select(s + 1, NULL, wset, NULL, &tv), 1); TEST_1(FD_ISSET(s, wset)); FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, rset); FD_SET(s, wset); tv.tv_sec = 0, tv.tv_usec = 1000; TEST(select(s + 1, rset, wset, NULL, &tv), 1); TEST_1(!FD_ISSET(s, rset)); TEST_1(FD_ISSET(s, wset)); FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, rset); FD_SET(s, wset); tv.tv_sec = 0, tv.tv_usec = 1000; TEST(select(s + 1, rset, NULL, NULL, &tv), 0); TEST_1(!FD_ISSET(s, rset)); FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, rset); FD_CLR(s, wset); tv.tv_sec = 0, tv.tv_usec = 1000; TEST(select(s + 1, rset, wset, NULL, &tv), 0); TEST_1(!FD_ISSET(s, rset)); TEST_1(!FD_ISSET(s, wset)); TEST(su_sendto(s, "foo", 3, 0, &su, sulen), 3); FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, rset); FD_CLR(s, wset); tv.tv_sec = 0, tv.tv_usec = 1000; TEST(select(s + 1, rset, wset, NULL, &tv), 1); TEST_1(FD_ISSET(s, rset)); TEST_1(!FD_ISSET(s, wset)); FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, rset); FD_SET(s, wset); tv.tv_sec = 0, tv.tv_usec = 1000; TEST(select(s + 1, rset, wset, NULL, &tv), 2); TEST_1(FD_ISSET(s, rset)); TEST_1(FD_ISSET(s, wset)); su_close(s); free(wset); free(rset); END(); }
int test_sendrecv(void) { su_socket_t s, l, a; ssize_t n; su_sockaddr_t su, csu; socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin; char b1[8], b2[8], b3[8]; su_iovec_t sv[3], rv[3]; sv[0].siv_base = "one!one!", sv[0].siv_len = 8; sv[1].siv_base = "two!two!", sv[1].siv_len = 8; sv[2].siv_base = "third!", sv[2].siv_len = 6; rv[0].siv_base = b1, rv[0].siv_len = 8; rv[1].siv_base = b2, rv[1].siv_len = 8; rv[2].siv_base = b3, rv[2].siv_len = 8; BEGIN(); s = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(s != -1); su_setblocking(s, 1); memset(&su, 0, sulen); su.su_len = sulen; su.su_family = AF_INET; TEST(su_inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1); TEST(bind(s, &su.su_sa, sulen), 0); TEST(getsockname(s, &su.su_sa, &sulen), 0); n = su_vsend(s, sv, 3, 0, &su, sulen); TEST(n, 8 + 8 + 6); n = su_vrecv(s, rv, 3, 0, &su, &sulen); TEST(n, 8 + 8 + 6); TEST_M(rv[0].siv_base, sv[0].siv_base, sv[0].siv_len); TEST_M(rv[1].siv_base, sv[1].siv_base, sv[1].siv_len); TEST_M(rv[2].siv_base, sv[2].siv_base, sv[2].siv_len); su_close(s); l = su_socket(AF_INET, SOCK_STREAM, 0); TEST_1(l != -1); s = su_socket(AF_INET, SOCK_STREAM, 0); TEST_1(s != -1); memset(&su, 0, sulen); su.su_len = sulen; su.su_family = AF_INET; TEST(su_inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1); TEST(bind(l, &su.su_sa, sulen), 0); TEST(bind(s, &su.su_sa, sulen), 0); TEST(getsockname(l, &su.su_sa, &sulen), 0); TEST(listen(l, 5), 0); TEST(su_setblocking(s, 1), 0); TEST(connect(s, &su.su_sa, sulen), 0); a = accept(l, &csu.su_sa, &csulen); TEST_1(a != -1); TEST(su_setblocking(a, 1), 0); n = su_vsend(s, sv, 3, 0, NULL, 0); TEST(n, 8 + 8 + 6); n = su_vrecv(a, rv, 3, 0, NULL, NULL); TEST(n, 8 + 8 + 6); TEST_M(rv[0].siv_base, sv[0].siv_base, sv[0].siv_len); TEST_M(rv[1].siv_base, sv[1].siv_base, sv[1].siv_len); TEST_M(rv[2].siv_base, sv[2].siv_base, sv[2].siv_len); n = send(a, "", 0, 0); TEST(n, 0); n = su_vsend(a, sv, 3, 0, NULL, 0); TEST(n, 8 + 8 + 6); { su_wait_t w[1] = { SU_WAIT_INIT }; TEST(su_wait_create(w, s, SU_WAIT_IN | SU_WAIT_HUP), 0); TEST(su_wait(w, 0, 500), SU_WAIT_TIMEOUT); TEST(su_wait(w, 1, 500), 0); TEST(su_wait_events(w, s), SU_WAIT_IN); TEST_SIZE(su_getmsgsize(s), 8 + 8 + 6); n = su_vrecv(s, rv, 3, 0, NULL, NULL); TEST(n, 8 + 8 + 6); TEST(su_wait(w, 1, 100), SU_WAIT_TIMEOUT); shutdown(a, 2); TEST(su_wait(w, 1, 100), 0); #if SU_HAVE_WINSOCK TEST_1(su_wait_events(w, s) & SU_WAIT_HUP); #else TEST_1(su_wait_events(w, s)); n = su_vrecv(s, rv, 3, 0, NULL, NULL); TEST(n, 0); #endif su_wait_destroy(w); } su_close(a); su_close(l); su_close(s); END(); }
int su_compile(su_state *s, const char *code, const char *name, char **inline_c, char **result, size_t *size) { const char *tmp; size_t buffer_size; lua_State *L = lua_open(); su_state *sc = su_init(su_allocator(s)); su_libinit(sc); ___saurus(sc); luaL_openlibs(L); luaopen_writebin(L); if (luaL_loadstring(L, compiler_code)) { *result = dup(s, lua_tostring(L, -1)); if (size) *size = strlen(*result); lua_close(L); su_close(sc); return -1; } if (lua_pcall(L, 0, 0, 0)) { lua_getglobal(L, "saurus_error"); if (lua_isnil(L, -1)) lua_pop(L, 1); *result = dup(s, lua_tostring(L, -1)); if (size) *size = strlen(*result); lua_close(L); su_close(sc); return -2; } lua_getglobal(L, "repl"); lua_pushstring(L, code); lua_pushstring(L, name ? name : "?"); if (lua_pcall(L, 2, 1, 0)) { lua_getglobal(L, "saurus_error"); if (lua_isnil(L, -1)) { lua_pop(L, 1); *result = dup(s, lua_tostring(L, -1)); } else { *result = dup(s, lua_tostring(L, -1)); } if (size) *size = strlen(*result); lua_close(L); su_close(sc); return -3; } tmp = lua_tolstring(L, -1, &buffer_size); *result = (char*)su_allocate(s, NULL, buffer_size); memcpy(*result, tmp, buffer_size); if (size) *size = buffer_size; if (inline_c) { lua_getglobal(L, "c_code"); if (lua_isnil(L, -1)) tmp = lua_tostring(L, -1); *inline_c = (char*)su_allocate(s, NULL, strlen(tmp) + 1); strcpy(*inline_c, tmp); } lua_close(L); su_close(sc); return 0; }
int main(int argc, char *argv[]) { int ret, i; int compile; FILE *fp; jmp_buf err; su_state *s; lua_State *L; char *tmp; const char *tmp2; const char *input, *output; int print_help = argc > 1 && strstr("-h -v --help --version", argv[1]) != NULL; int pipe = argc > 1 && !strcmp("--", argv[1]); compiler = su_init(NULL); su_libinit(compiler); ___saurus(compiler); atexit(shutdown); if (!pipe && (argc <= 1 || print_help)) { printf("S A U R U S\nCopyright (c) 2009-2015 Andreas T Jonsson <*****@*****.**>\nVersion: %s\n\n", su_version(NULL, NULL, NULL)); if (print_help) { puts("Usage: saurus <options> <input.su> <output.suc>\n\tOptions:\n\t\t'-c' Compile source file to binary file.\n\t\t'--' read from STDIN."); return 0; } } s = su_init(NULL); su_libinit(s); L = lua_open(); luaL_openlibs(L); luaopen_writebin(L); if (luaL_loadstring(L, compiler_code)) { fprintf(stderr, "%s\n", lua_tostring(L, -1)); lua_close(L); su_close(s); return -1; } if (lua_pcall(L, 0, 0, 0)) { lua_getglobal(L, "saurus_error"); if (lua_isnil(L, -1)) lua_pop(L, 1); fprintf(stderr, "%s\n", lua_tostring(L, -1)); lua_close(L); su_close(s); return -1; } ret = 0; if (argc < 2 || pipe) { if (!pipe) puts("Type '_h' for help or '_q' to exit.\n"); su_pushstring(s, repl_help_text); su_setglobal(s, "_h"); su_pushstring(s, "_q"); su_setglobal(s, "_q"); ret = setjmp(err); if (!pipe) su_seterror(s, err, ret); jump: for (;;) { if (!pipe) printf("> "); fgets(buffer, BUFFER_SIZE, stdin); lua_getglobal(L, "repl"); lua_pushstring(L, buffer); lua_pushstring(L, argv[0]); if (lua_pcall(L, 2, 1, 0)) { lua_getglobal(L, "saurus_error"); if (lua_isnil(L, -1)) { lua_pop(L, 1); puts(lua_tostring(L, -1)); } else { puts(lua_tostring(L, -1)); lua_pop(L, 1); } lua_pop(L, 1); goto jump; } lua_getglobal(L, "c_code"); su_assert(s, lua_isnil(L, -1), "Inline C is not supported in interpreter!"); lua_pop(L, 1); tmp2 = lua_tolstring(L, -1, NULL); su_assert(s, su_getglobal(s, "io"), "Could not retrieve 'io' namespace."); su_pushstring(s, "print"); su_assert(s, su_map_get(s, -2), "Could not retrieve 'print' function."); if (su_load(s, NULL, (void*)tmp2)) { su_close(s); lua_close(L); fprintf(stderr, "Could not load: %s\n", argv[1]); return -1; } lua_pop(L, 1); su_call(s, 0, 1); if (su_type(s, -1) == SU_STRING && !strcmp(su_tostring(s, -1, NULL), "_q")) { ret = 0; break; } su_call(s, 1, 0); su_pop(s, 1); } } else { compile = !strcmp(argv[1], "-c"); input = compile ? argv[2] : argv[1]; if (compile) { if (argc < 4) { fputs("Expected input and output file!", stderr); lua_close(L); su_close(s); return -1; } } else { fp = fopen(input, "rb"); if (!fp) { fprintf(stderr, "Could not open: %s\n", input); lua_close(L); su_close(s); return -1; } if (fread(buffer, 1, 1, fp) == 1) { if (*buffer == '\x1b') { rewind(fp); if (su_load(s, &reader_fp, fp)) { su_close(s); lua_close(L); fclose(fp); fprintf(stderr, "Could not load: %s\n", input); return -1; } su_pushstring(s, input); for (i = 2; i < argc; i++) su_pushstring(s, argv[i]); su_call(s, argc - 1, 1); if (su_type(s, -1) == SU_NUMBER) ret = (int)su_tonumber(s, -1); su_close(s); lua_close(L); fclose(fp); return ret; } } fclose(fp); } tmp = tmpnam(buffer); output = compile ? argv[3] : tmp; lua_getglobal(L, "compile"); lua_pushstring(L, input); lua_pushstring(L, output); lua_pushboolean(L, compile); if (lua_pcall(L, 3, 0, 0)) { lua_getglobal(L, "saurus_error"); if (lua_isnil(L, -1)) lua_pop(L, 1); fprintf(stderr, "%s\n", lua_tostring(L, -1)); lua_close(L); su_close(s); return -1; } if (!compile) { fp = fopen(output, "rb"); if (!fp) { fprintf(stderr, "Could not open: %s\n", output); lua_close(L); su_close(s); return -1; } if (su_load(s, &reader_fp, fp)) { su_close(s); lua_close(L); fclose(fp); remove(tmp); fprintf(stderr, "Could not load: %s\n", output); return -1; } fclose(fp); remove(tmp); su_pushstring(s, argv[1]); for (i = 2; i < argc; i++) su_pushstring(s, argv[i]); su_call(s, argc - 1, 1); if (su_type(s, -1) == SU_NUMBER) ret = (int)su_tonumber(s, -1); } } lua_close(L); su_close(s); return ret; }
void shutdown() { su_close(compiler); }