00001
00002 #include <sys/types.h>
00003 #include <sys/socket.h>
00004 #include <netinet/in.h>
00005 #include <arpa/inet.h>
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <unistd.h>
00010 #include <errno.h>
00011
00012
00013 #define SA struct sockaddr *
00014
00015 #define MSG_EOF MSG_FIN
00016
00017 const size_t MAXLINE = 2048;
00018
00019
00020
00021 #include <fstream>
00022 #include <iostream>
00023 #include <iomanip>
00024 #include <string>
00025 #include <vector>
00026
00027 using namespace std;
00028
00029
00030
00031
00032
00033 class ocSockServer
00034 {
00035
00036 private:
00037
00038 vector <char> readBuff;
00039 string error;
00040
00041
00042 struct sockaddr_in serv;
00043 struct sockaddr_in cli;
00044 int sockfd;
00045 int listenfd;
00046
00047
00048 ssize_t amountRead;
00049
00050 protected:
00051
00052
00053 void fatal_err( const char * errIn )
00054 {
00055 error = "\r\nFatal Error: ";
00056 error += errIn;
00057 throw exception();
00058 }
00059 void non_fatal_error( const char * errIn )
00060 {
00061 error = "\r\nError: ";
00062 error += errIn;
00063 }
00064
00065 public:
00066
00067
00068
00069
00070
00071
00072 ocSockServer( int port, int connections, const char * address = NULL )
00073 :readBuff(MAXLINE),error("")
00074 {
00075 if( (listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
00076 {
00077 fatal_err("socket function error");
00078 }
00079 memset(&serv, 0, sizeof(serv));
00080 serv.sin_family = AF_INET;
00081
00082 if( address == NULL )
00083 {
00084 serv.sin_addr.s_addr = htonl(INADDR_ANY);
00085 }
00086 else if( inet_aton(address, &serv.sin_addr) != 1 )
00087 {
00088 fatal_err("bad address string");
00089 }
00090 serv.sin_port = htons( port );
00091
00092
00093 if (bind(listenfd, (SA) &serv, sizeof(serv)) < 0)
00094 {
00095 fatal_err("connect function error");
00096 }
00097
00098
00099 if (listen(listenfd, connections) < 0)
00100 {
00101 fatal_err("listen error");
00102 }
00103 }
00104
00105 virtual ~ocSockServer()
00106 {
00107 close(sockfd);
00108 }
00109
00110 private:
00111
00112 virtual void daemonAction( void ) = 0;
00113
00114 public:
00115
00116 void daemonServe( void )
00117 {
00118 for ( ; ; )
00119 {
00120 size_t clilen = sizeof(cli);
00121 sockfd = accept(listenfd, (SA) &cli, &clilen);
00122 if ( sockfd < 0 )
00123 {
00124 fatal_err("accept error");
00125 }
00126 daemonAction();
00127 }
00128 }
00129
00130
00131
00132 bool SetTimeoutTime( size_t seconds )
00133 {
00134 struct timeval tv;
00135 tv.tv_sec = seconds;
00136 tv.tv_usec = 0;
00137 return (setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv) ) == 0);
00138 }
00139
00140
00141
00142
00143 ssize_t Write( const char * in, size_t amount )
00144 {
00145 size_t nwrote;
00146 const char *ptr;
00147 ptr = in;
00148 nwrote = 0;
00149
00150 while( (amount-nwrote) > 0)
00151 {
00152 nwrote = write(sockfd, ptr, amount - nwrote);
00153 if( nwrote <= 0 )
00154 {
00155 if (errno == EINTR) nwrote = 0;
00156 else fatal_err("could not write everything to socket");
00157 }
00158 ptr += nwrote;
00159 }
00160 return(amount);
00161 }
00162
00163
00164
00165
00166 char * Read( size_t amount )
00167 {
00168 amountRead = 0;
00169
00170
00171
00172 if( readBuff.size() < amount+1 )
00173 {
00174 readBuff.resize(amount+1);
00175 }
00176 char * base = & readBuff[0];
00177 do
00178 {
00179 amountRead += read( sockfd, base, amount-amountRead );
00180 if( amountRead > 0 ) base = & readBuff[amountRead];
00181
00182
00183
00184 } while( amountRead < (ssize_t)amount && errno == EINTR );
00185
00186
00187
00188
00189 if( amountRead == -1 && errno == EWOULDBLOCK)
00190 {
00191 non_fatal_error( "socket timeout on read" );
00192 return NULL;
00193 }
00194 return & readBuff[0];
00195 }
00196
00197
00198
00199
00200 char * ReadLine( size_t amount = 4096L )
00201 {
00202 amountRead = 0;
00203
00204
00205 if( readBuff.size() < (size_t)(amount+1) )
00206 {
00207 readBuff.resize(amount+1);
00208 }
00209
00210
00211 char * base = & readBuff[0];
00212 do
00213 {
00214
00215 ssize_t nRead = recv( sockfd, base, amount-amountRead, MSG_PEEK );
00216 if( nRead > 0 )
00217 {
00218 base[nRead] = '\0';
00219 string temp( base );
00220
00221 string::size_type idx;
00222 idx = temp.find( "\n" );
00223
00224 if(idx != string::npos )
00225 {
00226 amountRead += read( sockfd, base, idx+1 );
00227 break;
00228 }
00229 else
00230 {
00231 amountRead += read( sockfd, base, nRead );
00232 }
00233
00234 if( amountRead > 0 )
00235 {
00236 base = & readBuff[amountRead];
00237 }
00238 }
00239 else
00240 {
00241
00242 amountRead = nRead;
00243 }
00244
00245 }
00246 while( amountRead < (ssize_t) amount && errno == EINTR );
00247
00248 if( amountRead )
00249 {
00250 readBuff[amountRead] = '\0';
00251 }
00252
00253
00254 if( amountRead == -1 && errno == EWOULDBLOCK)
00255 {
00256 non_fatal_error( "socket timeout on read" );
00257 return NULL;
00258 }
00259 return & readBuff[0];
00260 }
00261
00262
00263
00264
00265 ssize_t GetAmountRead( void )
00266 {
00267 return amountRead;
00268 }
00269
00270
00271
00272
00273 string & getError(void)
00274 {
00275 return error;
00276 }
00277 };