00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00024 #include "common.h"
00025
00026 #include <errno.h>
00027 #include <fcntl.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031
00032
00033 #include <sys/types.h>
00034 #include <sys/socket.h>
00035 #include <netinet/in.h>
00036 #include <arpa/inet.h>
00037
00038
00039 #include "conn_handler.h"
00040
00041 #include "xmalloc.h"
00042 #include "buffer.h"
00043 #include "conftable.h"
00044 #include "logger.h"
00045 #include "http.h"
00046
00047
00049 #ifndef MSG_NOSIGNAL
00050 # define MSG_NOSIGNAL 0
00051 #endif
00052
00053
00054
00055
00056 #ifdef EAGAIN
00057 # ifndef EWOULDBLOCK
00058 # define EWOULDBLOCK EAGAIN
00059 # endif
00060 #else // EAGAIN not defined
00061 # ifdef EWOULDBLOCK
00062 # define EAGAIN EWOULDBLOCK
00063 # else
00064 # error Neither EAGAIN nor EWOULDBLOCK defined, aborting!
00065 # endif
00066 #endif
00067
00069 struct ConnHandler
00070 {
00071
00072 int socket;
00073 struct sockaddr_in client_addr;
00074 int client_addr_len;
00075
00076
00077 int error;
00078 time_t stamp;
00079
00080 HttpProtHandler prot_handler;
00081
00082
00083 struct Buffer recv_buf;
00084
00085
00086 struct Buffer* send_buf;
00087 };
00088
00089
00090
00091 static size_t recv_buf_size;
00092
00093
00094 int chModulePreInit()
00095 {
00096 recv_buf_size = getEntryDeflL(CONFENTRY_KEY_RECVBUFFER, STD_CONFENTRY_VAL_RECVBUFFER);
00097
00098 return 0;
00099 }
00100
00101
00102 int chModuleTerminate()
00103 {
00104 return 0;
00105 }
00106
00107
00108
00109
00110 ConnHandler chInit(int server_socket)
00111 {
00112 ConnHandler this;
00113
00114 this = (ConnHandler) pd_malloc(sizeof(struct ConnHandler));
00115
00116 this->client_addr_len = sizeof(this->client_addr);
00117 if ((this->socket = accept(server_socket,
00118 (struct sockaddr *) &this->client_addr,
00119 &this->client_addr_len)) == -1)
00120 {
00121 logerr(CONN_HANDLER, NOTICE, errno,
00122 "could not accept connection");
00123 return NULL;
00124 }
00125
00126 logger(CONN_HANDLER, NOTICE,
00127 "%d: connection to %s established",
00128 this->socket, inet_ntoa(this->client_addr.sin_addr));
00129
00130 fcntl(this->socket, F_SETFL, O_NONBLOCK);
00131
00132 logger(CONN_HANDLER, INFO,
00133 "%d: non-blocking mode set on socket", this->socket);
00134
00135 this->error = E_SUCCESS;
00136
00137 this->prot_handler = htInit(this);
00138
00139
00140 this->recv_buf = bufInit((char*) pd_malloc(recv_buf_size), recv_buf_size, 0);
00141
00142
00143 this->send_buf = NULL;
00144
00145 logger(CONN_HANDLER, NOTICE,
00146 "%d: connection initalised", this->socket);
00147
00148 this->stamp = time(NULL);
00149
00150 return this;
00151 }
00152
00153
00154 int chGetSocket(const ConnHandler this)
00155 {
00156 return this->socket;
00157 }
00158
00159
00160 time_t chGetStamp(const ConnHandler this)
00161 {
00162 return this->stamp;
00163 }
00164
00166 int readData(ConnHandler this)
00167 {
00168 ssize_t recv_len;
00169 errno = 0;
00170
00171 do {
00172 recv_len = recv(this->socket, this->recv_buf.data,
00173 this->recv_buf.len, MSG_NOSIGNAL);
00174 } while (recv_len == -1 && errno == EINTR);
00175
00176 if (recv_len != -1)
00177 this->stamp = time(NULL);
00178 else
00179 {
00180 switch(errno)
00181 {
00182 #if EAGAIN != EWOULDBLOCK
00183 case EAGAIN:
00184 #endif
00185 case EWOULDBLOCK:
00186 return 0;
00187 default:
00188 this->error = errno;
00189
00190 return -1;
00191 }
00192 }
00193 return recv_len;
00194 }
00195
00196
00197 int chReceive(ConnHandler this)
00198 {
00199 struct Buffer tmp_buf = bufInit(this->recv_buf.data, 0, 0);
00200
00201 if (this->socket == 0) return -1;
00202
00203 logger(CONN_HANDLER, DEBUG,
00204 "%d: reading pending data", this->socket);
00205
00206 tmp_buf.len = readData(this);
00207
00208 if (tmp_buf.len > 0)
00209 htReceive(this->prot_handler, tmp_buf);
00210 else {
00211
00212 logerr(CONN_HANDLER, NOTICE, this->error,
00213 "%d: error reading pending data", this->socket);
00214 this->error = EPIPE;
00215 }
00216
00217 return (this->error == E_SUCCESS) ? 0 : -1;
00218 }
00219
00221 inline int byteInQueue(const ConnHandler this)
00222 {
00223 return this->send_buf->len - this->send_buf->pos;
00224 }
00225
00226
00227 int chIsDataPending(const ConnHandler this)
00228 {
00229 if (this == NULL || this->send_buf == NULL)
00230 return false;
00231 return (byteInQueue(this) != 0);
00232 }
00233
00235 int forwardSendToProtHandler(ConnHandler this)
00236 {
00237 if (!chIsDataPending(this) && htIsDataPending(this->prot_handler))
00238 {
00239
00240 if (htSend(this->prot_handler, &(this->send_buf)) == -1)
00241 {
00242 return -1;
00243 }
00244
00245
00246 if (this->send_buf->data == NULL) return 1;
00247 }
00248
00249 return 0;
00250 }
00251
00252
00253 int chSend(ConnHandler this)
00254 {
00255 int data_sent;
00256 size_t data_left = byteInQueue(this);
00257 if (data_left == 0) return 0;
00258
00259 do
00260 {
00261 errno = 0;
00262
00263 logger(CONN_HANDLER, DEBUG,
00264 "%d: sending pending data", this->socket);
00265
00266 data_sent = send(this->socket, this->send_buf->data + this->send_buf->pos,
00267 data_left, MSG_NOSIGNAL);
00268
00269 if (data_sent != -1)
00270 this->stamp = time(NULL);
00271 else
00272 {
00273 switch(errno)
00274 {
00275 #if EAGAIN != EWOULDBLOCK
00276 case EAGAIN:
00277 #endif
00278 case EWOULDBLOCK:
00279 data_left /= 2;
00280 break;
00281 default:
00282 this->error = errno;
00283 logerr(CONN_HANDLER, NOTICE, this->error,
00284 "%d: error sending pending data", this->socket);
00285 return -1;
00286 }
00287 }
00288 } while(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN);
00289
00290 this->send_buf->pos += data_sent;
00291
00292
00293 return forwardSendToProtHandler(this);
00294
00295 }
00296
00297
00298
00299 int chProcess(ConnHandler this)
00300 {
00301
00302 forwardSendToProtHandler(this);
00303
00304
00305 return htProcess(this->prot_handler);
00306 }
00307
00308
00309 int chGetError(const ConnHandler this)
00310 {
00311 return this->error;
00312 }
00313
00314
00315 int chTerminate(ConnHandler this)
00316 {
00317 if (this == NULL) return -1;
00318
00319 logger(CONN_HANDLER, NOTICE,
00320 "%d: terminating connection", this->socket);
00321
00322 htTerminate(this->prot_handler);
00323
00324 shutdown(this->socket, 2);
00325 close(this->socket);
00326
00327 pd_free(this->recv_buf.data);
00328 pd_free(this);
00329
00330 return 0;
00331 }