// --------------------------------------------------------------
//
// Copyright (C) 2008 - All Rights Reserved
//
// Author: LiuYin
// File: SvcPostman
// Version: 1.0
// Date: 2008-4-2
//
// Purpose:
//
// --------------------------------------------------------------
#ifndef SvcPostman_H
#define SvcPostman_H
//
#include <ACE/Svc_Handler.h>
#include <ACE/SOCK_Stream.h>
#include <ACE/Synch_Traits.h>
#include <ACE/Global_Macros.h>
#include <ACE/os_include/os_netdb.h>
#include <ACE/Reactor_Notification_Strategy.h>
//
class CSvcPostman : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH>
{
typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> Super;
public:
CSvcPostman(size_t next_length = 256);
int send(const ACE_Message_Block &_message_block);
int open(void *p = 0);
int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE);
int handle_output(ACE_HANDLE fd = ACE_INVALID_HANDLE);
int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask mask);
protected:
virtual size_t handle_recv(const ACE_Message_Block &message_block) = 0;
~CSvcPostman();
private:
int send_block(ACE_Message_Block *message_block);
private:
size_t next_length_;
ACE_Reactor_Notification_Strategy notifier_;
};
//
#endif
/
#include "SvcPostman.h"
//
CSvcPostman::CSvcPostman(size_t next_length)
: next_length_(next_length),
notifier_(0, this, ACE_Event_Handler::WRITE_MASK)
{
ACE_TRACE(ACE_TEXT("CSvcPostman(size_t)"));
}
CSvcPostman::~CSvcPostman()
{
ACE_TRACE(ACE_TEXT("~CSvcPostman()"));
}
int CSvcPostman::send(const ACE_Message_Block &_message_block)
{
ACE_TRACE(ACE_TEXT("send(const ACE_Message_Block &)"));
ACE_Message_Block *message_block = _message_block.duplicate();
int ret = -1;
if (!message_block || get_handle() == ACE_INVALID_HANDLE) {
goto Exit;
}
if (this->putq(message_block, &(ACE_Time_Value(ACE_OS::gettimeofday()))) == -1) {
goto Exit;
}
ret = 0;
Exit:
if (ret == -1) {
if (message_block) {
message_block->release();
message_block = 0;
}
}
return ret;
}
int CSvcPostman::open(void *p)
{
ACE_TRACE(ACE_TEXT("open(void *)"));
notifier_.reactor(this->reactor());
this->msg_queue()->notification_strategy(¬ifier_);
return Super::open(p);
}
int CSvcPostman::handle_input(ACE_HANDLE fd)
{
ACE_TRACE(ACE_TEXT("handle_input(ACE_HANDLE)"));
ACE_Message_Block message_block;
message_block.init(next_length_);
ACE_OS::memset(message_block.base(), 0, message_block.size());
int recv_length = this->peer().recv(message_block.wr_ptr(), message_block.size());
if (recv_length > 0) {
message_block.wr_ptr(recv_length);
next_length_ = handle_recv(message_block);
}
else {
ACE_DEBUG((LM_DEBUG, "Peer Closed!/n"));
}
return (recv_length > 0) ? 0 : -1;
}
int CSvcPostman::handle_output(ACE_HANDLE fd)
{
ACE_TRACE(ACE_TEXT("handle_output(ACE_HANDLE)"));
ACE_Message_Block *message_block = 0;
int ret = -1;
while (this->getq(message_block, &(ACE_Time_Value(ACE_OS::gettimeofday()))) != -1) {
if (message_block) {
send_block(message_block);
}
}
ret = (this->msg_queue()->is_empty() ? -1 : 0);
Exit:
return ret;
}
int CSvcPostman::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask mask)
{
ACE_TRACE(ACE_TEXT("handle_close(ACE_HANDLE, ACE_Reactor_Mask)"));
if (ACE_BIT_ENABLED(mask, ACE_Event_Handler::READ_MASK)) {
delete this;
}
return 0;
}
int CSvcPostman::send_block(ACE_Message_Block *message_block)
{
int ret = -1;
while (message_block) {
if (message_block->length() > 0) {
ssize_t send_size = this->peer().send(message_block->rd_ptr(), message_block->length());
if (send_size < message_block->length()) {
if (send_size > 0) {
message_block->rd_ptr(ACE_static_cast(size_t, send_size));
}
this->ungetq(message_block);
break;
}
}
ACE_Message_Block *_message_block = message_block->cont();
message_block->release();
message_block = _message_block;
}
ret = 0;
Exit:
return ret;
}