E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gmsg_unix.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gmsg_unix.cpp
19 //
20
21 #include "gdef.h"
22 #include "gmsg.h"
23 #include "gprocess.h"
24 #include "gstr.h"
25 #include <cstring> // memcpy
26 #include <stdexcept>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/uio.h>
31
32 ssize_t G::Msg::send( int fd , const void * buffer , size_t size , int flags ,
33 int fd_to_send )
34 {
35 return sendto( fd , buffer , size , flags , nullptr , 0 , fd_to_send ) ;
36 }
37
38 ssize_t G::Msg::sendto( int fd , const void * buffer , size_t size , int flags ,
39 const sockaddr * address_p , socklen_t address_n , int fd_to_send )
40 {
41 static struct ::msghdr msg_zero ;
42 struct ::msghdr msg = msg_zero ;
43
44 msg.msg_name = const_cast<sockaddr*>(address_p) ;
45 msg.msg_namelen = address_n ;
46
47 static struct ::iovec io_zero ;
48 struct ::iovec io = io_zero ;
49 io.iov_base = const_cast<void*>(buffer) ;
50 io.iov_len = size ;
51 msg.msg_iov = &io ;
52 msg.msg_iovlen = 1 ;
53
54 char control_buffer[CMSG_SPACE(sizeof(int))] ;
55 if( fd_to_send == -1 )
56 {
57 msg.msg_control = nullptr ;
58 msg.msg_controllen = 0U ;
59 }
60 else
61 {
62 std::memset( control_buffer , 0 , sizeof(control_buffer) ) ;
63 msg.msg_control = control_buffer ;
64 msg.msg_controllen = sizeof(control_buffer) ;
65
66 struct ::cmsghdr * cmsg = CMSG_FIRSTHDR( &msg ) ;
67 cmsg->cmsg_len = CMSG_LEN( sizeof(int) ) ;
68 cmsg->cmsg_level = SOL_SOCKET ;
69 cmsg->cmsg_type = SCM_RIGHTS ;
70 std::memcpy( CMSG_DATA(cmsg) , &fd_to_send , sizeof(int) ) ;
71 }
72
73 return ::sendmsg( fd , &msg , flags | MSG_NOSIGNAL ) ;
74 }
75
76 ssize_t G::Msg::recv( int fd , void * buffer , size_t size , int flags )
77 {
78 return ::recv( fd , buffer , size , flags ) ;
79 }
80
81 ssize_t G::Msg::recv( int fd , void * buffer , size_t size , int flags ,
82 int * fd_received_p )
83 {
84 return recvfrom( fd , buffer , size , flags , nullptr , nullptr , fd_received_p ) ;
85 }
86
87 ssize_t G::Msg::recvfrom( int fd , void * buffer , size_t size , int flags ,
88 sockaddr * address_p , socklen_t * address_np , int * fd_received_p )
89 {
90 static struct ::msghdr msg_zero ;
91 struct ::msghdr msg = msg_zero ;
92
93 msg.msg_name = address_p ;
94 msg.msg_namelen = address_np == nullptr ? socklen_t(0) : *address_np ;
95
96 struct ::iovec io ;
97 io.iov_base = buffer ;
98 io.iov_len = size ;
99 msg.msg_iov = &io ;
100 msg.msg_iovlen = 1 ;
101
102 char control_buffer[CMSG_SPACE(sizeof(int))] ;
103 msg.msg_control = control_buffer ;
104 msg.msg_controllen = sizeof(control_buffer) ;
105
106 ssize_t rc = ::recvmsg( fd , &msg , flags ) ;
107 int e = G::Process::errno_() ;
108 if( rc >= 0 && msg.msg_controllen > 0U && fd_received_p != nullptr )
109 {
110 struct cmsghdr * cmsg = CMSG_FIRSTHDR( &msg ) ;
111 if( cmsg != nullptr && cmsg->cmsg_type == SCM_RIGHTS )
112 {
113 std::memcpy( fd_received_p , CMSG_DATA(cmsg) , sizeof(int) ) ;
114 }
115 }
116 if( rc >= 0 && address_np != nullptr )
117 {
118 *address_np = msg.msg_namelen ;
119 }
120 G::Process::errno_( G::SignalSafe() , e ) ;
121 return rc ; // with errno
122 }
123
124 bool G::Msg::fatal( int error )
125 {
126 return !(
127 error == 0 ||
128 error == EAGAIN ||
129 error == EINTR ||
130 error == EMSGSIZE || // moot
131 error == ENOBUFS ||
132 error == ENOMEM ||
133 false ) ;
134 }
135
136 /// \file gmsg_unix.cpp
G::SignalSafe
An empty structure that is used to indicate a signal-safe, reentrant implementation.
Definition: gsignalsafe.h:36
G::Msg::recv
static ssize_t recv(SOCKET, void *, size_t, int)
A recv() wrapper.
Definition: gmsg_unix.cpp:76
G::Msg::recvfrom
static ssize_t recvfrom(SOCKET, void *, size_t, int, sockaddr *, socklen_t *, int *fd_received_p=nullptr)
A recvfrom() replacement using recvmsg().
Definition: gmsg_unix.cpp:87
G::Msg::send
static ssize_t send(SOCKET, const void *, size_t, int, int fd_to_send=-1)
A send() replacement using sendmsg().
Definition: gmsg_unix.cpp:32
G::Msg::sendto
static ssize_t sendto(SOCKET, const void *, size_t, int, const sockaddr *, socklen_t, int fd_to_send=-1)
A sendto() replacement using sendmsg().
Definition: gmsg_unix.cpp:38
gstr.h
gprocess.h
gmsg.h
G::Msg::fatal
static bool fatal(int error)
Returns true if the error value indicates a permanent problem with the socket.
Definition: gmsg_unix.cpp:124