/*
Copyright (C) 2009 Red Hat, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see .
Author:
yhalperi@redhat.com
*/
#ifndef _H_CLIENT_NET_SOCKET
#define _H_CLIENT_NET_SOCKET
#include "platform_utils.h"
#include "common.h"
#include "process_loop.h"
/* interface for connections inside client LAN */
typedef enum {
SOCKET_STATUS_OPEN,
SOCKET_STATUS_SENT_FIN,
SOCKET_STATUS_RECEIVED_FIN,
SOCKET_STATUS_CLOSED,
} SocketStatus;
class ClientNetSocket: public EventSources::Socket {
public:
class ReceiveBuffer;
class SendBuffer;
class EventHandler;
class SendException {};
class ReceiveException {};
class ShutdownExcpetion {};
ClientNetSocket(uint16_t id, const struct in_addr& dst_addr, uint16_t dst_port,
ProcessLoop& process_loop, ClientNetSocket::EventHandler& event_handler);
virtual ~ClientNetSocket();
bool connect(uint32_t recv_tokens);
void push_disconnect();
void push_fin();
void push_send(SendBuffer& buf);
void add_recv_tokens(uint32_t num_tokens);
bool is_connected() {return _status != SOCKET_STATUS_CLOSED;}
inline uint16_t id() {return _id;}
inline const struct in_addr& local_addr() {return _local_addr;}
inline uint16_t local_port() {return _local_port;}
/* EventSources::Socket interface */
void on_event();
int get_socket() {return _peer;}
protected:
virtual ReceiveBuffer& alloc_receive_buffer() = 0;
private:
void send();
void receive();
uint32_t send_buf(const uint8_t* buf, uint32_t size);
uint32_t receive_buf(uint8_t* buf, uint32_t max_size, bool& shutdown);
bool can_receive();
bool can_send();
void apply_disconnect();
void apply_guest_fin();
void close();
void close_and_tell();
void handle_client_fin();
bool during_send();
void release_wait_send_messages();
void clear();
void send_message_done();
private:
uint16_t _id;
struct in_addr _local_addr;
uint16_t _local_port;
SOCKET _peer;
ProcessLoop& _process_loop;
EventHandler& _event_handler;
uint32_t _num_recv_tokens;
std::list _send_messages;
SendBuffer* _send_message;
uint32_t _send_pos;
SocketStatus _status;
bool _fin_pending;
bool _close_pending;
};
class ClientNetSocket::ReceiveBuffer {
public:
ReceiveBuffer() {}
virtual uint8_t* buf() = 0;
virtual uint32_t buf_max_size() = 0;
virtual void set_buf_size(uint32_t size) = 0;
virtual void release_buf() = 0;
protected:
virtual ~ReceiveBuffer() {}
};
class ClientNetSocket::SendBuffer {
public:
SendBuffer() {};
virtual const uint8_t* data() = 0;
virtual uint32_t size() = 0;
virtual ClientNetSocket::SendBuffer* ref() = 0;
virtual void unref() = 0;
protected:
virtual ~SendBuffer() {}
};
class ClientNetSocket::EventHandler {
public:
EventHandler() {}
virtual ~EventHandler() {}
virtual void on_socket_message_recv_done(ClientNetSocket& sckt, ReceiveBuffer& buf) = 0;
virtual void on_socket_message_send_done(ClientNetSocket& sckt) = 0;
virtual void on_socket_disconnect(ClientNetSocket& sckt) = 0;
virtual void on_socket_fin_recv(ClientNetSocket& sckt) = 0;
};
#endif