2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "BufferedSocket.h"
25 #include <ace/OS_NS_string.h>
26 #include <ace/INET_Addr.h>
27 #include <ace/SString.h>
30 #define MSG_NOSIGNAL 0
33 BufferedSocket::BufferedSocket(void):
35 remote_address_("<unknown>")
39 /*virtual*/ BufferedSocket::~BufferedSocket(void)
43 /*virtual*/ int BufferedSocket::open(void * arg
)
45 if(Base::open(arg
) == -1)
50 if(peer().get_remote_addr(addr
) == -1)
55 addr
.get_host_addr(address
, 1024);
57 this->remote_address_
= address
;
64 const std::string
& BufferedSocket::get_remote_address(void) const
66 return this->remote_address_
;
69 size_t BufferedSocket::recv_len(void) const
71 return this->input_buffer_
.length();
74 bool BufferedSocket::recv_soft(char *buf
, size_t len
)
76 if(this->input_buffer_
.length() < len
)
79 ACE_OS::memcpy(buf
, this->input_buffer_
.rd_ptr(), len
);
84 bool BufferedSocket::recv(char *buf
, size_t len
)
86 bool ret
= this->recv_soft(buf
, len
);
94 void BufferedSocket::recv_skip(size_t len
)
96 this->input_buffer_
.rd_ptr(len
);
99 ssize_t
BufferedSocket::noblk_send(ACE_Message_Block
&message_block
)
101 const size_t len
= message_block
.length();
106 // Try to send the message directly.
107 ssize_t n
= this->peer().send(message_block
.rd_ptr(), len
, MSG_NOSIGNAL
);
111 if(errno
== EWOULDBLOCK
)
124 // return bytes transmitted
128 bool BufferedSocket::send(const char *buf
, size_t len
)
130 if(buf
== NULL
|| len
== 0)
135 ACE_Message_Block::MB_DATA
,
139 ACE_Message_Block::DONT_DELETE
,
142 ACE_Message_Block
message_block(
144 ACE_Message_Block::DONT_DELETE
,
147 message_block
.wr_ptr(len
);
149 if(this->msg_queue()->is_empty())
151 // Try to send it directly.
152 ssize_t n
= this->noblk_send(message_block
);
159 // adjust how much bytes we sent
160 message_block
.rd_ptr((size_t)n
);
165 // enqueue the message, note: clone is needed cause we cant enqueue stuff on the stack
166 ACE_Message_Block
*mb
= message_block
.clone();
168 if(this->msg_queue()->enqueue_tail(mb
, (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
174 // tell reactor to call handle_output() when we can send more data
175 if(this->reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK
) == -1)
181 /*virtual*/ int BufferedSocket::handle_output(ACE_HANDLE
/*= ACE_INVALID_HANDLE*/)
183 ACE_Message_Block
*mb
= 0;
185 if(this->msg_queue()->is_empty())
187 // if no more data to send, then cancel notification
188 this->reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK
);
192 if(this->msg_queue()->dequeue_head(mb
, (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
195 ssize_t n
= this->noblk_send(*mb
);
202 else if(n
== mb
->length())
211 if(this->msg_queue()->enqueue_head(mb
, (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
220 ACE_NOTREACHED(return -1);
223 /*virtual*/ int BufferedSocket::handle_input(ACE_HANDLE
/*= ACE_INVALID_HANDLE*/)
225 const ssize_t space
= this->input_buffer_
.space();
227 ssize_t n
= this->peer().recv(this->input_buffer_
.wr_ptr(), space
);
231 // blocking signal or error
232 return errno
== EWOULDBLOCK
? 0 : -1;
240 this->input_buffer_
.wr_ptr((size_t)n
);
244 // move data in the buffer to the beginning of the buffer
245 this->input_buffer_
.crunch();
247 // return 1 in case there might be more data to read from OS
248 return n
== space
? 1 : 0;
251 /*virtual*/ int BufferedSocket::handle_close(ACE_HANDLE h
, ACE_Reactor_Mask m
)
255 Base::handle_close();
260 void BufferedSocket::close_connection(void)
262 this->peer().close_reader();
263 this->peer().close_writer();