nv2_label_server.c

Go to the documentation of this file.
00001 /*!@file NeovisionII/nv2_label_server.c */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/NeovisionII/nv2_label_server.c $
00035 // $Id: nv2_label_server.c 9765 2008-05-12 16:58:24Z rjpeters $
00036 //
00037 
00038 #ifndef NEOVISIONII_NV2_LABEL_SERVER_C_DEFINED
00039 #define NEOVISIONII_NV2_LABEL_SERVER_C_DEFINED
00040 
00041 #include "NeovisionII/nv2_label_server.h"
00042 
00043 #include "NeovisionII/nv2_common.h"
00044 
00045 // #include order matters here:
00046 #include <sys/types.h>
00047 #include <sys/socket.h>
00048 #include <netinet/in.h>
00049 #include <arpa/inet.h>
00050 
00051 #include <errno.h>
00052 #include <pthread.h>
00053 #include <stdio.h>
00054 #include <stdlib.h>
00055 #include <string.h>
00056 #include <unistd.h>
00057 
00058 struct nv2_label_server
00059 {
00060         pthread_mutex_t m_patch_lock;
00061         struct nv2_image_patch m_patch;
00062         int m_should_quit;
00063 
00064         int m_patch_reader_port;
00065         struct in_addr m_remote_label_reader_in_addr;
00066         int m_remote_label_reader_port;
00067 
00068         int m_verbosity;
00069 
00070         volatile int socket_fd;
00071 
00072         pthread_t m_patch_reader_thread;
00073 };
00074 
00075 static void* run_patch_reader(void* vq)
00076 {
00077         struct nv2_label_server* const q = (struct nv2_label_server*) vq;
00078 
00079         q->socket_fd = socket(PF_INET, SOCK_STREAM, 0);
00080         if (q->socket_fd == -1)
00081                 nv2_fatal("socket() failed");
00082 
00083         {
00084                 const int set_on = 1;
00085                 if (setsockopt(q->socket_fd,
00086                                SOL_SOCKET, SO_REUSEADDR,
00087                                &set_on, sizeof(set_on)) == -1)
00088                         nv2_warn("setsockopt() failed");
00089         }
00090 
00091         struct sockaddr_in name;
00092         name.sin_family = AF_INET;
00093         name.sin_addr.s_addr = htonl(INADDR_ANY); // accept from any host
00094         name.sin_port = htons(q->m_patch_reader_port);
00095         if (bind(q->socket_fd, (struct sockaddr*)(&name), sizeof(name)) == -1)
00096                 nv2_fatal("bind() failed");
00097 
00098         listen(q->socket_fd, 5);
00099 
00100         int client_socket_fd = -1;
00101 
00102         // Accept incoming connections
00103         while (q->socket_fd > 0)
00104         {
00105                 struct sockaddr_in client_name;
00106                 socklen_t client_name_len = sizeof(client_name);
00107 
00108                 client_socket_fd =
00109                         accept(q->socket_fd,
00110                                (struct sockaddr*)(&client_name),
00111                                &client_name_len);
00112 
00113                 if (client_socket_fd < 0)
00114                 {
00115                         // if accept() failed because q->socket_fd was
00116                         // closed() and/or is less than 0, then that
00117                         // is because the main thread closed the
00118                         // socket to force us to shut down, so let's
00119                         // quit without any nv2_warn()
00120                         if (q->socket_fd < 0)
00121                                 break;
00122 
00123                         if (q->m_verbosity >= 1)
00124                                 fprintf(stderr, "accept() failed "
00125                                         "(strerror=%s)\n",
00126                                         strerror(errno));
00127                         continue;
00128                 }
00129 
00130                 struct nv2_image_patch p;
00131                 nv2_image_patch_init_empty(&p);
00132 
00133                 if (nv2_robust_read(client_socket_fd, &p,
00134                                     NV2_IMAGE_PATCH_HEADER_SIZE, NULL)
00135                     != NV2_IMAGE_PATCH_HEADER_SIZE)
00136                 {
00137                         if (q->m_verbosity >= 1)
00138                                 fprintf(stderr, "read(header) failed\n");
00139                         break;
00140                 }
00141 
00142                 p.protocol_version = ntohl(p.protocol_version);
00143                 p.width            = ntohl(p.width);
00144                 p.height           = ntohl(p.height);
00145                 p.id               = ntohl(p.id);
00146                 p.is_training_image= ntohl(p.is_training_image);
00147                 p.type             = ntohl(p.type);
00148                 p.training_label[sizeof(p.training_label)-1] = '\0';
00149                 p.remote_command[sizeof(p.remote_command)-1] = '\0';
00150 
00151                 const uint32_t npixbytes =
00152                         p.width * p.height * nv2_pixel_type_bytes_per_pixel(p.type);
00153 
00154                 // set a maximum image size of 16MB, so that we avoid
00155                 // trying to allocate too much memory when filling in
00156                 // the pixel array
00157                 const uint32_t maxbytes = 4096*4096;
00158 
00159                 int doquit = 0;
00160 
00161                 if (npixbytes > maxbytes)
00162                 {
00163                         if (q->m_verbosity >= 1)
00164                                 fprintf(stderr,
00165                                         "image patch was %ux%u%u=%u bytes, "
00166                                         "but the maximum allowable size "
00167                                         "is %u bytes\n",
00168                                         (unsigned int) p.width,
00169                                         (unsigned int) p.height,
00170                                         (unsigned int) nv2_pixel_type_bytes_per_pixel(p.type),
00171                                         (unsigned int) npixbytes,
00172                                         (unsigned int) maxbytes);
00173 
00174                         doquit = 1;
00175                 }
00176                 else if (p.protocol_version == 0)
00177                 {
00178                         // client will send protocol_version == 0 to
00179                         // tell us to quit:
00180                         doquit = 1;
00181                 }
00182                 else if (p.protocol_version != NV2_PATCH_PROTOCOL_VERSION)
00183                 {
00184                         if (q->m_verbosity >= 1)
00185                                 fprintf(stderr,
00186                                         "wrong patch protocol version "
00187                                         "(got %u, expected %u)",
00188                                         (unsigned int) p.protocol_version,
00189                                         (unsigned int) NV2_PATCH_PROTOCOL_VERSION);
00190 
00191                         doquit = 1;
00192                 }
00193                 else
00194                 {
00195                         p.data = (unsigned char*) malloc(npixbytes);
00196 
00197                         int nchunks_read = 0;
00198 
00199                         const size_t n =
00200                                 nv2_robust_read(client_socket_fd,
00201                                                 p.data, npixbytes,
00202                                                 &nchunks_read);
00203 
00204                         if (n != npixbytes)
00205                         {
00206                                 doquit = 1;
00207                                 if (q->m_verbosity >= 1)
00208                                         nv2_warn("read(pixels) failed");
00209                         }
00210 
00211                         if (q->m_verbosity >= 2)
00212                                 fprintf(stderr,
00213                                         "got patch = { .protocol_version=%u, "
00214                                         ".width=%u, .height=%u, .id=%u, "
00215                                         ".is_training=%u, "
00216                                         ".label='%s', .cmd='%s', "
00217                                         ".data=[%d bytes in %d chunks] }\n",
00218                                         (unsigned int) p.protocol_version,
00219                                         (unsigned int) p.width,
00220                                         (unsigned int) p.height,
00221                                         (unsigned int) p.id,
00222                                         (unsigned int) p.is_training_image,
00223                                         &p.training_label[0],
00224                                         &p.remote_command[0],
00225                                         (int) n, (int) nchunks_read);
00226                 }
00227 
00228                 close(client_socket_fd);
00229                 client_socket_fd = -1;
00230 
00231                 if (doquit)
00232                         break;
00233 
00234                 pthread_mutex_lock(&q->m_patch_lock);
00235                 nv2_image_patch_destroy(&q->m_patch);
00236                 q->m_patch = p;
00237                 pthread_mutex_unlock(&q->m_patch_lock);
00238         }
00239 
00240         pthread_mutex_lock(&q->m_patch_lock);
00241         q->m_should_quit = 1;
00242         pthread_mutex_unlock(&q->m_patch_lock);
00243 
00244         if (client_socket_fd >= 0)
00245                 close(client_socket_fd);
00246 
00247         close(q->socket_fd);
00248 
00249         return (void*) 0;
00250 }
00251 
00252 struct nv2_label_server* nv2_label_server_create(
00253         const int patch_reader_port,
00254         const char* remote_label_reader_addr,
00255         const int remote_label_reader_port)
00256 {
00257         struct nv2_label_server* p =
00258                 (struct nv2_label_server*)
00259                 malloc(sizeof(struct nv2_label_server));
00260 
00261         if (p == 0)
00262                 nv2_fatal("malloc() failed");
00263 
00264         pthread_mutex_init(&p->m_patch_lock, 0);
00265         nv2_image_patch_init_empty(&p->m_patch);
00266         p->m_should_quit = 0;
00267 
00268         p->m_patch_reader_port = patch_reader_port;
00269 
00270         if (inet_aton(remote_label_reader_addr,
00271                       &p->m_remote_label_reader_in_addr) == 0)
00272                 nv2_fatal("inet_aton() failed");
00273 
00274         p->m_remote_label_reader_port = remote_label_reader_port;
00275 
00276         p->socket_fd = -1;
00277 
00278         p->m_verbosity = 2;
00279 
00280         if (0 != pthread_create(&p->m_patch_reader_thread, 0,
00281                                 &run_patch_reader,
00282                                 (void*) p))
00283                 nv2_fatal("pthread_create() failed");
00284 
00285         return p;
00286 }
00287 
00288 
00289 void nv2_label_server_destroy(struct nv2_label_server* p)
00290 {
00291         if (p->socket_fd != -1)
00292         {
00293                 const int oldfd = p->socket_fd;
00294                 p->socket_fd = -1;
00295                 close(oldfd);
00296         }
00297 
00298         if (0 != pthread_join(p->m_patch_reader_thread, 0))
00299                 nv2_fatal("pthread_join() failed");
00300         nv2_image_patch_destroy(&p->m_patch);
00301         pthread_mutex_destroy(&p->m_patch_lock);
00302 }
00303 
00304 enum nv2_image_patch_result
00305 nv2_label_server_get_current_patch(struct nv2_label_server* p,
00306                                    struct nv2_image_patch* ret)
00307 {
00308         pthread_mutex_lock(&p->m_patch_lock);
00309         *ret = p->m_patch;
00310         const int doquit = p->m_should_quit;
00311         nv2_image_patch_init_empty(&p->m_patch);
00312         pthread_mutex_unlock(&p->m_patch_lock);
00313 
00314         if (doquit)             return NV2_IMAGE_PATCH_END;
00315         else if (ret->id > 0)   return NV2_IMAGE_PATCH_VALID;
00316         else                    return NV2_IMAGE_PATCH_NONE;
00317 }
00318 
00319 enum nv2_label_send_result
00320 nv2_label_server_send_label(struct nv2_label_server* p,
00321                             const struct nv2_patch_label* l)
00322 {
00323         const int socket_fd = socket(PF_INET, SOCK_STREAM, 0);
00324 
00325         if (socket_fd == -1)
00326                 nv2_fatal("socket() failed");
00327 
00328         // Specify the server address and port
00329         struct sockaddr_in name;
00330         name.sin_family = AF_INET;
00331         name.sin_addr = p->m_remote_label_reader_in_addr;
00332         name.sin_port = htons(p->m_remote_label_reader_port);
00333 
00334         struct nv2_patch_label nl = *l;
00335         nl.protocol_version = htonl(l->protocol_version);
00336         nl.patch_id = htonl(l->patch_id);
00337         nl.confidence = htonl(l->confidence);
00338 
00339         enum nv2_label_send_result retval = NV2_LABEL_SEND_OK;
00340 
00341         errno = 0;
00342         if (connect(socket_fd, (struct sockaddr*)(&name), sizeof(name))
00343             == -1)
00344         {
00345                 if (p->m_verbosity >= 1)
00346                         nv2_warn("connect() failed");
00347                 retval = NV2_LABEL_SEND_FAIL;
00348         }
00349         else if (nv2_robust_write(socket_fd, &nl, sizeof(nl))
00350                  != sizeof(nl))
00351         {
00352                 if (p->m_verbosity >= 1)
00353                         nv2_warn("write(nv2_patch_label) failed");
00354                 retval = NV2_LABEL_SEND_FAIL;
00355         }
00356 
00357         close(socket_fd);
00358 
00359         return retval;
00360 }
00361 
00362 void nv2_label_server_set_verbosity(struct nv2_label_server* p,
00363                                     const int verbosity)
00364 {
00365         p->m_verbosity = verbosity;
00366 }
00367 
00368 // ######################################################################
00369 /* So things look consistent in everyone's emacs... */
00370 /* Local Variables: */
00371 /* indent-tabs-mode: nil */
00372 /* c-file-style: "linux" */
00373 /* End: */
00374 
00375 #endif // NEOVISIONII_NV2_LABEL_SERVER_C_DEFINED
Generated on Sun May 8 08:41:02 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3