00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00040 #include <assert.h>
00041 #include <stdarg.h>
00042 #include <global.h>
00043 #include <newclient.h>
00044 #include <sproto.h>
00045 #include <errno.h>
00046
00054 static void SockList_Ensure(const SockList *sl, size_t size);
00055
00056
00057
00058
00059
00060
00061
00067 void SockList_Init(SockList *sl) {
00068 SockList_Reset(sl);
00069 }
00070
00077 void SockList_Term(SockList *sl) {
00078 }
00079
00085 void SockList_Reset(SockList *sl) {
00086 sl->len = 2;
00087 }
00088
00094 void SockList_ResetRead(SockList *sl) {
00095 sl->len = 0;
00096 }
00097
00103 void SockList_AddChar(SockList *sl, char data) {
00104 SockList_Ensure(sl, 1);
00105 sl->buf[sl->len++] = data;
00106 }
00107
00113 void SockList_AddShort(SockList *sl, uint16 data) {
00114 SockList_Ensure(sl, 2);
00115 sl->buf[sl->len++] = (data>>8)&0xff;
00116 sl->buf[sl->len++] = data&0xff;
00117 }
00118
00124 void SockList_AddInt(SockList *sl, uint32 data) {
00125 SockList_Ensure(sl, 4);
00126 sl->buf[sl->len++] = (data>>24)&0xff;
00127 sl->buf[sl->len++] = (data>>16)&0xff;
00128 sl->buf[sl->len++] = (data>>8)&0xff;
00129 sl->buf[sl->len++] = data&0xff;
00130 }
00131
00137 void SockList_AddInt64(SockList *sl, uint64 data) {
00138 SockList_Ensure(sl, 8);
00139 sl->buf[sl->len++] = (char)((data>>56)&0xff);
00140 sl->buf[sl->len++] = (char)((data>>48)&0xff);
00141 sl->buf[sl->len++] = (char)((data>>40)&0xff);
00142 sl->buf[sl->len++] = (char)((data>>32)&0xff);
00143 sl->buf[sl->len++] = (char)((data>>24)&0xff);
00144 sl->buf[sl->len++] = (char)((data>>16)&0xff);
00145 sl->buf[sl->len++] = (char)((data>>8)&0xff);
00146 sl->buf[sl->len++] = (char)(data&0xff);
00147 }
00148
00154 void SockList_AddString(SockList *sl, const char *data) {
00155 SockList_AddData(sl, data, strlen(data));
00156 }
00157
00164 void SockList_AddData(SockList *sl, const void *data, size_t len) {
00165 SockList_Ensure(sl, len);
00166 memcpy(sl->buf+sl->len, data, len);
00167 sl->len += len;
00168 }
00169
00176 void SockList_AddLen8Data(SockList *sl, const void *data, size_t len) {
00177 assert(len <= 255);
00178 SockList_AddChar(sl, len);
00179 SockList_AddData(sl, data, len);
00180 }
00181
00187 void SockList_AddPrintf(SockList *sl, const char *format, ...) {
00188 size_t size;
00189 int n;
00190 va_list arg;
00191
00192 size = sizeof(sl->buf)-sl->len;
00193
00194 va_start(arg, format);
00195 n = vsnprintf((char *)sl->buf+sl->len, size, format, arg);
00196 va_end(arg);
00197
00198 if (n <= -1 || (size_t)n >= size) {
00199 fatal(OUT_OF_MEMORY);
00200 }
00201 sl->len += (size_t)n;
00202 }
00203
00210 void SockList_AddStringBuffer(SockList *sl, StringBuffer *sb) {
00211 char *p;
00212
00213 p = stringbuffer_finish(sb);
00214 SockList_AddString(sl, p);
00215 free(p);
00216 }
00217
00222 void SockList_NullTerminate(SockList *sl) {
00223 SockList_Ensure(sl, 1);
00224 sl->buf[sl->len] = '\0';
00225 }
00226
00231 size_t SockList_Avail(const SockList *sl) {
00232 return sizeof(sl->buf)-sl->len;
00233 }
00234
00239 int GetInt_String(const unsigned char *data) {
00240 return ((data[0]<<24)+(data[1]<<16)+(data[2]<<8)+data[3]);
00241 }
00242
00243 short GetShort_String(const unsigned char *data) {
00244 return ((data[0]<<8)+data[1]);
00245 }
00246
00247
00248
00249
00250
00251
00252
00260 int SockList_ReadPacket(int fd, SockList *sl, int len) {
00261 int stat, toread;
00262 char err[MAX_BUF];
00263
00264
00265 if (sl->len < 2) {
00266 #ifdef WIN32
00267
00268 stat = recv(fd, sl->buf+sl->len, 2-sl->len, 0);
00269
00270 #else
00271 do {
00272 stat = read(fd, sl->buf+sl->len, 2-sl->len);
00273 } while ((stat == -1) && (errno == EINTR));
00274 #endif
00275 if (stat < 0) {
00276
00277
00278
00279 #ifdef WIN32
00280 if ((stat == -1) && WSAGetLastError() != WSAEWOULDBLOCK) {
00281 if (WSAGetLastError() == WSAECONNRESET)
00282 LOG(llevDebug, "Connection closed by client\n");
00283 else {
00284 LOG(llevDebug, "ReadPacket got error %d, returning -1\n", WSAGetLastError());
00285 }
00286 return -1;
00287 }
00288 #else
00289 if (errno == ECONNRESET) {
00290 LOG(llevDebug, "ReadPacket got error %s, returning -1\n", strerror_local(errno, err, sizeof(err)));
00291 return -1;
00292 }
00293 if (errno != EAGAIN && errno != EWOULDBLOCK) {
00294 LOG(llevDebug, "ReadPacket got error %s, returning 0\n", strerror_local(errno, err, sizeof(err)));
00295 }
00296 #endif
00297 return 0;
00298 }
00299 if (stat == 0)
00300 return -1;
00301 sl->len += stat;
00302 #ifdef CS_LOGSTATS
00303 cst_tot.ibytes += stat;
00304 cst_lst.ibytes += stat;
00305 #endif
00306 if (stat < 2)
00307 return 0;
00308 }
00309
00310
00311
00312 toread = 2+(sl->buf[0]<<8)+sl->buf[1]-sl->len;
00313 if ((toread+(int)sl->len) >= len) {
00314 LOG(llevError, "SockList_ReadPacket: Want to read more bytes than will fit in buffer (%lu>=%lu).\n", (unsigned long)toread+sl->len, (unsigned long)len);
00315
00316
00317
00318
00319 #ifdef WIN32
00320 recv(fd, sl->buf+2, 100, 0);
00321 #else
00322 read(fd, sl->buf+2, 100);
00323 #endif
00324
00325
00326 return -1;
00327 }
00328 do {
00329 #ifdef WIN32
00330 stat = recv(fd, sl->buf+sl->len, toread, 0);
00331 #else
00332 do {
00333 stat = read(fd, sl->buf+sl->len, toread);
00334 } while ((stat < 0) && (errno == EINTR));
00335 #endif
00336 if (stat < 0) {
00337 #ifdef WIN32
00338 if ((stat == -1) && WSAGetLastError() != WSAEWOULDBLOCK) {
00339 if (WSAGetLastError() == WSAECONNRESET)
00340 LOG(llevDebug, "Connection closed by client\n");
00341 else {
00342 LOG(llevDebug, "ReadPacket got error %d, returning -1\n", WSAGetLastError());
00343 }
00344 return -1;
00345 }
00346 #else
00347 if (errno != EAGAIN && errno != EWOULDBLOCK) {
00348 LOG(llevDebug, "ReadPacket got error %s, returning 0\n", strerror_local(errno, err, sizeof(err)));
00349 }
00350 #endif
00351 return 0;
00352 }
00353 if (stat == 0)
00354 return -1;
00355 sl->len += stat;
00356 #ifdef CS_LOGSTATS
00357 cst_tot.ibytes += stat;
00358 cst_lst.ibytes += stat;
00359 #endif
00360 toread -= stat;
00361 if (toread == 0)
00362 return 1;
00363 if (toread < 0) {
00364 LOG(llevError, "SockList_ReadPacket: Read more bytes than desired.\n");
00365 return 1;
00366 }
00367 } while (toread > 0);
00368 return 0;
00369 }
00370
00371
00372
00373
00374
00375
00376
00383 static void add_to_buffer(socket_struct *ns, const unsigned char *buf, int len) {
00384 int avail, end;
00385
00386 if ((len+ns->outputbuffer.len) > SOCKETBUFSIZE) {
00387 LOG(llevDebug, "Socket on fd %d has overrun internal buffer - marking as dead\n", ns->fd);
00388 ns->status = Ns_Dead;
00389 return;
00390 }
00391
00392
00393
00394
00395
00396 end = ns->outputbuffer.start+ns->outputbuffer.len;
00397
00398 if (end >= SOCKETBUFSIZE)
00399 end -= SOCKETBUFSIZE;
00400 avail = SOCKETBUFSIZE-end;
00401
00402
00403 if (avail >= len) {
00404 memcpy(ns->outputbuffer.data+end, buf, len);
00405 } else {
00406 memcpy(ns->outputbuffer.data+end, buf, avail);
00407 memcpy(ns->outputbuffer.data, buf+avail, len-avail);
00408 }
00409 ns->outputbuffer.len += len;
00410 }
00411
00418 void write_socket_buffer(socket_struct *ns) {
00419 int amt, max;
00420
00421 if (ns->outputbuffer.len == 0) {
00422 LOG(llevDebug, "write_socket_buffer called when there is no data, fd=%d\n", ns->fd);
00423 return;
00424 }
00425
00426 do {
00427 max = SOCKETBUFSIZE-ns->outputbuffer.start;
00428 if (ns->outputbuffer.len < max)
00429 max = ns->outputbuffer.len;
00430
00431 #ifdef WIN32
00432 amt = send(ns->fd, ns->outputbuffer.data+ns->outputbuffer.start, max, 0);
00433 #else
00434 do {
00435 amt = write(ns->fd, ns->outputbuffer.data+ns->outputbuffer.start, max);
00436 } while ((amt < 0) && (errno == EINTR));
00437 #endif
00438
00439 if (amt < 0) {
00440
00441 #ifdef WIN32
00442 if (amt == -1 && WSAGetLastError() != WSAEWOULDBLOCK) {
00443 LOG(llevError, "New socket write failed (wsb) (%d).\n", WSAGetLastError());
00444 #else
00445 if (errno != EWOULDBLOCK) {
00446 char err[MAX_BUF];
00447
00448 LOG(llevError, "New socket write failed (wsb) (%d: %s).\n", errno, strerror_local(errno, err, sizeof(err)));
00449 #endif
00450 ns->status = Ns_Dead;
00451 return;
00452 } else {
00453
00454 ns->can_write = 0;
00455 return;
00456 }
00457 }
00458 ns->outputbuffer.start += amt;
00459
00460 if (ns->outputbuffer.start == SOCKETBUFSIZE)
00461 ns->outputbuffer.start = 0;
00462 ns->outputbuffer.len -= amt;
00463 #ifdef CS_LOGSTATS
00464 cst_tot.obytes += amt;
00465 cst_lst.obytes += amt;
00466 #endif
00467 } while (ns->outputbuffer.len > 0);
00468 }
00469
00477 static void Write_To_Socket(socket_struct *ns, const unsigned char *buf, int len) {
00478 int amt = 0;
00479 const unsigned char *pos = buf;
00480 char err[MAX_BUF];
00481
00482 if (ns->status == Ns_Dead || !buf) {
00483 LOG(llevDebug, "Write_To_Socket called with dead socket\n");
00484 return;
00485 }
00486
00487 #ifndef __GNU__
00488 if (!ns->can_write) {
00489 add_to_buffer(ns, buf, len);
00490 return;
00491 }
00492 #endif
00493
00494 while (len > 0) {
00495
00496 #ifdef WIN32
00497 amt = send(ns->fd, pos, len, 0);
00498 #else
00499 do {
00500 amt = write(ns->fd, pos, len);
00501 } while ((amt < 0) && (errno == EINTR));
00502 #endif
00503
00504 if (amt < 0) {
00505 #ifdef WIN32
00506 if (amt == -1 && WSAGetLastError() != WSAEWOULDBLOCK) {
00507 LOG(llevError, "New socket write failed WTS (%d).\n", WSAGetLastError());
00508 #else
00509 if (errno != EWOULDBLOCK) {
00510 LOG(llevError, "New socket write failed WTS (%d: %s).\n", errno, strerror_local(errno, err, sizeof(err)));
00511 #endif
00512 ns->status = Ns_Dead;
00513 return;
00514 } else {
00515
00516 add_to_buffer(ns, pos, len);
00517 ns->can_write = 0;
00518 return;
00519 }
00520
00521
00522
00523 } else if (amt == 0) {
00524 LOG(llevError, "Write_To_Socket: No data written out.\n");
00525 }
00526 len -= amt;
00527 pos += amt;
00528 #ifdef CS_LOGSTATS
00529 cst_tot.obytes += amt;
00530 cst_lst.obytes += amt;
00531 #endif
00532 }
00533 }
00534
00541 void Send_With_Handling(socket_struct *ns, SockList *sl) {
00542 if (ns->status == Ns_Dead || sl == NULL)
00543 return;
00544
00545 sl->buf[0] = ((sl->len-2)>>8)&0xFF;
00546 sl->buf[1] = (sl->len-2)&0xFF;
00547 Write_To_Socket(ns, sl->buf, sl->len);
00548 }
00549
00550
00551
00552
00553
00554
00555
00556 #ifdef CS_LOGSTATS
00557
00558
00559
00560 CS_Stats cst_tot, cst_lst;
00561
00565 void write_cs_stats(void) {
00566 time_t now = time(NULL);
00567
00568
00569 if (cst_lst.ibytes == 0 && cst_lst.obytes == 0)
00570 return;
00571
00572
00573 LOG(llevInfo, "CSSTAT: %.16s tot %d %d %d %ld inc %d %d %d %ld\n",
00574 ctime(&now), cst_tot.ibytes, cst_tot.obytes, cst_tot.max_conn,
00575 (long)(now-cst_tot.time_start), cst_lst.ibytes, cst_lst.obytes,
00576 cst_lst.max_conn, (long)(now-cst_lst.time_start));
00577 cst_lst.ibytes = 0;
00578 cst_lst.obytes = 0;
00579 cst_lst.max_conn = socket_info.nconns;
00580 cst_lst.time_start = now;
00581 }
00582 #endif
00583
00584 static void SockList_Ensure(const SockList *sl, size_t size) {
00585 if (sl->len+size > sizeof(sl->buf)) {
00586 fatal(OUT_OF_MEMORY);
00587 }
00588 }