UID2354
帖子
精華
主題
積分234087
現金
積極性
威望
違規
熱心
推廣次數
閱讀權限50
註冊時間2007-8-17
在線時間 小時
最後登錄1970-1-1
TA的每日心情 | 開心 2021-12-17 05:30 AM |
---|
簽到天數: 237 天 連續簽到: 1 天 [LV.7]常住居民III
|
發表於 2009-1-22 18:54:32
|
顯示全部樓層
這是抽取出來的原碼
不過很難看的懂
繼續研究
紅色部分是顯示錯誤的地方
藍色是說明語法意義
/// advance the WFIFO cursor (marking 'len' bytes for sending)
int WFIFOSET(int fd, size_t len)
{
size_t newreserve;
struct socket_data* s = session[fd];
if( !session_isValid(fd) || s->wdata == NULL )
return 0;
// we have written len bytes to the buffer already before calling WFIFOSET
if(s->wdata_size+len > s->max_wdata)
{ // actually there was a buffer overflow already
uint32 ip = s->client_addr;
ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n", fd, CONVIP(ip), len, s->wdata_size, s->max_wdata);
ShowDebug("Likely command that caused it: 0x%x\n", (*(unsigned short*)(s->wdata + s->wdata_size)));
// no other chance, make a better fifo model
exit(EXIT_FAILURE);
}
s->wdata_size += len;
//If the interserver has 200% of its normal size full, flush the data.
if( s->flag.server && s->wdata_size >= 2*FIFOSIZE_SERVERLINK )
flush_fifo(fd);
// always keep a WFIFO_SIZE reserve in the buffer
// For inter-server connections, let the reserve be 1/4th of the link size.
newreserve = s->wdata_size + ( s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE);
// readjust the buffer to the newly chosen size
realloc_writefifo(fd, newreserve);
#ifdef SEND_SHORTLIST
send_shortlist_add_fd(fd);
#endif
return 0;
}
int do_sockets(int next)
{
fd_set rfd;
struct timeval timeout;
int ret,i;
// PRESEND Timers are executed before do_sendrecv and can send packets and/or set sessions to eof.
// Send remaining data and process client-side disconnects here.
#ifdef SEND_SHORTLIST
send_shortlist_do_sends();
#else
for (i = 1; i < fd_max; i++)
{
if(!session)
continue;
if(session->wdata_size)
session->func_send(i);
}
#endif
// can timeout until the next tick
timeout.tv_sec = next/1000;
timeout.tv_usec = next%1000*1000;
memcpy(&rfd, &readfds, sizeof(rfd));
ret = sSelect(fd_max, &rfd, NULL, NULL, &timeout);
if( ret == SOCKET_ERROR )
{
if( sErrno != S_EINTR )
{
ShowFatalError("do_sockets: select() failed, error code %d!\n", sErrno);
exit(EXIT_FAILURE);
}
return 0; // interrupted by a signal, just loop and try again
}
last_tick = time(NULL);
#if defined(WIN32)
// on windows, enumerating all members of the fd_set is way faster if we access the internals
for( i = 0; i < (int)rfd.fd_count; ++i )
{
int fd = sock2fd(rfd.fd_array);
if( session[fd] )
session[fd]->func_recv(fd);
}
#else
// otherwise assume that the fd_set is a bit-array and enumerate it in a standard way
for( i = 1; ret && i < fd_max; ++i )
{
if(sFD_ISSET(i,&rfd) && session)
{
session->func_recv(i);
--ret;
}
}
#endif
// POSTSEND Send remaining data and handle eof sessions.
#ifdef SEND_SHORTLIST
send_shortlist_do_sends();
#else
for (i = 1; i < fd_max; i++)
{
if(!session)
continue;
if(session->wdata_size)
session->func_send(i);
if(session->eof) //func_send can't free a session, this is safe.
{ //Finally, even if there is no data to parse, connections signalled eof should be closed, so we call parse_func [Skotlex]
session->func_parse(i); //This should close the session immediately.
}
}
#endif
// parse input data on each socket
for(i = 1; i < fd_max; i++)
{
if(!session)
continue;
if (session->rdata_tick && DIFF_TICK(last_tick, session->rdata_tick) > stall_time) {
ShowInfo("Session #%d timed out\n", i);
set_eof(i);
}
session->func_parse(i);
if(!session)
continue;
// after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed)
if (session->rdata_size == RFIFO_SIZE && session->max_rdata == RFIFO_SIZE) {
set_eof(i);
continue;
}
RFIFOFLUSH(i);
}
return 0;
}
[ 本帖最後由 pan00017 於 2009-1-22 07:00 PM 編輯 ] |
|