/*---------------------------------------------------------------------------*/
/* recording.h                                                               */
/* copyright (c) innovaphone 2013                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#ifndef RECORDING_H
#define RECORDING_H

NAMESPACE_BEGIN

#define RECORD_OPENING      1
#define RECORD_OPENED       2
#define RECORD_WRITING      3

#define RECORD_LOCAL_PORT   16386
#define RECORD_REMOTE_PORT  16388

#define RECORD_BUFFER_SIZE  10000
#define RECORD_BUFFER_LIMIT 100000 // enough to hold 5 seconds bi-directional g711 with packet headers (RTP+UDP+IP+ETH+RPCAP)

class MediaRecordingUser {
public:
    virtual void RecordingStopped(const char * error) = 0;
    virtual void RecordingStarted() = 0;
    virtual void RecordingCloseComplete() = 0;
};

class MediaRecording : public UHTTPClient {

    void SipXmit(std::vector<char> * data);
    void SipRecv(std::vector<char> * data);
    void AddPcapHeader(std::vector<char> * data);
    void AddEthernetHeader(std::vector<char> * data);
    void AddIpHeader(std::vector<char> * data, IP4addr src, IP4addr dst, byte protocol);
    void AddUdpHeader(std::vector<char> * data, word src_port, word dst_port);
    short IpChecksum(byte *addr, byte len);
    void Write();
    void GetMacAddress(char * macBuffer);

    void HTTPClientConnectComplete(IHTTPClient * const httpClient);
    void HTTPClientShutdown(IHTTPClient * const httpClient, http_shutdown_reason_t reason);
    void HTTPClientSendResult(IHTTPClient * const httpClient);
    void HTTPClientRecvResult(IHTTPClient * const httpClient, byte * buffer, size_t len, bool transferComplete);
    void HTTPClientRecvCanceled(IHTTPClient * const httpClient, byte * buffer);
    void HTTPClientRequestComplete(IHTTPClient * const httpClient);

    class MediaRecordingUser * recording_user;
    word media_type, media_pt, localDtmfPt, remoteDtmfPt;
    bool error_reported;
    char * fileUrl;
    char recordingPath[256];
    std::vector<char> * buffer;
    byte state;
    IP4addr local;
    IP4addr remote;
    bool closing;
    bool is_on;
    enum MediaType type;
    char * recordingUsername;
    char * recordingPassword;

    static unsigned seq;

    static const char * sdp;
    static const char * invite;
    static const char * invite_ok;
    static const char * ack;
    static const char * bye;
    static const char * bye_ok;

    IHTTPClient * http;
    IIoMux * iomux;
    ISocketProvider * tcpSocketProvider;
    ISocketProvider * tlsSocketProvider;

    class IInstanceLog * log;

public:
    MediaRecording(class IIoMux * iomux, class ISocketProvider * tcpSocketProvider, class ISocketProvider * tlsSocketProvider, IPaddr addr, const char * url, OS_GUID * guid, enum MediaType type, class IInstanceLog * const log, bool recordOn, const char * currentUserSip, const char * recordingUsername, const char * recordingPassword);
    ~MediaRecording();
    void Start(IPaddr remote, word media_type, word media_pt, word localDtmfPt, word remoteDtmfPt, class MediaRecordingUser * recording_user);
    void Start();
    void RtpRecv(char * data, size_t len);
    void RtpXmit(char * data, size_t len);
    void Close();
    void Recording(bool on);

    inline bool On() { return http!=0; };
};

#ifndef PCAP_MAGIC_NUMBER

#define PCAP_MAGIC_NUMBER       0xa1b2c3d4      // default magic number for pcap global header
#define PCAP_VERSION_MAJOR      0x2             // current major version
#define PCAP_VERSION_MINOR      0x4             // current minor version
#define PCAP_NETWORK            0x1             // only network type ethernet in our case
#define PCAP_USB_LINUX          0xBD            // for usb

struct pcap_global_header
{
    dword magic_number;     /* magic number */
    word version_major;     /* major version number */
    word version_minor;     /* minor version number */
    int this_zone;          /* GMT to local correction */
    dword sig_figs;         /* accuracy of timestamps */
    dword snap_len;         /* max length of captured packets, in octets */
    dword network;          /* data link type */
};

struct pcap_packet_header
{
    dword ts_sec;           /* timestamp seconds */
    dword ts_usec;          /* timestamp microseconds */
    dword incl_len;         /* number of octets of packet saved in file */
    dword orig_len;         /* actual length of packet */
};

struct ip_header
{
    char    ip_verlen;      /* IP version & header length (in longs) */
    byte    ip_tos;         /* type of service */
    short   ip_len;         /* total packet length (in octets) */
    short   ip_id;          /* datagram id */
    short   ip_fragoff;     /* fragment offset (in 8-octet's) */
    byte    ip_ttl;         /* time to live, in gateway hops */
    char    ip_proto;       /* IP protocol (see IPT_* above) */
    short   ip_chksum;      /* header checksum */
    IP4addr  ip_src;        /* IP address of source */
    IP4addr  ip_dst;        /* IP address of destination */
};

struct udp_header
{
    word src_port;
    word dst_port;
    word len;
    word chksum;
};

#endif

NAMESPACE_END
#endif