Česky
Kamil Dudka

Tiny programs (C, C++, C#, ...)

File detail

Name:Downloadnntp_client.h [Download]
Location: tiny > ISA > nntpbackup
Size:4.7 KB
Last modification:2022-09-09 13:06

Source code

/*
 * file: nntp_client.h - NNTP protocol layer encapsulation
 * project: nntpbackup (ISA)
 * By Kamil Dudka, xdudka00
 * mailto: xdudka00@gmail.com
 */
 
#ifndef NNTP_CLIENT_H
#define NNTP_CLIENT_H
 
#include "tcp_client.h"
#include <iostream>
#include <string>
 
/**
 * Class stands for TCP layer encapsulation
 */
class TcpConnection {
  public:
    struct Err {};					///< General TCP error
    struct ErrConnect: Err {};				///< Error during TCP connect()
    struct ErrRead: Err {};				///< Error while reading from socket
    struct ErrWrite: Err {};				///< Error while writeing to socket
 
    /**
     * Create an TCP connection
     * \param szAddr Address of server to connect (IPv4 or server name)
     * \param uPort Port number to connect to
     */
    TcpConnection (const char *szAddr, unsigned uPort);
    ~TcpConnection ();
 
    /**
     * Write ascii text to socket.
     * \param szText Zero ended string to write to socket.
     * \return Return this. It can be useful for operator concatenation.
     */
    TcpConnection &operator<< (const char *szText);
 
    /**
     * Read one line (ended with CR-LF) from socket. CR-LF is dropped.
     * \param pszText *pszText will point to zero-ended line text (without CR-LF).
     * \return Return this. It can be useful for operator concatenation.
     */
    TcpConnection &operator>> (const char **pszText);
 
  private:
    TSocket _sockfd;
    PNetLine _netLine;
};
 
/**
 * NNTP protocol encapsulation.
 */
class NntpProtocol {
  public:
    struct Err {};					///< Generic NNTP error
    struct ErrConnect: Err {};				///< Initial server response error
    struct ErrNoStatus: Err {};				///< No status code in server response
    struct ErrDot: Err {};				///< Dot notation error
    struct ErrCmd: Err {				///< Error status returned from server
        int _iStatus;					///< Errorneous status code
        ErrCmd (int iStatus): _iStatus (iStatus) {}
    };
 
    /**
     * NNTP protocol command abstraction.
     */
    struct Cmd {
	virtual ~Cmd();					///< Always use virtual destructor
	virtual void handleStatus (int iStatus) =0;	///< Abstract method handling command's status code
        std::string _strCmd;				///< Command's string without CR-LF
    };
    struct CmdGroup: public Cmd {			///< GROUP nntp command
        CmdGroup (const char *szGroup);			///< \param szGroup Group name to select.
        virtual void handleStatus (int);
    };
    struct CmdArticle: public Cmd {			///< ARTICLE nntp command
        CmdArticle();
	virtual void handleStatus (int);
    };
    struct CmdNext: public Cmd {			///< NEXT nntp command
        CmdNext();
	virtual void handleStatus (int);
    };
    struct CmdQuit: public Cmd {			///< QUIT nntp command
        CmdQuit();
	virtual void handleStatus (int);
    };
 
    static const char *const szEndl;			///< CR-LF
    static const char *const szEndText;			///< "."
 
    NntpProtocol (TcpConnection &tcp);			///< \param tcp Established tcp connection to nntp server.
    ~NntpProtocol();
 
    /**
     * Send command to server and handle status response.
     * Command object will be always deleted by this method. Be careful.
     * \param cmd_to_send_and_DELETE Pointer to dynamically allocated Cmd object.
     * \return Return this. It can be useful for operator concatenation.
     */
    NntpProtocol &operator<< (Cmd *cmd_to_send_and_DELETE);
    int getStatus() const { return _iStatus; }		///< \return Return last command status response.
 
    /**
     * Read next data line from server. Memory allocation is maintained by lower layers.
     * \param pszLine *pszLine will point to zero-ended string containing line text without CR-LF.
     * \return Return false if there is no line to read.
     */
    bool getLine(const char **pszLine);
 
  private:
    TcpConnection &_tcp;
    const char *_szLine;
    int _iStatus;
    void readStatus();
};
 
/**
 * Simple NNTP client class.
 * There is no need to use it.
 */
class NntpClient {
  public:
    static const unsigned DEF_NNTP_PORT= 119;		///< nntp default port number
    struct Err {};					///< Generic client exception
 
    /**
     * \param szServer Server address (URL or IP).
     * \param uPort Port number. DEF_NNTP_PORT is used by default.
     */
    NntpClient (const char *szServer, unsigned uPort=DEF_NNTP_PORT);
    ~NntpClient ();
 
    /**
     * Select group on nntp server.
     * \param szGroup Group name to select.
     */
    void groupSelect (const char *szGroup);
 
    /**
     * Grab next article on server to stream.
     * \param streamTo Outpout stream to write to.
     * \return Return false if there is no article left in group.
     */
    bool readNext (std::ostream &streamTo);
 
  private:
    TcpConnection _tcp;
    NntpProtocol _nntp;
    bool _bEnd;
};
 
#endif