Main Page | Data Structures | Directories | File List | Data Fields | Globals

comm.c

Go to the documentation of this file.
00001 #include <config.h>
00002 
00003 #include <stdio.h>
00004 #include <unistd.h>
00005 #include <string.h>
00006 #include <sys/types.h>
00007 #include <sys/socket.h>
00008 #include <netinet/in.h>
00009 #include <netinet/tcp.h>
00010 #include <netdb.h>
00011 #include <fcntl.h>
00012 #include <sys/ioctl.h>
00013 #include <errno.h>
00014 
00015 #define DEBUG_LEVEL 1
00016 #include "debug.h"
00017 #include <cartcomm/comm.h>
00018 #include <cartcomm/cframe.h>
00019 
00021 
00025 int cartcomm_connect(char *host, int port) {
00026     int sockfd, result;
00027     struct hostent *server_he;
00028     struct sockaddr_in server_addr;
00029     int true_flag = 1;
00030     struct timeval timeout;
00031 
00032     server_he = gethostbyname(host);
00033     if(server_he == NULL) {
00034         DEBUG1("Error looking up host!");
00035         return -1;
00036     }
00037 
00038     sockfd = socket(AF_INET, SOCK_STREAM, 0);
00039     if(sockfd < 0) {
00040         DEBUG1("Error opening socket");
00041         return -1;
00042     }
00043 
00044     // Control the maximum waiting on a socket
00045     timeout.tv_sec = 0;
00046     timeout.tv_usec = 2 * COMM_PERIOD_US;
00047     result = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout,
00048                         sizeof(timeout));
00049     result += setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout,
00050                         sizeof(timeout));
00051     if(result < 0) {
00052         DEBUG1("Couldn't set socket timeouts!");
00053         close(sockfd);
00054         return -1;
00055     }
00056 
00057     bzero(&server_addr, sizeof(server_addr));
00058     server_addr.sin_family = AF_INET;
00059     bcopy(server_he->h_addr, &server_addr.sin_addr.s_addr, server_he->h_length);
00060     server_addr.sin_port = htons(port);
00061 
00062     result = connect(sockfd, (struct sockaddr *) &server_addr,
00063                      sizeof(server_addr));
00064     if(result < 0) {
00065         DEBUG2("Error connecting to server");
00066         close(sockfd);
00067         return -1;
00068     }
00069 
00070     // Request there be no delaying of coalescing of TCP packets
00071     result = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &true_flag,
00072                         sizeof(true_flag));
00073     if(result < 0) {
00074         DEBUG1("Couldn't set TCP_NODELAY!");
00075         close(sockfd);
00076         return -1;
00077     }
00078 
00079     return sockfd;
00080 }
00081 
00083 
00085 void cartcomm_disconnect(int sockfd) {
00086     close(sockfd);
00087 }
00088 
00090 
00096 int cartcomm_synchronize(int sockfd) {
00097     int retries = MAX_RETRIES;
00098     char buf[4096];
00099     int size;
00100     cframe_t cf;
00101     int result;
00102 
00103     bzero(buf, sizeof(buf));
00104     bzero(&cf, sizeof(cframe_t));
00105 
00106     ioctl(sockfd, FIONREAD, &size);
00107     DEBUG2("bytes in buffer = %d", size);
00108 
00109     // Empty the socket buffer
00110     while(size > 0) {
00111         recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT);
00112         ioctl(sockfd, FIONREAD, &size);
00113         DEBUG2("bytes in buffer = %d", size);
00114     }
00115 
00116     for(;;) {
00117         DEBUG1("Waiting for connection to be ready..");
00118 
00119         result = cartcomm_read_msg(sockfd, buf, sizeof(buf));
00120         if(result < 0) {
00121             DEBUG1("read_msg failed!");
00122             continue;
00123         }
00124         cartcomm_send_msg(sockfd, buf);
00125 
00126         cartcomm_decode_msg(&cf, buf);
00127         if(strcmp(cf.status, "ready") == 0)
00128             break;
00129 
00130         retries--;
00131         if(retries <= 0)
00132             return -1;
00133     }
00134 
00135     return 0;
00136 }
00137 
00139 
00143 int cartcomm_connect_sync(char *host, int port) {
00144     int sockfd;
00145     int result;
00146 
00147     sockfd = cartcomm_connect(host, port);
00148     if(sockfd < 0) {
00149         DEBUG2("Couldn't connect to server!");
00150         return sockfd;
00151     }
00152 
00153     result = cartcomm_synchronize(sockfd);
00154     if(result < 0) {
00155         DEBUG2("Couldn't synchronize to server!\n");
00156         cartcomm_disconnect(sockfd);
00157         return result;
00158     }
00159 
00160     return sockfd;
00161 }
00162 
00164 
00177 int cartcomm_read_msg(int sockfd, char *buf, int bufsize) {
00178     int i;
00179     int size;
00180 
00181 start_over:
00182     // Block for recieving the first byte of the message
00183     size = recv(sockfd, buf, 1, MSG_PEEK | MSG_WAITALL);
00184     if(size <= 0) {
00185         DEBUG1("recv failed!");
00186         return -1;
00187     }
00188 
00189     // Nonblocking to find the end of the message
00190     for(;;) {
00191         size = recv(sockfd, buf, MAX_MSG_SIZE, MSG_PEEK | MSG_DONTWAIT);
00192         if(size == 0)
00193             goto start_over;
00194         if(size < 0) {
00195             DEBUG1("recv failed (%s)", strerror(errno));
00196             continue;
00197         }
00198 
00199         if(buf[0] != '{') {
00200             for(i = 0; i < size; i++) {
00201                 if(buf[i] == '{') {
00202                     // Throw away junk data
00203                     DEBUG1("discarded a partial message");
00204                     recv(sockfd, buf, i, 0);
00205                     break;
00206                 }
00207             }
00208             continue;
00209         }
00210 
00211         for(i = 1; i < size; i++) {
00212             if(buf[i] == '{') {
00213                 // Throw away junk data
00214                 DEBUG1("discarded a missed message");
00215                 recv(sockfd, buf, i, 0);
00216                 break;
00217             }
00218         }
00219 
00220         for(i = 0; i < size; i++) {
00221             if(buf[i] == '}') {
00222                 // Remove message from socket
00223                 recv(sockfd, buf, i + 1, 0);
00224                 buf[i + 1] = 0;
00225                 return 0;
00226             }
00227         }
00228     }
00229 
00230     return 0;
00231 }
00232 
00234 
00240 int cartcomm_send_msg(int sockfd, char *buf) {
00241     int retries = MAX_RETRIES;
00242     int size = -1;
00243 
00244     while(retries > 0 && size < 0) {
00245         size = send(sockfd, buf, strlen(buf), 0);
00246         if(size < strlen(buf)) {
00247             retries--;
00248             continue;
00249         }
00250     }
00251 
00252     if(retries > 0)
00253         return 0;
00254     else {
00255         DEBUG1("too many retries");
00256         return -1;
00257     }
00258 }

Generated on Thu Sep 6 13:13:10 2007 for driver by  doxygen 1.3.9.1