summaryrefslogtreecommitdiff
path: root/erts/emulator
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2014-07-22 18:01:19 +0200
committerErlang/OTP <otp@erlang.org>2014-07-22 18:01:19 +0200
commit52810718bcd607ebb538036bdbb87b5e94634984 (patch)
treeb6cc19578e968c38a2510585e481b98c279bf7c4 /erts/emulator
parent450f0f893b5d28e6d967b163111f8a8a6032b0e1 (diff)
parenta60f3d879dfcdd018f1fea20790be901fbafeae4 (diff)
downloaderlang-52810718bcd607ebb538036bdbb87b5e94634984.tar.gz
Merge branch 'lukas/kernel/bind_with_fdopen/OTP-12061' into maint-r16
* lukas/kernel/bind_with_fdopen/OTP-12061: Fix default behaviour for legacy fdopen erts: Fix inet close on prebound fds kernel: When doing an fdopen we now also bind the fd to the specified addr/port
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/drivers/common/inet_drv.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 45fac69303..4cc31c1344 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -4053,7 +4053,7 @@ static int erl_inet_close(inet_descriptor* desc)
desc_close(desc);
desc->state = INET_STATE_CLOSED;
} else if (desc->prebound && (desc->s != INVALID_SOCKET)) {
- sock_select(desc, FD_READ | FD_WRITE | FD_CLOSE, 0);
+ sock_select(desc, FD_READ | FD_WRITE | FD_CLOSE | ERL_DRV_USE_NO_CALLBACK, 0);
desc->event_mask = 0;
#ifdef __WIN32__
desc->forced_events = 0;
@@ -4155,7 +4155,8 @@ static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type,
/* as inet_open but pass in an open socket (MUST BE OF RIGHT TYPE) */
static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
- SOCKET s, char** rbuf, ErlDrvSizeT rsize)
+ SOCKET s, Uint32 bound,
+ char** rbuf, ErlDrvSizeT rsize)
{
inet_address name;
unsigned int sz = sizeof(name);
@@ -4172,7 +4173,12 @@ static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
#ifdef __WIN32__
driver_select(desc->port, desc->event, ERL_DRV_READ, 1);
#endif
- desc->state = INET_STATE_BOUND; /* assume bound */
+
+ if (bound)
+ desc->state = INET_STATE_BOUND;
+ else
+ desc->state = INET_STATE_OPEN;
+
if (type == SOCK_STREAM) { /* check if connected */
sz = sizeof(name);
if (!IS_SOCKET_ERROR(sock_peer(s, (struct sockaddr*) &name, &sz)))
@@ -8642,10 +8648,11 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
break;
}
- case INET_REQ_FDOPEN: { /* pass in an open socket */
+ case INET_REQ_FDOPEN: { /* pass in an open (and optionally bound) socket */
int domain;
+ int bound;
DEBUGF(("tcp_inet_ctl(%ld): FDOPEN\r\n", (long)desc->inet.port));
- if (len != 6) return ctl_error(EINVAL, rbuf, rsize);
+ if (len != 6 && len != 10) return ctl_error(EINVAL, rbuf, rsize);
switch(buf[0]) {
case INET_AF_INET:
domain = AF_INET;
@@ -8663,8 +8670,13 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
return ctl_error(EINVAL, rbuf, rsize);
}
if (buf[1] != INET_TYPE_STREAM) return ctl_error(EINVAL, rbuf, rsize);
+
+ if (len == 6) bound = 1;
+ else bound = get_int32(buf+2+4);
+
return inet_ctl_fdopen(INETP(desc), domain, SOCK_STREAM,
- (SOCKET) get_int32(buf+2), rbuf, rsize);
+ (SOCKET) get_int32(buf+2),
+ bound, rbuf, rsize);
break;
}
@@ -10409,10 +10421,11 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
return replen;
- case INET_REQ_FDOPEN: { /* pass in an open (and bound) socket */
+ case INET_REQ_FDOPEN: { /* pass in an open (and optionally bound) socket */
SOCKET s;
+ int bound;
DEBUGF(("packet inet_ctl(%ld): FDOPEN\r\n", (long)desc->port));
- if (len != 6) {
+ if (len != 6 && len != 10) {
return ctl_error(EINVAL, rbuf, rsize);
}
switch (buf[0]) {
@@ -10437,7 +10450,11 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
return ctl_error(EINVAL, rbuf, rsize);
}
s = (SOCKET)get_int32(buf+2);
- replen = inet_ctl_fdopen(desc, af, type, s, rbuf, rsize);
+
+ if (len == 6) bound = 1;
+ else bound = get_int32(buf+2+4);
+
+ replen = inet_ctl_fdopen(desc, af, type, s, bound, rbuf, rsize);
if ((*rbuf)[0] != INET_REP_ERROR) {
if (desc->active)