#ifndef __SMTP_H__
#define __SMTP_H__

/*
 *          (RFC 821)
 *          CONNECTION ESTABLISHMENT
 *             S: 220
 *             F: 421
 *          HELO
 *             S: 250
 *             E: 500, 501, 504, 421
 *          MAIL
 *             S: 250
 *             F: 552, 451, 452
 *             E: 500, 501, 421
 *          RCPT 
 *             S: 250, 251
 *             F: 550, 551, 552, 553, 450, 451, 452
 *             E: 500, 501, 503, 421
 *          DATA
 *             I: 354 -> data -> S: 250
 *                               F: 552, 554, 451, 452
 *             F: 451, 554
 *             E: 500, 501, 503, 421
 *          RSET
 *             S: 250
 *             E: 500, 501, 504, 421
 *          QUIT
 *             S: 221
 *             E: 500
 *
 *
 *    First, the diagram that represents most of the SMTP commands:
 *       
 *                                1,3    +---+
 *                           ----------->| E |
 *                          |            +---+
 *                          |
 *       +---+    cmd    +---+    2      +---+
 *       | B |---------->| W |---------->| S |
 *       +---+           +---+           +---+
 *                          |
 *                          |     4,5    +---+
 *                           ----------->| F |
 *                                       +---+
 *
 *       This diagram models the commands:
 *
 *          HELO, MAIL, RCPT, SEND, QUIT
 *
 *
 *       A more complex diagram models the DATA command: 
 *
 *       +---+   DATA    +---+ 1,2                 +---+
 *       | B |---------->| W |-------------------->| E |
 *       +---+           +---+        ------------>+---+
 *                       3| |4,5     |
 *                        | |        |
 *          --------------   -----   |
 *         |                      |  |             +---+
 *         |               ----------     -------->| S |
 *         |              |       |      |         +---+
 *         |              |  ------------
 *         |              | |     |
 *         V           1,3| |2    |
 *       +---+   data    +---+     --------------->+---+
 *       |   |---------->| W |                     | F |
 *       +---+           +---+-------------------->+---+
 *                            4,5
 *
 *
 *       Note that the "data" here is a series of lines sent from the
 *       sender to the receiver with no response expected until the last
 *       line is sent.
 *
 *
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>


#include "tcp_client.h"
#include "smtp_struct.h"


/*
 * Reference RFC 821 Section 4.2.1
 */
#define UNKNOWN_COMMAND		"500"	/* 500 Syntax error, command unrecognized */
					/*     [This may include errors such as command line too long] */
#define WRONG_PARAMETER		"501"	/* 501 Syntax error in parameters or arguments */
#define COMMAND_NOT_IMPLEMENT	"502"	/* 502 Command not implemented */
#define BAD_COMMAND_SEQUENCE	"503"	/* 503 Bad sequence of commands */
#define PARAMETER_NOT_IMPLEMENT	"504"	/* 504 Command parameter not implemented */

#define SYSTEM_STATUS		"211"	/* 211 System status, or system help reply */
#define HELP_MESSAGE		"214"	/* 214 Help message */
					/*     [Information on how to use the receiver or the meaning of a */
					/*     particular non-standard command; this reply is useful only */
					/*     to the human user] */
 
#define SERVICE_READY		"220"	/* 220 <domain> Service ready */
#define SERVICE_CLOSE		"221"	/* 221 <domain> Service closing transmission channel */

#define SERVICE_NOT_AVAILABLE	"421"	/* 421 <domain> Service not available, */
					/*      closing transmission channel */
					/*     [This may be a reply to any command if the service knows it */
					/*     must shut down] */

#define MAIL_ACTION_OK		"250"	/* 250 Requested mail action okay, completed */
#define USER_NOT_LOCAL_FORWARD	"251"	/* 251 User not local; will forward to <forward-path> */

#define MAILBOX_BUSY		"450"	/* 450 Requested mail action not taken: mailbox unavailable */
					/*     [E.g., mailbox busy] */
#define MAILBOX_NOT_ACCESS	"550"	/* 550 Requested action not taken: mailbox unavailable */
					/*     [E.g., mailbox not found, no access] */

#define ERROR_IN_PROCESSING	"451"	/* 451 Requested action aborted: error in processing */
#define USER_NOT_LOCAL		"551"	/* 551 User not local; please try <forward-path> */
#define LACK_SYSTEM_STORAGE	"452"	/* 452 Requested action not taken: insufficient system storage */
#define EXCEEDED_STORAGE_ALLOC	"552"	/* 552 Requested mail action aborted: exceeded storage allocation */
#define WRONG_MAILBOX_NAME	"553"	/* 553 Requested action not taken: mailbox name not allowed */
					/*     [E.g., mailbox syntax incorrect] */
#define START_MAIL_INPUT	"354"	/* 354 Start mail input; end with <CRLF>.<CRLF> */
#define TRANSACTION_FAILED	"554"	/* 554 Transaction failed */

typedef enum
{
	SMTP_TX_BEGIN=0,					//0
	SMTP_TX_CONNECTING,					//1
	SMTP_TX_SEND_HELO,					//2
	SMTP_TX_WAIT_FOR_HELO_RESP,			//3
	SMTP_TX_SEND_AUTH_LOGIN,			//4
	SMTP_TX_WAIT_FOR_AUTH_LOGIN_RESP,	//5
	SMTP_TX_SEND_USERNAME,				//6
	SMTP_TX_WAIT_FOR_USER_NAME_RESP,	//7
	SMTP_TX_SEND_PASSWD,				//8
	SMTP_TX_WAIT_FOR_PASSWORD_RESP,		//9
	SMTP_TX_SEND_MAIL_FROM,				//10
	SMTP_TX_WAIT_FOR_MAIL_RESP,			//11
	SMTP_TX_SEND_RCPT,					//12
	SMTP_TX_WAIT_FOR_RCPT_RESP,			//13
	SMTP_TX_SEND_DATA,					//14
	SMTP_TX_WAIT_FOR_DATA_RESP,			//15
	SMTP_TX_SEND_CONTENT,				//16
	SMTP_TX_WAIT_FOR_CONTENT_RESP,		//17
	SMTP_TX_SEND_QUIT,					//18
	SMTP_TX_END							//19
} smtp_tx_state_type;

void smtp_tx_begin(void *);
void smtp_tx_connecting(void *);
void smtp_tx_wait_for_helo_resp(void *);

void smtp_tx_wait_for_auth_login_resp(void *);
void smtp_tx_wait_for_user_name_resp(void *);
void smtp_tx_wait_for_password_resp(void *);

void smtp_tx_wait_for_mail_resp(void *);
void smtp_tx_wait_for_rcpt_resp(void *);
void smtp_tx_wait_for_data_resp(void *);
void smtp_tx_wait_for_data_input_resp(void *);
void smtp_tx_end(void *);
void smtp_tx_restart(struct tSmtpPort *);

#define BASE64_PAD64 '='
static int cmove_bits(unsigned char src, unsigned lnum, unsigned rnum) 
{
   src <<= lnum;
   src >>= rnum;
   return src;
}
char* base64_encode(const char *data);
char* base64_decode(const char *bdata);

void	smtp_tx_fsm(struct tSmtpPort *tx_port);

int smtp_tx_port_assign(SMTP_MSG*);

void smtp_tx_port_release(struct tSmtpPort *p);

#define	LISTEN_NUMS	 256
#define	Exe_num		128
#define wait_queue_num 256

struct Smtp_wait_queue
{
	int start;
	int end;
	int wait_queue[wait_queue_num];
};
// move to smeg_smtp.c by simon, at 2024/06/11
// struct Smtp_wait_queue smtp_wait_queue;
void insert_smtp_wait_queue(int);
void smtp_inser_Execute(int *);

char * delete_characters(const char *, const char *, int );
int sm2email(SMTP_MSG *, char *);

///----------Server
#define EHLO_CMD		"EHLO"
#define HELO_CMD    "HELO"
#define MAIL_CMD		"MAIL FROM"
#define RCPT_CMD		"RCPT TO"
#define DATA_CMD		"DATA"
#define	QUIT_CMD		"QUIT"

#define PARSE_ERROR   0
#define PARSE_SUCCESS 1

int smtp_rx_port_assign(int temp_fd, struct tSmtpPort *Smtp_Serv);
void smtp_rx_port_release(struct tSmtpPort *p);
typedef enum
{
	SMTP_RX_BEGIN = 0,
	SMTP_RX_WAIT_HELO,		
	SMTP_RX_SEND_HELO_RESP,
	SMTP_RX_WAIT_MAIL,	
	SMTP_RX_SEND_MAIL_RESP,	
	SMTP_RX_WAIT_RCPT_DATA,
	SMTP_RX_SEND_RCPT_RESP,
	SMTP_RX_SEND_DATA_RESP,
	SMTP_RX_WAIT_CONTENT,
	SMTP_RX_SEND_CONTENT_RESP,
	SMTP_RX_WAIT_QUIT,
	SMTP_RX_QUIT_RESP
} smtp_rx_state_type;

int 	parse_field(struct tSmtpPort *pSmtpRxPort, char *pt);
int Qp_decode(char *, const char *, int);
//#define BYTE   unsigned char
//-----common


void add_socket_fd(int );
void delete_socket_fd(int );

int check_write_read();
void setnonblocking(int );

void add_socket_tx();
void add_socket_rx();
void delt_socket_tx();
void delt_socket_rx();

#endif /* __SMTP_H__ */


