00001 /*!@file Psycho/StimListener.C A thread to grab commands from a 00002 StimListener through a shared buffer and render them using SDL. */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: David Berg <dberg@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Psycho/StimListener.C $ 00036 #include "Psycho/StimListener.H" 00037 #include "Util/sformat.H" 00038 00039 #define BUFSIZE 50 00040 #define PORT "9999" 00041 00042 // ###################################################################### 00043 //implementation of StimListener 00044 // ###################################################################### 00045 StimListener::StimListener() : 00046 itsEventLog(), itsBuffer() { }; 00047 00048 // ###################################################################### 00049 StimListener::~StimListener() { }; 00050 00051 // ###################################################################### 00052 void StimListener::setBuffer(const rutz::shared_ptr<SharedBuffer<StimData> >& buffer) 00053 { 00054 itsBuffer = buffer; 00055 } 00056 00057 // ###################################################################### 00058 void StimListener::setEventLog(const nub::soft_ref<EventLog>& elog) 00059 { 00060 itsEventLog = elog; 00061 } 00062 00063 // ###################################################################### 00064 void StimListener::pushEvent(const std::string& msg, const bool& useLinfo) 00065 { 00066 if (useLinfo) 00067 LINFO(msg.c_str()); 00068 00069 if (itsEventLog.isValid()) 00070 itsEventLog->pushEvent(msg); 00071 } 00072 00073 // ###################################################################### 00074 void StimListener::addData(const StimData&, const data) 00075 { 00076 itsBuffer.push(data); 00077 pushEvent(sformat("Recieved::%d bytes",d->buflen)); 00078 } 00079 00080 // ###################################################################### 00081 void StimListener::start() 00082 { 00083 if ( !itsBuffer.is_valid() ) 00084 LFATAL("A call to setBuffer(rutz::shared_ptr<SharedBuffer<StimData> >) is" 00085 " needed to start"); 00086 } 00087 00088 // ###################################################################### 00089 void StimListener::stop() 00090 { 00091 00092 } 00093 00094 // ###################################################################### 00095 void StimListener::run() 00096 { 00097 listen(); 00098 } 00099 00100 // ###################################################################### 00101 const char* StimListener::jobType() const 00102 { 00103 return "Stimulus Listener"; 00104 } 00105 00106 // ###################################################################### 00107 int StimListener::priority() const 00108 { 00109 return 0; 00110 } 00111 00112 // ###################################################################### 00113 //implementation of StimListenerDML 00114 // ###################################################################### 00115 StimListenerDML::StimListenerDML(unsigned char exitcode, const unsigned char[] msg) : 00116 StimListener(), sockfd(0), myInfo(NULL), 00117 hostInfo(NULL), keepGoing(true),itsExitCode(exitcode), itsConnected(false) 00118 { 00119 //setup our default messages 00120 itsMsg = new unsigned char[sizeof(msg)]; 00121 strcpy(itsMsg, msg); 00122 }; 00123 00124 // ###################################################################### 00125 StimListenerDML::~StimListenerDML() 00126 { 00127 delete itsMsg; 00128 delete myInfo; 00129 delete hostInfo; 00130 }; 00131 00132 // ###################################################################### 00133 void StimListenerDML::start() 00134 { 00135 00136 StimListener::start(); //call our parents start2 00137 00138 FD_ZERO(&master); // clear the master and temp sets 00139 00140 //setup the type of socket to request 00141 struct addrinfo hints; 00142 memset(&hints, 0, sizeof hints); 00143 hints.ai_family = AF_UNSPEC;//ipv4 or ipv6 00144 hints.ai_socktype = SOCK_DGRAM;//UDP 00145 hints.ai_flags = AI_PASSIVE; // use my IP 00146 00147 //get some info about our own adress 00148 int rv; 00149 if ((rv = getaddrinfo(NULL, PORT, &hints, &myInfo)) < 0) 00150 { 00151 pushEvent(sformat("getaddrinfo: %s", gai_strerror(rv)),true); 00152 freeaddrinfo(myInfo); 00153 LFATAL("Fatal Error"); 00154 } 00155 00156 // loop through all the results and bind to the first we can 00157 for(; myInfo != NULL; myInfo = myInfo->ai_next) 00158 { 00159 if ((sockfd = socket(myInfo->ai_family, myInfo->ai_socktype, 00160 myInfo->ai_protocol)) == -1) 00161 { 00162 pushEvent("Error::Socket",true); 00163 continue; 00164 } 00165 00166 //bind our socket 00167 int bindr; 00168 if ((bindr = bind(sockfd, myInfo->ai_addr, myInfo->ai_addrlen)) < 0) 00169 { 00170 close(sockfd); 00171 pushEvent("Error::Listener bind",true); 00172 continue; 00173 } 00174 else break; 00175 } 00176 00177 if (myInfo == NULL) 00178 { 00179 pushEvent("Error: Failed to bind socket",true); 00180 freeaddrinfo(myInfo); 00181 LFATAL("Fatal Error"); 00182 } 00183 if (hostInfo == NULL) 00184 pushEvent("No host. Getting host from packets"); 00185 00186 // add the socket to the master set 00187 FD_SET(sockfd, &master); 00188 itsConnected = true; 00189 pushEvent("Socket creation succesful",true); 00190 itsConnected = true; 00191 } 00192 00193 // ###################################################################### 00194 void StimListenerDML::stop() 00195 { 00196 StimListener::stop(); // call our parent stop 00197 keepGoing = false; 00198 usleep(50000); 00199 FD_CLR(sockfd, &master); // remove from master set 00200 close(sockfd); 00201 //free our server info 00202 if (hostInfo!=myInfo) 00203 freeaddrinfo(hostInfo); 00204 freeaddrinfo(myInfo); 00205 hostInfo = NULL; 00206 myInfo = NULL; 00207 itsConnected = false; 00208 } 00209 00210 // ###################################################################### 00211 bool StimListenerDML::sendMessage(const unsigned char* msg) 00212 { 00213 if (itsConnected) 00214 { 00215 //return a status code to sender 00216 int check = 0; 00217 (hostInfo != NULL)? 00218 check = sendto(sockfd, msg, strlen(msg), 0, 00219 hostInfo->ai_addr, hostInfo->ai_addrlen) 00220 :check = sendto(sockfd, msg, strlen(msg), 0, 00221 &lasthost_addr, lasthost_addrlen); 00222 00223 if (check < 0) 00224 { 00225 pushEvent("Error::Sending",true); 00226 return false; 00227 } 00228 else 00229 { 00230 pushEvent( std::string("Listener::Sent '" + std::string(msg) + "'"), 00231 true); 00232 return true; 00233 } 00234 } 00235 else 00236 { 00237 pushEvent("Must be Connected to send a message",true); 00238 return false; 00239 } 00240 } 00241 00242 // ###################################################################### 00243 bool StimListenerDML::listen() 00244 { 00245 if (itsConnected) 00246 { 00247 int numbytes = 0, retval=0; 00248 unsigned char status_code = '\0'; 00249 fd_set read_fds; // temp file descriptor list for select() 00250 FD_ZERO(&read_fds); 00251 00252 //run until we get an exit code 00253 pushEvent("Listener::Waiting",true); 00254 while( (status_code != itsExitCode) && keepGoing) 00255 { 00256 do 00257 {//repeat select until we catch a signal 00258 read_fds = master; // copy it 00259 retval = select(sockfd+1, &read_fds, NULL, NULL, NULL); 00260 } 00261 while( (retval ==-1) && (errno==EINTR) && (keepGoing) ); 00262 00263 if (retval < 0) 00264 { 00265 pushEvent("Error::select",true); 00266 status_code = itsExitCode; 00267 continue; 00268 } 00269 00270 if (FD_ISSET(sockfd, &read_fds)) 00271 {//ready to read 00272 lasthost_addrlen = sizeof lasthost_addr; 00273 unsigned char recvbuffer[BUFSIZE]; 00274 if ( (numbytes = recvfrom(sockfd, recvbuffer, BUFSIZE-1 , 0, 00275 &lasthost_addr, 00276 &lasthost_addrlen)) <= 0) 00277 { 00278 // got error or connection closed by client 00279 if (numbytes == 0) 00280 { 00281 // connection closed 00282 pushEvent("Error::socket closed",true); 00283 } 00284 else 00285 { 00286 pushEvent("Error::recieve",true); 00287 } 00288 status_code = itsExitCode; 00289 } 00290 else 00291 { 00292 addData(StimData(recvbuffer,(uint)numbytes)); 00293 sendOK(); 00294 } 00295 } 00296 } 00297 if ((retval < 0) || (numbytes==0)) 00298 return false; 00299 else 00300 return true; 00301 } 00302 else 00303 { 00304 pushEvent("Must be Conncted to listen",true); 00305 return false; 00306 } 00307 } 00308 00309 // ###################################################################### 00310 void StimListenerDML::setHostName(const std::string hostname) 00311 { 00312 00313 if (!itsConnected) 00314 { 00315 struct addrinfo hints; 00316 memset(&hints, 0, sizeof hints); 00317 hints.ai_family = AF_UNSPEC;//ipv4 or ipv6 00318 hints.ai_socktype = SOCK_DGRAM;//UDP 00319 int rv; 00320 if ( (rv = getaddrinfo(hostname.c_str(),PORT,&hints,&hostInfo)) == -1) 00321 { 00322 pushEvent(sformat("error host connection setup: %s", 00323 gai_strerror(rv)),true); 00324 freeaddrinfo(hostInfo); 00325 hostInfo = NULL; 00326 } 00327 pushEvent("Got info for " + hostname,true); 00328 } 00329 else 00330 { 00331 pushEvent("Cannot setHostName() while connected, please call stop()," 00332 "setHostName(), and start()",true); 00333 LFATAL("Fatal Error"); 00334 } 00335 } 00336 00337 // ###################################################################### 00338 const char* StimListenerDML::jobType() const 00339 { 00340 return "Stimulus Listener DML"; 00341 } 00342 00343 00344 // ###################################################################### 00345 void StimListener::sendOK() 00346 { 00347 sendMessage(itsMsg); 00348 } 00349 00350 00351 // ###################################################################### 00352 /* So things look consistent in everyone's emacs... */ 00353 /* Local Variables: */ 00354 /* indent-tabs-mode: nil */ 00355 /* End: */