MASA-Core
SocketCellsReader.cpp
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2010-2015   Edans Sandes
00004  *
00005  * This file is part of MASA-Core.
00006  * 
00007  * MASA-Core is free software: you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation, either version 3 of the License, or
00010  * (at your option) any later version.
00011  * 
00012  * MASA-Core is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with MASA-Core.  If not, see <http://www.gnu.org/licenses/>.
00019  *
00020  ******************************************************************************/
00021 
00022 #include "SocketCellsReader.hpp"
00023 
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <unistd.h>
00027 #include <stdlib.h>
00028 #include <sys/socket.h> /* for socket(), bind(), and connect() */
00029 #include <arpa/inet.h>  /* for sockaddr_in and inet_ntoa() */
00030 #include <errno.h>
00031 #include <netdb.h> //hostent
00032 
00033 SocketCellsReader::SocketCellsReader(string hostname, int port) {
00034     this->hostname = hostname;
00035     this->port = port;
00036     this->socketfd = -1;
00037     init();
00038 }
00039 
00040 SocketCellsReader::~SocketCellsReader() {
00041         close();
00042 }
00043 
00044 void SocketCellsReader::close() {
00045     fprintf(stderr, "SocketCellsReader::close(): %d\n", socketfd);
00046     if (socketfd != -1) {
00047         ::close(socketfd);
00048         socketfd = -1;
00049     }
00050 }
00051 
00052 int SocketCellsReader::getType() {
00053         return INIT_WITH_CUSTOM_DATA;
00054 }
00055 
00056 int SocketCellsReader::read(cell_t* buf, int len) {
00057     int pos = 0;
00058     while (pos < len*sizeof(cell_t)) {
00059         int ret = recv(socketfd, (void*)(((unsigned char*)buf)+pos), len*sizeof(cell_t), 0);
00060         if (ret == -1) {
00061                 close();
00062             fprintf(stderr, "recv: Socket error -1\n");
00063             break;
00064         }
00065         pos += ret;
00066     }
00067     return pos/sizeof(cell_t);
00068 }
00069 
00070 void SocketCellsReader::init() {
00071     int rc;
00072     int sock;                        /* Socket descriptor */
00073     struct sockaddr_in echoServAddr; /* Echo server address */
00074 
00075 
00076 
00077     /* Create a reliable, stream socket using TCP */
00078         if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
00079                 fprintf(stderr, "ERROR creating socket: %s\n", strerror(errno));
00080                 sleep(1);
00081         }
00082 
00083         /* Resolving DNS */
00084         char ip[100];
00085         if (resolveDNS(hostname.c_str(), ip)) {
00086         fprintf(stderr, "FATAL: cannot resolve hostname: %s\n", hostname.c_str());
00087         exit(-1);
00088         }
00089 
00090     /* Construct the server address structure */
00091     memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
00092     echoServAddr.sin_family      = AF_INET;             /* Internet address family */
00093     echoServAddr.sin_addr.s_addr = inet_addr(ip);   /* Server IP address */
00094     echoServAddr.sin_port        = htons(port); /* Server port */
00095 
00096     /* Establish the connection to the echo server */
00097     int max_retries = 3000;
00098     int retries = 0;
00099     int ok = 0;
00100     fprintf(stderr, "Listening on %s %d\n", hostname.c_str(), port);
00101     while ((retries < max_retries) && !ok) {
00102                 if ((rc=connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))) < 0) {
00103                         if (retries % 100 == 0) {
00104                                 fprintf(stderr, "ERROR connecting to Server %s:%d [Retry %d/%d]. %s\n", ip, port,
00105                                                 retries, max_retries, strerror(errno));
00106                         }
00107                         retries++;
00108                         usleep(10000);
00109                 } else {
00110                         ok = 1;
00111                 }
00112         }
00113         if (!ok) {
00114                 fprintf(stderr, "ERROR connecting to Server. Aborting\n");
00115                 exit(-1);
00116         }
00117     fprintf(stderr, "Connected to Server %s\n", inet_ntoa(echoServAddr.sin_addr));
00118 
00119     this->socketfd = sock;
00120 }
00121 
00122 int SocketCellsReader::resolveDNS(const char * hostname , char* ip) {
00123     struct hostent *he;
00124     struct in_addr **addr_list;
00125     int i;
00126 
00127     if ( (he = gethostbyname( hostname ) ) == NULL)
00128     {
00129         // get the host info
00130         herror("gethostbyname");
00131         return 1;
00132     }
00133 
00134     addr_list = (struct in_addr **) he->h_addr_list;
00135 
00136     for(i = 0; addr_list[i] != NULL; i++)
00137     {
00138         //Return the first one;
00139         strcpy(ip , inet_ntoa(*addr_list[i]) );
00140         return 0;
00141     }
00142 
00143     return 1;
00144 }