37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
44 #include <sys/socket.h>
45 #include <netinet/in.h>
47 #include <arpa/inet.h>
51 #include "ac/getopt.h"
61 static struct s2s_t *s2s_list = 0;
84 for (p = &::s2s_list; *p != 0; p = &(*p)->
next) {
106 b =
" -b {y|n}\t\t" "blocking mode (default: yes)\n";
107 C =
" -C\t\t\t" "create socket (default: connect to existing)\n";
108 h =
" -h <host>\t\t" "host name (for INET sockets; default: \"localhost\")\n";
109 n =
" -n <channels>\t" "number of channels (default: auto-detect)\n";
110 p =
" -p <port>\t\t" "port number (for INET sockets)\n";
111 P =
" -P <path>\t\t" "path (for LOCAL sockets)\n";
112 s =
" -s\t\t\t" "decrease verbosity level\n";
113 t =
" -t <type>\t\t" "socket type { tcp | udp }\n";
116 F =
" -F <format>\t\t" "output format (%[.<precision>]{eEfF})\n";
121 " MBDyn (C) is a multibody analysis code.\n"
122 " http://www.mbdyn.org\n"
124 " Copyright (C) 1996-2017\n"
126 " Pierangelo Masarati <masarati@aero.polimi.it>\n"
128 " Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano\n"
129 " via La Masa, 34 - 20156 Milano, Italy\n"
130 " http://www.aero.polimi.it\n"
132 " usage: " << this->
progname <<
" [options]\n"
150 if (this->
sock >= 0) {
162 s2s_shutdown(
int signum)
164 struct s2s_t **p, **nextp;
166 for (p = &::s2s_list; *p != 0; p = nextp ) {
178 parse_format(
const char *fmt)
180 char *f = (
char *)fmt, *
next;
188 unsigned precision = strtoul(f, &
next, 10);
190 silent_cerr(
"unable to parse \"precision\" "
192 "\"" << fmt <<
"\"" << std::endl);
195 std::cout.precision(precision);
199 if (f[0] ==
'e' || f[0] ==
'E') {
200 std::cout.setf(std::ios::scientific);
202 }
else if (f[0] !=
'f' && f[0] !=
'F') {
203 silent_cerr(
"unable to parse format string "
204 "\"" << fmt <<
"\"" << std::endl);
214 next = std::strrchr(argv[0],
'/');
223 if (strncmp(next,
"lt-",
STRLENOF(
"lt-")) == 0) {
227 if (strcmp(next,
"socket2stream") == 0) {
231 }
else if (strcmp(next,
"stream2socket") == 0) {
236 silent_cerr(
"tool name mismatch: \"" << argv[0] <<
"\"" << std::endl);
240 const char *optstring;
242 optstring =
"b:Ch:n:p:P:st:";
245 optstring =
"b:CF:h:n:p:P:st:";
249 int opt =
getopt(argc, argv, optstring);
257 if (strcmp(
optarg,
"y") == 0) {
259 }
else if (strcmp(
optarg,
"n") == 0) {
262 silent_cerr(
"invalid value "
284 if (next[0] !=
'\0') {
285 silent_cerr(
"unable to parse option -n "
294 if (next[0] !=
'\0') {
295 silent_cerr(
"unable to parse option -p "
311 if (strcasecmp(
optarg,
"udp") == 0) {
314 }
else if (strcasecmp(
optarg,
"tcp") != 0) {
315 silent_cerr(
"unable to parse option -p "
327 if (this->
path == 0 && (this->
host == 0 && this->
port == -1)) {
336 struct sockaddr *addrp = 0;
341 this->addr.ms_len =
sizeof(this->addr.ms_addr.ms_addr_local);
346 this->path, this->addr.ms_type, this->create, &save_errno);
348 if (this->
sock == -1) {
349 const char *err_msg = strerror(save_errno);
351 silent_cerr(
"socket(" << this->
buf <<
") failed "
352 "(" << save_errno <<
": " << err_msg <<
")"
356 }
else if (this->
sock == -2) {
357 const char *err_msg = strerror(save_errno);
359 silent_cerr(
"bind(" << this->
buf <<
") failed "
360 "(" << save_errno <<
": " << err_msg <<
")"
368 addr.
ms_len =
sizeof(this->addr.ms_addr.ms_addr_inet);
370 if (this->
host == 0) {
372 this->
host =
"127.0.0.1";
375 char *p = std::strchr(const_cast<char *>(this->
host),
':');
377 if (this->
port != -1) {
378 silent_cerr(
"port already passed as '-p'" << std::endl);
383 unsigned long tmp_port;
387 tmp_port = strtoul(p, &next, 10);
388 if (next[0] !=
'\0') {
389 silent_cerr(
"unable to parse port out of "
390 "\"" << this->
host <<
":" << p <<
"\""
395 this->
port = tmp_port;
399 std::ostringstream os;
400 os << this->
host <<
":" << this->
port;
401 this->
buf = os.str();
404 this->host, this->port, this->addr.ms_type, this->create, &save_errno);
406 if (this->
sock == -1) {
407 const char *err_msg = strerror(save_errno);
409 silent_cerr(
"socket(" << this->
buf <<
") failed "
410 "(" << save_errno <<
": " << err_msg <<
")"
414 }
else if (this->
sock == -2) {
415 const char *err_msg = strerror(save_errno);
417 silent_cerr(
"bind(" << this->
buf <<
") failed "
418 "(" << save_errno <<
": " << err_msg <<
")"
422 }
else if (this->
sock == -3) {
423 silent_cerr(
"illegal host[:port] name \"" << this->
buf <<
"\" "
424 "(" << save_errno <<
")"
432 if (listen(this->
sock, 1) < 0) {
434 const char *err_msg = strerror(save_errno);
436 silent_cerr(
"listen(" << this->
sock <<
"," << this->
buf <<
") failed "
437 "(" << save_errno <<
": " << err_msg <<
")"
444 this->sock = accept(sock, addrp, &len);
446 if (this->sock == -1) {
448 const char *err_msg = strerror(save_errno);
450 silent_cerr(
"accept(" << this->sock <<
",\"" << this->
buf <<
"\") "
451 "failed (" << save_errno <<
": " << err_msg <<
")"
457 if (connect(this->sock, addrp,
addr.
ms_len) < 0) {
459 const char *err_msg = strerror(save_errno);
461 silent_cerr(
"connect(" << this->sock <<
",\"" << this->
buf <<
"\"," <<
addr.
ms_len <<
") "
462 "failed (" << save_errno <<
": " << err_msg <<
")"
469 signal(SIGTERM, s2s_shutdown);
470 signal(SIGINT, s2s_shutdown);
471 signal(SIGPIPE, s2s_shutdown);
485 flags |= MSG_DONTWAIT;
489 flags &= ~MSG_DONTWAIT;
495 return ::send(sock, (
char *)&
dbuf[0],
sizeof(
double)*
nChannels, flags);
498 return ::sendto(sock, (
char *)&
dbuf[0],
sizeof(
double)*
nChannels, flags,
510 flags |= MSG_DONTWAIT;
514 flags &= ~MSG_DONTWAIT;
520 return ::recv(sock, (
char *)&
dbuf[0],
sizeof(
double)*
nChannels, flags);
523 return ::recvfrom(sock, (
char *)&
dbuf[0],
sizeof(
double)*
nChannels, flags, 0, 0);
union s2s_sockaddr_t::@54 ms_addr
int mbdyn_make_named_socket_type(struct sockaddr_un *name, const char *path, int socket_type, int dobind, int *perror)
struct sockaddr_in ms_addr_inet
struct sockaddr ms_addr_generic
ssize_t send(int flags) const
int mbdyn_make_inet_socket_type(struct sockaddr_in *name, const char *hostname, unsigned short int port, int socket_type, int dobind, int *perror)
bool is_blocking(void) const
struct sockaddr_un ms_addr_local
std::vector< double > dbuf
int getopt(int argc, char *const argv[], const char *opts)
void parse(int argc, char *argv[])