MASA-Core
SocketBuffer.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 "SocketBuffer.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 
00032 SocketBuffer::SocketBuffer(string hostname, int port) {
00033     this->hostname = hostname;
00034     this->port = port;
00035     this->socketfd = -1;
00036 }
00037 
00038 
00039 SocketBuffer::~SocketBuffer() {
00040     if (socketfd != -1) {
00041         fprintf(stderr, "Buffer::destroy()...\n");
00042         Buffer::destroy();
00043         fprintf(stderr, "Close Socket...\n");
00044         //close(socketfd);
00045         //Buffer::joinThreads();
00046     }
00047 }
00048 
00049 void SocketBuffer::autoFlushThread() {
00050     char data[512];
00051     
00052     int pos = 0;
00053     while (!isDestroyed()) {
00054         int len = readBuffer(data, 1, sizeof(data));
00055         pos += len;
00056         int ret = send(socketfd, data, len, 0);
00057         if (ret == -1) {
00058             fprintf(stderr, "send: Socket error: -1\n");
00059             break;
00060         }
00061         if (ret != len) {
00062             fprintf(stderr, "Socket error: Sanity Check. Only %d bytes sent (< %d)\n", ret, len);
00063             break;
00064         }
00065 
00066     }
00067     ::close(socketfd);
00068     socketfd = -1;
00069     fprintf(stderr, "End of flush data: %d bytes\n", pos);
00070 }
00071 
00072 void SocketBuffer::autoLoadThread() {
00073     char data[512];
00074     int pos = 0;
00075     while (!isDestroyed()) {
00076         int len = recv(socketfd, data, sizeof(data), 0);
00077         fprintf(stderr, "recv(): %d\n", len);
00078         if (len == -1) {
00079             fprintf(stderr, "recv: Socket error -1\n");
00080             break;
00081         }
00082         if (len == 0) {
00083             break;
00084         }
00085         pos += len;
00086         writeBuffer(data, 1, len);
00087     }
00088     ::close(socketfd);
00089     socketfd = -1;
00090     fprintf(stderr, "Socket closed by peer: %d bytes\n", pos);
00091 }
00092 
00093 void SocketBuffer::initAutoLoad() {
00094     int rc;
00095     int sock;                        /* Socket descriptor */
00096     struct sockaddr_in echoServAddr; /* Echo server address */
00097     
00098 
00099 
00100     /* Create a reliable, stream socket using TCP */
00101         if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
00102                 fprintf(stderr, "ERROR creating socket: %s\n", strerror(errno));
00103                 sleep(1);
00104         }
00105 
00106     /* Construct the server address structure */
00107     memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
00108     echoServAddr.sin_family      = AF_INET;             /* Internet address family */
00109     echoServAddr.sin_addr.s_addr = inet_addr(hostname.c_str());   /* Server IP address */
00110     echoServAddr.sin_port        = htons(port); /* Server port */
00111 
00112     /* Establish the connection to the echo server */
00113     int max_retries = 10;
00114     int retries = 0;
00115     int ok = 0;
00116     while ((retries < max_retries) && !ok) {
00117                 if ((rc=connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))) < 0) {
00118                         retries++;
00119                         fprintf(stderr, "ERROR connecting to Server [Retry %d/%d]. %s\n",
00120                                         retries, max_retries, strerror(errno));
00121                         sleep(1);
00122                 } else {
00123                         ok = 1;
00124                 }
00125         }
00126         if (!ok) {
00127                 fprintf(stderr, "ERROR connecting to Server. Aborting\n");
00128                 exit(-1);
00129         }
00130     fprintf(stderr, "Connected to Server %s\n", inet_ntoa(echoServAddr.sin_addr));
00131     
00132     this->socketfd = sock;
00133 }
00134 
00135 void SocketBuffer::destroyAutoLoad() {
00136     ::close(socketfd);
00137 }
00138 
00139 void SocketBuffer::initAutoFlush() {
00140     int rc;
00141     int servSock;                    /* Socket descriptor for server */
00142     int clntSock;                    /* Socket descriptor for client */
00143     struct sockaddr_in echoServAddr; /* Local address */
00144     struct sockaddr_in echoClntAddr; /* Client address */
00145     unsigned int clntLen;            /* Length of client address data structure */
00146     
00147     /* Create socket for incoming connections */
00148     if ((servSock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
00149         fprintf(stderr, "ERROR creating server socket; return code from socket() is %d\n", servSock);
00150         exit(-1);
00151     }
00152     
00153     int optval = 1;
00154     setsockopt(servSock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
00155     
00156     
00157     
00158     /* Construct local address structure */
00159     memset(&echoServAddr, 0, sizeof(echoServAddr));   /* Zero out structure */
00160     echoServAddr.sin_family = AF_INET;                /* Internet address family */
00161     echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
00162     echoServAddr.sin_port = htons(port);      /* Local port */
00163     
00164     /* Bind to the local address */
00165     if ((rc = bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))) < 0) {
00166         fprintf(stderr, "ERROR; return code from bind() is %d\n", rc);
00167         exit(-1);
00168     }
00169     
00170     /* Mark the socket so it will listen for incoming connections */
00171     if ((rc=listen(servSock, 1)) < 0) {
00172         fprintf(stderr, "ERROR; return code from listen() is %d\n", rc);
00173         exit(-1);
00174     }
00175     
00176     /* Set the size of the in-out parameter */
00177     clntLen = sizeof(echoClntAddr);
00178     
00179     /* Wait for a client to connect */
00180     if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0){
00181         fprintf(stderr, "ERROR; return code from accept() is %d\n", clntSock);
00182         exit(-1);
00183     }
00184     
00185     /* clntSock is connected to a client! */
00186     
00187     fprintf(stderr, "Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr));
00188     
00189     //HandleTCPClient(clntSock);
00190     
00191     ::close(servSock);
00192     
00193     this->socketfd = clntSock;
00194 }
00195 
00196 void SocketBuffer::destroyAutoFlush() {
00197 
00198 }