mirror of
https://github.com/janet-lang/janet
synced 2024-12-27 00:40:26 +00:00
Add bind option to net/connect
This will allow us to set the address we use for outgoing connections. Builds, haven't checked it passes current tests, haven't checked it actually works either.
This commit is contained in:
parent
7037532943
commit
6e8584e8e0
@ -259,8 +259,9 @@ static int janet_get_sockettype(Janet *argv, int32_t argc, int32_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Needs argc >= offset + 2 */
|
/* Needs argc >= offset + 2 */
|
||||||
/* For unix paths, just rertuns a single sockaddr and sets *is_unix to 1, otherwise 0 */
|
/* For unix paths, just rertuns a single sockaddr and sets *is_unix to 1,
|
||||||
static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int socktype, int passive, int *is_unix) {
|
* otherwise 0. Also, ignores is_bind when is a unix socket. */
|
||||||
|
static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int socktype, int passive, int *is_unix, int is_bind) {
|
||||||
/* Unix socket support - not yet supported on windows. */
|
/* Unix socket support - not yet supported on windows. */
|
||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
if (janet_keyeq(argv[offset], "unix")) {
|
if (janet_keyeq(argv[offset], "unix")) {
|
||||||
@ -285,12 +286,29 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Get host and port */
|
/* Get host and port */
|
||||||
const char *host = janet_getcstring(argv, offset);
|
char *host = NULL, *port = NULL;
|
||||||
const char *port;
|
char *err = NULL;
|
||||||
|
/* if is_bind is set, skip offsets and ports! */
|
||||||
|
if (!is_bind) {
|
||||||
|
host = (char *)janet_getcstring(argv, offset);
|
||||||
if (janet_checkint(argv[offset + 1])) {
|
if (janet_checkint(argv[offset + 1])) {
|
||||||
port = (const char *)janet_to_string(argv[offset + 1]);
|
port = (char *)janet_to_string(argv[offset + 1]);
|
||||||
} else {
|
} else {
|
||||||
port = janet_optcstring(argv, offset + 2, offset + 1, NULL);
|
port = (char *)janet_optcstring(argv, offset + 2, offset + 1, NULL);
|
||||||
|
}
|
||||||
|
err = "could not get address info: %s";
|
||||||
|
} else {
|
||||||
|
/* when is_bind is set, we're performing a connect, but wanting to
|
||||||
|
* specify from where we connect, and in general don't care about a
|
||||||
|
* port */
|
||||||
|
int32_t current_offset = 3;
|
||||||
|
if (janet_keyeq(argv[current_offset], "stream") ||
|
||||||
|
janet_keyeq(argv[current_offset], "datagram")) {
|
||||||
|
current_offset = 4;
|
||||||
|
}
|
||||||
|
host = (char *)janet_getcstring(argv, current_offset);
|
||||||
|
port = NULL;
|
||||||
|
err = "could not get address info for connect bind: %s";
|
||||||
}
|
}
|
||||||
/* getaddrinfo */
|
/* getaddrinfo */
|
||||||
struct addrinfo *ai = NULL;
|
struct addrinfo *ai = NULL;
|
||||||
@ -301,7 +319,7 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock
|
|||||||
hints.ai_flags = passive ? AI_PASSIVE : 0;
|
hints.ai_flags = passive ? AI_PASSIVE : 0;
|
||||||
int status = getaddrinfo(host, port, &hints, &ai);
|
int status = getaddrinfo(host, port, &hints, &ai);
|
||||||
if (status) {
|
if (status) {
|
||||||
janet_panicf("could not get address info: %s", gai_strerror(status));
|
janet_panicf(err, gai_strerror(status));
|
||||||
}
|
}
|
||||||
*is_unix = 0;
|
*is_unix = 0;
|
||||||
return ai;
|
return ai;
|
||||||
@ -322,7 +340,7 @@ JANET_CORE_FN(cfun_net_sockaddr,
|
|||||||
int socktype = janet_get_sockettype(argv, argc, 2);
|
int socktype = janet_get_sockettype(argv, argc, 2);
|
||||||
int is_unix = 0;
|
int is_unix = 0;
|
||||||
int make_arr = (argc >= 3 && janet_truthy(argv[3]));
|
int make_arr = (argc >= 3 && janet_truthy(argv[3]));
|
||||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix);
|
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, 0);
|
||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
/* no unix domain socket support on windows yet */
|
/* no unix domain socket support on windows yet */
|
||||||
if (is_unix) {
|
if (is_unix) {
|
||||||
@ -361,11 +379,11 @@ JANET_CORE_FN(cfun_net_connect,
|
|||||||
"Open a connection to communicate with a server. Returns a duplex stream "
|
"Open a connection to communicate with a server. Returns a duplex stream "
|
||||||
"that can be used to communicate with the server. Type is an optional keyword "
|
"that can be used to communicate with the server. Type is an optional keyword "
|
||||||
"to specify a connection type, either :stream or :datagram. The default is :stream. ") {
|
"to specify a connection type, either :stream or :datagram. The default is :stream. ") {
|
||||||
janet_arity(argc, 2, 3);
|
janet_arity(argc, 2, 4);
|
||||||
|
|
||||||
int socktype = janet_get_sockettype(argv, argc, 2);
|
int socktype = janet_get_sockettype(argv, argc, 2);
|
||||||
int is_unix = 0;
|
int is_unix = 0;
|
||||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix);
|
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, 0);
|
||||||
|
|
||||||
/* Create socket */
|
/* Create socket */
|
||||||
JSock sock = JSOCKDEFAULT;
|
JSock sock = JSOCKDEFAULT;
|
||||||
@ -401,6 +419,35 @@ JANET_CORE_FN(cfun_net_connect,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: check if need bind and bind! */
|
||||||
|
ai = NULL;
|
||||||
|
if (argc >= 3 && is_unix == 0) {
|
||||||
|
if (argc == 4 ||
|
||||||
|
(!janet_keyeq(argv[3], "stream") &&
|
||||||
|
!janet_keyeq(argv[3], "datagram"))) {
|
||||||
|
ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check all addrinfos in a loop for the first that we can bind to. */
|
||||||
|
struct addrinfo *rp = NULL;
|
||||||
|
for (rp = ai; rp != NULL; rp = rp->ai_next) {
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
sock = WSASocketW(rp->ai_family, rp->ai_socktype | JSOCKFLAGS, rp->ai_protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
|
||||||
|
#else
|
||||||
|
sock = socket(rp->ai_family, rp->ai_socktype | JSOCKFLAGS, rp->ai_protocol);
|
||||||
|
#endif
|
||||||
|
if (!JSOCKVALID(sock)) continue;
|
||||||
|
|
||||||
|
/* Bind */
|
||||||
|
if (bind(sock, rp->ai_addr, (int) rp->ai_addrlen) == 0) break;
|
||||||
|
JSOCKCLOSE(sock);
|
||||||
|
}
|
||||||
|
freeaddrinfo(ai);
|
||||||
|
if (NULL == rp) {
|
||||||
|
janet_panic("could not bind to any sockets");
|
||||||
|
}
|
||||||
|
|
||||||
/* Connect to socket */
|
/* Connect to socket */
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
int status = WSAConnect(sock, addr, addrlen, NULL, NULL, NULL, NULL);
|
int status = WSAConnect(sock, addr, addrlen, NULL, NULL, NULL, NULL);
|
||||||
@ -502,7 +549,7 @@ JANET_CORE_FN(cfun_net_listen,
|
|||||||
/* Get host, port, and handler*/
|
/* Get host, port, and handler*/
|
||||||
int socktype = janet_get_sockettype(argv, argc, 2);
|
int socktype = janet_get_sockettype(argv, argc, 2);
|
||||||
int is_unix = 0;
|
int is_unix = 0;
|
||||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix);
|
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix, 0);
|
||||||
|
|
||||||
JSock sfd = JSOCKDEFAULT;
|
JSock sfd = JSOCKDEFAULT;
|
||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
|
Loading…
Reference in New Issue
Block a user