UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
platform_pipe.cpp File Reference
#include "config_unix.h"
#include "config_win32.h"
#include "compat/platform_pipe.h"
#include "rtp/net_udp.h"
#include <thread>
Include dependency graph for platform_pipe.cpp:

Go to the source code of this file.

Classes

struct  params
 

Macros

#define DECLARE_TIMEOUT(name, init_val_s)
 
#define socket_error(...)
 

Typedefs

typedef void * sockopt_t
 

Functions

static fd_t connect_to_socket (int local_port)
 
static fd_t open_socket (int *port)
 
void platform_pipe_close (fd_t pipe)
 
int platform_pipe_init (fd_t p[2])
 
static int system_pipe (fd_t p[2])
 return regular pipe if available if our implementation fails
 
static void * worker (void *args)
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

Definition in file platform_pipe.cpp.

Macro Definition Documentation

◆ DECLARE_TIMEOUT

#define DECLARE_TIMEOUT ( name,
init_val_s )
Value:
struct timeval name = { init_val_s, 0 }
const char * name
Definition settings.cpp:193

Definition at line 55 of file platform_pipe.cpp.

Referenced by connect_to_socket(), and platform_pipe_init().

◆ socket_error

Typedef Documentation

◆ sockopt_t

typedef void* sockopt_t

Definition at line 56 of file platform_pipe.cpp.

Function Documentation

◆ connect_to_socket()

static fd_t connect_to_socket ( int local_port)
static

Definition at line 94 of file platform_pipe.cpp.

95{
96 struct sockaddr_in s_in;
97 memset(&s_in, 0, sizeof(s_in));
98 s_in.sin_family = AF_INET;
99 s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
100 s_in.sin_port = htons(local_port);
101 fd_t fd = socket(AF_INET, SOCK_STREAM, 0);
102 if (fd == INVALID_SOCKET) {
103 return INVALID_SOCKET;
104 }
105 int ret;
106
107 DECLARE_TIMEOUT(timeout, 1);
108 DECLARE_TIMEOUT(old_timeout, 0);
109 socklen_t old_timeout_len = sizeof old_timeout;
110 if (getsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<sockopt_t>(&old_timeout), &old_timeout_len) != 0) {
111 socket_error("pipe getsockopt");
112 }
113 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<sockopt_t>(&timeout), sizeof timeout) != 0) {
114 socket_error("pipe setsockopt");
115 }
116 ret = connect(fd, (struct sockaddr *) &s_in,
117 sizeof(s_in));
118 if (ret != 0) {
119 socket_error("pipe connect");
120 CLOSESOCKET(fd);
121 return INVALID_SOCKET;
122 }
123 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<sockopt_t>(&old_timeout), old_timeout_len) != 0) {
124 socket_error("pipe setsockopt");
125 }
126
127 return fd;
128}
int fd_t
#define INVALID_SOCKET
#define CLOSESOCKET
#define DECLARE_TIMEOUT(name, init_val_s)
#define socket_error(...)
void * sockopt_t

References CLOSESOCKET, DECLARE_TIMEOUT, INVALID_SOCKET, and socket_error.

Referenced by worker().

◆ open_socket()

static fd_t open_socket ( int * port)
static

Definition at line 63 of file platform_pipe.cpp.

64{
65 fd_t sock;
66 sock = socket(AF_INET, SOCK_STREAM, 0);
67 if (sock == INVALID_SOCKET) {
68 return INVALID_SOCKET;
69 }
70
71 struct sockaddr_in s_in;
72 memset(&s_in, 0, sizeof(s_in));
73 s_in.sin_family = AF_INET;
74 s_in.sin_addr.s_addr = htonl(INADDR_ANY);
75 s_in.sin_port = htons(0);
76 if (::bind(sock, (const struct sockaddr *) &s_in,
77 sizeof(s_in)) != 0) {
78 CLOSESOCKET(sock);
79 return INVALID_SOCKET;
80 }
81 if (listen(sock, 10) != 0) {
82 CLOSESOCKET(sock);
83 return INVALID_SOCKET;
84 }
85 socklen_t len = sizeof(s_in);
86 if (getsockname(sock, (struct sockaddr *) &s_in, &len) != 0) {
87 CLOSESOCKET(sock);
88 return INVALID_SOCKET;
89 }
90 *port = ntohs(s_in.sin_port);
91 return sock;
92}
int void size_t * len

References CLOSESOCKET, INVALID_SOCKET, and len.

Referenced by platform_pipe_init().

◆ platform_pipe_close()

void platform_pipe_close ( fd_t pipe)

Definition at line 227 of file platform_pipe.cpp.

228{
229 CLOSESOCKET(pipe);
230#ifdef _WIN32
231 WSACleanup();
232#endif
233}

References CLOSESOCKET.

Referenced by state_root::~state_root(), control_done(), control_thread(), udp_exit(), udp_reader(), and ug_control_connection_done().

◆ platform_pipe_init()

int platform_pipe_init ( fd_t p[2])

Definition at line 155 of file platform_pipe.cpp.

156{
157#ifdef _WIN32
158 // This needs to be called twice, indeed, since WSACleanup will be run
159 // on both ends. This call is also required because not all pipes are
160 // destroyed before common_cleanup which calls WSACleanup
161 WSADATA wsaData;
162 int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
163 if (err != 0) {
164 fprintf(stderr, "WSAStartup failed with error %d.", err);
165 return -1;
166 }
167 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
168 fprintf(stderr, "Counld not found usable version of Winsock.\n");
169 WSACleanup();
170 return -1;
171 }
172 err = WSAStartup(MAKEWORD(2, 2), &wsaData);
173 if (err != 0) {
174 fprintf(stderr, "WSAStartup failed with error %d.", err);
175 WSACleanup();
176 return -1;
177 }
178 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
179 fprintf(stderr, "Counld not found usable version of Winsock.\n");
180 WSACleanup();
181 WSACleanup();
182 return -1;
183 }
184#endif
185
186 struct params par{};
187 fd_t sock = open_socket(&par.port);
188 if (sock == INVALID_SOCKET) {
189 perror("open_socket");
190 return system_pipe(p);
191 }
192
193 DECLARE_TIMEOUT(timeout, 1);
194 DECLARE_TIMEOUT(old_timeout, 0);
195 socklen_t old_timeout_len = sizeof old_timeout;
196 if (getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<sockopt_t>(&old_timeout), &old_timeout_len) != 0) {
197 socket_error("pipe getsockopt");
198 }
199 if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<sockopt_t>(&timeout), sizeof timeout) != 0) {
200 socket_error("pipe setsockopt");
201 }
202
203 thread thr(worker, &par);
204
205 p[0] = accept(sock, NULL, NULL);
206 if (p[0] == INVALID_SOCKET) {
207 perror("pipe accept");
208 thr.join();
209 CLOSESOCKET(sock);
210 return system_pipe(p);
211 }
212 thr.join();
213 if (setsockopt(p[0], SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<sockopt_t>(&old_timeout), old_timeout_len) != 0) {
214 socket_error("pipe setsockopt");
215 }
216 p[1] = par.sock;
217 if (p[1] == INVALID_SOCKET) {
218 CLOSESOCKET(sock);
219 perror("accept");
220 return system_pipe(p);
221 }
222 CLOSESOCKET(sock);
223
224 return 0;
225}
static fd_t open_socket(int *port)
static void * worker(void *args)
static int system_pipe(fd_t p[2])
return regular pipe if available if our implementation fails

References CLOSESOCKET, DECLARE_TIMEOUT, INVALID_SOCKET, open_socket(), params::port, params::sock, socket_error, system_pipe(), and worker().

Referenced by state_root::state_root(), control_start(), udp_init_if(), and ug_control_connection_init().

Here is the call graph for this function:

◆ system_pipe()

static int system_pipe ( fd_t p[2])
static

return regular pipe if available if our implementation fails

Definition at line 144 of file platform_pipe.cpp.

145{
146#ifdef _WIN32
147 (void) p;
148 return -1;
149#else
150 fprintf(stderr, "Using native pipe instead of custom implementaton.\n");
151 return pipe(p);
152#endif
153}

Referenced by platform_pipe_init().

◆ worker()

static void * worker ( void * args)
static

Definition at line 135 of file platform_pipe.cpp.

136{
137 struct params *p = (struct params *) args;
138 p->sock = connect_to_socket(p->port);
139
140 return NULL;
141}
static fd_t connect_to_socket(int local_port)

References connect_to_socket(), params::port, and params::sock.

Referenced by platform_pipe_init().

Here is the call graph for this function: