4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include <netinet/tcp.h>
17 #include "lutf_message.h"
19 static lutf_rc_t doNonBlockingConnect(int iSockFd, struct sockaddr *psSA,
20 int iSAlen, int iNsec)
27 iN = connect(iSockFd, (struct sockaddr *)psSA, iSAlen);
29 if (errno != EINPROGRESS) {
30 PERROR("Connect Failed: %s:%d", strerror(errno), errno);
31 return EN_LUTF_RC_FAIL;
37 FD_SET(iSockFd, &rset);
42 iN = select(iSockFd+1, &rset, &wset, NULL,
43 iNsec ? &tval : NULL);
46 PERROR("Select timed out");
47 return EN_LUTF_RC_FAIL;
51 return EN_LUTF_RC_FAIL;
53 if (FD_ISSET(iSockFd, &rset) || FD_ISSET(iSockFd, &wset)) {
54 iLen = sizeof(iError);
55 if (getsockopt(iSockFd, SOL_SOCKET, SO_ERROR, &iError,
56 (socklen_t *)&iLen) < 0) {
57 PERROR("getsockopt failed indicating connect failure, errno= %d",
59 return EN_LUTF_RC_FAIL;
62 PERROR("select error: sockfd not set");
63 return EN_LUTF_RC_FAIL;
67 /* There was some error when connecting */
70 PERROR("Error on connect. errno = %s", strerror(errno));
71 return EN_LUTF_RC_FAIL;
77 int establishTCPConnection(unsigned long uiAddress,
82 int iOption = 1, iFlags;
84 struct sockaddr_in tm_addr;
85 lutf_rc_t eRc = EN_LUTF_RC_OK;
87 /* Create TCP socket */
88 rsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
90 return EN_LUTF_RC_FAIL;
92 /* Turn off Nagle's algorithm for this TCP socket. */
93 setsockopt(rsocket, IPPROTO_TCP, TCP_NODELAY, (void *)&iOption,
97 if (setsockopt(rsocket, SOL_SOCKET, SO_REUSEADDR, (void *)&iFlags,
98 sizeof(iFlags)) < 0) {
99 /* Cannot change the socket options. */
101 return EN_LUTF_RC_FAIL;
104 iFlags = fcntl(rsocket, F_GETFL, 0);
106 fcntl(rsocket, F_SETFL, iFlags | O_NONBLOCK);
108 fcntl(rsocket, F_SETFL, iFlags & (~O_NONBLOCK));
110 /* Set address parameters for TCP connection */
111 bzero((char *) &tm_addr, sizeof(tm_addr));
112 tm_addr.sin_addr.s_addr = (endian) ? htonl(uiAddress) : uiAddress;
113 tm_addr.sin_port = (endian) ? htons(iPort) : iPort;
114 tm_addr.sin_family = AF_INET;
116 eRc = doNonBlockingConnect(rsocket, (struct sockaddr *)&tm_addr,
117 sizeof(tm_addr), SOCKET_CONN_TIMEOUT_SEC);
118 if (eRc != EN_LUTF_RC_OK) {
126 lutf_rc_t closeTcpConnection(int iTcpSocket)
130 PDEBUG("closing socket %d", iTcpSocket);
131 rc = close(iTcpSocket);
132 if (rc && errno != EINPROGRESS && errno != ECONNRESET) {
133 PERROR("failed to close %d:%d\n", iTcpSocket, errno);
134 return EN_LUTF_RC_FAIL;
137 return EN_LUTF_RC_OK;
142 * Send a TCP message to the specified TCP socket.
144 * Parameters: iTcpSocket - Socket file descriptor
145 * pcBody - TCP message to send.
146 * iBodySize - size of the body
149 lutf_rc_t sendTcpMessage(int iTcpSocket, char *pcBody, int iBodySize)
155 if (iTcpSocket == INVALID_TCP_SOCKET)
156 return(EN_LUTF_RC_FAIL);
158 /* Start writing bytes to the socket and keep writing until we have
159 * the requested number of bytes sent.
161 pcCur = (char *)pcBody;
165 /* Send as many bytes, up to current maximum, as we can. */
166 tNwritten = write(iTcpSocket, pcCur, tNleft);
169 if (errno == EINTR) {
170 /* We were interrupted, but this is not an
175 /* System error has occurred. */
176 PERROR("Failed to send message (%d, %p, %d, %u) %s:%d",
177 iTcpSocket, pcBody, iBodySize, tNwritten,
178 strerror(errno), errno);
179 return EN_LUTF_RC_SYS_ERR;
187 return EN_LUTF_RC_OK;
192 * populate the LUTF message header with the passed in information.
194 * Parameters: rsocket - Socket file descriptor
195 * msg_hdr - pointer to the message header.
196 * msg_type - type of message
197 * msg_size - message size
198 * lutf_version_number - version number
201 lutf_rc_t populateMsgHdr(int rsocket, char *msg_hdr,
202 int msg_type, int msg_size,
203 int lutf_version_number)
205 lutf_message_hdr_t *hdr = NULL;
206 struct sockaddr_in sock;
207 int len = sizeof(sock);
210 if (rsocket == INVALID_TCP_SOCKET ||
212 PERROR("bad parameter: hdr = %p, socket = %d",
214 return EN_LUTF_RC_FAIL;
217 hdr = (lutf_message_hdr_t *)msg_hdr;
219 /* get the local IP address we are connected on */
220 rc = getsockname(rsocket,
221 (struct sockaddr *)&sock,
224 PERROR("getsockname failure %s:%s:%d",
225 strerror(errno), strerror(rc), rc);
226 return EN_LUTF_RC_FAIL;
229 hdr->type = htonl(msg_type);
230 hdr->len = htonl(msg_size);
231 hdr->ip.s_addr = sock.sin_addr.s_addr;
232 hdr->version = htonl(lutf_version_number);
234 return EN_LUTF_RC_OK;
237 lutf_rc_t readTcpMessage(int iFd, char *pcBuffer,
238 int iBufferSize, int iTimeout)
243 struct timeval sTimeout;
246 /* Grab a copy of the client's file descriptor
247 * (and make sure it isn't -1).
250 return EN_LUTF_RC_CLIENT_CLOSED;
252 /* set the timeout */
254 sTimeout.tv_sec = iTimeout;
255 sTimeout.tv_usec = 0;
256 setsockopt(iFd, SOL_SOCKET, SO_RCVTIMEO, (void *)&sTimeout,
258 setsockopt(iFd, SOL_SOCKET, SO_SNDTIMEO, (void *)&sTimeout,
261 iFlags = fcntl(iFd, F_GETFL, 0);
262 fcntl(iFd, F_SETFL, iFlags & (~O_NONBLOCK));
264 /* if no timeout specified do a non blocking read */
265 iFlags = fcntl(iFd, F_GETFL, 0);
266 fcntl(iFd, F_SETFL, iFlags | O_NONBLOCK);
269 /* Start reading in bytes from the socket and keep reading until we have
270 * the requested number of bytes or EOF occurs.
273 tNleft = iBufferSize;
275 /* Get as many bytes, up to current maximum as we can. */
276 tNread = read(iFd, pcCur, tNleft);
279 if (errno == EINTR) {
280 /* We were interrupted, but this is not an
284 } else if ((errno == EAGAIN) && (!iTimeout)) {
285 return EN_LUTF_RC_SOCKET_FAIL;
287 /* System error has occurred. */
288 return EN_LUTF_RC_SOCKET_FAIL;
292 /* End of file encountered. This is most
293 * likely the client closing their end of the
296 return EN_LUTF_RC_SOCKET_FAIL;
304 return EN_LUTF_RC_OK;
307 lutf_rc_t lutf_send_msg(int fd, char *msg, size_t msg_size,
308 lutf_msg_type_t type)
310 lutf_rc_t rc = EN_LUTF_RC_RPC_FAIL;
311 lutf_message_hdr_t hdr;
313 rc = populateMsgHdr(fd, (char *)&hdr, type,
314 msg_size, LUTF_VERSION_NUMBER);
315 if (rc != EN_LUTF_RC_OK) {
316 PERROR("Failed to populate message header");
320 rc = sendTcpMessage(fd, (char *)&hdr, sizeof(hdr));
321 if (rc != EN_LUTF_RC_OK) {
322 PERROR("Failed to send msg header");
327 rc = sendTcpMessage(fd, msg, msg_size);
328 if (rc != EN_LUTF_RC_OK) {
329 PERROR("Failed to send msg body");