From: Takashi Yano <takashi.yano@nifty.ne.jp>
To: cygwin@cygwin.com
Subject: Problems of AF_INET domain socket regarding out-of-band data.
Date: Wed, 13 Jun 2018 15:02:00 -0000 [thread overview]
Message-ID: <20180613224858.7822b08abb75d76b72920095@nifty.ne.jp> (raw)
[-- Attachment #1: Type: text/plain, Size: 1594 bytes --]
Hello,
I have found a few problems of AF_INET domain socket regarding
out-of-band data.
1. recv() with MSG_OOB flag eats normal data if no OOB data
is sent yet.
2. Calling recv() with MSG_OOB flag is blocked if no OOB data
is sent yet.
3. Calling recv() without MSG_OOB flag after receiving OOB data
is blocked even if received data exist in buffer.
Regarding problem 1 and 2, POSIX states as follows about recv().
[EINVAL]
The MSG_OOB flag is set and no out-of-band data is available.
http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
Attached is a sample program to reproduce these problems.
Argument to this program specifies the test mode.
0: cause problem 1
2: cause problem 2
3: cause problem 3
Expected results:
debian:~/OOB> ./server_client 0
recv(OOB): Invalid argument
OOB : (-1)
NORMAL: 1234567890 (10)
debian:~/OOB> ./server_client 1
OOB : A (1)
NORMAL: 1234567890 (10)
debian:~/OOB> ./server_client 2
recv(OOB): Invalid argument
OOB : (-1)
NORMAL: 1234567890 (10)
debian:~/OOB> ./server_client 3
OOB : A (1)
NORMAL: 1234567890 (10)
debian:~/OOB>
Result on cygwin:
[yano@Express5800-S70 ~/OOB]$ ./server_client 0
OOB : 1234567890 (10)
NORMAL: (0)
[yano@Express5800-S70 ~/OOB]$ ./server_client 1
OOB : A (1)
NORMAL: 1234567890 (10)
[yano@Express5800-S70 ~/OOB]$ ./server_client 2
[yano@Express5800-S70 ~/OOB]$ ./server_client 3
OOB : A (1)
[yano@Express5800-S70 ~/OOB]$
Only the result of test mode 1 is as expected.
I have confirmed this occurs in both latest 32bit and 64 bit
cygwin.
--
Takashi Yano <takashi.yano@nifty.ne.jp>
[-- Attachment #2: server_client.c --]
[-- Type: text/x-csrc, Size: 2632 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#define PORT 12345
#define HOST "127.0.0.1"
int server(int mode)
{
int sock0, sock1;
struct sockaddr_in addr;
struct sockaddr_in client;
socklen_t len;
/* Create a socket */
sock0 = socket(AF_INET, SOCK_STREAM, 0);
if (sock0 < 0) {
perror("socket");
return -1;
}
/* Bind */
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sock0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return -1;
}
/* Wait for connection from client */
if (listen(sock0, 1) < 0) {
perror("listen");
return -1;
}
/* Accept connection */
len = sizeof(client);
sock1 = accept(sock0, (struct sockaddr *)&client, &len);
if (sock1 < 0) {
perror("accept");
return -1;
}
/* Send normal data */
if (send(sock1, "1234567890", 10, 0) < 0) {
perror("send");
return -1;
}
if (mode & 1) {
/* Send out-of-band data */
if (send(sock1, "A", 1, MSG_OOB) < 0) {
perror("send(OOB)");
return -1;
}
}
/* Wait for receiving all data at client side */
usleep(200000);
if (mode & 2) {
return -1; /* return -1 to kill client */
}
/* Close client socket */
close(sock1);
/* Close socket for listen */
close(sock0);
return 0;
}
int client()
{
struct sockaddr_in server;
int sock;
char buf[256];
int n;
/* Create a socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("sock");
return -1;
}
/* Setting for connection */
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = inet_addr(HOST);
/* Connect to server */
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("connect");
return -1;
}
/* Wait for sending all data at server side */
usleep(100000);
/* Receive out-of-band data from server */
memset(buf, 0, sizeof(buf));
n = recv(sock, buf, sizeof(buf), MSG_OOB);
if (n<0) {
perror("recv(OOB)");
}
printf("OOB : %s (%d)\n", buf, n);
/* Receive normal data from server */
memset(buf, 0, sizeof(buf));
n = recv(sock, buf, sizeof(buf), 0);
if (n<0) {
perror("recv");
}
printf("NORMAL: %s (%d)\n", buf, n);
/* Close socket */
close(sock);
return 0;
}
int main(int argc, char *argv[])
{
int mode = 0;
pid_t pid;
if (argc >= 2) {
mode = atoi(argv[1]);
}
pid = fork();
if (pid) {
if (server(mode) < 0) kill(pid, SIGTERM);
wait(NULL);
} else {
return client();
}
return 0;
}
[-- Attachment #3: Type: text/plain, Size: 219 bytes --]
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
next reply other threads:[~2018-06-13 13:49 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-13 15:02 Takashi Yano [this message]
2018-06-21 1:35 ` Takashi Yano
2018-06-21 14:05 ` Corinna Vinschen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180613224858.7822b08abb75d76b72920095@nifty.ne.jp \
--to=takashi.yano@nifty.ne.jp \
--cc=cygwin@cygwin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).