00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef USE_TCP
00031
00032 #include <sys/types.h>
00033 #include <sys/socket.h>
00034 #include <sys/uio.h>
00035 #include <stdlib.h>
00036 #include <errno.h>
00037 #include <string.h>
00038
00039 #include "dprint.h"
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 int recv_all(int socket, void* data, int data_len, int flags)
00060 {
00061 int b_read;
00062 int n;
00063
00064 b_read=0;
00065 again:
00066 n=recv(socket, (char*)data, data_len, flags);
00067 if (n<0){
00068
00069 if (errno==EINTR) goto again;
00070
00071 if ((errno==EAGAIN)||(errno==EWOULDBLOCK)) return n;
00072 LM_CRIT("1st recv on %d failed: %s\n", socket, strerror(errno));
00073 return n;
00074 }
00075 b_read+=n;
00076 while( (b_read!=data_len) && (n)){
00077 n=recv(socket, (char*)data+b_read, data_len-b_read, MSG_WAITALL);
00078 if (n<0){
00079
00080 if (errno==EINTR) continue;
00081 LM_CRIT("2nd recv on %d failed: %s\n",
00082 socket, strerror(errno));
00083 return n;
00084 }
00085 b_read+=n;
00086 }
00087 return b_read;
00088 }
00089
00090
00091
00092
00093
00094 int send_all(int socket, void* data, int data_len)
00095 {
00096 int n;
00097
00098 again:
00099 n=send(socket, data, data_len, 0);
00100 if (n<0){
00101
00102 if (errno==EINTR) goto again;
00103 LM_CRIT("send on %d failed: %s\n", socket, strerror(errno));
00104 }
00105 return n;
00106 }
00107
00108
00109
00110 int send_fd(int unix_socket, void* data, int data_len, int fd)
00111 {
00112 struct msghdr msg;
00113 struct iovec iov[1];
00114 int ret;
00115 #ifdef HAVE_MSGHDR_MSG_CONTROL
00116 struct cmsghdr* cmsg;
00117
00118 union {
00119 struct cmsghdr cm;
00120 char control[CMSG_SPACE(sizeof(fd))];
00121 }control_un;
00122
00123 msg.msg_control=control_un.control;
00124
00125
00126 msg.msg_controllen=CMSG_LEN(sizeof(fd));
00127
00128 cmsg=CMSG_FIRSTHDR(&msg);
00129 cmsg->cmsg_level = SOL_SOCKET;
00130 cmsg->cmsg_type = SCM_RIGHTS;
00131 cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
00132 *(int*)CMSG_DATA(cmsg)=fd;
00133 msg.msg_flags=0;
00134 #else
00135 msg.msg_accrights=(caddr_t) &fd;
00136 msg.msg_accrightslen=sizeof(fd);
00137 #endif
00138
00139 msg.msg_name=0;
00140 msg.msg_namelen=0;
00141
00142 iov[0].iov_base=data;
00143 iov[0].iov_len=data_len;
00144 msg.msg_iov=iov;
00145 msg.msg_iovlen=1;
00146
00147 again:
00148 ret=sendmsg(unix_socket, &msg, 0);
00149 if (ret<0){
00150 if (errno==EINTR) goto again;
00151 LM_CRIT("sendmsg failed on %d: %s\n", unix_socket, strerror(errno));
00152 }
00153
00154 return ret;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 int receive_fd(int unix_socket, void* data, int data_len, int* fd, int flags)
00168 {
00169 struct msghdr msg;
00170 struct iovec iov[1];
00171 int new_fd;
00172 int ret;
00173 int n;
00174 #ifdef HAVE_MSGHDR_MSG_CONTROL
00175 struct cmsghdr* cmsg;
00176 union{
00177 struct cmsghdr cm;
00178 char control[CMSG_SPACE(sizeof(new_fd))];
00179 }control_un;
00180
00181 msg.msg_control=control_un.control;
00182 msg.msg_controllen=sizeof(control_un.control);
00183 #else
00184 msg.msg_accrights=(caddr_t) &new_fd;
00185 msg.msg_accrightslen=sizeof(int);
00186 #endif
00187
00188 msg.msg_name=0;
00189 msg.msg_namelen=0;
00190
00191 iov[0].iov_base=data;
00192 iov[0].iov_len=data_len;
00193 msg.msg_iov=iov;
00194 msg.msg_iovlen=1;
00195
00196 again:
00197 ret=recvmsg(unix_socket, &msg, flags);
00198 if (ret<0){
00199 if (errno==EINTR) goto again;
00200 if ((errno==EAGAIN)||(errno==EWOULDBLOCK)) goto error;
00201 LM_CRIT("recvmsg on %d failed: %s\n", unix_socket, strerror(errno));
00202 goto error;
00203 }
00204 if (ret==0){
00205
00206 LM_CRIT("EOF on %d\n", unix_socket);
00207 goto error;
00208 }
00209 if (ret<data_len){
00210 LM_WARN("too few bytes read (%d from %d) trying to fix...\n",
00211 ret, data_len);
00212
00213 n=recv_all(unix_socket, (char*)data+ret, data_len-ret, MSG_WAITALL);
00214 if (n>=0) ret+=n;
00215 else{
00216 ret=n;
00217 goto error;
00218 }
00219 }
00220
00221 #ifdef HAVE_MSGHDR_MSG_CONTROL
00222 cmsg=CMSG_FIRSTHDR(&msg);
00223 if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
00224 if (cmsg->cmsg_type!= SCM_RIGHTS){
00225 LM_ERR("msg control type != SCM_RIGHTS\n");
00226 ret=-1;
00227 goto error;
00228 }
00229 if (cmsg->cmsg_level!= SOL_SOCKET){
00230 LM_ERR("msg level != SOL_SOCKET\n");
00231 ret=-1;
00232 goto error;
00233 }
00234 *fd=*((int*) CMSG_DATA(cmsg));
00235 }else{
00236
00237
00238
00239 *fd=-1;
00240
00241 }
00242 #else
00243 if (msg.msg_accrightslen==sizeof(int)){
00244 *fd=new_fd;
00245 }else{
00246
00247
00248 *fd=-1;
00249 }
00250 #endif
00251
00252 error:
00253 return ret;
00254 }
00255 #endif