http_client_upcall : support IPv4/IPv6 only modes
diff --git a/programs/http_client_upcall.c b/programs/http_client_upcall.c
index a13b4ba..00276f3 100644
--- a/programs/http_client_upcall.c
+++ b/programs/http_client_upcall.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2018 Felix Weinrank
+ * Copyright (C) 2016-2019 Felix Weinrank
*
* All rights reserved.
*
@@ -52,6 +52,10 @@
#endif
#include <usrsctp.h>
+#define RETVAL_CATCHALL 50
+#define RETVAL_ECONNREFUSED 60
+#define RETVAL_TIMEOUT 61
+
int done = 0;
int writePending = 1;
@@ -65,7 +69,6 @@
#define BUFFERSIZE (1<<16)
-
static void handle_upcall(struct socket *sock, void *arg, int flgs)
{
int events = usrsctp_get_events(sock);
@@ -128,19 +131,53 @@
main(int argc, char *argv[])
{
struct socket *sock;
+ struct sockaddr *addr;
+ socklen_t addr_len;
struct sockaddr_in addr4;
struct sockaddr_in6 addr6;
+ struct sockaddr_in bind4;
+ struct sockaddr_in6 bind6;
struct sctp_udpencaps encaps;
+ struct sctp_sndinfo sndinfo;
struct sctp_rtoinfo rtoinfo;
struct sctp_initmsg initmsg;
- int result;
+ int result = 0;
+ uint8_t address_family = 0;
if (argc < 3) {
printf("Usage: http_client_upcall remote_addr remote_port [local_port] [local_encaps_port] [remote_encaps_port] [uri]\n");
return(EXIT_FAILURE);
}
- result = 0;
+ memset((void *)&addr4, 0, sizeof(struct sockaddr_in));
+ memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
+
+ if (inet_pton(AF_INET, argv[1], &addr4.sin_addr) == 1) {
+ address_family = AF_INET;
+
+ addr = (struct sockaddr *)&addr4;
+ addr_len = sizeof(addr4);
+#ifdef HAVE_SIN_LEN
+ addr4.sin_len = sizeof(struct sockaddr_in);
+#endif
+ addr4.sin_family = AF_INET;
+ addr4.sin_port = htons(atoi(argv[2]));
+ } else if (inet_pton(AF_INET6, argv[1], &addr6.sin6_addr) == 1) {
+ address_family = AF_INET6;
+
+ addr = (struct sockaddr *)&addr6;
+ addr_len = sizeof(addr6);
+#ifdef HAVE_SIN6_LEN
+ addr6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_port = htons(atoi(argv[2]));
+ } else {
+ printf("Unsupported destination address - use IPv4 or IPv6 address\n");
+ result = RETVAL_CATCHALL;
+ goto out;
+ }
+
if (argc > 4) {
usrsctp_init(atoi(argv[4]), NULL, debug_printf);
} else {
@@ -153,9 +190,9 @@
usrsctp_sysctl_set_sctp_blackhole(2);
- if ((sock = usrsctp_socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) == NULL) {
+ if ((sock = usrsctp_socket(address_family, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) == NULL) {
perror("usrsctp_socket");
- result = 1;
+ result = RETVAL_CATCHALL;
goto out;
}
@@ -168,7 +205,7 @@
if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RTOINFO, (const void *)&rtoinfo, (socklen_t)sizeof(struct sctp_rtoinfo)) < 0) {
perror("setsockopt");
usrsctp_close(sock);
- result = 3;
+ result = RETVAL_CATCHALL;
goto out;
}
initmsg.sinit_num_ostreams = 1;
@@ -178,34 +215,52 @@
if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, (const void *)&initmsg, (socklen_t)sizeof(struct sctp_initmsg)) < 0) {
perror("setsockopt");
usrsctp_close(sock);
- result = 3;
+ result = RETVAL_CATCHALL;
goto out;
}
if (argc > 3) {
- memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
+
+ if (address_family == AF_INET) {
+ memset((void *)&bind4, 0, sizeof(struct sockaddr_in));
#ifdef HAVE_SIN6_LEN
- addr6.sin6_len = sizeof(struct sockaddr_in6);
+ bind4.sin_len = sizeof(struct sockaddr_in6);
#endif
- addr6.sin6_family = AF_INET6;
- addr6.sin6_port = htons(atoi(argv[3]));
- addr6.sin6_addr = in6addr_any;
- if (usrsctp_bind(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
- perror("bind");
- usrsctp_close(sock);
- result = 2;
- goto out;
+ bind4.sin_family = AF_INET;
+ bind4.sin_port = htons(atoi(argv[3]));
+ bind4.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (usrsctp_bind(sock, (struct sockaddr *)&bind4, sizeof(bind4)) < 0) {
+ perror("bind");
+ usrsctp_close(sock);
+ result = RETVAL_CATCHALL;
+ goto out;
+ }
+ } else {
+ memset((void *)&bind6, 0, sizeof(struct sockaddr_in6));
+#ifdef HAVE_SIN6_LEN
+ bind6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ bind6.sin6_family = AF_INET6;
+ bind6.sin6_port = htons(atoi(argv[3]));
+ bind6.sin6_addr = in6addr_any;
+ if (usrsctp_bind(sock, (struct sockaddr *)&bind6, sizeof(bind6)) < 0) {
+ perror("bind");
+ usrsctp_close(sock);
+ result = RETVAL_CATCHALL;
+ goto out;
+ }
}
}
if (argc > 5) {
memset(&encaps, 0, sizeof(struct sctp_udpencaps));
- encaps.sue_address.ss_family = AF_INET6;
+ encaps.sue_address.ss_family = address_family;
encaps.sue_port = htons(atoi(argv[5]));
if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void *)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
perror("setsockopt");
usrsctp_close(sock);
- result = 3;
+ result = RETVAL_CATCHALL;
goto out;
}
}
@@ -224,44 +279,35 @@
#endif
}
+ printf("\nHTTP request:\n%s\n", request);
+ printf("\nHTTP response:\n");
+
usrsctp_set_upcall(sock, handle_upcall, NULL);
- memset((void *)&addr4, 0, sizeof(struct sockaddr_in));
- memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
-#ifdef HAVE_SIN_LEN
- addr4.sin_len = sizeof(struct sockaddr_in);
-#endif
-#ifdef HAVE_SIN6_LEN
- addr6.sin6_len = sizeof(struct sockaddr_in6);
-#endif
- addr4.sin_family = AF_INET;
- addr6.sin6_family = AF_INET6;
- addr4.sin_port = htons(atoi(argv[2]));
- addr6.sin6_port = htons(atoi(argv[2]));
- if (inet_pton(AF_INET6, argv[1], &addr6.sin6_addr) == 1) {
- if (usrsctp_connect(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
- if (errno != EINPROGRESS) {
- perror("usrsctp_connect");
- usrsctp_close(sock);
- result = 4;
- goto out;
+ if (usrsctp_connect(sock, addr, addr_len) < 0) {
+ if (errno != EINPROGRESS) {
+ perror("usrsctp_connect");
+ usrsctp_close(sock);
+
+ if (errno == ECONNREFUSED) {
+ result = RETVAL_ECONNREFUSED;
+ } else {
+ result = RETVAL_CATCHALL;
}
+ goto out;
}
- } else if (inet_pton(AF_INET, argv[1], &addr4.sin_addr) == 1) {
- if (usrsctp_connect(sock, (struct sockaddr *)&addr4, sizeof(struct sockaddr_in)) < 0) {
- if (errno != EINPROGRESS) {
- perror("usrsctp_connect");
- usrsctp_close(sock);
- result = 5;
- goto out;
- }
- }
- } else {
- printf("Illegal destination address\n");
+ }
+
+ memset(&sndinfo, 0, sizeof(struct sctp_sndinfo));
+ sndinfo.snd_ppid = htonl(63); /* PPID for HTTP/SCTP */
+ /* send GET request */
+ if (usrsctp_sendv(sock, request, strlen(request), NULL, 0, &sndinfo, sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) {
+ perror("usrsctp_sendv");
usrsctp_close(sock);
- result = 6;
+ result = RETVAL_CATCHALL;
goto out;
}
+
while (!done) {
#ifdef _WIN32
Sleep(1*1000);