|
25 | 25 | #include <sys/types.h>
|
26 | 26 | #include <sys/mman.h>
|
27 | 27 |
|
| 28 | +#include <arpa/inet.h> |
| 29 | + |
28 | 30 | #include <netdb.h>
|
29 | 31 | #include <netinet/in.h>
|
30 | 32 |
|
@@ -1211,23 +1213,42 @@ static void parse_setsock_options(const char *name)
|
1211 | 1213 | exit(1);
|
1212 | 1214 | }
|
1213 | 1215 |
|
1214 |
| -void xdisconnect(int fd, int addrlen) |
| 1216 | +void xdisconnect(int fd) |
1215 | 1217 | {
|
1216 |
| - struct sockaddr_storage empty; |
| 1218 | + socklen_t addrlen = sizeof(struct sockaddr_storage); |
| 1219 | + struct sockaddr_storage addr, empty; |
1217 | 1220 | int msec_sleep = 10;
|
1218 |
| - int queued = 1; |
1219 |
| - int i; |
| 1221 | + void *raw_addr; |
| 1222 | + int i, cmdlen; |
| 1223 | + char cmd[128]; |
| 1224 | + |
| 1225 | + /* get the local address and convert it to string */ |
| 1226 | + if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) < 0) |
| 1227 | + xerror("getsockname"); |
| 1228 | + |
| 1229 | + if (addr.ss_family == AF_INET) |
| 1230 | + raw_addr = &(((struct sockaddr_in *)&addr)->sin_addr); |
| 1231 | + else if (addr.ss_family == AF_INET6) |
| 1232 | + raw_addr = &(((struct sockaddr_in6 *)&addr)->sin6_addr); |
| 1233 | + else |
| 1234 | + xerror("bad family"); |
| 1235 | + |
| 1236 | + strcpy(cmd, "ss -M | grep -q "); |
| 1237 | + cmdlen = strlen(cmd); |
| 1238 | + if (!inet_ntop(addr.ss_family, raw_addr, &cmd[cmdlen], |
| 1239 | + sizeof(cmd) - cmdlen)) |
| 1240 | + xerror("inet_ntop"); |
1220 | 1241 |
|
1221 | 1242 | shutdown(fd, SHUT_WR);
|
1222 | 1243 |
|
1223 |
| - /* while until the pending data is completely flushed, the later |
| 1244 | + /* |
| 1245 | + * wait until the pending data is completely flushed and all |
| 1246 | + * the MPTCP sockets reached the closed status. |
1224 | 1247 | * disconnect will bypass/ignore/drop any pending data.
|
1225 | 1248 | */
|
1226 | 1249 | for (i = 0; ; i += msec_sleep) {
|
1227 |
| - if (ioctl(fd, SIOCOUTQ, &queued) < 0) |
1228 |
| - xerror("can't query out socket queue: %d", errno); |
1229 |
| - |
1230 |
| - if (!queued) |
| 1250 | + /* closed socket are not listed by 'ss' */ |
| 1251 | + if (system(cmd) != 0) |
1231 | 1252 | break;
|
1232 | 1253 |
|
1233 | 1254 | if (i > poll_timeout)
|
@@ -1281,9 +1302,9 @@ int main_loop(void)
|
1281 | 1302 | return ret;
|
1282 | 1303 |
|
1283 | 1304 | if (cfg_truncate > 0) {
|
1284 |
| - xdisconnect(fd, peer->ai_addrlen); |
| 1305 | + xdisconnect(fd); |
1285 | 1306 | } else if (--cfg_repeat > 0) {
|
1286 |
| - xdisconnect(fd, peer->ai_addrlen); |
| 1307 | + xdisconnect(fd); |
1287 | 1308 |
|
1288 | 1309 | /* the socket could be unblocking at this point, we need the
|
1289 | 1310 | * connect to be blocking
|
|
0 commit comments