/*
 * bsk_tftpd.h
 *
 *  Created on: 25/ago/2016
 *      Author: chessaa
 */

#ifndef BSK_TFTPD_H_
#define BSK_TFTPD_H_

#ifdef __cplusplus
extern "C" {
#endif

typedef int bsk_tftpd_context_id_t;
typedef void* bsk_tftp_cookie_t;

typedef struct
{
    const char* name;
    unsigned int port;
    bsk_tftp_cookie_t cookie;
} bsk_tftpd_context_info_t;

typedef enum
{
  bsk_tftpd_open_file,  //data is the filename, null terminaled. block and size N/A

  bsk_tftpd_data,
  bsk_tftpd_end,  //last block, with maybe a zero len data

  bsk_tftpd_open_read_not_supported,  //data is the filename, null terminaled. block and size N/A

  bsk_tftpd_error
} bsk_tftpd_receive_delegate_operation_t;

#define  TFTP_EUNDEF      0       /* not defined */
#define  TFTP_ENOTFOUND   1       /* file not found */
#define  TFTP_EACCESS     2       /* access violation */
#define  TFTP_ENOSPACE    3       /* disk full or allocation exceeded */
#define  TFTP_EBADOP      4       /* illegal TFTP operation */
#define  TFTP_EBADID      5       /* unknown transfer ID */
#define  TFTP_EEXISTS     6       /* file already exists */
#define  TFTP_ENOUSER     7       /* no such user */
#define  TFTP_EBADOPTION  8        /* bad option */
#define  TFTP_ECANCELLED 99      /* cancelled by administrator */

typedef enum
{
  bsk_tftpd_ok=0,
  bsk_tftpd_err_not_found=1,
  bsk_tftpd_err_access,
  bsk_tftpd_err_no_space,
  bsk_tftpd_err_bad_operation,
  bsk_tftpd_err_bad_id,
  bsk_tftpd_err_file_exists,

  bsk_tftpd_dont_ack=100

} bsk_tftpd_status_t;

typedef struct
{
  bsk_tftpd_status_t sts;
  const char* ack_msg;
} bsk_tftpd_receive_status_t;


const bsk_tftpd_context_info_t* bsk_tftpd_context_info(bsk_tftpd_context_id_t);

bsk_tftpd_context_id_t bsk_tftpd_context_initialize(bsk_tftpd_context_id_t id, const char* name, unsigned int port, bsk_tftp_cookie_t cookie);

extern int bsk_tftpd_process_packet(bsk_tftpd_context_id_t id, unsigned int client_address, unsigned int client_port, const void* packet, unsigned int size_bytes);

extern int bsk_tftpd_send_ack(bsk_tftpd_context_id_t id, bsk_tftpd_status_t code, const char* msg);

extern int bsk_tftpd_set_busy(bsk_tftpd_context_id_t id, const char* msg);    //msg=0 means NO BUSY


//Delegates:
typedef int (*bsk_tftpd_send_delegate_t)(bsk_tftpd_context_id_t, unsigned int client_address, unsigned int port, const void* const data, unsigned int size);

extern void bsk_tftpd_set_send_delegate(bsk_tftpd_context_id_t id, bsk_tftpd_send_delegate_t send_delegate);

typedef int (*bsk_tftpd_log_delegate_t)(bsk_tftpd_context_id_t, const char* const msg, ...);

extern void bsk_tftpd_set_log_delegate(bsk_tftpd_context_id_t, bsk_tftpd_log_delegate_t log_delegate);

typedef bsk_tftpd_receive_status_t (*bsk_tftpd_receive_delegate_t)(bsk_tftpd_context_id_t id, bsk_tftpd_receive_delegate_operation_t op, const void* const data, unsigned int block, unsigned int offset, unsigned int size_bytes);

extern void bsk_tftpd_set_receive_delegate(bsk_tftpd_context_id_t, bsk_tftpd_receive_delegate_t receive_delegate);

//Client I/F
extern int bsk_tftpd_send_rrq(unsigned int client_address, unsigned int port, const char* fname);

#ifdef __cplusplus
}
#endif


#endif /* BSK_TFTPD_H_ */
