Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

socket.c

00001 /* 
00002  *  socket.c - TCP/IP socket routines.
00003  *             This file is part of the FreeLCD package.
00004  *
00005  *  $Id: socket_8c-source.html,v 1.1 2003/02/16 22:50:41 unicorn Exp $
00006  *
00007  *  This program is free software; you can redistribute it and/or modify it
00008  *  under the terms of the GNU General Public License as published by the
00009  *  Free Software Foundation; either version 2 of the License, or (at your
00010  *  option) any later version.
00011  * 
00012  *  This program 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 this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00020  *  MA  02111-1307  USA
00021  *
00022  *  Copyright (c) 2002, 2003, Jeroen van den Berg <unicorn@hippie.nu>
00023  */
00024 
00025 
00026 #include <string.h>
00027 #include <unistd.h>
00028 #include <fcntl.h>
00029 #include <netdb.h>
00030 #include <errno.h>
00031 #include <netinet/in.h>
00032 #include <arpa/inet.h>
00033 #include <sys/types.h>
00034 #include <sys/socket.h>
00035 #include <sys/time.h>
00036 
00037 #include "socket.h"
00038 
00039 /*------------------------------------------------------- socket_create --*/
00040 socket_t
00041 socket_create (const char *addr, unsigned port)
00042 {
00043   struct sockaddr_in s_in;
00044   socket_t sock;
00045   int result;
00046   int sock_opt;
00047 
00048   sock = socket (AF_INET, SOCK_STREAM, 0);
00049   if (sock < 0)
00050     return -1;
00051 
00052   memset (&s_in, 0, sizeof (s_in));
00053   s_in.sin_family = PF_INET;
00054   s_in.sin_port = htons (port);
00055   s_in.sin_addr.s_addr = htonl (INADDR_ANY);
00056 
00057   result = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
00058                        &sock_opt, sizeof (sock_opt));
00059   if (result < 0)
00060     return -2;
00061 
00062   /* Translate the given address to a binary format */
00063   if (addr)
00064     inet_aton (addr, &s_in.sin_addr);
00065 
00066   result = bind (sock, (struct sockaddr *) (&s_in), sizeof (s_in));
00067   if (result < 0)
00068     return -3;
00069 
00070   return sock;
00071 }
00072 
00073 /*------------------------------------------------ socket_create_server --*/
00074 socket_t
00075 socket_create_server (unsigned port, fd_set * fdset)
00076 {
00077   socket_t sock = socket_create (0, port);
00078   int result;
00079 
00080   if (sock < 0)
00081     return sock;
00082 
00083   result = listen (sock, 5);
00084   if (result < 0)
00085     return -4;
00086 
00087   FD_ZERO (fdset);
00088   FD_SET (sock, fdset);
00089 
00090   return sock;
00091 }
00092 
00093 /*--------------------------------------------------------- socket_poll --*/
00094 int
00095 socket_poll (socket_t sock, fd_set * fdset,
00096              void (*callback_newconn) (socket_t),
00097              void (*callback_data) (socket_t, char *, int),
00098              void (*callback_close) (socket_t))
00099 {
00100   static char read_buf[4097];
00101   socket_t new_sock;
00102   fd_set readset = *fdset;
00103   struct sockaddr_in s_in;
00104   struct timeval tv;
00105   socklen_t s_len;
00106   int result;
00107   int i;
00108 
00109   tv.tv_sec = 0;
00110   tv.tv_usec = 300000;
00111 
00112   result = select (FD_SETSIZE, &readset, 0, 0, &tv);
00113   if (result < 0)
00114     return -1;
00115 
00116   for (i = 0; i < FD_SETSIZE; ++i)
00117     {
00118       if (FD_ISSET (i, &readset))
00119         {
00120           if (i == sock)
00121             {
00122               /* New connection on server socket */
00123               s_len = sizeof (s_in);
00124               new_sock = accept (sock, (struct sockaddr *) (&s_in), &s_len);
00125               if (new_sock < 0)
00126                 return -2;
00127 
00128               FD_SET (new_sock, fdset);
00129               fcntl (new_sock, F_SETFL, O_NONBLOCK);
00130               callback_newconn (new_sock);
00131             }
00132           else
00133             {
00134               /* Read data from existing connection */
00135               /* FIXME: too much indentation */
00136               do
00137                 {
00138                   result = recv (i, read_buf, 4096, 0);
00139                   if (result <= 0)
00140                     {
00141                       if (result == 0 || errno != EAGAIN)
00142                         {
00143                           callback_close (i);
00144                           close (i);
00145                           FD_CLR (i, fdset);
00146                           FD_CLR (i, &readset);
00147                         }
00148                     }
00149                   else if (result > 0)
00150                     {
00151                       read_buf[result] = 0;
00152                       callback_data (i, read_buf, result);
00153                     }
00154                 }
00155               while (result > 0);
00156             }
00157         }
00158     }
00159 
00160   return 0;
00161 }

Generated on Sun Feb 16 23:39:49 2003 for FreeLCD by doxygen1.2.18