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 if ((iN = connect(iSockFd, (struct sockaddr *)psSA, iSAlen)) < 0) {
28 if (errno != EINPROGRESS) {
29 PERROR("Connect Failed: %s:%d", strerror(errno), errno);
30 return EN_LUTF_RC_FAIL;
36 FD_SET(iSockFd, &rset);
41 if ((iN = select(iSockFd+1, &rset, &wset, NULL,
42 iNsec ? &tval : NULL)) == 0) {
44 PERROR("Select timed out");
45 return EN_LUTF_RC_FAIL;
49 return EN_LUTF_RC_FAIL;
51 if (FD_ISSET(iSockFd, &rset) || FD_ISSET(iSockFd, &wset)) {
52 iLen = sizeof(iError);
53 if (getsockopt(iSockFd, SOL_SOCKET, SO_ERROR, &iError, (socklen_t *)&iLen) < 0) {
54 PERROR("getsockopt failed indicating connect failure, errno= %d", errno);
55 return EN_LUTF_RC_FAIL;
58 PERROR("select error: sockfd not set");
59 return EN_LUTF_RC_FAIL;
63 /* There was some error when connecting */
66 PERROR("Error on connect. errno = %s", strerror(errno));
67 return EN_LUTF_RC_FAIL;
73 int establishTCPConnection(unsigned long uiAddress,
78 int iOption = 1, iFlags;
80 struct sockaddr_in tm_addr;
81 lutf_rc_t eRc = EN_LUTF_RC_OK;
83 /* Create TCP socket */
84 if ((rsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
86 return EN_LUTF_RC_FAIL;
88 /* Turn off Nagle's algorithm for this TCP socket. */
89 setsockopt(rsocket, IPPROTO_TCP, TCP_NODELAY, (void *)&iOption,
93 if (setsockopt(rsocket, SOL_SOCKET, SO_REUSEADDR, (void *)&iFlags,
94 sizeof(iFlags)) < 0) {
95 /* Cannot change the socket options. */
97 return EN_LUTF_RC_FAIL;
100 iFlags = fcntl(rsocket, F_GETFL, 0);
102 fcntl(rsocket, F_SETFL, iFlags | O_NONBLOCK);
104 fcntl(rsocket, F_SETFL, iFlags & (~O_NONBLOCK));
106 /* Set address parameters for TCP connection */
107 bzero((char *) &tm_addr, sizeof(tm_addr));
108 tm_addr.sin_addr.s_addr = (endian) ? htonl(uiAddress) : uiAddress;
109 tm_addr.sin_port = (endian) ? htons(iPort) : iPort;
110 tm_addr.sin_family = AF_INET;
112 if ((eRc = doNonBlockingConnect(rsocket,
113 (struct sockaddr *)&tm_addr,
115 SOCKET_CONN_TIMEOUT_SEC))
124 lutf_rc_t closeTcpConnection(int iTcpSocket)
128 PDEBUG("closing socket %d", iTcpSocket);
129 rc = close(iTcpSocket);
130 if (!rc && errno != EINPROGRESS && errno != ECONNRESET) {
131 PERROR("failed to close %d:%d\n", iTcpSocket, errno);
132 return EN_LUTF_RC_FAIL;
135 return EN_LUTF_RC_OK;
140 * Send a TCP message to the specified TCP socket.
142 * Parameters: iTcpSocket - Socket file descriptor
143 * pcBody - TCP message to send.
144 * iBodySize - size of the body
147 lutf_rc_t sendTcpMessage(int iTcpSocket, char *pcBody, int iBodySize)
153 if (iTcpSocket == INVALID_TCP_SOCKET)
154 return(EN_LUTF_RC_FAIL);
156 /* Start writing bytes to the socket and keep writing until we have
157 * the requested number of bytes sent.
159 pcCur = (char *)pcBody;
163 /* Send as many bytes, up to current maximum, as we can. */
164 tNwritten = write(iTcpSocket, pcCur, tNleft);
167 if (errno == EINTR) {
168 /* We were interrupted, but this is not an
173 /* System error has occurred. */
174 PERROR("Failed to send message (%d, %p, %d, %u) %s:%d",
175 iTcpSocket, pcBody, iBodySize, tNwritten,
176 strerror(errno), errno);
177 return EN_LUTF_RC_SYS_ERR;
185 return EN_LUTF_RC_OK;
190 * populate the LUTF message header with the passed in information.
192 * Parameters: rsocket - Socket file descriptor
193 * msg_hdr - pointer to the message header.
194 * msg_type - type of message
195 * msg_size - message size
196 * lutf_version_number - version number
199 lutf_rc_t populateMsgHdr(int rsocket, char *msg_hdr,
200 int msg_type, int msg_size,
201 int lutf_version_number)
203 lutf_message_hdr_t *hdr = NULL;
204 struct sockaddr_in sock;
205 int len = sizeof(sock);
208 if (rsocket == INVALID_TCP_SOCKET ||
210 PERROR("bad parameter: hdr = %p, socket = %d",
212 return EN_LUTF_RC_FAIL;
215 hdr = (lutf_message_hdr_t *)msg_hdr;
217 /* get the local IP address we are connected on */
218 rc = getsockname(rsocket,
219 (struct sockaddr *)&sock,
222 PERROR("getsockname failure %s:%s:%d",
223 strerror(errno), strerror(rc), rc);
224 return EN_LUTF_RC_FAIL;
227 hdr->type = htonl(msg_type);
228 hdr->len = htonl(msg_size);
229 hdr->ip.s_addr = sock.sin_addr.s_addr;
230 hdr->version = htonl(lutf_version_number);
232 return EN_LUTF_RC_OK;
235 lutf_rc_t readTcpMessage(int iFd, char *pcBuffer,
236 int iBufferSize, int iTimeout)
241 struct timeval sTimeout;
244 /* Grab a copy of the client's file descriptor
245 * (and make sure it isn't -1).
248 return EN_LUTF_RC_CLIENT_CLOSED;
250 /* set the timeout */
252 sTimeout.tv_sec = iTimeout;
253 sTimeout.tv_usec = 0;
254 setsockopt(iFd, SOL_SOCKET, SO_RCVTIMEO, (void *)&sTimeout,
256 setsockopt(iFd, SOL_SOCKET, SO_SNDTIMEO, (void *)&sTimeout,
259 iFlags = fcntl(iFd, F_GETFL, 0);
260 fcntl(iFd, F_SETFL, iFlags & (~O_NONBLOCK));
262 /* if no timeout specified do a non blocking read */
263 iFlags = fcntl(iFd, F_GETFL, 0);
264 fcntl(iFd, F_SETFL, iFlags | O_NONBLOCK);
267 /* Start reading in bytes from the socket and keep reading until we have
268 * the requested number of bytes or EOF occurs.
271 tNleft = iBufferSize;
273 /* Get as many bytes, up to current maximum as we can. */
274 tNread = read(iFd, pcCur, tNleft);
277 if (errno == EINTR) {
278 /* We were interrupted, but this is not an error condition. */
280 } else if ((errno == EAGAIN) && (!iTimeout)) {
281 return EN_LUTF_RC_SOCKET_FAIL;
283 /* System error has occurred. */
284 return EN_LUTF_RC_SOCKET_FAIL;
288 /* End of file encountered. This is most
289 * likely the client closing their end of the
292 return EN_LUTF_RC_SOCKET_FAIL;
300 return EN_LUTF_RC_OK;
303 lutf_rc_t lutf_send_msg(int fd, char *msg, size_t msg_size,
304 lutf_msg_type_t type)
306 lutf_rc_t rc = EN_LUTF_RC_RPC_FAIL;
307 lutf_message_hdr_t hdr;
309 rc = populateMsgHdr(fd, (char *)&hdr, type,
310 msg_size, LUTF_VERSION_NUMBER);
311 if (rc != EN_LUTF_RC_OK) {
312 PERROR("Failed to populate message header");
316 rc = sendTcpMessage(fd, (char *)&hdr, sizeof(hdr));
317 if (rc != EN_LUTF_RC_OK) {
318 PERROR("Failed to send msg header");
323 rc = sendTcpMessage(fd, msg, msg_size);
324 if (rc != EN_LUTF_RC_OK) {
325 PERROR("Failed to send msg body");