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
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
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
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
00183 size = recv(sockfd, buf, 1, MSG_PEEK | MSG_WAITALL);
00184 if(size <= 0) {
00185 DEBUG1("recv failed!");
00186 return -1;
00187 }
00188
00189
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
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
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
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 }