[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-protcl/ftp/lynq_ftpclient.c b/src/lynq/lib/liblynq-protcl/ftp/lynq_ftpclient.c
new file mode 100644
index 0000000..87220ee
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/ftp/lynq_ftpclient.c
@@ -0,0 +1,939 @@
+#include "ftp/lynq_ftp.h"
+
+int lynq_ftp_login(lynq_ftp_socker_info *FTP)
+{
+ struct sockaddr_in serv_addr;
+ char recvdate;
+ char sendline[MAXSIZE] = "", recvline[MAXSIZE] = "";
+ struct hostent *host = NULL;
+
+ char name[MAXSIZE] = "", password[MAXSIZE] = "";
+ LYDBGLOG("[%s-%d] ftp,enter the hostname = %s\n", __FUNCTION__, __LINE__, FTP->sevname);
+
+ host = gethostbyname(FTP->sevname);
+
+ if(host == NULL)
+ {
+ error = 35;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+ else
+ {
+ FTP->control_sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(FTP->control_sockfd < 0)
+ {
+ error = 50;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ LYDBGLOG("[%s-%d]\n", __FUNCTION__, __LINE__);
+ login_yes = 0;
+ }
+
+ bzero(&serv_addr, sizeof(serv_addr));
+
+ memset(&serv_addr, 0, sizeof(struct sockaddr_in));
+ memcpy(&serv_addr.sin_addr.s_addr, host->h_addr, host->h_length);
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(FTP->portnum);
+
+ if((connect(FTP->control_sockfd, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr))) < 0)
+ {
+ error = 33;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+
+
+ recvdate = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(recvdate == -1)
+ {
+ error = 33;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+ else if(strncmp(recvline, "220", 3) == 0)
+ {
+ LYDBGLOG("ftp,connect success\n");
+ login_yes = 1;
+ }
+ else
+ {
+ error = 33;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+ if(login_yes == 1)
+ {
+ int sendbytes, recvbytes;
+
+ zeromery(name, 1024);
+ zeromery(password, 1024);
+ zeromery(recvline, 1024);
+ zeromery(sendline, 1024);
+ strcat(sendline, "USER ");
+ strcat(sendline, FTP->username);
+ strcat(sendline, "\r\n");
+ //printf("[%s %d] --->%s\n",__FUNCTION__ , __LINE__,sendline);
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes == -1)
+ {
+ error = 38;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ //return FTP_USER_ERROR;
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(strncmp(recvline, "331", 3) == 0)
+ {
+ LYDBGLOG("[%s %d] ftp,331 please specify the password.\n", __FUNCTION__ , __LINE__);
+ }
+ else
+ {
+ error = 38;
+ LYDBGLOG("[%s-%d] ftp,recv date is error.%d\n", __FUNCTION__ , __LINE__, error);
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ //printf("ftp-> ");
+ strcat(sendline, "PASS ");
+ strcat(sendline, FTP->pw);
+ strcat(sendline, "\r\n");
+ //printf("[%s %d]--->%s\n",__FUNCTION__, __LINE__, sendline);
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes == -1)
+ {
+ error = 39;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(strncmp(recvline, "230", 3) == 0)
+ {
+ LYVERBLOG("+[ftp][login][session%d]: ok!!\n", FTP->session);
+ login_yes = 1;
+ }
+ else
+ {
+ error = 39;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+
+#if 1
+ //support rest
+ char str[255];
+ sprintf(str, "%d", FTP->rest);
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ strcat(sendline, "REST ");
+ strcat(sendline, str);
+ strcat(sendline, "\r\n");
+ //printf("[%s-%d]--->%s\n", __FUNCTION__, __LINE__, sendline);
+ sendbytes = send(FTP->control_sockfd,sendline,strlen(sendline),0);
+ if(sendbytes == -1)
+ {
+ error = 41;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline,sizeof(recvline),0);
+ if(recvbytes == -1)
+ {
+ error = 41;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+ if(strncmp(recvline, "350",3) == 0)
+ {
+ LYDBGLOG("[%s-%d] support rest\n", __FUNCTION__, __LINE__);
+ login_yes = 1;
+ }
+ else
+ {
+ error = 41;
+ LYDBGLOG("[%s-%d] ftp,not support rest%d\n", __FUNCTION__, __LINE__, error);
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ login_yes = 0;
+ }
+#endif
+ }
+
+ }
+ return login_yes;
+}
+
+void zeromery(char *a,int len)
+{
+ int i;
+ len = sizeof(a);
+ for(i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ }
+}
+
+void lynq_ftp_pwd(int control_sockfd)
+{
+ int recvbytes,sendbytes;
+ char sendline[1024], recvline[1024];
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ strcat(sendline, "PWD");
+ strcat(sendline, "\r\n");
+ sendbytes = send(FTP->control_sockfd,sendline,strlen(sendline),0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] ftp,pwd,send is error\n", __FUNCTION__, __LINE__);
+ error = 52;
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline,sizeof(recvline),0);
+ if(strncmp(recvline, "257",3) == 0)
+ {
+ LYDBGLOG("[%s-%d] ftp,current directory is:%s\n", __FUNCTION__, __LINE__, recvline);
+ }
+ else
+ {
+ error = 51;
+ LYDBGLOG("[%s-%d] ftp,pwd,recv is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][login][session%d]: error num = %d\n", FTP->session, error);
+ }
+}
+
+//rest
+void lynq_ftp_rest(int control_sockfd)
+{
+
+ int recvbytes,sendbytes;
+ char sendline[1024], recvline[1024];
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ strcat(sendline, "REST ");
+ strcat(sendline, "500");
+ strcat(sendline, "\r\n");
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ error = 52;
+ LYDBGLOG("[%s-%d] ftp,stru send is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][reset][session%d]: error num = %d\n", FTP->session, error);
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(recvbytes < 0)
+ {
+ error = 51;
+ LYVERBLOG("+[ftp][reset][session%d]: error num = %d\n", FTP->session, error);
+ }
+ if(strncmp(recvline, "350",3) == 0)
+ {
+ LYDBGLOG("[%s-%d] ftp,%s\n", __FUNCTION__, __LINE__, recvline);
+ }
+}
+
+int strtosrv(char *str)
+{
+
+ int addr[6];
+ //printf("%s\n",str);
+ sscanf(str, "%*[^(](%d,%d,%d,%d,%d,%d)", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]);
+
+ LYDBGLOG("[%s-%d] ftp,%d,%d,%d,%d\n", __FUNCTION__, __LINE__, addr[0],addr[1],addr[2],addr[3]);
+ bzero(hoster, strlen(hoster));
+ sprintf(hoster, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
+
+ LYDBGLOG("[%s-%d] ftp,hoster = %s", __FUNCTION__, __LINE__, hoster);
+ int port = addr[4]*256 + addr[5];
+ LYDBGLOG("[%s-%d] ftp,port = %d\n", __FUNCTION__, __LINE__, port);
+ return port;
+}
+
+
+int lynq_ftp_download(lynq_ftp_socker_info* FTP)
+{
+ char catbuf[1024];
+ int data_sock;
+ int recvbytes, sendbytes;
+ char sendline[1024] = "", recvline[1024] = "";
+ char getfilepath[FTP_MAX_ASCII_LEN+5] = "/tmp/";
+
+#if 1
+ //type
+
+ zeromery(recvline, 1024);
+ zeromery(sendline, 1024);
+ strcat(sendline, "TYPE ");
+ strcat(sendline, FTP->file_type);
+ strcat(sendline, "\r\n");
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline),0);
+ if(sendbytes < 0)
+ {
+ error = 52;//FTP_SEND_ERROR
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+ return FTP_SEND_ERROR;
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ LYDBGLOG("[%s-%d] ftp,recvline = %s\n",__FUNCTION__, __LINE__, recvline);
+ if(strncmp(recvline, "200", 3) == 0)
+ {
+ LYDBGLOG("[%s-%d] ftp,binary transmisson\n",__FUNCTION__, __LINE__);
+ }
+ else
+ {
+ error = 46; //FTP_DOWNLOAD_ERROR
+ LYDBGLOG("[%s-%d] ftp,download error\n",__FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+ return FTP_DOWNLOAD_ERROR;
+ }
+#endif
+
+ zeromery(recvline, 1024);
+ zeromery(sendline, 1024);
+ strcat(sendline, FTP->is_pasv_mode);
+ strcat(sendline, " \r\n");
+
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ error = 52; //FTP_SEND_ERROR
+ LYDBGLOG("[%s-%d] type send is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+ return FTP_SEND_ERROR;
+ }
+
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(strncmp(recvline, "227", 3) == 0)
+ {
+ LYDBGLOG("[%s-%d] ftp,binary transmisson\n", __FUNCTION__, __LINE__);
+ }
+ else
+ {
+ error = 43;//FTP_ACTIVE_ERROR
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+ LYDBGLOG("[%s-%d] type recv is error!\n", __FUNCTION__, __LINE__);
+ return FTP_ACTIVE_ERROR;
+ }
+
+ LYDBGLOG("-------- [%s-%d] recvline = %s\n", __FUNCTION__, __LINE__, recvline);
+ int port1 = strtosrv(recvline);
+ data_sock = cliopen(hoster, port1);
+
+ LYDBGLOG("[%s-%d] ftp,data_sock = %d\n", __FUNCTION__, __LINE__, data_sock);
+ LYDBGLOG("[%s-%d] FTP->getfilename = %s\n", __FUNCTION__, __LINE__, FTP->getfilename);
+ LYDBGLOG("[%s-%d] FTP->getfilename_path = %s\n", __FUNCTION__, __LINE__, FTP->getfilename_path);
+
+ //send the command retr;
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ strcat(sendline, "RETR ");
+ strcat(sendline, FTP->getfilename_path);
+ strcat(sendline, "/");
+ strcat(sendline, FTP->getfilename);
+ strcat(sendline, "\r\n");
+ //printf("%s\n", sendline);
+
+ LYDBGLOG("[%s-%d] ftp,%ld\n", __FUNCTION__, __LINE__, write(FTP->control_sockfd,sendline,strlen(sendline)));
+ LYDBGLOG("[%s-%d] getfilename= %s FTP->control_sockfd = %d\n", __FUNCTION__, __LINE__, FTP->getfilename, FTP->control_sockfd);
+#if 1
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+
+ if(recvbytes < 0)
+ {
+ error = 52;//FTP_SEND_ERROR
+ LYDBGLOG("[%s-%d] retr recv is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+
+ return FTP_SEND_ERROR;
+ }
+ LYDBGLOG("[%s-%d] recvline = %s\n", __FUNCTION__, __LINE__, recvline);
+ if(strncmp(recvline, "400", 3) > 0)
+ {
+ error = 51;//FTP_RCV_ERROR
+
+ LYDBGLOG("[%s-%d] return is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+ return FTP_RCV_ERROR;
+ }
+
+ strcat(getfilepath, FTP->getfilename);
+ lynq_ftp_get(data_sock, getfilepath, FTP->session);
+
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+
+ strcpy(FTP->respond, recvline);
+
+ LYDBGLOG("[%s-%d] FTP->respond = %s\n", __FUNCTION__, __LINE__, FTP->respond);
+
+ if(strncmp(FTP->respond, "550", 3) == 0)
+ {
+ error = 46; //FTP_DOWNLOAD_ERROR
+ LYDBGLOG("[%s-%d] download is error %d \n", __FUNCTION__, __LINE__, error);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+
+ return FTP_DOWNLOAD_ERROR;
+ }
+
+ if(strncmp(FTP->respond, "421",3) == 0)
+ {
+ error = 34;//FTP_TIMEROUT
+ LYDBGLOG("[%s-%d] download is error %d \n", __FUNCTION__, __LINE__, error);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", FTP->session, error);
+
+ return FTP_TIMEROUT;
+ }
+
+ if((strncmp(FTP->respond, "226", 3) == 0) || (strncmp(FTP->respond, "125",3) == 0))
+ {
+ LYVERBLOG("+[ftp][get][session%d]: ok!!\n", FTP->session);
+ }
+#endif
+ return 0;
+
+}
+
+int lynq_ftp_put(int sck, char *pUploadFileName_s)
+{
+ int handle = open(pUploadFileName_s, O_RDWR);
+ int nread;
+ if(handle == -1)
+ return -1;
+
+ while(1)
+ {
+ if((nread = read(handle, rbuf1, 1024)) < 0)
+ {
+ error = 54;//FTP_READ_ERROR
+ LYDBGLOG("[%s-%d] read error!", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, error);
+ }
+ else if(nread == 0)
+ break;
+ LYDBGLOG("[%s-%d] rbuf1 = %s \n", __FUNCTION__, __LINE__, rbuf1);
+
+ if(write(sck, rbuf1, nread) != nread){
+ error = 54;
+ LYDBGLOG("[%s-%d] send error!", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, error);
+ }
+ memset(rbuf1,0,1024);
+ }
+ if(close(sck) < 0)
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, FTP_CLOSE_ERROR);
+
+ return 0;
+}
+
+
+int lynq_ftp_up(lynq_ftp_socker_info* FTP)
+{
+ char catbuf[1024];
+ int data_sock;
+ int recvbytes,sendbytes;
+ char sendline[1024], recvline[1024];
+ int put_ret = -1;
+
+ if((access(FTP->putfilename, F_OK)) == -1)
+ {
+ //FTP_SOCK_ERROR
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, FTP_SOCK_ERROR);
+ LYDBGLOG("[%s-%d] %s file does not exist\n", __FUNCTION__, __LINE__, FTP->putfilename);
+ return FTP_SOCK_ERROR;
+ }
+
+#if 1
+ zeromery(recvline, 1024);
+ zeromery(sendline, 1024);
+ strcat(sendline, "TYPE ");
+ strcat(sendline, FTP->file_type);
+ strcat(sendline, "\r\n");
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] ftp type send is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, FTP_SEND_ERROR);
+ return FTP_SEND_ERROR;
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline,sizeof(recvline),0);
+ if(strncmp(recvline, "200",3) == 0)
+ {
+ LYDBGLOG("[%s-%d] initalize\n", __FUNCTION__, __LINE__);
+ }
+ else
+ {
+ LYDBGLOG("[%s-%d] type recv is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, FTP_RCV_ERROR);
+ return FTP_RCV_ERROR;
+ }
+#endif
+
+ //PASV
+ zeromery(recvline, 1024);
+ zeromery(sendline, 1024);
+ strcat(sendline, FTP->is_pasv_mode);
+ strcat(sendline, " \r\n");
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] type send is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, FTP_SEND_ERROR);
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline,sizeof(recvline), 0);
+ if(strncmp(recvline, "227", 3) == 0)
+ {
+ LYDBGLOG("[%s-%d] binary transmisson\n", __FUNCTION__, __LINE__);
+ }
+ else
+ {
+ error = 43;//FTP_ACTIVE_ERROR
+ LYDBGLOG("[%s-%d] type recv is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, error);
+ return FTP_ACTIVE_ERROR;
+ }
+
+ //init datelink server port information
+ int port1 = strtosrv(recvline);
+ LYDBGLOG("[%s-%d] ftp,hoster =%s,port1 = %d\n", __FUNCTION__, __LINE__, hoster,port1);
+ data_sock = cliopen(hoster, port1);
+
+ LYDBGLOG("[%s-%d] ftp,data_sock = %d\n", __FUNCTION__, __LINE__, data_sock);
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ strcat(sendline, FTP->put_opt);
+ strcat(sendline, " ");
+ strcat(sendline, FTP->putfilename_path);
+ strcat(sendline, "/");
+ strcat(sendline, FTP->putfilename);
+ strcat(sendline, "\r\n");
+
+ LYDBGLOG("[%s-%d] ftp,%s\n", __FUNCTION__, __LINE__, sendline);
+ LYDBGLOG("%ld\n", write(FTP->control_sockfd, sendline, strlen(sendline)));
+ LYDBGLOG("[%s-%d] ftp,filename = %s\n", __FUNCTION__, __LINE__, FTP->putfilename);
+
+
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+
+ LYDBGLOG("RETR RECVLINE = %s\n", recvline);
+ if(recvbytes < 0)
+ {
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, FTP_RCV_ERROR);
+ LYDBGLOG("[%s-%d] retr recv is error!\n", __FUNCTION__, __LINE__);
+ return FTP_RCV_ERROR;
+ }
+ if(strncmp(recvline, "400", 3) > 0)
+ {
+ error = 400;
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, error);
+ }
+
+ lynq_ftp_put(data_sock, FTP->putfilename);
+
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+
+ strcpy(FTP->respond, recvline);
+
+ if(strncmp(FTP->respond, "226",3) == 0)
+ {
+ LYDBGLOG("[%s-%d] FTP->respond = %s\n", __FUNCTION__, __LINE__, FTP->respond);
+ LYVERBLOG("+[ftp][up][session%d]: ok!!\n", FTP->session);
+ }
+ else
+ {
+ error = 45;//FTP_UPLOAD_ERROR
+ LYVERBLOG("+[ftp][up][session%d]: error num = %d\n", FTP->session, error);
+ return FTP_UPLOAD_ERROR;
+ }
+ return 0;
+
+}
+
+
+int lynq_ftp_ls(lynq_ftp_socker_info* FTP)
+{
+ char catbuf[1024];
+ int data_sock;
+ int recvbytes, sendbytes;
+ char sendline[1024], recvline[1024];
+
+
+ //PASV
+ zeromery(recvline, 1024);
+ zeromery(sendline, 1024);
+ strcat(sendline, FTP->is_pasv_mode);
+ strcat(sendline, " \r\n");
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] type send is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][ls][session%d]: error num = %d\n", FTP->session, FTP_SEND_ERROR);
+ return FTP_SEND_ERROR;
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline,sizeof(recvline), 0);
+ if(strncmp(recvline, "227",3) == 0)
+ {
+ LYDBGLOG("[%s-%d] binary transmit\n", __FUNCTION__, __LINE__);
+ }
+ else
+ {
+ error = 43;
+ LYDBGLOG("[%s-%d] type recv is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][ls][session%d]: error num = %d\n", FTP->session, error);
+ return error;
+ }
+
+ //init datelink server port information
+ int port1 = strtosrv(recvline);
+ LYDBGLOG("[%s-%d] ftp,hoster =%s,port1 = %d\n", __FUNCTION__, __LINE__, hoster,port1);
+ data_sock = cliopen(hoster, port1);
+
+ //printf("data_sock = %d\n",data_sock);
+
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ strcat(sendline, "LIST -al ");
+ strcat(sendline, FTP->dir);
+ strcat(sendline, "\r\n");
+
+ LYDBGLOG("%ld\n", write(FTP->control_sockfd, sendline, strlen(sendline)));
+
+ LYDBGLOG("[%s-%d] ftp,%s\n", __FUNCTION__, __LINE__,sendline);
+
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+
+ //printf("RETR RECVLINE = %s\n",recvline);
+ LYDBGLOG("[%s-%d] recvline = %s\n", __FUNCTION__, __LINE__, recvline);
+
+ if(recvbytes < 0)
+ {
+ LYVERBLOG("+[ftp][ls][session%d]: error num = %d\n", FTP->session, FTP_SEND_ERROR);
+ }
+ if(strncmp(recvline, "400", 3)>0)
+ {
+ error = 400;
+ LYDBGLOG("[%s-%d] type recv is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][ls][session%d]: error num = %d\n", FTP->session, error);
+ return error;
+ }
+
+ ftp_list(data_sock, FTP->session);
+
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+
+ LYDBGLOG("[%s-%d] recvline = %s\n", __FUNCTION__, __LINE__, recvline);
+
+ strcpy(FTP->respond, recvline);
+
+ if((strncmp(FTP->respond, "226", 3) == 0) || (strncmp(FTP->respond, "150",3) == 0) || strncmp(FTP->respond, "125", 3) == 0)
+ {
+ if(strstr(FTP->respond, ". 0 bytes")){//rita add @2021.07.19 for ls
+ LYDBGLOG("[%s-%d] FTP->respond = %s\n", __FUNCTION__, __LINE__, FTP->respond);
+ LYVERBLOG("+[ftp][ls][session%d]: error num = %d\n", FTP->session, FTP_LS_ERROR);
+ return FTP_LS_ERROR;
+ }
+ else
+ LYVERBLOG("+[ftp][ls][session%d]: ok!!\n", FTP->session);
+ }
+ else{
+ error = 44;
+ LYDBGLOG("[%s-%d] ls error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][ls][session%d]: error num = %d\n", FTP->session, error);
+ return error;
+ }
+
+ return 0;
+}
+
+
+void lynq_ftp_get(int sck, char *pDownloadFileName, int session)
+{
+ int handle = open(pDownloadFileName, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD| S_IWRITE);
+ int nread;
+
+ while(1)
+ {
+ //printf("%d\n",sck);
+ //printf("%d\n",handle);
+ if((nread = recv(sck, rbuf1, 1024, 0)) < 0)
+ {
+ error = 51;
+ //LYDBGLOG("[%s-%d] ftp,rbuf1 = %s\n", __FUNCTION__, __LINE__, rbuf1);
+ LYDBGLOG("[%s-%d] receive error\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", session, error);
+ return;
+ }
+ else if(nread == 0)
+ {
+ LYDBGLOG("[%s-%d] over\n", __FUNCTION__, __LINE__);
+ break;
+ }
+ if(write(handle, rbuf1, nread) != nread)
+ {
+ LYDBGLOG("[%s-%d] receive error from server!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", session, FTP_WRITE_ERROR);
+ }
+
+ //LYDBGLOG("[%s-%d] rbuf1 = %s \n", __FUNCTION__, __LINE__, rbuf1);
+
+ memset(rbuf1,0,1024);
+ }
+ if(close(sck) < 0){
+ LYDBGLOG("[%s-%d] close error\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][get][session%d]: error num = %d\n", session, FTP_CLOSE_ERROR);
+ }
+}
+
+
+
+int cliopen(char *hoster, int port)
+{
+
+ int control_sockfd;
+
+ struct sockaddr_in serv_addr;
+ struct hostent *host = NULL;
+
+ //get hostent argument
+ char name[MAXSIZE];
+ //printf("please enter the hostname\n");
+ //printf("ftp-> ");
+
+ strcpy(name, hoster);
+ host = gethostbyname(name);
+ if(host == NULL)
+ {
+ LYDBGLOG("[%s-%d] ftp,get host by name is error!\n", __FUNCTION__, __LINE__);
+ login_yes = 0;
+ }
+ else
+ {
+ //creact socket
+ control_sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(control_sockfd < 0)
+ {
+ //printf("socket is error\n");
+ LYDBGLOG("[%s-%d] ftp,socket is error\n", __FUNCTION__, __LINE__);
+ login_yes = 0;
+ }
+
+ //set sockaddr_in
+ bzero(&serv_addr, sizeof(serv_addr));
+
+ memset(&serv_addr, 0, sizeof(struct sockaddr_in));
+ memcpy(&serv_addr.sin_addr.s_addr, host->h_addr, host->h_length);
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(port);
+
+ //printf("line port = %d\n",port);
+ if((connect(control_sockfd, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr))) < 0)
+ {
+ //printf("connect is error\n");
+ LYDBGLOG("[%s-%d] ftp,connect is error\n", __FUNCTION__, __LINE__);
+ login_yes = 0;
+ }
+ }
+ return control_sockfd;
+}
+
+void ftp_list(int sockfd, int session)
+{
+ int nread;
+
+ for(;;)
+ {
+ if((nread = recv(sockfd, rbuf1, 1024, 0)) < 0)
+ {
+ LYDBGLOG("[%s-%d] recv error\n", __FUNCTION__, __LINE__);
+ }
+ else if(nread == 0)
+ {
+ LYDBGLOG("[%s-%d] disconnect \n", __FUNCTION__, __LINE__);
+ break;
+ }
+ LYVERBLOG("+[ftp][ls][session%d]: data = %s\n", session, rbuf1);
+ LYVERBLOG("+[ftp][ls][session%d]: ok!! \n", session);
+ memset(rbuf1, 0, 1024);
+ }
+ if(close(sockfd) < 0){
+ LYDBGLOG("[%s-%d] close error\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][ls][session%d]: error num = %d\n", session, FTP_CLOSE_ERROR);
+ }
+}
+
+void lynq_ftp_cd(lynq_ftp_socker_info* FTP)
+{
+ char catbuf[1024];
+ char sendline[1024];
+ char recvline[1024];
+
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ int recvbytes, sendbytes;
+ int issuccess;
+
+ if(strcmp(FTP->del_mkr_filename, "..") == 0)
+ {
+ sprintf(sendline, "CDUP %s\n", FTP->del_mkr_filename);
+ }
+ else
+ {
+ sprintf(sendline, "CWD %s\n", FTP->del_mkr_filename);
+ }
+ strcat(sendline, "\r\n");
+
+ LYDBGLOG("[%s-%d] %s\n", __FUNCTION__, __LINE__, sendline);
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("cd send is error!");
+ exit(1);
+ }
+
+
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(strncmp(recvline, "257", 3) == 0)
+ {
+ issuccess = 1;
+ }
+ else
+ {
+ error = 44;
+ issuccess = 0;
+ }
+}
+
+void lynq_ftp_creat_mkd(lynq_ftp_socker_info* FTP)
+{
+ char catbuf[1024];
+ char sendline[1024];
+ char recvline[1024];
+
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ int recvbytes, sendbytes;
+ int issuccess;
+ strcat(sendline, "MKD ");
+ strcat(sendline, FTP->del_mkr_filename);
+ strcat(sendline, "\r\n");
+ LYDBGLOG("[%s-%d] %s\n", __FUNCTION__, __LINE__, sendline);
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] mkd send is error!", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][mkdir][session%d]: error num = %s\n", FTP->session, FTP_SEND_ERROR);
+ exit(1);
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(strncmp(recvline, "257", 3) == 0)
+ {
+ issuccess = 1;
+ LYVERBLOG("+[ftp][mkdir][session%d]: ok!!\n", FTP->session);
+ }
+ else
+ {
+ error = 44;
+ LYVERBLOG("+[ftp][mkdir][session%d]: error num = %d\n", FTP->session, error);
+ issuccess = 0;
+ }
+}
+
+
+void lynq_ftp_delete_mkd(lynq_ftp_socker_info* FTP)
+{
+ char sendline[1024];
+ char recvline[1024];
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ int recvbytes, sendbytes;
+ int issuccess;
+ char catbuf[1024];
+
+ strcat(sendline, "RMD ");
+ strcat(sendline, FTP->del_mkr_filename);
+ strcat(sendline, "\r\n");
+ LYDBGLOG("[%s-%d] %s\n", __FUNCTION__, __LINE__,sendline);
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] rmd send is error!", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][rmd][session%d]: error num = %s\n", FTP->session, FTP_SEND_ERROR);
+ exit(1);
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(strncmp(recvline, "250", 3) == 0)
+ {
+ issuccess = 1;
+ LYVERBLOG("+[ftp][rmd][session%d]: ok!!\n", FTP->session);
+ }
+ else
+ {
+ error = 44;
+ issuccess = 0;
+ LYVERBLOG("+[ftp][rmd][session%d]: error num = %s\n", FTP->session, error);
+ }
+}
+
+void lynq_ftp_quit(lynq_ftp_socker_info* FTP)
+{
+
+ int recvbytes, sendbytes;
+ char sendline[1024], recvline[1024];
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+
+
+ strcat(sendline, "bye ");
+ strcat(sendline, "\n");
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] stru send is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][quit][session%d]: error num = %s\n", FTP->session, FTP_SEND_ERROR);
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+
+ LYDBGLOG("[%s-%d] quit = %s\n", __FUNCTION__, __LINE__, recvline);
+ if(recvbytes < 0)
+ {
+ LYDBGLOG("[%s-%d] stru recv is error!\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[ftp][quit][session%d]: error num = %s\n", FTP->session, FTP_RCV_ERROR);
+ }
+ if(strncmp(recvline, "221", 3) == 0)
+ {
+ LYVERBLOG("+[ftp][quit][session%d]: ok!!\n", FTP->session);
+ }
+}
+
+void lynq_ftp_deletefile_mkd(lynq_ftp_socker_info* FTP)
+{
+ char sendline[1024];
+ char recvline[1024];
+
+ zeromery(sendline, 1024);
+ zeromery(recvline, 1024);
+ int recvbytes, sendbytes;
+ int issuccess;
+ char catbuf[1024];
+ strcat(sendline, "DELE ");
+ strcat(sendline, FTP->del_mkr_filename);
+ strcat(sendline, "\r\n");
+ LYDBGLOG("[%s-%d] %s\n", __FUNCTION__, __LINE__,sendline);
+ sendbytes = send(FTP->control_sockfd, sendline, strlen(sendline), 0);
+ if(sendbytes < 0)
+ {
+ LYVERBLOG("+[ftp][delfile][session%d]: error num = %d\n", FTP->session, FTP_SEND_ERROR);
+ exit(1);
+ }
+ recvbytes = recv(FTP->control_sockfd, recvline, sizeof(recvline), 0);
+ if(strncmp(recvline, "250", 3) == 0)
+ {
+ issuccess = 1;
+ LYVERBLOG("+[ftp][delfile][session%d]: ok!!\n", FTP->session);
+ }
+ else
+ {
+ error = 44;
+ issuccess = 0;
+ LYVERBLOG("+[ftp][delfile][session%d]: error num = %d\n", FTP->session, error);
+ }
+}
+
diff --git a/src/lynq/lib/liblynq-protcl/ftp/lynq_ftpshm.c b/src/lynq/lib/liblynq-protcl/ftp/lynq_ftpshm.c
new file mode 100644
index 0000000..e4d4bed
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/ftp/lynq_ftpshm.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "ftp/lynq_ftp.h"
+
+int lynq_ftpshm_create( void )
+{
+ key_t key;
+ int shm_id;
+
+ key = ftok(FTPSHMPATH,FTPSHMID);
+ shm_id = shmget(key,sizeof(struct ftp_socket_info),0664 | IPC_CREAT | IPC_EXCL);
+
+ if(shm_id < 0)
+ {
+ if(errno == EEXIST)
+ shm_id = shmget(key,sizeof(struct ftp_socket_info),0664 | IPC_CREAT );
+
+ else
+ {
+ LYDBGLOG("[%s-%d] ftp,shm_create_fail", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ }
+ return shm_id;
+}
+
+lynq_ftp_socker_info *ftpshm_act(int shmid)
+{
+ lynq_ftp_socker_info *p = NULL;
+
+ p = shmat(shmid,NULL,0);
+
+ if(p == NULL)
+ {
+ LYDBGLOG("[%s-%d] ftp,shm_act_fail", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ return p;
+}
+
+void lynq_ftpshm_deact(lynq_ftp_socker_info *shm)
+{
+ int ret;
+
+ ret = shmdt(shm);
+
+ if(ret < 0)
+ {
+ LYDBGLOG("[%s-%d] ftp,shm_deact_fail", __FUNCTION__, __LINE__);
+ return ;
+ }
+
+ return;
+}
+
+void lynq_ftpshm_del(int shmid)
+{
+ int ret;
+
+ ret = shmctl(shmid, IPC_RMID, 0);
+
+ if(ret == -1)
+ {
+ LYDBGLOG("[%s-%d] ftp,shm_del_fail", __FUNCTION__, __LINE__);
+ return ;
+ }
+
+ return;
+}
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/ca.crt b/src/lynq/lib/liblynq-protcl/http/cert/ca.crt
new file mode 100644
index 0000000..a9007d2
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/ca.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDfzCCAmegAwIBAgIJAODN6ztlacOjMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV
+BAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5nMRAwDgYD
+VQQKDAdUZWFtc3VuMRAwDgYDVQQLDAdUZWFtc3VuMCAXDTIwMDkyODEwMTUwNVoY
+DzIxMjAwOTA0MTAxNTA1WjBVMQswCQYDVQQGEwJDTjEQMA4GA1UECAwHQmVpamlu
+ZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVhbXN1bjEQMA4GA1UECwwH
+VGVhbXN1bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqVvba2fnHk
+gayq5P0kLQIV+xu1yND/LPOuuCTwnVHHqp0VHxtIP8TvYhxXT7oaqsMNQlPKm+SH
+1wDVpe+mrbrv3G9vVsfjPdHf772fP3gLb/+MbnADfD9cq9rIFWKfXNw5F9GYetA2
+gEo/oA0jD2t6Z69hJqsnmhw4LAJhVJxTefyAcOLm59PHB3FRLPOfWOZIX4m16yXn
+C+Pgi3t7fAZDt2ty3VGxg63rLGEoCh0J1AlQhU4QfF7wu1eqxWbMIukkpOzex88k
+C3chj4aWYOscUNCoiPtV2EtR1gqyoyqMIGUtMPtw703oY8A8fNcAjLtqUsObr1JD
+vay+VBVG7V0CAwEAAaNQME4wHQYDVR0OBBYEFOHWjOIKOO7OKH1/+0PjMs8eYK2t
+MB8GA1UdIwQYMBaAFOHWjOIKOO7OKH1/+0PjMs8eYK2tMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggEBAFUK/09WXsFVHhOzfFYquHqNcDyYeld9XVQ7NrZp
+vzI/+rxeHswvQ8+iQF9pV0aOMo27ccE7AjuHwdFwQQHal9y892tzFXSUxfhATT/I
+ZAySC3Gvsf8AQYkcu+fWDLB0FZmRbxvO3+tSTnL+4jkI+IJbSsDvDB6VG9ugWTwd
+O14X+gOalwO1TcsZuMV1d4a1nB8X6pkG78KcQfMwkrb/KPWhZKaxcksBLxBkKHt8
+sZY+FERnWZf3sNaCpm0Uwvd3Ua+IU+f/FpiShBZnSk5mqXB/C6sx2PbXyXNh6fv/
+5rTIpv3nlxAVHNVJo0LFAE5wPpCMCNj082WuT25OkVxKIyY=
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/ca.key b/src/lynq/lib/liblynq-protcl/http/cert/ca.key
new file mode 100644
index 0000000..4758736
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAupW9trZ+ceSBrKrk/SQtAhX7G7XI0P8s8664JPCdUceqnRUf
+G0g/xO9iHFdPuhqqww1CU8qb5IfXANWl76atuu/cb29Wx+M90d/vvZ8/eAtv/4xu
+cAN8P1yr2sgVYp9c3DkX0Zh60DaASj+gDSMPa3pnr2EmqyeaHDgsAmFUnFN5/IBw
+4ubn08cHcVEs859Y5khfibXrJecL4+CLe3t8BkO3a3LdUbGDressYSgKHQnUCVCF
+ThB8XvC7V6rFZswi6SSk7N7HzyQLdyGPhpZg6xxQ0KiI+1XYS1HWCrKjKowgZS0w
++3DvTehjwDx81wCMu2pSw5uvUkO9rL5UFUbtXQIDAQABAoIBAH/D+/X6v1kkHTvs
+hgNl20AbZykRcOLUaaawFL6O2Vtfu0/3X6ah8bDcLzWzABAzJI2OLcYM7nUuI6cZ
+pZgWbc6dYzgXaLhVvkZR7uvM+XwtcNLwCcvARztoLPISoro24DKZEdtfa3HacDzn
+lqSIRo3VctygTQdUhe4e9NvoZDTqtOvjdu2NDYPTKawBe0KHWNFTsp8eUS+5rwcb
+IWWnfjcq9Z6HHobY5wf274izlloG1wNtxgqX4PTVRKlK6gAnZVaFFaRBLypBj4IC
+XmqmWrxtitGnIXTaSZjlkRo6SkFGiz+ovnjs0qbfBKu+0C83qZVS93aK9lVLvoum
+JKsLUe0CgYEA5T7s16uow0AG6UBmvjjlEtb6F0mXCqaGij9cO1ClZ4tBBzVxohRW
+ZCo4mGOSBToUnPTby3B/ZiN0+Pwz7nmOploIv9X65V6798MA6v5juWwThI7lQmu+
+S7rxpxkolDqTdyochqseqcIHv8ZuxRI0JtapjXNDQ1H+rd7iozm7btcCgYEA0FxB
+gxaIilQkQdw4byDv41tlGbbgeVCOKp86VxxkpDTz6MMs0yIRp+F9p58rostkPcIh
+ToWtoneeaT6P4WwuA2ETvI6g03H4nN1X1MTdx+M0FniYNMe20Ye0N1GhCILLXsTb
+XKNB0/u7nBIbjNkZ/0mCFGjGd71JjVQ5KaSpgusCgYEAiveKO3Mj6rh1eBBCOC3l
+L3aCRHunxB0Okd+22X4Zxprz4JrVN5t8g1vU0wwJCIIc3MjSNJENqaz0y7qXAIlP
+oCgUBbaBUWoMKDVd6RYs/co2SrUU5R7LTL0WoGTv5Gtd2W79u+UfwWiNqgNwQqa2
+VpTqU4T70WNzL5Ndb/UfWiECgYEAguNBYCi6kzLyJ9FAPkcRiuAx7WpdLrg05n9p
+9ajna+O7yN86fFMthil3duHdVoGwMb+OjrYY8jN0dqaPWctMSGEmNc/fJZS12UyO
+TSFyNIv8f5U4AAfpR0yZIBsOLruDJ8BAELyZsKG1JACX/+2tkBnMNifvbO6ikr5y
+vj8rIQsCgYEAhO/0Ky4A3jOvMK4f1NAVWBcuOt3UzmF06cRU6rCF6Roi1WNoDHsd
+XR2qZfVgozhqj0YzXQ4J83HuyeCLWynKLptJkgqEdZDoBJ6vGVg9GZmyYoQD0wRH
+l8q/xQvrdMhlJvZX7zKDv2h7QS/i2DODFAeYtnYN/aBzGfPSgpV1N+o=
+-----END RSA PRIVATE KEY-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/ca.p12 b/src/lynq/lib/liblynq-protcl/http/cert/ca.p12
new file mode 100644
index 0000000..85eafa4
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/ca.p12
Binary files differ
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.crt b/src/lynq/lib/liblynq-protcl/http/cert/client.crt
new file mode 100644
index 0000000..7eb321f
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.crt
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:16:35 2020 GMT
+ Not After : Sep 28 10:16:35 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guog, CN=guog
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:99:5f:72:71:bc:e4:08:76:43:77:32:9d:17:61:
+ 74:f7:44:49:33:ef:3c:7f:89:0e:97:0e:ce:d9:39:
+ 32:ca:10:34:af:6c:8c:39:19:58:38:16:9f:11:1e:
+ 55:9f:95:89:ac:fb:e2:cb:5f:ee:1a:bd:3d:25:79:
+ cd:18:20:36:83:ef:df:93:2e:7a:9e:1f:2f:98:05:
+ b0:65:c9:4f:93:c2:00:0b:70:84:2b:fb:44:01:d1:
+ 36:22:a6:5a:43:f7:c6:54:f4:81:cc:a6:26:47:e4:
+ 92:f5:e6:97:41:34:3e:c5:37:89:13:64:c6:cc:93:
+ 6c:a2:b0:0e:64:e0:3b:7d:a2:2e:b1:e4:42:79:cf:
+ a7:06:5e:89:53:4b:56:46:f5:07:54:99:5e:0f:80:
+ 1b:28:2f:19:63:c2:cd:e9:97:8f:09:cd:38:f4:05:
+ d4:83:00:4a:3b:14:00:51:d9:fe:b9:d4:82:52:c3:
+ a3:2f:2a:2d:f4:98:b1:44:0f:8c:ca:ee:0c:94:7e:
+ af:8b:b8:ab:8c:21:9d:16:1e:72:ee:9b:3d:04:70:
+ 1c:c6:46:06:d3:df:12:59:97:b6:af:3c:97:8d:b9:
+ 2e:88:d0:c9:c5:42:14:bb:c2:dd:ac:a3:3a:80:8a:
+ af:34:d2:e4:85:26:92:da:0e:99:20:3b:e8:78:11:
+ ba:e3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 27:96:0E:38:74:AA:00:98:D8:8C:54:5F:09:98:D9:03:C8:3D:D7:9C
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ a8:89:a9:9c:48:86:04:10:bf:5a:83:60:78:44:eb:42:59:af:
+ 9b:58:33:2c:68:33:f5:e1:c0:a9:d2:07:87:55:07:dc:95:68:
+ 18:20:9d:d2:3a:ad:3c:fc:d7:03:ec:f1:d4:91:26:09:d5:dd:
+ cd:90:74:0a:2a:c6:5a:98:6a:f7:e8:4f:04:e7:35:23:70:5e:
+ ea:20:83:b6:b7:6f:8b:2c:80:3e:0e:c5:f0:a1:30:4a:5e:df:
+ 6a:bc:60:43:2f:91:c8:e2:14:ca:47:af:9c:6b:ad:8d:c5:a6:
+ cd:1f:f8:1a:82:d8:02:b0:e7:d4:06:a2:47:bc:f7:b7:0e:dc:
+ 89:8d:3e:c9:50:55:8a:a1:04:5e:e6:a6:23:d8:54:37:57:c5:
+ 1e:57:0d:ed:1b:45:2a:1a:e3:10:ba:17:95:cf:c3:7d:a3:ec:
+ 08:d2:57:db:24:32:a0:9f:8e:30:95:81:20:00:fb:97:eb:c9:
+ 0c:e9:82:0f:62:a5:16:fa:ed:ae:7c:59:2c:f1:f2:b5:fd:8d:
+ c0:fe:20:ba:d2:f8:40:ef:2f:2e:ec:98:c3:55:b1:dd:83:4d:
+ 2a:9a:a3:f2:fc:4a:29:71:70:5f:3f:44:47:07:af:8f:ad:57:
+ 2c:1a:d9:68:19:c4:e8:c0:6b:2e:50:f9:d6:5c:97:ec:5a:8a:
+ cd:ac:8c:0f
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE2MzVaFw0yMTA5Mjgx
+MDE2MzVaME8xCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ0wCwYDVQQLDARndW9nMQ0wCwYDVQQDDARndW9nMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV9ycbzkCHZDdzKdF2F090RJM+88f4kO
+lw7O2TkyyhA0r2yMORlYOBafER5Vn5WJrPviy1/uGr09JXnNGCA2g+/fky56nh8v
+mAWwZclPk8IAC3CEK/tEAdE2IqZaQ/fGVPSBzKYmR+SS9eaXQTQ+xTeJE2TGzJNs
+orAOZOA7faIuseRCec+nBl6JU0tWRvUHVJleD4AbKC8ZY8LN6ZePCc049AXUgwBK
+OxQAUdn+udSCUsOjLyot9JixRA+Myu4MlH6vi7irjCGdFh5y7ps9BHAcxkYG098S
+WZe2rzyXjbkuiNDJxUIUu8LdrKM6gIqvNNLkhSaS2g6ZIDvoeBG64wIDAQABo3sw
+eTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
+ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUJ5YOOHSqAJjYjFRfCZjZA8g915wwHwYDVR0j
+BBgwFoAU4daM4go47s4ofX/7Q+Myzx5gra0wDQYJKoZIhvcNAQELBQADggEBAKiJ
+qZxIhgQQv1qDYHhE60JZr5tYMyxoM/XhwKnSB4dVB9yVaBggndI6rTz81wPs8dSR
+JgnV3c2QdAoqxlqYavfoTwTnNSNwXuogg7a3b4ssgD4OxfChMEpe32q8YEMvkcji
+FMpHr5xrrY3Fps0f+BqC2AKw59QGoke897cO3ImNPslQVYqhBF7mpiPYVDdXxR5X
+De0bRSoa4xC6F5XPw32j7AjSV9skMqCfjjCVgSAA+5fryQzpgg9ipRb67a58WSzx
+8rX9jcD+ILrS+EDvLy7smMNVsd2DTSqao/L8SilxcF8/REcHr4+tVywa2WgZxOjA
+ay5Q+dZcl+xais2sjA8=
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.csr b/src/lynq/lib/liblynq-protcl/http/cert/client.csr
new file mode 100644
index 0000000..f6b6207
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.csr
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAO
+BgNVBAcMB0JlaWppbmcxEDAOBgNVBAoMB1RlYW1zdW4xDTALBgNVBAsMBGd1b2cx
+DTALBgNVBAMMBGd1b2cwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ
+X3JxvOQIdkN3Mp0XYXT3REkz7zx/iQ6XDs7ZOTLKEDSvbIw5GVg4Fp8RHlWflYms
+++LLX+4avT0lec0YIDaD79+TLnqeHy+YBbBlyU+TwgALcIQr+0QB0TYiplpD98ZU
+9IHMpiZH5JL15pdBND7FN4kTZMbMk2yisA5k4Dt9oi6x5EJ5z6cGXolTS1ZG9QdU
+mV4PgBsoLxljws3pl48JzTj0BdSDAEo7FABR2f651IJSw6MvKi30mLFED4zK7gyU
+fq+LuKuMIZ0WHnLumz0EcBzGRgbT3xJZl7avPJeNuS6I0MnFQhS7wt2sozqAiq80
+0uSFJpLaDpkgO+h4EbrjAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAdntI2cu7
+H+N3BURFIfq+Zjzd2djO6SthHJ3h5KaUkxvGfuL3gVau+7w/RO6hgkPeQ0/E7dSy
+ZHxURkLNlbVgZz/zVH/rxPPlkwDP+HqOLMRrSkckvNjuuinxWizM1wKASOS4Yefp
+CS/1AtAKBePdmxqTmgFO3yciIs0I/IEf6Gw1XuW8iVfCcR2aTRLI/SQfPgXOp/FK
+YSpIs0WbVDp8SZd8994rVOyujqbfjcjc+zHEqyb24pUoEMstXK51QWZOjixoLHH3
+CdmxKwNk6GlAEXELhC1FjvwZLJR5emEoqsu4NdEPopfsZ0kLRDbJo0KdeErbh1e9
+6ixDUYO5TkWU5w==
+-----END CERTIFICATE REQUEST-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.key b/src/lynq/lib/liblynq-protcl/http/cert/client.key
new file mode 100644
index 0000000..3d63cca
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAmV9ycbzkCHZDdzKdF2F090RJM+88f4kOlw7O2TkyyhA0r2yM
+ORlYOBafER5Vn5WJrPviy1/uGr09JXnNGCA2g+/fky56nh8vmAWwZclPk8IAC3CE
+K/tEAdE2IqZaQ/fGVPSBzKYmR+SS9eaXQTQ+xTeJE2TGzJNsorAOZOA7faIuseRC
+ec+nBl6JU0tWRvUHVJleD4AbKC8ZY8LN6ZePCc049AXUgwBKOxQAUdn+udSCUsOj
+Lyot9JixRA+Myu4MlH6vi7irjCGdFh5y7ps9BHAcxkYG098SWZe2rzyXjbkuiNDJ
+xUIUu8LdrKM6gIqvNNLkhSaS2g6ZIDvoeBG64wIDAQABAoIBAGQ7moF2Xtig4Wpu
+63cyO8y1FdoZCUKYAa77AHe6B9VCTgwvNlzCkYLmVcJMPszyX21rmEYtRWC4N9Pc
+DAsuUjJbe5Omln/sBaCmZye+LoF0Ea9oMxjDNyiw3145tVgh/73ZpVJnazEk0l5d
++o+kYzlkF/NSsxFTb3XK9T07xeVOK3dpher/YKJIFTicGIp+PUenIuVBMVWjiUM3
+ku/xHedoCCjURMMaoBXolA7L5YNw6dapV4BYBTFZ5H/eTdtEmIRpBypStHSuxrKC
+qsEPLPD0/vFgRoD6fzGoYsa/is4kX56vB/LISslaazY1D57c6hC1o/OwBt7/MzAk
+0rMeoiECgYEAy/lr72yHpeG2+6LXxSRixKd20x1Z4mZbtAKy+9XHyjof8I45QqDp
+sIAdj1VbVacGibb71BjYxrkSDQXpK94padlfpGcyxnRtg+wZaIne5HVJShqUjcRH
+G/aKXxjnGkyRmP7eJgvEkKrgLXoC8n/86PFPehP6QgjAgNh+XYq/qBkCgYEAwH37
+5ZJlWrTUjVzDjszqIB4ELPu2UId1wMnoTIocQ89XsWwk7RLmrknV8y8DfnwF8fbp
+nVLVTBB11bX5cbwu8iw8J5XvBAu3zs0UTHE6c4DUsqq92KO2a7qSVJeHB8IZErei
+DWCSv8qcfVc3ZVOMg4N1VGoYqNq8jQd8fqBgClsCgYEAsF4jeOtTwxgPGzfr7/eN
+O1M9yD+Zx8wPwO+QiXaJARAPK/YeBsGSLt4oMRZyGfaJDazdxMATOIkv1Xjl69t1
+3aNqMoJVAgoL48TTF3QW+V18mImxJ3+uqLwdWyryMOhCAJNnzGfid+B4ZHoacEpA
+ib6VpQ3/FvfwU7heU020eIkCgYBKBCeH7vLqHf5dHP5VOpYMI36XjXJdJLkymHCq
+fbDAokml/19ziYEKI3oROFKvoCDpGXha9i7uQKYOtxpjkWi71iaLUivF8nuLGXBk
+tGU1ZKRkzyKQ2uKaKfN6c4mIgioB+HpnimrjNJVX3OGAJNAzAalr/B/fTbySvf4w
+8pn7YQKBgE4c1e2Xr67DqvGbpJx42fKlYYT0eW5ZxbzHkGj0Q5CZet61/S3lF9g8
+Bjm9TVhDBR2UJJbaaMuWed4Xp1UXZ9qWTeHtn3bX2BHr5HDY4ba+0sebVkdOmvre
+/p+sfKCBGkkIBgGjNld/UFErkbat/FfG0AWJZtX+5ulSEo7CodD4
+-----END RSA PRIVATE KEY-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/client.p12 b/src/lynq/lib/liblynq-protcl/http/cert/client.p12
new file mode 100644
index 0000000..4de6ab8
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/client.p12
Binary files differ
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt b/src/lynq/lib/liblynq-protcl/http/cert/index.txt
new file mode 100644
index 0000000..4c34e96
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt
@@ -0,0 +1,2 @@
+V 210928101551Z 01 unknown /C=CN/ST=Beijing/O=Teamsun/OU=guoxu/CN=guoxu
+V 210928101635Z 02 unknown /C=CN/ST=Beijing/O=Teamsun/OU=guog/CN=guog
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr.old b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr.old
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.attr.old
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/index.txt.old b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.old
new file mode 100644
index 0000000..2037566
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/index.txt.old
@@ -0,0 +1 @@
+V 210928101551Z 01 unknown /C=CN/ST=Beijing/O=Teamsun/OU=guoxu/CN=guoxu
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/newcerts/01.pem b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/01.pem
new file mode 100644
index 0000000..e92b642
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/01.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:15:51 2020 GMT
+ Not After : Sep 28 10:15:51 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guoxu, CN=guoxu
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a5:10:f2:43:40:a8:83:25:07:17:61:3e:8e:90:
+ 88:d1:b2:3d:5a:51:55:5e:fb:5f:c8:ee:3b:57:8a:
+ 13:64:4e:af:d9:74:0a:e5:db:42:1f:a8:3c:04:4f:
+ 2b:ed:08:fd:47:98:1c:4f:10:d3:2b:48:7a:3e:6a:
+ ec:4d:bf:9d:6a:a6:5b:78:b6:22:28:12:1c:36:b6:
+ 84:de:b9:d4:60:dd:f3:b2:9d:c2:07:db:1c:f5:e8:
+ 02:6a:64:99:44:fe:4f:86:a4:d9:14:6a:cd:d2:9d:
+ 4f:e3:01:54:f8:06:d5:7a:0c:14:f0:61:93:a7:1f:
+ f0:8b:44:f2:16:37:81:9d:3a:9b:f2:75:d0:fb:68:
+ 36:5d:59:23:38:bd:75:4e:e8:4d:6a:56:6c:a3:95:
+ c4:71:1e:3b:2a:29:e4:d6:01:83:c9:a2:75:82:c6:
+ 42:d3:cd:3b:0f:2e:2f:09:57:9b:ed:b8:76:84:85:
+ 5d:49:95:d0:9e:de:cb:8a:2a:bc:d0:7d:29:b1:fe:
+ 92:02:65:a9:24:28:b8:24:8b:68:69:e0:2b:14:f3:
+ 62:e1:91:12:2d:89:5f:02:10:78:48:76:49:9e:82:
+ 8a:94:ff:f0:bb:6f:0d:82:10:e0:7f:78:58:f3:53:
+ 4a:dc:54:ee:f3:7d:fc:15:40:8d:48:c3:bc:a3:5d:
+ df:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 5C:7C:6F:02:4F:B5:EB:F7:74:88:2F:2A:05:4C:D9:6A:4C:17:A2:ED
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 61:1d:fb:07:16:a2:33:7b:bd:d0:fe:3f:f8:73:06:ea:26:1b:
+ 28:2e:de:f9:90:8d:ee:62:a4:97:f6:d4:04:05:a1:8e:11:93:
+ af:3b:3e:de:24:eb:68:ff:32:9a:d3:16:86:61:68:27:9e:2b:
+ d3:ff:50:e7:f7:f6:c4:81:e4:c3:87:41:f7:bb:3b:85:00:ee:
+ f7:5f:86:7c:b9:2a:d6:4f:1a:60:f6:55:77:cc:e7:84:2b:6c:
+ f4:d3:58:8f:ed:df:af:d3:f8:b6:f5:46:de:1b:19:91:a5:93:
+ 31:db:5b:14:07:0f:8e:d9:db:ab:00:ea:6c:58:2c:67:24:bf:
+ b2:f7:a5:5c:d2:e1:cd:8b:42:0c:a5:b1:a3:03:aa:79:bc:10:
+ 4f:79:4f:9b:7e:8b:28:09:3e:70:68:fa:a3:c5:ec:3b:33:80:
+ 91:5b:1d:65:86:a3:9f:f4:25:48:d4:cf:9f:31:ce:54:a9:ce:
+ 3e:7b:bb:00:21:27:b7:5c:44:bf:67:63:23:1b:c8:8d:b5:f4:
+ bd:5b:fa:ae:7d:fa:21:a0:0d:6e:8d:23:af:23:aa:e9:69:ef:
+ d7:64:37:5b:13:be:ea:c7:40:dd:8e:7d:e6:e2:1f:e2:7c:08:
+ 57:27:0f:16:05:a1:e3:d0:ea:99:6b:d8:41:60:80:58:29:72:
+ 80:d5:22:91
+-----BEGIN CERTIFICATE-----
+MIIDnDCCAoSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE1NTFaFw0yMTA5Mjgx
+MDE1NTFaMFExCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ4wDAYDVQQLDAVndW94dTEOMAwGA1UEAwwFZ3VveHUwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClEPJDQKiDJQcXYT6OkIjRsj1aUVVe
++1/I7jtXihNkTq/ZdArl20IfqDwETyvtCP1HmBxPENMrSHo+auxNv51qplt4tiIo
+Ehw2toTeudRg3fOyncIH2xz16AJqZJlE/k+GpNkUas3SnU/jAVT4BtV6DBTwYZOn
+H/CLRPIWN4GdOpvyddD7aDZdWSM4vXVO6E1qVmyjlcRxHjsqKeTWAYPJonWCxkLT
+zTsPLi8JV5vtuHaEhV1JldCe3suKKrzQfSmx/pICZakkKLgki2hp4CsU82LhkRIt
+iV8CEHhIdkmegoqU//C7bw2CEOB/eFjzU0rcVO7zffwVQI1Iw7yjXd9vAgMBAAGj
+ezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
+IENlcnRpZmljYXRlMB0GA1UdDgQWBBRcfG8CT7Xr93SILyoFTNlqTBei7TAfBgNV
+HSMEGDAWgBTh1oziCjjuzih9f/tD4zLPHmCtrTANBgkqhkiG9w0BAQsFAAOCAQEA
+YR37BxaiM3u90P4/+HMG6iYbKC7e+ZCN7mKkl/bUBAWhjhGTrzs+3iTraP8ymtMW
+hmFoJ54r0/9Q5/f2xIHkw4dB97s7hQDu91+GfLkq1k8aYPZVd8znhCts9NNYj+3f
+r9P4tvVG3hsZkaWTMdtbFAcPjtnbqwDqbFgsZyS/svelXNLhzYtCDKWxowOqebwQ
+T3lPm36LKAk+cGj6o8XsOzOAkVsdZYajn/QlSNTPnzHOVKnOPnu7ACEnt1xEv2dj
+IxvIjbX0vVv6rn36IaANbo0jryOq6Wnv12Q3WxO+6sdA3Y595uIf4nwIVycPFgWh
+49DqmWvYQWCAWClygNUikQ==
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/newcerts/02.pem b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/02.pem
new file mode 100644
index 0000000..7eb321f
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/newcerts/02.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:16:35 2020 GMT
+ Not After : Sep 28 10:16:35 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guog, CN=guog
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:99:5f:72:71:bc:e4:08:76:43:77:32:9d:17:61:
+ 74:f7:44:49:33:ef:3c:7f:89:0e:97:0e:ce:d9:39:
+ 32:ca:10:34:af:6c:8c:39:19:58:38:16:9f:11:1e:
+ 55:9f:95:89:ac:fb:e2:cb:5f:ee:1a:bd:3d:25:79:
+ cd:18:20:36:83:ef:df:93:2e:7a:9e:1f:2f:98:05:
+ b0:65:c9:4f:93:c2:00:0b:70:84:2b:fb:44:01:d1:
+ 36:22:a6:5a:43:f7:c6:54:f4:81:cc:a6:26:47:e4:
+ 92:f5:e6:97:41:34:3e:c5:37:89:13:64:c6:cc:93:
+ 6c:a2:b0:0e:64:e0:3b:7d:a2:2e:b1:e4:42:79:cf:
+ a7:06:5e:89:53:4b:56:46:f5:07:54:99:5e:0f:80:
+ 1b:28:2f:19:63:c2:cd:e9:97:8f:09:cd:38:f4:05:
+ d4:83:00:4a:3b:14:00:51:d9:fe:b9:d4:82:52:c3:
+ a3:2f:2a:2d:f4:98:b1:44:0f:8c:ca:ee:0c:94:7e:
+ af:8b:b8:ab:8c:21:9d:16:1e:72:ee:9b:3d:04:70:
+ 1c:c6:46:06:d3:df:12:59:97:b6:af:3c:97:8d:b9:
+ 2e:88:d0:c9:c5:42:14:bb:c2:dd:ac:a3:3a:80:8a:
+ af:34:d2:e4:85:26:92:da:0e:99:20:3b:e8:78:11:
+ ba:e3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 27:96:0E:38:74:AA:00:98:D8:8C:54:5F:09:98:D9:03:C8:3D:D7:9C
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ a8:89:a9:9c:48:86:04:10:bf:5a:83:60:78:44:eb:42:59:af:
+ 9b:58:33:2c:68:33:f5:e1:c0:a9:d2:07:87:55:07:dc:95:68:
+ 18:20:9d:d2:3a:ad:3c:fc:d7:03:ec:f1:d4:91:26:09:d5:dd:
+ cd:90:74:0a:2a:c6:5a:98:6a:f7:e8:4f:04:e7:35:23:70:5e:
+ ea:20:83:b6:b7:6f:8b:2c:80:3e:0e:c5:f0:a1:30:4a:5e:df:
+ 6a:bc:60:43:2f:91:c8:e2:14:ca:47:af:9c:6b:ad:8d:c5:a6:
+ cd:1f:f8:1a:82:d8:02:b0:e7:d4:06:a2:47:bc:f7:b7:0e:dc:
+ 89:8d:3e:c9:50:55:8a:a1:04:5e:e6:a6:23:d8:54:37:57:c5:
+ 1e:57:0d:ed:1b:45:2a:1a:e3:10:ba:17:95:cf:c3:7d:a3:ec:
+ 08:d2:57:db:24:32:a0:9f:8e:30:95:81:20:00:fb:97:eb:c9:
+ 0c:e9:82:0f:62:a5:16:fa:ed:ae:7c:59:2c:f1:f2:b5:fd:8d:
+ c0:fe:20:ba:d2:f8:40:ef:2f:2e:ec:98:c3:55:b1:dd:83:4d:
+ 2a:9a:a3:f2:fc:4a:29:71:70:5f:3f:44:47:07:af:8f:ad:57:
+ 2c:1a:d9:68:19:c4:e8:c0:6b:2e:50:f9:d6:5c:97:ec:5a:8a:
+ cd:ac:8c:0f
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE2MzVaFw0yMTA5Mjgx
+MDE2MzVaME8xCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ0wCwYDVQQLDARndW9nMQ0wCwYDVQQDDARndW9nMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV9ycbzkCHZDdzKdF2F090RJM+88f4kO
+lw7O2TkyyhA0r2yMORlYOBafER5Vn5WJrPviy1/uGr09JXnNGCA2g+/fky56nh8v
+mAWwZclPk8IAC3CEK/tEAdE2IqZaQ/fGVPSBzKYmR+SS9eaXQTQ+xTeJE2TGzJNs
+orAOZOA7faIuseRCec+nBl6JU0tWRvUHVJleD4AbKC8ZY8LN6ZePCc049AXUgwBK
+OxQAUdn+udSCUsOjLyot9JixRA+Myu4MlH6vi7irjCGdFh5y7ps9BHAcxkYG098S
+WZe2rzyXjbkuiNDJxUIUu8LdrKM6gIqvNNLkhSaS2g6ZIDvoeBG64wIDAQABo3sw
+eTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
+ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUJ5YOOHSqAJjYjFRfCZjZA8g915wwHwYDVR0j
+BBgwFoAU4daM4go47s4ofX/7Q+Myzx5gra0wDQYJKoZIhvcNAQELBQADggEBAKiJ
+qZxIhgQQv1qDYHhE60JZr5tYMyxoM/XhwKnSB4dVB9yVaBggndI6rTz81wPs8dSR
+JgnV3c2QdAoqxlqYavfoTwTnNSNwXuogg7a3b4ssgD4OxfChMEpe32q8YEMvkcji
+FMpHr5xrrY3Fps0f+BqC2AKw59QGoke897cO3ImNPslQVYqhBF7mpiPYVDdXxR5X
+De0bRSoa4xC6F5XPw32j7AjSV9skMqCfjjCVgSAA+5fryQzpgg9ipRb67a58WSzx
+8rX9jcD+ILrS+EDvLy7smMNVsd2DTSqao/L8SilxcF8/REcHr4+tVywa2WgZxOjA
+ay5Q+dZcl+xais2sjA8=
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/serial b/src/lynq/lib/liblynq-protcl/http/cert/serial
new file mode 100644
index 0000000..75016ea
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/serial
@@ -0,0 +1 @@
+03
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/serial.old b/src/lynq/lib/liblynq-protcl/http/cert/serial.old
new file mode 100644
index 0000000..9e22bcb
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/serial.old
@@ -0,0 +1 @@
+02
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.crt b/src/lynq/lib/liblynq-protcl/http/cert/server.crt
new file mode 100644
index 0000000..e92b642
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.crt
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CN, ST=Beijing, L=Beijing, O=Teamsun, OU=Teamsun
+ Validity
+ Not Before: Sep 28 10:15:51 2020 GMT
+ Not After : Sep 28 10:15:51 2021 GMT
+ Subject: C=CN, ST=Beijing, O=Teamsun, OU=guoxu, CN=guoxu
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a5:10:f2:43:40:a8:83:25:07:17:61:3e:8e:90:
+ 88:d1:b2:3d:5a:51:55:5e:fb:5f:c8:ee:3b:57:8a:
+ 13:64:4e:af:d9:74:0a:e5:db:42:1f:a8:3c:04:4f:
+ 2b:ed:08:fd:47:98:1c:4f:10:d3:2b:48:7a:3e:6a:
+ ec:4d:bf:9d:6a:a6:5b:78:b6:22:28:12:1c:36:b6:
+ 84:de:b9:d4:60:dd:f3:b2:9d:c2:07:db:1c:f5:e8:
+ 02:6a:64:99:44:fe:4f:86:a4:d9:14:6a:cd:d2:9d:
+ 4f:e3:01:54:f8:06:d5:7a:0c:14:f0:61:93:a7:1f:
+ f0:8b:44:f2:16:37:81:9d:3a:9b:f2:75:d0:fb:68:
+ 36:5d:59:23:38:bd:75:4e:e8:4d:6a:56:6c:a3:95:
+ c4:71:1e:3b:2a:29:e4:d6:01:83:c9:a2:75:82:c6:
+ 42:d3:cd:3b:0f:2e:2f:09:57:9b:ed:b8:76:84:85:
+ 5d:49:95:d0:9e:de:cb:8a:2a:bc:d0:7d:29:b1:fe:
+ 92:02:65:a9:24:28:b8:24:8b:68:69:e0:2b:14:f3:
+ 62:e1:91:12:2d:89:5f:02:10:78:48:76:49:9e:82:
+ 8a:94:ff:f0:bb:6f:0d:82:10:e0:7f:78:58:f3:53:
+ 4a:dc:54:ee:f3:7d:fc:15:40:8d:48:c3:bc:a3:5d:
+ df:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 5C:7C:6F:02:4F:B5:EB:F7:74:88:2F:2A:05:4C:D9:6A:4C:17:A2:ED
+ X509v3 Authority Key Identifier:
+ keyid:E1:D6:8C:E2:0A:38:EE:CE:28:7D:7F:FB:43:E3:32:CF:1E:60:AD:AD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 61:1d:fb:07:16:a2:33:7b:bd:d0:fe:3f:f8:73:06:ea:26:1b:
+ 28:2e:de:f9:90:8d:ee:62:a4:97:f6:d4:04:05:a1:8e:11:93:
+ af:3b:3e:de:24:eb:68:ff:32:9a:d3:16:86:61:68:27:9e:2b:
+ d3:ff:50:e7:f7:f6:c4:81:e4:c3:87:41:f7:bb:3b:85:00:ee:
+ f7:5f:86:7c:b9:2a:d6:4f:1a:60:f6:55:77:cc:e7:84:2b:6c:
+ f4:d3:58:8f:ed:df:af:d3:f8:b6:f5:46:de:1b:19:91:a5:93:
+ 31:db:5b:14:07:0f:8e:d9:db:ab:00:ea:6c:58:2c:67:24:bf:
+ b2:f7:a5:5c:d2:e1:cd:8b:42:0c:a5:b1:a3:03:aa:79:bc:10:
+ 4f:79:4f:9b:7e:8b:28:09:3e:70:68:fa:a3:c5:ec:3b:33:80:
+ 91:5b:1d:65:86:a3:9f:f4:25:48:d4:cf:9f:31:ce:54:a9:ce:
+ 3e:7b:bb:00:21:27:b7:5c:44:bf:67:63:23:1b:c8:8d:b5:f4:
+ bd:5b:fa:ae:7d:fa:21:a0:0d:6e:8d:23:af:23:aa:e9:69:ef:
+ d7:64:37:5b:13:be:ea:c7:40:dd:8e:7d:e6:e2:1f:e2:7c:08:
+ 57:27:0f:16:05:a1:e3:d0:ea:99:6b:d8:41:60:80:58:29:72:
+ 80:d5:22:91
+-----BEGIN CERTIFICATE-----
+MIIDnDCCAoSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJDTjEQ
+MA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEQMA4GA1UECgwHVGVh
+bXN1bjEQMA4GA1UECwwHVGVhbXN1bjAeFw0yMDA5MjgxMDE1NTFaFw0yMTA5Mjgx
+MDE1NTFaMFExCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQK
+DAdUZWFtc3VuMQ4wDAYDVQQLDAVndW94dTEOMAwGA1UEAwwFZ3VveHUwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClEPJDQKiDJQcXYT6OkIjRsj1aUVVe
++1/I7jtXihNkTq/ZdArl20IfqDwETyvtCP1HmBxPENMrSHo+auxNv51qplt4tiIo
+Ehw2toTeudRg3fOyncIH2xz16AJqZJlE/k+GpNkUas3SnU/jAVT4BtV6DBTwYZOn
+H/CLRPIWN4GdOpvyddD7aDZdWSM4vXVO6E1qVmyjlcRxHjsqKeTWAYPJonWCxkLT
+zTsPLi8JV5vtuHaEhV1JldCe3suKKrzQfSmx/pICZakkKLgki2hp4CsU82LhkRIt
+iV8CEHhIdkmegoqU//C7bw2CEOB/eFjzU0rcVO7zffwVQI1Iw7yjXd9vAgMBAAGj
+ezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
+IENlcnRpZmljYXRlMB0GA1UdDgQWBBRcfG8CT7Xr93SILyoFTNlqTBei7TAfBgNV
+HSMEGDAWgBTh1oziCjjuzih9f/tD4zLPHmCtrTANBgkqhkiG9w0BAQsFAAOCAQEA
+YR37BxaiM3u90P4/+HMG6iYbKC7e+ZCN7mKkl/bUBAWhjhGTrzs+3iTraP8ymtMW
+hmFoJ54r0/9Q5/f2xIHkw4dB97s7hQDu91+GfLkq1k8aYPZVd8znhCts9NNYj+3f
+r9P4tvVG3hsZkaWTMdtbFAcPjtnbqwDqbFgsZyS/svelXNLhzYtCDKWxowOqebwQ
+T3lPm36LKAk+cGj6o8XsOzOAkVsdZYajn/QlSNTPnzHOVKnOPnu7ACEnt1xEv2dj
+IxvIjbX0vVv6rn36IaANbo0jryOq6Wnv12Q3WxO+6sdA3Y595uIf4nwIVycPFgWh
+49DqmWvYQWCAWClygNUikQ==
+-----END CERTIFICATE-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.csr b/src/lynq/lib/liblynq-protcl/http/cert/server.csr
new file mode 100644
index 0000000..853b893
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.csr
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICqDCCAZACAQAwYzELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAO
+BgNVBAcMB0JlaWppbmcxEDAOBgNVBAoMB1RlYW1zdW4xDjAMBgNVBAsMBWd1b3h1
+MQ4wDAYDVQQDDAVndW94dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKUQ8kNAqIMlBxdhPo6QiNGyPVpRVV77X8juO1eKE2ROr9l0CuXbQh+oPARPK+0I
+/UeYHE8Q0ytIej5q7E2/nWqmW3i2IigSHDa2hN651GDd87KdwgfbHPXoAmpkmUT+
+T4ak2RRqzdKdT+MBVPgG1XoMFPBhk6cf8ItE8hY3gZ06m/J10PtoNl1ZIzi9dU7o
+TWpWbKOVxHEeOyop5NYBg8midYLGQtPNOw8uLwlXm+24doSFXUmV0J7ey4oqvNB9
+KbH+kgJlqSQouCSLaGngKxTzYuGREi2JXwIQeEh2SZ6CipT/8LtvDYIQ4H94WPNT
+StxU7vN9/BVAjUjDvKNd328CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQApPn/s
+nVyEdO6QOK/c1ThZ8t8A+CVdllgsJrP2qZsnWnwKyAHcYSC2nuv4qvw20MNFdprd
+z/kIQz79o4lOCO9OHkpP5h6WaQ0z2u3kqCkIdkntkfkIKo1xq9MCO2ETKIkKEJcI
+HL9zLLiqL7tyHhv87celbqdiyvKfDKtH1/n7zT3nuU/PNzzUK6rLrlMASO5DQ5TI
+u/B+gfSem4aVyfgk4FqtpMnVhGlkdst+ajMJiFRNrB9nK8VhQZ7zdydt1TIT5E2H
+GSVFBi7TrC7lN1WHTPCRJXWlP4gaXO7imJ26IydSUaLi/X7DhDMXVAlOw38yvlUE
+MSJfg2BZDDSn7jVH
+-----END CERTIFICATE REQUEST-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.key b/src/lynq/lib/liblynq-protcl/http/cert/server.key
new file mode 100644
index 0000000..995401a
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEApRDyQ0CogyUHF2E+jpCI0bI9WlFVXvtfyO47V4oTZE6v2XQK
+5dtCH6g8BE8r7Qj9R5gcTxDTK0h6PmrsTb+daqZbeLYiKBIcNraE3rnUYN3zsp3C
+B9sc9egCamSZRP5PhqTZFGrN0p1P4wFU+AbVegwU8GGTpx/wi0TyFjeBnTqb8nXQ
++2g2XVkjOL11TuhNalZso5XEcR47Kink1gGDyaJ1gsZC0807Dy4vCVeb7bh2hIVd
+SZXQnt7Liiq80H0psf6SAmWpJCi4JItoaeArFPNi4ZESLYlfAhB4SHZJnoKKlP/w
+u28NghDgf3hY81NK3FTu8338FUCNSMO8o13fbwIDAQABAoIBAC5t39bu3vdUePQo
+lDIBkZp6Kiu3aO34gu6/o81xtxal02y06UPSMn05EvibVF2uA6AZtwy+TMeF8WyR
+IrqTxTF0bZI8mMrwnSL+n80ONCCzDZMWMLeI+FJq2hMXDM2NQs06nRzTFeXB/fB6
+NW42beGQeGtM5v1BTKW/1OBO6JRSrkODUwKluuTDZOwErfGZyuaJsZdghQ1Fh6jw
+WEpb9OzyqzRu5BQjk0xRyPSSDDNWi2jRCTYlk3hDCqeBvzqMHXMLh2biSIdUsEEG
+88STOFHGXR57Szpj+zl3P3AnH/c5ZLIHwq6b8gwC02TUb9cPK7setmXHrliWvVYT
+WXxsFuECgYEA1cPxmEqsZ9QW1j7rm1zMop+R0ft23zuKD93nskNreKinaPyOKyDG
+7+WQjCrdglIuuMnMmPJyhLx1taDMvOpzN1LbFWjxTwG1S6dp0tkTHAVaoKH58rxq
+XwDgWe3o9Txtt4dk9NuvJztxblT7qU7wIFXr3w5z13Y9GnqQvvfpTykCgYEAxa3X
+e6DAurK5A6+44eKrQXcvesjBJknYphVnQoFq+YjrYb/vCa/AgOFi5xQ1Co/q+F7r
+gtTAj/2KEbzdzxED+akIn0/pSsCxz8mbK85O8vBlaymrmMtRFVDIrDxMKxrgMT7Q
+4oKyB+JJy/6Muwlq/NTeMel0aFUP3WTI0GZpxNcCgYEArEajIVolAfSChx3kYaxz
+WyiAq5senR/tz4XGIfuF1JMPgGPx674ZteLsEJrHNC0pbFFuK2FRe7oqnzs9ZY8J
+Ve/XkrSlrUeyJYuBlKTPasjB1i1UNBU3IOOi67b6BRIzVjKu4UtfKJ4Wd5XT0ApH
+Kbg1ROnv4BhxfDKFDvLbO6kCgYBQyRW5+V0qL2X7ArI85iR00Z9+v1JoMl+uqCqV
+/EvahMElJooq3D+ArBt+Mjzm/x/YtvnqcsXrUoM9coD3YY3NVu4mJUNDAHLqZwra
+ISsUj3fzDomJHPYbDvOjp9S8/PPITFKTbzQQksLz8ihTO6sUfm372dtv0+ty4ABN
+Yr0w6wKBgGwfvkITtbYU0gFOC8G7XX8liT23HOegvTXraBm38IWXHMVqOwk0lCEQ
+crk54pXDzJd3yXqwFIq5g1w/enjeGq+ly6C/XWuSAepkQjecHxzkYTcrCdyWWifx
+zZD9xKOvXNqU26ZdoZQHNaAktCoXYEC3BA6jSJtfinLzzwS4olV1
+-----END RSA PRIVATE KEY-----
diff --git a/src/lynq/lib/liblynq-protcl/http/cert/server.p12 b/src/lynq/lib/liblynq-protcl/http/cert/server.p12
new file mode 100644
index 0000000..eb0ceea
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/cert/server.p12
Binary files differ
diff --git a/src/lynq/lib/liblynq-protcl/http/src/lynq_http.c b/src/lynq/lib/liblynq-protcl/http/src/lynq_http.c
new file mode 100644
index 0000000..94b8ef1
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/src/lynq_http.c
@@ -0,0 +1,1289 @@
+#include "http/lynq_http.h"
+
+
+
+#define _stricmp strcasecmp
+#define _strnicmp strncasecmp
+
+
+const int kSelectRead = 1 << 0;
+const int kSelectWrite = 1 << 1;
+const int kSelectError = 1 << 2;
+
+#define DEFAULT_USER_AGENT_STR "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0\r\n"
+#define CONNECT_KEEP_STR "Connection: keep-alive\r\n"
+#define CONNECT_CLOSE_STR "Connection: close\r\n"
+#define ACCEPT_STR "Accept: */*\r\n"
+#define CONTENT_LENGTH_STR "Content-Length"
+#define CONTENT_TYPE_STR "Content-Type:application/x-www-form-urlencoded\r\n"
+#define CONTENT_DISPOSITION_STR "Content-Disposition"
+#define CRLF "\r\n"
+
+#define CA_ROOT "cert/ca.crt"
+#define CA_CLICRT "cert/client.crt"
+#define CA_CLIKEY "cert/client.key"
+
+
+static char* _strdup(const char* src)
+{
+ char* dst = NULL;
+ int len = 0;
+ if(src == NULL)
+ {
+ return NULL;
+ }
+ len = strlen(src);
+ dst = (char*)malloc(len + 1);
+ if(dst == NULL)
+ {
+ return NULL;
+ }
+ strcpy(dst, src);
+ return dst;
+}
+
+static void http_ssl_free(lynq_http_client_t* http)
+{
+ if(http->ssl != NULL)
+ {
+ SSL_shutdown(http->ssl);
+ SSL_free(http->ssl);
+ http->ssl = NULL;
+ }
+ if(http->ctx != NULL)
+ {
+ SSL_CTX_free(http->ctx);
+ http->ctx = NULL;
+ }
+}
+
+int lynq_http_init()
+{
+ OpenSSL_add_all_algorithms();
+ ERR_load_BIO_strings();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+
+ if(SSL_library_init() < 0)
+ {
+ LYVERBLOG("+[http][init]: error num = %d\n", ERR_SSL_CREATE_SSL);
+ return ERR_SSL_CREATE_SSL;
+ }
+ return 0;
+}
+
+lynq_http_client_t* lynq_http_new()
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)calloc(1, sizeof(lynq_http_client_t));
+
+ return http;
+}
+
+void lynq_http_destroy(lynq_http_client_t* http)
+{
+ if(http == NULL) return;
+
+ free_member(http->body);
+ free_member(http->header_field);
+ free_member(http->header_value);
+ free_member(http->redirect_url);
+ free_member(http->filename);
+ close_socket(http->fd);
+ close_file(http->pf);
+
+ http_ssl_free(http);
+
+ free(http);
+}
+
+int lynq_http_get_error_code(lynq_http_client_t* http)
+{
+ if(http == NULL)
+ {
+ return -1;
+ }
+ return http->error_code;
+}
+
+static int socket_noblocking(socket_t fd, int noblocking)
+{
+
+ int flags;
+ if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
+ {
+ return -1;
+ }
+ if(noblocking)
+ {
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ }
+ else
+ {
+ return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ return 0;
+}
+
+static int last_error()
+{
+ return errno;
+}
+
+static int socket_select(lynq_http_client_t* http, int mode, int timeout)
+{
+ fd_set rfd, wfd, efd;
+ int r = 0;
+ int error = 0;
+ int remaind = timeout;
+ socklen_t len = sizeof(error);
+
+ struct timeval tv, start, elapsed;
+
+ gettimeofday(&start, 0);
+
+ while(remaind > 0)
+ {
+ if(mode & kSelectRead) { FD_ZERO(&rfd); FD_SET(http->fd, &rfd); }
+ if(mode & kSelectWrite){ FD_ZERO(&wfd); FD_SET(http->fd, &wfd); }
+ if(mode & kSelectError){ FD_ZERO(&efd); FD_SET(http->fd, &efd); }
+
+ tv.tv_sec = remaind / 1000;
+ tv.tv_usec = remaind % 1000 * 1000;
+
+ r = select(http->fd+1,
+ (mode & kSelectRead) ? &rfd : NULL,
+ (mode & kSelectWrite) ? &wfd : NULL,
+ (mode & kSelectError) ? &efd : NULL,
+ &tv);
+
+ if( r == 0)
+ {
+ return -1;
+ }
+
+ if( r > 0)
+ {
+ if(getsockopt(http->fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) == 0 && error == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ if( r < 0 )
+ {
+ if(last_error() == HTTP_EINTR)
+ {
+ gettimeofday(&elapsed, 0);
+ remaind = timeout - ((int)(elapsed.tv_sec - start.tv_sec) * 1000 + (int)(elapsed.tv_usec - start.tv_usec) / 1000);
+
+ continue;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ };
+
+ return -1;
+}
+
+static int _field_value_malloc(char** str, unsigned short* cur_size, unsigned short* size, const char* at, size_t length)
+{
+ if(*str == NULL)
+ {
+#define DEFAULT_HEADER_SIZE 128
+ *size = length > DEFAULT_HEADER_SIZE ? length: DEFAULT_HEADER_SIZE;
+ *str = (char*)calloc(1, *size + 1);
+ if(*str == NULL)
+ {
+ return -1;
+ }
+ *cur_size = 0;
+ }
+ else if(*cur_size + length > *size)
+ {
+ *size = *cur_size + length;
+ *str = (char*)realloc(*str, *size + 1);
+ if(*str == NULL)
+ {
+ return -1;
+ }
+ }
+ memcpy(*str + *cur_size, at, length);
+ *cur_size += length;
+ (*str)[*cur_size] = '\0';
+ return 0;
+}
+
+static int parser_field_value(lynq_http_client_t* http)
+{
+ if(http->cur_value_size > 0 &&
+ http->cur_field_size > 0 &&
+ http->header_field && http->header_value)
+ {
+ if(_stricmp(http->header_field, "Location") == 0)
+ {
+ free_member(http->redirect_url);
+ http->redirect_url = _strdup(http->header_value);
+
+ http->redirect = 1;
+ return -1;
+ }
+ else if(_stricmp(http->header_field, CONTENT_LENGTH_STR) == 0)
+ {
+ http->content_length = atol(http->header_value);
+ }
+ else
+ {
+ /* extract other header field value */
+ }
+ http->cur_field_size = 0;
+ http->cur_value_size = 0;
+ }
+
+ return 0;
+}
+
+static int on_header_field_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->parser_statue == PARSERD_VALUE)
+ {
+ if( parser_field_value(http) != 0)
+ {
+ return -1;
+ }
+ }
+ http->parser_statue = PARSERD_FIELD;
+ return _field_value_malloc(&http->header_field, &http->cur_field_size, &http->field_size, at, length);
+}
+
+static int on_header_value_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->parser_statue == PARSERD_FIELD || http->parser_statue == PARSERD_VALUE)
+ {
+ http->parser_statue = PARSERD_VALUE;
+ return _field_value_malloc(&http->header_value, &http->cur_value_size, &http->value_size, at, length);
+ }
+ return 0;
+}
+
+static int on_status_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+ http->status_code = parser->status_code;
+ return 0;
+}
+
+static int on_headers_complete_cb(http_parser* parser)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+ if(parser_field_value(http) != 0)
+ {
+ return -1;
+ }
+ free_member(http->header_field);
+ free_member(http->header_value);
+ http->parser_statue = PARSERD_BODY;
+ http->cur_field_size = http->cur_value_size = 0;
+ return 0;
+}
+
+static int on_download_file_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->status_code >= 200 && http->status_code <= 299)
+ {
+ if(http->pf == NULL)
+ {
+ if(http->filename != NULL)
+ {
+ http->pf = fopen(http->filename, "wb");
+ }
+ }
+
+ if(http->pf == NULL)
+ {
+ return -1;
+ }
+ if( http->recv_cb && (http->recv_cb)(http, at, length, http->content_length, http->user) != 0)
+ {
+ return -1;
+ }
+
+ fwrite(at, 1, length, http->pf);
+ }
+
+ return 0;
+}
+
+static int on_body_cb(http_parser* parser, const char *at, size_t length)
+{
+ lynq_http_client_t* http = (lynq_http_client_t*)parser->data;
+
+ if(http->body == NULL)
+ {
+
+ if(http->content_length > 0)
+ {
+ http->body = (char*)calloc(1, http->content_length + 1);
+ }
+ else
+ {
+ http->body = (char*)calloc(1, length + 1);
+ }
+ }
+ else
+ {
+ if(http->content_length <= 0)
+ {
+ http->body = (char*)realloc(http->body, http->body_len + length + 1);
+ }
+ }
+ if(http->body == NULL)
+ {
+ return -1;
+ }
+ memcpy(http->body + http->body_len, at, length);
+ http->body_len += length;
+
+ return 0;
+}
+
+static int on_message_complete_cb(http_parser* parser)
+{
+ return 0;
+}
+
+static int http_check_error(lynq_http_client_t* http, int mode, int ret)
+{
+ int error_code;
+ if(http->proto_type == PROTO_HTTPS)
+ {
+ int error = SSL_get_error(http->ssl, ret);
+ if(SSL_ERROR_ZERO_RETURN == error)
+ {
+ return -1;
+ }
+ else if(error == SSL_ERROR_WANT_WRITE ||
+ error == SSL_ERROR_WANT_READ)
+ {
+ return 0;
+ }
+ else if(SSL_ERROR_SYSCALL == error)
+ {
+ goto check_select;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+check_select:
+ error_code = last_error();
+ if(error_code == HTTP_EINTR)
+ {
+ return 0;
+ }
+ else if(error_code == HTTP_EINPROGRESS || error_code == HTTP_EWOULDBLOCK)
+ {
+ if(socket_select(http, mode, http->timeout) == 0)
+ {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int http_read_write(lynq_http_client_t* http, const char* data, int len, int read)
+{
+ int n = 0, r = 0;
+
+ do
+ {
+ if(http->exit == 1)
+ {
+ return -1;
+ }
+
+ if(http->proto_type == PROTO_HTTPS)
+ {
+
+ r = read ? SSL_read(http->ssl, (char*)data + n, len - n) : SSL_write(http->ssl, data + n, len - n);
+ }
+ else
+ {
+ r = read ? recv(http->fd, (char*)data + n, len - n, 0) : send(http->fd, data + n, len - n, 0);
+ }
+
+ if(r > 0)
+ {
+ n += r;
+ }
+ else if(r == 0)
+ {
+ return n;
+ }
+ else
+ {
+ if(http_check_error(http, read ? kSelectRead : kSelectWrite, r) == 0)
+ {
+ continue;
+ }
+ return -1;
+ }
+
+ http->data = data;
+ LYDBGLOG("[%s-%d] +http%s, session = %d, data = %s \n", __FUNCTION__, __LINE__, http->action, http->session, data);
+ LYVERBLOG("+[http][%s][session%d]: data = %s\n", http->action, http->session, data);
+ LYVERBLOG("+[http][%s][session%d]: ok!!\n", http->action, http->session);
+ }while(n < len);
+ http->data = NULL;
+
+ return n;
+}
+
+#define HTTP_KEY "self.key"
+#define HTTP_CERTIFICATE "self.crt"
+
+static int sslSetCertFile(SSL_CTX *sslctx, char *certFile)
+{
+ if (sslctx == NULL)
+ {
+ return -1;
+ }
+
+ if (SSL_CTX_use_certificate_file(sslctx, certFile, SSL_FILETYPE_PEM) <= 0) {
+ if (SSL_CTX_use_certificate_file(sslctx, certFile, SSL_FILETYPE_ASN1) <= 0) {
+ return -1;
+ }
+ }
+
+ if(!SSL_CTX_check_private_key(sslctx)){
+ return -1;
+ }
+ return 0;
+}
+
+
+static int sslSetKeyFile(SSL_CTX *sslctx, char *keyFile)
+{
+ if (sslctx == NULL)
+ {
+ return -1;
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
+ if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_ASN1) <= 0) {
+ return -1;
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+#define VERIFY_DEPTH 10
+static int verify_X509Certificate(int ok, X509_STORE_CTX *xContext)
+{
+ X509 *cert;
+ char subject[260], issuer[260], peer[260];
+ int error, depth;
+ subject[0] = issuer[0] = '\0';
+ cert = X509_STORE_CTX_get_current_cert(xContext);
+ error = X509_STORE_CTX_get_error(xContext);
+ depth = X509_STORE_CTX_get_error_depth(xContext);
+ ok = 1;
+
+ if (X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject) - 1) < 0) {
+ ok = 0;
+ }
+
+ if (X509_NAME_oneline(X509_get_issuer_name(cert), issuer, sizeof(issuer) - 1) < 0) {
+ ok = 0;
+ }
+
+ if (ok && VERIFY_DEPTH < depth) {
+ if (error == 0) {
+ error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+ }
+ switch (error) {
+ case X509_V_OK:
+ break ;
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_OUT_OF_MEM:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_REVOKED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_CA:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_PURPOSE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_UNTRUSTED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CERT_REJECTED:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_AKID_SKID_MISMATCH:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_EXTENSION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_INVALID_POLICY_EXTENSION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_NO_EXPLICIT_POLICY:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_DIFFERENT_CRL_SCOPE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_PERMITTED_VIOLATION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_EXCLUDED_VIOLATION:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_SUBTREE_MINMAX:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
+ ok = 0;
+ break;
+
+ case X509_V_ERR_APPLICATION_VERIFICATION:
+ ok = 0;
+ break;
+
+ default:
+ ok = 0;
+ break;
+ }
+
+ return ok;
+}
+
+void https_certificate_validation(SSL * ssl)
+{
+ X509 *cert;
+ char *line;
+
+ cert = SSL_get_peer_certificate(ssl);
+ if(SSL_get_verify_result(ssl) == X509_V_OK){
+ LYDBGLOG("Certificate verification passed\n");
+ }
+ if (cert != NULL) {
+ line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ free(line);
+ line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ free(line);
+ X509_free(cert);
+ } else
+ LYDBGLOG("[%s %d] No certificate information\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_NOCERT);
+}
+
+static int http_ssl_connect(lynq_http_client_t* http)
+{
+ int ssl_ret = 0;
+ int remaind = http->timeout;
+ struct timeval start, elapsed;
+
+ http->ctx = SSL_CTX_new(SSLv23_client_method());
+ if(http->ctx == NULL)
+ {
+ return -1;
+ }
+ SSL_CTX_set_verify(http->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_X509Certificate);
+ SSL_CTX_set_verify_depth(http->ctx, VERIFY_DEPTH);
+
+ if (SSL_CTX_load_verify_locations(http->ctx, CA_ROOT, NULL) <= 0){
+ LYVERBLOG("+[http][%s][session%d]: error num = %d\n", http->action, http->session, ERR_SSL_CREATE_CTX);
+ return ERR_SSL_CREATE_CTX;
+ }
+
+ sslSetCertFile(http->ctx, CA_CLICRT);
+
+ sslSetKeyFile(http->ctx, CA_CLIKEY);
+
+ http->ssl = SSL_new(http->ctx);
+ if(http->ssl == NULL)
+ {
+ return -1;
+ }
+ if(SSL_set_fd(http->ssl, http->fd) == 0)
+ {
+ return -1;
+ }
+
+ gettimeofday(&start, 0);
+
+ do
+ {
+ ssl_ret = SSL_connect(http->ssl);
+
+ if (ssl_ret == -1) {
+ ERR_print_errors_fp(stderr);
+ }
+
+ else {
+ LYDBGLOG("[%s %d] Connected with %s encryption\n", __FUNCTION__, __LINE__, SSL_get_cipher(http->ssl));
+ //Show certificate information
+ //https_certificate_validation(http->ssl);
+ }
+
+ gettimeofday(&elapsed, 0);
+ remaind = http->timeout - ((int)(elapsed.tv_sec - start.tv_sec) * 1000 + (int)(elapsed.tv_usec - start.tv_usec) / 1000);
+
+ if(ssl_ret > 0)
+ {
+ return 0;
+ }
+ else
+ {
+ if(remaind <= 0)
+ {
+ return -1;
+ }
+ else if(http_check_error(http, kSelectRead+kSelectWrite, ssl_ret) == 0)
+ {
+ continue;
+ }
+ return -1;
+ }
+ }while(1);
+
+ return -1;
+}
+
+static int http_connect_host(lynq_http_client_t* http, const char* url, struct http_parser_url* u)
+{
+ struct sockaddr_in sin;
+ char host[256] = {0};
+ int r;
+ unsigned short port = 80;
+
+ if(u->field_set & (1 << UF_SCHEMA))
+ {
+ if(_strnicmp("http://", url + u->field_data[UF_SCHEMA].off, 7) == 0)
+ {
+ port = 80; http->proto_type = PROTO_HTTP;
+ }
+
+ else if(_strnicmp("https://", url + u->field_data[UF_SCHEMA].off, 8) == 0)
+ {
+ port = 443; http->proto_type = PROTO_HTTPS;
+ }
+
+ else
+ {
+ return ERR_URL_INVALID_PROTO;
+ }
+ }
+
+ if(!(u->field_set & (1 << UF_HOST)))
+ {
+ return ERR_URL_INVALID_HOST;
+ }
+
+ if(u->field_set & (1 << UF_PORT))
+ {
+ port = (unsigned short)atoi(url + u->field_data[UF_PORT].off);
+ }
+
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ memcpy(host, url + u->field_data[UF_HOST].off, u->field_data[UF_HOST].len);
+ if(host[0] >= '0' && host[0] <= '9')
+ {
+ sin.sin_addr.s_addr = (unsigned long)inet_addr(host);
+ }
+ else
+ {
+ struct hostent* he = gethostbyname(host);
+ if(he == NULL || he->h_addrtype != AF_INET)
+ {
+ return ERR_URL_RESOLVED_HOST;
+ }
+ sin.sin_addr = *((struct in_addr *)he->h_addr_list[0]);
+ }
+
+ if(sin.sin_addr.s_addr == INADDR_NONE)
+ {
+ return ERR_URL_RESOLVED_HOST;
+ }
+
+ sin.sin_port = htons(port);
+ sin.sin_family = AF_INET;
+
+
+ http->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if(http->fd == HTTP_INVALID_SOCKET)
+ {
+ return ERR_SOCKET_CREATE;
+ }
+
+ {
+ struct linger linger;
+ linger.l_onoff = 1;
+ linger.l_linger = 0;
+
+ if(setsockopt(http->fd,SOL_SOCKET, SO_LINGER,(const char *) &linger,sizeof(linger)) != 0)
+ {
+ return ERR_SOCKET_SET_OPT;
+ }
+ if(socket_noblocking(http->fd, 1) != 0)
+ {
+ return ERR_SOCKET_NOBLOCKING;
+ }
+ }
+
+ do
+ {
+ r = connect(http->fd, (struct sockaddr*)&sin, sizeof(sin));
+ if(r < 0)
+ {
+ int error = last_error();
+ if(error == HTTP_EINTR)
+ {
+ continue;
+ }
+ else if( error == HTTP_EINPROGRESS || error == HTTP_EWOULDBLOCK || error == HTTP_EALREADY)
+ {
+ if(socket_select(http, kSelectWrite, http->timeout) == 0)
+ {
+ break;
+ }
+ else
+ {
+ return ERR_SOCKET_CONNECT_TIMEOUT;
+ }
+ }
+ return ERR_SOCKET_CONNECT;
+ }
+ }while(1);
+
+ if(http->proto_type == PROTO_HTTPS)
+ {
+ if(http_ssl_connect(http) != 0)
+ {
+ return ERR_SSL_CONNECT;
+ }
+ }
+
+ return ERR_OK;
+}
+
+void http_init(lynq_http_client_t* http)
+{
+
+ http->redirect = 0;
+ http->body_len = 0;
+ http->content_length = 0;
+ http->cur_field_size = 0;
+ http->cur_value_size = 0;
+ http->field_size = 0;
+ http->value_size = 0;
+ http->parser_statue = 0;
+ http->error_code = 0;
+ http->user_header = 0;
+ http->user_header_len = 0;
+
+ if(http->timeout == 0) http->timeout = 1500000;
+}
+
+int http_connect(lynq_http_client_t* http)
+{
+ int r = 0;
+ if( http_parser_parse_url(http->url, strlen(http->url), 0, &http->u) != 0 )
+ {
+ LYDBGLOG("[%s-%d] ==============\n", __FUNCTION__, __LINE__);
+ return (http->error_code = ERR_URL_INVALID);
+ }
+
+ r = http_connect_host(http, http->url, &http->u);
+ if(r != ERR_OK)
+ {
+ LYDBGLOG("[%s-%d] ==============\n", __FUNCTION__, __LINE__);
+ return (http->error_code = r);
+ }
+
+ return 0;
+}
+
+int CHECK(int ret, lynq_http_client_t* http)
+{
+ if(ret <= 0)
+ return (http->error_code = ERR_SOCKET_WRITE);
+
+ return 0;
+}
+
+void http_write_headers(lynq_http_client_t* http)
+{
+ char *url = NULL;
+ if(http->redirect == 1)
+ url = http->redirect_url;
+ else
+ url = http->url;
+
+ if(http->method == M_GET)
+ {
+ CHECK(http_read_write(http, "GET ", 4, 0), http);
+ }
+ else if(http->method == M_POST)
+ {
+ CHECK(http_read_write(http, "POST ", 5, 0), http);
+ }
+
+ if(http->u.field_set & (1 << UF_PATH))
+ {
+ CHECK(http_read_write(http, url + http->u.field_data[UF_PATH].off, http->u.field_data[UF_PATH].len, 0), http);
+ }
+ else
+ {
+ CHECK(http_read_write(http, "/", 1, 0), http);
+ }
+
+ if(http->u.field_set & (1 << UF_QUERY))
+ {
+ CHECK(http_read_write(http, "?", 1, 0), http);
+ CHECK(http_read_write(http, url + http->u.field_data[UF_QUERY].off, http->u.field_data[UF_QUERY].len, 0), http);
+ }
+
+ CHECK(http_read_write(http, " HTTP/1.1\r\nHost:", 16, 0), http);
+ CHECK(http_read_write(http, url + http->u.field_data[UF_HOST].off, http->u.field_data[UF_HOST].len, 0), http);
+
+ if(http->conn_method == M_KEEP) {
+ CHECK(http_read_write(http, CRLF CONNECT_KEEP_STR ACCEPT_STR DEFAULT_USER_AGENT_STR ,
+ 2 + strlen(CONNECT_KEEP_STR) + strlen(ACCEPT_STR) + strlen(DEFAULT_USER_AGENT_STR), 0), http);
+ }
+ else {
+ CHECK(http_read_write(http, CRLF CONNECT_CLOSE_STR ACCEPT_STR DEFAULT_USER_AGENT_STR ,
+ 2 + strlen(CONNECT_CLOSE_STR) + strlen(ACCEPT_STR) + strlen(DEFAULT_USER_AGENT_STR), 0), http);
+ }
+
+ if(http->user_header != NULL)
+ {
+ CHECK(http_read_write(http, http->user_header, http->user_header_len, 0), http);
+ }
+
+ if(http->post_data && http->post_data_len > 0)
+ {
+ char len_data[256] = {0};
+ int n = sprintf(len_data, "%s:%d\r\n", CONTENT_TYPE_STR CONTENT_LENGTH_STR, http->post_data_len);
+ CHECK(http_read_write(http, len_data, n, 0), http);
+ }
+
+ CHECK(http_read_write(http, CRLF, 2, 0), http);
+
+
+}
+
+void http_write_data(lynq_http_client_t* http)
+{
+ CHECK(http_read_write(http, http->post_data, http->post_data_len, 0), http);
+}
+
+int lynq_http_data_send(char *data)
+{
+ struct mymesg ckxmsg;
+ ckxmsg.mtype = 1;
+ strcpy(ckxmsg.mtext, data);
+ int id = lynq_msgq_init("/tmp", 0666);
+ lynq_msgq_send(id, &ckxmsg);
+}
+
+void *lynq_http_write_head_data(lynq_http_client_t* http)
+{
+
+ http_write_headers(http);
+
+ if(http->post_data && http->post_data_len > 0)
+ {
+ http_write_data(http);
+ }
+ http->post_data = "";
+}
+
+void *http_write_head_data_thread(void* arg)
+{
+ int id = 0;
+ int runing = 1 ;
+ struct mymesg ckxmsg;
+
+ lynq_http_client_t* http = (lynq_http_client_t*)arg;
+
+ id = lynq_msgq_init("/tmp", 0666);
+
+ while(runing)
+ {
+#if 1
+ if(!strcmp(http->post_data, "") && http->conn_method == M_KEEP)
+ {
+ if(msgrcv(id, (void *)&ckxmsg, 512, 1, 0) < 0)
+ {
+ LYDBGLOG("[%s-%d] receive msg error \n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_MSG);
+ return ERR_MSG;
+ }
+ LYDBGLOG("[%s-%d] mtext :%s\n", __FUNCTION__, __LINE__, ckxmsg.mtext);
+
+ if (!strcmp(ckxmsg.mtext,"close"))
+ return NULL;
+
+ http->post_data = ckxmsg.mtext;
+ }
+#endif
+ lynq_http_write_head_data(http);
+
+ }
+}
+
+
+void *http_read_data_thread(void* arg)
+{
+ int parsed = 0;
+ lynq_http_client_t* http = (lynq_http_client_t*)arg;
+ do
+ {
+ int nread = 0;
+
+ if(http->download == 0 && http->parser_statue == PARSERD_BODY && http->body && http->content_length > 0)
+ {
+ nread = http_read_write(http, http->body+http->body_len, http->content_length - http->body_len, 1);
+ if(nread > 0)
+ {
+ http->body_len += nread;
+ break;
+ }
+ }
+ else
+ {
+ char buf[RECV_BUF_SIZE + 1] = {0};
+
+ nread = http_read_write(http, buf, RECV_BUF_SIZE, 1);
+
+ if(nread > 0)
+ {
+ parsed = http_parser_execute(&http->parser, &http->parser_setting, buf, nread);
+
+ if(http->redirect)
+ {
+ break;
+ }
+
+ if(parsed != nread)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ if(nread == 0)
+ {
+ break;
+ }
+ else if(nread < 0)
+ {
+ return NULL;
+ }
+
+ } while (1);
+
+ return NULL;
+}
+
+
+
+static int http_internal_sync_request(lynq_http_client_t* http)
+{
+ int ret = 0;
+ http_init(http);
+
+ ret = http_connect(http);
+ if(ret != ERR_OK)
+ {
+ LYDBGLOG("[%s %d] return error\n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http][%s][session%d]: error num = %d\n", http->action, http->session, http->error_code);
+ return (http->error_code);
+ }
+
+ if(http->conn_method == M_CLOSE)
+ lynq_http_write_head_data(http);
+ else {
+ pthread_t tid;
+ pthread_create(&tid, NULL, http_write_head_data_thread, http);
+ }
+ memset(&http->parser_setting, 0, sizeof(http->parser_setting));
+ http->parser_setting.on_body = http->download ? on_download_file_cb : on_body_cb;
+ http->parser_setting.on_message_complete = on_message_complete_cb;
+ http->parser_setting.on_header_field = on_header_field_cb;
+ http->parser_setting.on_header_value = on_header_value_cb;
+ http->parser_setting.on_headers_complete = on_headers_complete_cb;
+ http->parser_setting.on_status = on_status_cb;
+
+ http_parser_init(&http->parser, HTTP_RESPONSE);
+ http->parser.data = http;
+
+ if(http->conn_method == M_CLOSE)
+ http_read_data_thread(http);
+ else {
+ pthread_t read_tid;
+ pthread_create(&read_tid, NULL, http_read_data_thread, http);
+ }
+
+ if(http->redirect == 1)
+ {
+ return http_internal_sync_request(http);
+ }
+ else
+ {
+ if(http->download)
+ {
+ if(http->pf)
+ {
+ fclose(http->pf);
+ http->pf = NULL;
+ }
+ }
+ if(http->body && http->body_len > 0)
+ {
+ http->body[http->body_len] = '\0';
+ }
+ }
+ return http->error_code;
+}
+
+const char* lynq_http_sync_request(lynq_http_client_t* http, const char* url, http_request_method_e m, http_connent_method_e c_m)
+{
+ if(http == NULL)
+ {
+ return NULL;
+ }
+
+ http->method = m;
+ http->conn_method = c_m;
+ http->download = 0;
+ http->url = (char *)url;
+ http->error_code = http_internal_sync_request(http);
+
+ return http->body;
+}
+
+const char* lynq_http_sync_post_request(lynq_http_client_t* http, char* url, char* post_data, http_request_method_e m, http_connent_method_e c_m)
+{
+ if(http == NULL)
+ {
+ return NULL;
+ }
+
+ http->method = m;
+ http->conn_method = c_m;
+ http->download = 0;
+ free_member(http->post_data);
+ http->post_data = post_data;
+ http->url = url;
+ http->post_data_len = strlen(http->post_data);
+
+ http->error_code = http_internal_sync_request(http);
+
+ return http->body;
+}
+
+ int lynq_http_sync_download_file(lynq_http_client_t* http, char* url, char* filepath, http_request_method_e m, http_connent_method_e c_m)
+{
+ if(http == NULL)
+ {
+ return -1;
+ }
+
+ http->method = m;
+ http->conn_method = c_m;
+ http->download = 1;
+
+ http->post_data = "";
+
+ free_member(http->url);
+
+ http->url = url;
+
+ free_member(http->filename);
+
+ if(filepath == NULL || !strcmp(filepath, ""))
+ {
+ filepath = strrchr(http->url, '/') + 1 ;
+ }
+
+ if(filepath != NULL)
+ {
+ http->filename = _strdup(filepath);
+
+ if(http->filename == NULL)
+ {
+ return http->error_code = ERR_OUT_MEMORY;
+ }
+ }
+
+ if(http_internal_sync_request(http) == ERR_OK)
+ {
+ return ERR_OK;
+ }
+
+ return http->error_code;
+}
+
+int lynq_http_exit(lynq_http_client_t* http)
+{
+ if(http) http->exit = 1;
+
+ return 0;
+}
+
+int ft_http_set_data_recv_cb(lynq_http_client_t* http, data_recv_cb_t cb, void* user)
+{
+ if(http)
+ {
+ http->user = user;
+ http->recv_cb = cb;
+ }
+ return 0;
+}
diff --git a/src/lynq/lib/liblynq-protcl/http/src/lynq_http_parser.c b/src/lynq/lib/liblynq-protcl/http/src/lynq_http_parser.c
new file mode 100644
index 0000000..306e6db
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/src/lynq_http_parser.c
@@ -0,0 +1,2267 @@
+#include "http/lynq_http_parser.h"
+#include <assert.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifndef ULLONG_MAX
+# define ULLONG_MAX ((uint64_t) -1)
+#endif
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#ifndef BIT_AT
+# define BIT_AT(a, i) \
+ (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
+ (1 << ((unsigned int) (i) & 7))))
+#endif
+
+#ifndef ELEM_AT
+# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
+#endif
+
+#define SET_ERRNO(e) \
+ do { \
+ parser->http_errno = (e); \
+ } while(0)
+
+#define CURRENT_STATE() p_state
+#define UPDATE_STATE(V) p_state = (enum state) (V);
+#define RETURN(V) \
+ do { \
+ parser->state = CURRENT_STATE(); \
+ return (V); \
+ } while (0);
+#define REEXECUTE() \
+ goto reexecute; \
+
+# define LIKELY(X) __builtin_expect(!!(X), 1)
+# define UNLIKELY(X) __builtin_expect(!!(X), 0)
+
+
+
+/* Run the notify callback FOR, returning ER if it fails */
+#define CALLBACK_NOTIFY_(FOR, ER) \
+ do { \
+ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
+ \
+ if (LIKELY(settings->on_##FOR)) { \
+ parser->state = CURRENT_STATE(); \
+ if (UNLIKELY(0 != settings->on_##FOR(parser))) { \
+ SET_ERRNO(HPE_CB_##FOR); \
+ } \
+ UPDATE_STATE(parser->state); \
+ \
+ /* We either errored above or got paused; get out */ \
+ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
+ return (ER); \
+ } \
+ } \
+ } while (0)
+
+#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)
+#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)
+#define CALLBACK_DATA_(FOR, LEN, ER) \
+ do { \
+ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
+ \
+ if (FOR##_mark) { \
+ if (LIKELY(settings->on_##FOR)) { \
+ parser->state = CURRENT_STATE(); \
+ if (UNLIKELY(0 != \
+ settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
+ SET_ERRNO(HPE_CB_##FOR); \
+ } \
+ UPDATE_STATE(parser->state); \
+ \
+ /* We either errored above or got paused; get out */ \
+ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
+ return (ER); \
+ } \
+ } \
+ FOR##_mark = NULL; \
+ } \
+ } while (0)
+
+#define CALLBACK_DATA(FOR) \
+ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
+
+#define CALLBACK_DATA_NOADVANCE(FOR) \
+ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
+
+#define MARK(FOR) \
+ do { \
+ if (!FOR##_mark) { \
+ FOR##_mark = p; \
+ } \
+ } while (0)
+
+#define COUNT_HEADER_SIZE(V) \
+ do { \
+ parser->nread += (V); \
+ if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \
+ SET_ERRNO(HPE_HEADER_OVERFLOW); \
+ goto error; \
+ } \
+ } while (0)
+
+
+#define PROXY_CONNECTION "proxy-connection"
+#define CONNECTION "connection"
+#define CONTENT_LENGTH "content-length"
+#define TRANSFER_ENCODING "transfer-encoding"
+#define UPGRADE "upgrade"
+#define CHUNKED "chunked"
+#define KEEP_ALIVE "keep-alive"
+#define CLOSE "close"
+
+
+static const char *method_strings[] =
+{
+#define XX(num, name, string) #string,
+ HTTP_METHOD_MAP(XX)
+#undef XX
+};
+
+static const char tokens[256] = {
+ /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+ 0, '!', 0, '#', '$', '%', '&', '\'',
+ /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+ 0, 0, '*', '+', 0, '-', '.', 0,
+ /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+ '8', '9', 0, 0, 0, 0, 0, 0,
+ /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+ 'x', 'y', 'z', 0, 0, 0, '^', '_',
+ /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+ 'x', 'y', 'z', 0, '|', 0, '~', 0 };
+
+
+static const int8_t unhex[256] =
+{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+};
+
+
+#if HTTP_PARSER_STRICT
+# define T(v) 0
+#else
+# define T(v) v
+#endif
+
+
+static const uint8_t normal_url_char[32] = {
+ /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+ /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+ 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
+ /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+ /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+ /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+ 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
+ /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
+ /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+ /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
+
+#undef T
+
+enum state
+{
+ s_dead = 1,
+ s_start_req_or_res,
+ s_res_or_resp_H,
+ s_start_res,
+ s_res_H,
+ s_res_HT,
+ s_res_HTT,
+ s_res_HTTP,
+ s_res_first_http_major,
+ s_res_http_major,
+ s_res_first_http_minor,
+ s_res_http_minor,
+ s_res_first_status_code,
+ s_res_status_code,
+ s_res_status_start,
+ s_res_status,
+ s_res_line_almost_done,
+ s_start_req,
+ s_req_method,
+ s_req_spaces_before_url,
+ s_req_schema,
+ s_req_schema_slash,
+ s_req_schema_slash_slash,
+ s_req_server_start,
+ s_req_server,
+ s_req_server_with_at,
+ s_req_path,
+ s_req_query_string_start,
+ s_req_query_string,
+ s_req_fragment_start,
+ s_req_fragment,
+ s_req_http_start,
+ s_req_http_H,
+ s_req_http_HT,
+ s_req_http_HTT,
+ s_req_http_HTTP,
+ s_req_first_http_major,
+ s_req_http_major,
+ s_req_first_http_minor,
+ s_req_http_minor,
+ s_req_line_almost_done,
+ s_header_field_start,
+ s_header_field,
+ s_header_value_discard_ws,
+ s_header_value_discard_ws_almost_done,
+ s_header_value_discard_lws,
+ s_header_value_start,
+ s_header_value,
+ s_header_value_lws,
+ s_header_almost_done,
+ s_chunk_size_start,
+ s_chunk_size,
+ s_chunk_parameters,
+ s_chunk_size_almost_done,
+ s_headers_almost_done,
+ s_headers_done,
+ s_chunk_data,
+ s_chunk_data_almost_done,
+ s_chunk_data_done,
+ s_body_identity,
+ s_body_identity_eof,
+ s_message_done,
+};
+
+
+#define PARSING_HEADER(state) (state <= s_headers_done)
+
+
+enum header_states
+{
+ h_general = 0,
+ h_C,
+ h_CO,
+ h_CON,
+ h_matching_connection,
+ h_matching_proxy_connection,
+ h_matching_content_length,
+ h_matching_transfer_encoding,
+ h_matching_upgrade,
+
+ h_connection,
+ h_content_length,
+ h_transfer_encoding,
+ h_upgrade,
+
+ h_matching_transfer_encoding_chunked,
+ h_matching_connection_token_start,
+ h_matching_connection_keep_alive,
+ h_matching_connection_close,
+ h_matching_connection_upgrade,
+ h_matching_connection_token,
+
+ h_transfer_encoding_chunked,
+ h_connection_keep_alive,
+ h_connection_close,
+ h_connection_upgrade,
+};
+
+enum http_host_state
+{
+ s_http_host_dead = 1,
+ s_http_userinfo_start,
+ s_http_userinfo,
+ s_http_host_start,
+ s_http_host_v6_start,
+ s_http_host,
+ s_http_host_v6,
+ s_http_host_v6_end,
+ s_http_host_v6_zone_start,
+ s_http_host_v6_zone,
+ s_http_host_port_start,
+ s_http_host_port,
+};
+
+/* Macros for character classes; depends on strict-mode */
+#define CR '\r'
+#define LF '\n'
+#define LOWER(c) (unsigned char)(c | 0x20)
+#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
+#define IS_NUM(c) ((c) >= '0' && (c) <= '9')
+#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
+#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
+#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
+ (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
+ (c) == ')')
+#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
+ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
+ (c) == '$' || (c) == ',')
+
+#define STRICT_TOKEN(c) (tokens[(unsigned char)c])
+
+#if HTTP_PARSER_STRICT
+#define TOKEN(c) (tokens[(unsigned char)c])
+#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
+#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
+#else
+#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
+#define IS_URL_CHAR(c) \
+ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
+#define IS_HOST_CHAR(c) \
+ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
+#endif
+
+
+#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
+
+
+#if HTTP_PARSER_STRICT
+# define STRICT_CHECK(cond) \
+ do { \
+ if (cond) { \
+ SET_ERRNO(HPE_STRICT); \
+ goto error; \
+ } \
+ } while (0)
+# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
+#else
+# define STRICT_CHECK(cond)
+# define NEW_MESSAGE() start_state
+#endif
+
+
+/* Map errno values to strings for human-readable output */
+#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
+static struct {
+ const char *name;
+ const char *description;
+} http_strerror_tab[] = {
+ HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
+};
+#undef HTTP_STRERROR_GEN
+
+int http_message_needs_eof(const http_parser *parser);
+
+static enum state
+parse_url_char(enum state s, const char ch)
+{
+ if (ch == ' ' || ch == '\r' || ch == '\n') {
+ return s_dead;
+ }
+
+#if HTTP_PARSER_STRICT
+ if (ch == '\t' || ch == '\f') {
+ return s_dead;
+ }
+#endif
+
+ switch (s) {
+ case s_req_spaces_before_url:
+ if (ch == '/' || ch == '*') {
+ return s_req_path;
+ }
+
+ if (IS_ALPHA(ch)) {
+ return s_req_schema;
+ }
+
+ break;
+
+ case s_req_schema:
+ if (IS_ALPHA(ch)) {
+ return s;
+ }
+
+ if (ch == ':') {
+ return s_req_schema_slash;
+ }
+
+ break;
+
+ case s_req_schema_slash:
+ if (ch == '/') {
+ return s_req_schema_slash_slash;
+ }
+
+ break;
+
+ case s_req_schema_slash_slash:
+ if (ch == '/') {
+ return s_req_server_start;
+ }
+
+ break;
+
+ case s_req_server_with_at:
+ if (ch == '@') {
+ return s_dead;
+ }
+ case s_req_server_start:
+ case s_req_server:
+ if (ch == '/') {
+ return s_req_path;
+ }
+
+ if (ch == '?') {
+ return s_req_query_string_start;
+ }
+
+ if (ch == '@') {
+ return s_req_server_with_at;
+ }
+
+ if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
+ return s_req_server;
+ }
+
+ break;
+
+ case s_req_path:
+ if (IS_URL_CHAR(ch)) {
+ return s;
+ }
+
+ switch (ch) {
+ case '?':
+ return s_req_query_string_start;
+
+ case '#':
+ return s_req_fragment_start;
+ }
+
+ break;
+
+ case s_req_query_string_start:
+ case s_req_query_string:
+ if (IS_URL_CHAR(ch)) {
+ return s_req_query_string;
+ }
+
+ switch (ch) {
+ case '?':
+ /* allow extra '?' in query string */
+ return s_req_query_string;
+
+ case '#':
+ return s_req_fragment_start;
+ }
+
+ break;
+
+ case s_req_fragment_start:
+ if (IS_URL_CHAR(ch)) {
+ return s_req_fragment;
+ }
+
+ switch (ch) {
+ case '?':
+ return s_req_fragment;
+
+ case '#':
+ return s;
+ }
+
+ break;
+
+ case s_req_fragment:
+ if (IS_URL_CHAR(ch)) {
+ return s;
+ }
+
+ switch (ch) {
+ case '?':
+ case '#':
+ return s;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return s_dead;
+}
+
+size_t http_parser_execute (http_parser *parser,
+ const http_parser_settings *settings,
+ const char *data,
+ size_t len)
+{
+ char c, ch;
+ int8_t unhex_val;
+ const char *p = data;
+ const char *header_field_mark = 0;
+ const char *header_value_mark = 0;
+ const char *url_mark = 0;
+ const char *body_mark = 0;
+ const char *status_mark = 0;
+ enum state p_state = (enum state) parser->state;
+
+ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+ return 0;
+ }
+
+ if (len == 0) {
+ switch (CURRENT_STATE()) {
+ case s_body_identity_eof:
+ CALLBACK_NOTIFY_NOADVANCE(message_complete);
+ return 0;
+
+ case s_dead:
+ case s_start_req_or_res:
+ case s_start_res:
+ case s_start_req:
+ return 0;
+
+ default:
+ SET_ERRNO(HPE_INVALID_EOF_STATE);
+ return 1;
+ }
+ }
+
+ if (CURRENT_STATE() == s_header_field)
+ header_field_mark = data;
+ if (CURRENT_STATE() == s_header_value)
+ header_value_mark = data;
+ switch (CURRENT_STATE()) {
+ case s_req_path:
+ case s_req_schema:
+ case s_req_schema_slash:
+ case s_req_schema_slash_slash:
+ case s_req_server_start:
+ case s_req_server:
+ case s_req_server_with_at:
+ case s_req_query_string_start:
+ case s_req_query_string:
+ case s_req_fragment_start:
+ case s_req_fragment:
+ url_mark = data;
+ break;
+ case s_res_status:
+ status_mark = data;
+ break;
+ default:
+ break;
+ }
+
+ for (p=data; p != data + len; p++) {
+ ch = *p;
+
+ if (PARSING_HEADER(CURRENT_STATE()))
+ COUNT_HEADER_SIZE(1);
+
+reexecute:
+ switch (CURRENT_STATE()) {
+
+ case s_dead:
+ if (LIKELY(ch == CR || ch == LF))
+ break;
+
+ SET_ERRNO(HPE_CLOSED_CONNECTION);
+ goto error;
+
+ case s_start_req_or_res:
+ {
+ if (ch == CR || ch == LF)
+ break;
+ parser->flags = 0;
+ parser->content_length = ULLONG_MAX;
+
+ if (ch == 'H') {
+ UPDATE_STATE(s_res_or_resp_H);
+
+ CALLBACK_NOTIFY(message_begin);
+ } else {
+ parser->type = HTTP_REQUEST;
+ UPDATE_STATE(s_start_req);
+ REEXECUTE();
+ }
+
+ break;
+ }
+
+ case s_res_or_resp_H:
+ if (ch == 'T') {
+ parser->type = HTTP_RESPONSE;
+ UPDATE_STATE(s_res_HT);
+ } else {
+ if (UNLIKELY(ch != 'E')) {
+ SET_ERRNO(HPE_INVALID_CONSTANT);
+ goto error;
+ }
+
+ parser->type = HTTP_REQUEST;
+ parser->method = HTTP_HEAD;
+ parser->index = 2;
+ UPDATE_STATE(s_req_method);
+ }
+ break;
+
+ case s_start_res:
+ {
+ parser->flags = 0;
+ parser->content_length = ULLONG_MAX;
+
+ switch (ch) {
+ case 'H':
+ UPDATE_STATE(s_res_H);
+ break;
+
+ case CR:
+ case LF:
+ break;
+
+ default:
+ SET_ERRNO(HPE_INVALID_CONSTANT);
+ goto error;
+ }
+
+ CALLBACK_NOTIFY(message_begin);
+ break;
+ }
+
+ case s_res_H:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_res_HT);
+ break;
+
+ case s_res_HT:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_res_HTT);
+ break;
+
+ case s_res_HTT:
+ STRICT_CHECK(ch != 'P');
+ UPDATE_STATE(s_res_HTTP);
+ break;
+
+ case s_res_HTTP:
+ STRICT_CHECK(ch != '/');
+ UPDATE_STATE(s_res_first_http_major);
+ break;
+
+ case s_res_first_http_major:
+ if (UNLIKELY(ch < '0' || ch > '9')) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major = ch - '0';
+ UPDATE_STATE(s_res_http_major);
+ break;
+
+ case s_res_http_major:
+ {
+ if (ch == '.') {
+ UPDATE_STATE(s_res_first_http_minor);
+ break;
+ }
+
+ if (!IS_NUM(ch)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major *= 10;
+ parser->http_major += ch - '0';
+
+ if (UNLIKELY(parser->http_major > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_res_first_http_minor:
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor = ch - '0';
+ UPDATE_STATE(s_res_http_minor);
+ break;
+
+ /* minor HTTP version or end of request line */
+ case s_res_http_minor:
+ {
+ if (ch == ' ') {
+ UPDATE_STATE(s_res_first_status_code);
+ break;
+ }
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor *= 10;
+ parser->http_minor += ch - '0';
+
+ if (UNLIKELY(parser->http_minor > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_res_first_status_code:
+ {
+ if (!IS_NUM(ch)) {
+ if (ch == ' ') {
+ break;
+ }
+
+ SET_ERRNO(HPE_INVALID_STATUS);
+ goto error;
+ }
+ parser->status_code = ch - '0';
+ UPDATE_STATE(s_res_status_code);
+ break;
+ }
+
+ case s_res_status_code:
+ {
+ if (!IS_NUM(ch)) {
+ switch (ch) {
+ case ' ':
+ UPDATE_STATE(s_res_status_start);
+ break;
+ case CR:
+ UPDATE_STATE(s_res_line_almost_done);
+ break;
+ case LF:
+ UPDATE_STATE(s_header_field_start);
+ break;
+ default:
+ SET_ERRNO(HPE_INVALID_STATUS);
+ goto error;
+ }
+ break;
+ }
+
+ parser->status_code *= 10;
+ parser->status_code += ch - '0';
+
+ if (UNLIKELY(parser->status_code > 999)) {
+ SET_ERRNO(HPE_INVALID_STATUS);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_res_status_start:
+ {
+ if (ch == CR) {
+ UPDATE_STATE(s_res_line_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_field_start);
+ break;
+ }
+
+ MARK(status);
+ UPDATE_STATE(s_res_status);
+ parser->index = 0;
+ break;
+ }
+
+ case s_res_status:
+ if (ch == CR) {
+ UPDATE_STATE(s_res_line_almost_done);
+ CALLBACK_DATA(status);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_field_start);
+ CALLBACK_DATA(status);
+ break;
+ }
+
+ break;
+
+ case s_res_line_almost_done:
+ STRICT_CHECK(ch != LF);
+ UPDATE_STATE(s_header_field_start);
+ break;
+
+ case s_start_req:
+ {
+ if (ch == CR || ch == LF)
+ break;
+ parser->flags = 0;
+ parser->content_length = ULLONG_MAX;
+
+ if (UNLIKELY(!IS_ALPHA(ch))) {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+
+ parser->method = (enum http_method) 0;
+ parser->index = 1;
+ switch (ch) {
+ case 'A': parser->method = HTTP_ACL; break;
+ case 'B': parser->method = HTTP_BIND; break;
+ case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
+ case 'D': parser->method = HTTP_DELETE; break;
+ case 'G': parser->method = HTTP_GET; break;
+ case 'H': parser->method = HTTP_HEAD; break;
+ case 'L': parser->method = HTTP_LOCK; break;
+ case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
+ case 'N': parser->method = HTTP_NOTIFY; break;
+ case 'O': parser->method = HTTP_OPTIONS; break;
+ case 'P': parser->method = HTTP_POST;
+ /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
+ break;
+ case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
+ case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
+ case 'T': parser->method = HTTP_TRACE; break;
+ case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND */ break;
+ default:
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ UPDATE_STATE(s_req_method);
+
+ CALLBACK_NOTIFY(message_begin);
+
+ break;
+ }
+
+ case s_req_method:
+ {
+ const char *matcher;
+ if (UNLIKELY(ch == '\0')) {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+
+ matcher = method_strings[parser->method];
+ if (ch == ' ' && matcher[parser->index] == '\0') {
+ UPDATE_STATE(s_req_spaces_before_url);
+ } else if (ch == matcher[parser->index]) {
+ ; /* nada */
+ } else if (parser->method == HTTP_CONNECT) {
+ if (parser->index == 1 && ch == 'H') {
+ parser->method = HTTP_CHECKOUT;
+ } else if (parser->index == 2 && ch == 'P') {
+ parser->method = HTTP_COPY;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_MKCOL) {
+ if (parser->index == 1 && ch == 'O') {
+ parser->method = HTTP_MOVE;
+ } else if (parser->index == 1 && ch == 'E') {
+ parser->method = HTTP_MERGE;
+ } else if (parser->index == 1 && ch == '-') {
+ parser->method = HTTP_MSEARCH;
+ } else if (parser->index == 2 && ch == 'A') {
+ parser->method = HTTP_MKACTIVITY;
+ } else if (parser->index == 3 && ch == 'A') {
+ parser->method = HTTP_MKCALENDAR;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_SUBSCRIBE) {
+ if (parser->index == 1 && ch == 'E') {
+ parser->method = HTTP_SEARCH;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_REPORT) {
+ if (parser->index == 2 && ch == 'B') {
+ parser->method = HTTP_REBIND;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->index == 1 && parser->method == HTTP_POST) {
+ if (ch == 'R') {
+ parser->method = HTTP_PROPFIND;
+ } else if (ch == 'U') {
+ parser->method = HTTP_PUT;
+ } else if (ch == 'A') {
+ parser->method = HTTP_PATCH;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->index == 2) {
+ if (parser->method == HTTP_PUT) {
+ if (ch == 'R') {
+ parser->method = HTTP_PURGE;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_UNLOCK) {
+ if (ch == 'S') {
+ parser->method = HTTP_UNSUBSCRIBE;
+ } else if(ch == 'B') {
+ parser->method = HTTP_UNBIND;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
+ parser->method = HTTP_PROPPATCH;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+
+ ++parser->index;
+ break;
+ }
+
+ case s_req_spaces_before_url:
+ {
+ if (ch == ' ') break;
+
+ MARK(url);
+ if (parser->method == HTTP_CONNECT) {
+ UPDATE_STATE(s_req_server_start);
+ }
+
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_req_schema:
+ case s_req_schema_slash:
+ case s_req_schema_slash_slash:
+ case s_req_server_start:
+ {
+ switch (ch) {
+ case ' ':
+ case CR:
+ case LF:
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ default:
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ }
+ }
+
+ break;
+ }
+
+ case s_req_server:
+ case s_req_server_with_at:
+ case s_req_path:
+ case s_req_query_string_start:
+ case s_req_query_string:
+ case s_req_fragment_start:
+ case s_req_fragment:
+ {
+ switch (ch) {
+ case ' ':
+ UPDATE_STATE(s_req_http_start);
+ CALLBACK_DATA(url);
+ break;
+ case CR:
+ case LF:
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ UPDATE_STATE((ch == CR) ?
+ s_req_line_almost_done :
+ s_header_field_start);
+ CALLBACK_DATA(url);
+ break;
+ default:
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+ SET_ERRNO(HPE_INVALID_URL);
+ goto error;
+ }
+ }
+ break;
+ }
+
+ case s_req_http_start:
+ switch (ch) {
+ case 'H':
+ UPDATE_STATE(s_req_http_H);
+ break;
+ case ' ':
+ break;
+ default:
+ SET_ERRNO(HPE_INVALID_CONSTANT);
+ goto error;
+ }
+ break;
+
+ case s_req_http_H:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_req_http_HT);
+ break;
+
+ case s_req_http_HT:
+ STRICT_CHECK(ch != 'T');
+ UPDATE_STATE(s_req_http_HTT);
+ break;
+
+ case s_req_http_HTT:
+ STRICT_CHECK(ch != 'P');
+ UPDATE_STATE(s_req_http_HTTP);
+ break;
+
+ case s_req_http_HTTP:
+ STRICT_CHECK(ch != '/');
+ UPDATE_STATE(s_req_first_http_major);
+ break;
+
+ case s_req_first_http_major:
+ if (UNLIKELY(ch < '1' || ch > '9')) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major = ch - '0';
+ UPDATE_STATE(s_req_http_major);
+ break;
+
+ case s_req_http_major:
+ {
+ if (ch == '.') {
+ UPDATE_STATE(s_req_first_http_minor);
+ break;
+ }
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_major *= 10;
+ parser->http_major += ch - '0';
+
+ if (UNLIKELY(parser->http_major > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_req_first_http_minor:
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor = ch - '0';
+ UPDATE_STATE(s_req_http_minor);
+ break;
+
+ case s_req_http_minor:
+ {
+ if (ch == CR) {
+ UPDATE_STATE(s_req_line_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_field_start);
+ break;
+ }
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ parser->http_minor *= 10;
+ parser->http_minor += ch - '0';
+
+ if (UNLIKELY(parser->http_minor > 999)) {
+ SET_ERRNO(HPE_INVALID_VERSION);
+ goto error;
+ }
+
+ break;
+ }
+
+ case s_req_line_almost_done:
+ {
+ if (UNLIKELY(ch != LF)) {
+ SET_ERRNO(HPE_LF_EXPECTED);
+ goto error;
+ }
+
+ UPDATE_STATE(s_header_field_start);
+ break;
+ }
+
+ case s_header_field_start:
+ {
+ if (ch == CR) {
+ UPDATE_STATE(s_headers_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_headers_almost_done);
+ REEXECUTE();
+ }
+
+ c = TOKEN(ch);
+
+ if (UNLIKELY(!c)) {
+ SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+ goto error;
+ }
+
+ MARK(header_field);
+
+ parser->index = 0;
+ UPDATE_STATE(s_header_field);
+
+ switch (c) {
+ case 'c':
+ parser->header_state = h_C;
+ break;
+
+ case 'p':
+ parser->header_state = h_matching_proxy_connection;
+ break;
+
+ case 't':
+ parser->header_state = h_matching_transfer_encoding;
+ break;
+
+ case 'u':
+ parser->header_state = h_matching_upgrade;
+ break;
+
+ default:
+ parser->header_state = h_general;
+ break;
+ }
+ break;
+ }
+
+ case s_header_field:
+ {
+ const char* start = p;
+ for (; p != data + len; p++) {
+ ch = *p;
+ c = TOKEN(ch);
+
+ if (!c)
+ break;
+
+ switch (parser->header_state) {
+ case h_general:
+ break;
+
+ case h_C:
+ parser->index++;
+ parser->header_state = (c == 'o' ? h_CO : h_general);
+ break;
+
+ case h_CO:
+ parser->index++;
+ parser->header_state = (c == 'n' ? h_CON : h_general);
+ break;
+
+ case h_CON:
+ parser->index++;
+ switch (c) {
+ case 'n':
+ parser->header_state = h_matching_connection;
+ break;
+ case 't':
+ parser->header_state = h_matching_content_length;
+ break;
+ default:
+ parser->header_state = h_general;
+ break;
+ }
+ break;
+
+ case h_matching_connection:
+ parser->index++;
+ if (parser->index > sizeof(CONNECTION)-1
+ || c != CONNECTION[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(CONNECTION)-2) {
+ parser->header_state = h_connection;
+ }
+ break;
+
+ case h_matching_proxy_connection:
+ parser->index++;
+ if (parser->index > sizeof(PROXY_CONNECTION)-1
+ || c != PROXY_CONNECTION[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
+ parser->header_state = h_connection;
+ }
+ break;
+
+ case h_matching_content_length:
+ parser->index++;
+ if (parser->index > sizeof(CONTENT_LENGTH)-1
+ || c != CONTENT_LENGTH[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
+ parser->header_state = h_content_length;
+ }
+ break;
+
+ case h_matching_transfer_encoding:
+ parser->index++;
+ if (parser->index > sizeof(TRANSFER_ENCODING)-1
+ || c != TRANSFER_ENCODING[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
+ parser->header_state = h_transfer_encoding;
+ }
+ break;
+
+ case h_matching_upgrade:
+ parser->index++;
+ if (parser->index > sizeof(UPGRADE)-1
+ || c != UPGRADE[parser->index]) {
+ parser->header_state = h_general;
+ } else if (parser->index == sizeof(UPGRADE)-2) {
+ parser->header_state = h_upgrade;
+ }
+ break;
+
+ case h_connection:
+ case h_content_length:
+ case h_transfer_encoding:
+ case h_upgrade:
+ if (ch != ' ') parser->header_state = h_general;
+ break;
+
+ default:
+ assert(0 && "Unknown header_state");
+ break;
+ }
+ }
+
+ COUNT_HEADER_SIZE(p - start);
+
+ if (p == data + len) {
+ --p;
+ break;
+ }
+
+ if (ch == ':') {
+ UPDATE_STATE(s_header_value_discard_ws);
+ CALLBACK_DATA(header_field);
+ break;
+ }
+
+ SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+ goto error;
+ }
+
+ case s_header_value_discard_ws:
+ if (ch == ' ' || ch == '\t') break;
+
+ if (ch == CR) {
+ UPDATE_STATE(s_header_value_discard_ws_almost_done);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_value_discard_lws);
+ break;
+ }
+
+ case s_header_value_start:
+ {
+ MARK(header_value);
+
+ UPDATE_STATE(s_header_value);
+ parser->index = 0;
+
+ c = LOWER(ch);
+
+ switch (parser->header_state) {
+ case h_upgrade:
+ parser->flags |= F_UPGRADE;
+ parser->header_state = h_general;
+ break;
+
+ case h_transfer_encoding:
+ if ('c' == c) {
+ parser->header_state = h_matching_transfer_encoding_chunked;
+ } else {
+ parser->header_state = h_general;
+ }
+ break;
+
+ case h_content_length:
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ goto error;
+ }
+
+ parser->content_length = ch - '0';
+ break;
+
+ case h_connection:
+ if (c == 'k') {
+ parser->header_state = h_matching_connection_keep_alive;
+ } else if (c == 'c') {
+ parser->header_state = h_matching_connection_close;
+ } else if (c == 'u') {
+ parser->header_state = h_matching_connection_upgrade;
+ } else {
+ parser->header_state = h_matching_connection_token;
+ }
+ break;
+
+ case h_matching_connection_token_start:
+ break;
+
+ default:
+ parser->header_state = h_general;
+ break;
+ }
+ break;
+ }
+
+ case s_header_value:
+ {
+ const char* start = p;
+ enum header_states h_state = (enum header_states) parser->header_state;
+ for (; p != data + len; p++) {
+ ch = *p;
+ if (ch == CR) {
+ UPDATE_STATE(s_header_almost_done);
+ parser->header_state = h_state;
+ CALLBACK_DATA(header_value);
+ break;
+ }
+
+ if (ch == LF) {
+ UPDATE_STATE(s_header_almost_done);
+ COUNT_HEADER_SIZE(p - start);
+ parser->header_state = h_state;
+ CALLBACK_DATA_NOADVANCE(header_value);
+ REEXECUTE();
+ }
+
+ c = LOWER(ch);
+
+ switch (h_state) {
+ case h_general:
+ {
+ const char* p_cr;
+ const char* p_lf;
+ size_t limit = data + len - p;
+
+ limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
+
+ p_cr = (const char*) memchr(p, CR, limit);
+ p_lf = (const char*) memchr(p, LF, limit);
+ if (p_cr != NULL) {
+ if (p_lf != NULL && p_cr >= p_lf)
+ p = p_lf;
+ else
+ p = p_cr;
+ } else if (UNLIKELY(p_lf != NULL)) {
+ p = p_lf;
+ } else {
+ p = data + len;
+ }
+ --p;
+
+ break;
+ }
+
+ case h_connection:
+ case h_transfer_encoding:
+ assert(0 && "Shouldn't get here.");
+ break;
+
+ case h_content_length:
+ {
+ uint64_t t;
+
+ if (ch == ' ') break;
+
+ if (UNLIKELY(!IS_NUM(ch))) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ parser->header_state = h_state;
+ goto error;
+ }
+
+ t = parser->content_length;
+ t *= 10;
+ t += ch - '0';
+
+ if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ parser->header_state = h_state;
+ goto error;
+ }
+
+ parser->content_length = t;
+ break;
+ }
+
+ case h_matching_transfer_encoding_chunked:
+ parser->index++;
+ if (parser->index > sizeof(CHUNKED)-1
+ || c != CHUNKED[parser->index]) {
+ h_state = h_general;
+ } else if (parser->index == sizeof(CHUNKED)-2) {
+ h_state = h_transfer_encoding_chunked;
+ }
+ break;
+
+ case h_matching_connection_token_start:
+ if (c == 'k') {
+ h_state = h_matching_connection_keep_alive;
+ } else if (c == 'c') {
+ h_state = h_matching_connection_close;
+ } else if (c == 'u') {
+ h_state = h_matching_connection_upgrade;
+ } else if (STRICT_TOKEN(c)) {
+ h_state = h_matching_connection_token;
+ } else if (c == ' ' || c == '\t') {
+ /* Skip lws */
+ } else {
+ h_state = h_general;
+ }
+ break;
+
+ case h_matching_connection_keep_alive:
+ parser->index++;
+ if (parser->index > sizeof(KEEP_ALIVE)-1
+ || c != KEEP_ALIVE[parser->index]) {
+ h_state = h_matching_connection_token;
+ } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
+ h_state = h_connection_keep_alive;
+ }
+ break;
+
+ case h_matching_connection_close:
+ parser->index++;
+ if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
+ h_state = h_matching_connection_token;
+ } else if (parser->index == sizeof(CLOSE)-2) {
+ h_state = h_connection_close;
+ }
+ break;
+
+ case h_matching_connection_upgrade:
+ parser->index++;
+ if (parser->index > sizeof(UPGRADE) - 1 ||
+ c != UPGRADE[parser->index]) {
+ h_state = h_matching_connection_token;
+ } else if (parser->index == sizeof(UPGRADE)-2) {
+ h_state = h_connection_upgrade;
+ }
+ break;
+
+ case h_matching_connection_token:
+ if (ch == ',') {
+ h_state = h_matching_connection_token_start;
+ parser->index = 0;
+ }
+ break;
+
+ case h_transfer_encoding_chunked:
+ if (ch != ' ') h_state = h_general;
+ break;
+
+ case h_connection_keep_alive:
+ case h_connection_close:
+ case h_connection_upgrade:
+ if (ch == ',') {
+ if (h_state == h_connection_keep_alive) {
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
+ } else if (h_state == h_connection_close) {
+ parser->flags |= F_CONNECTION_CLOSE;
+ } else if (h_state == h_connection_upgrade) {
+ parser->flags |= F_CONNECTION_UPGRADE;
+ }
+ h_state = h_matching_connection_token_start;
+ parser->index = 0;
+ } else if (ch != ' ') {
+ h_state = h_matching_connection_token;
+ }
+ break;
+
+ default:
+ UPDATE_STATE(s_header_value);
+ h_state = h_general;
+ break;
+ }
+ }
+ parser->header_state = h_state;
+
+ COUNT_HEADER_SIZE(p - start);
+
+ if (p == data + len)
+ --p;
+ break;
+ }
+
+ case s_header_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+
+ UPDATE_STATE(s_header_value_lws);
+ break;
+ }
+
+ case s_header_value_lws:
+ {
+ if (ch == ' ' || ch == '\t') {
+ UPDATE_STATE(s_header_value_start);
+ REEXECUTE();
+ }
+
+ /* finished the header */
+ switch (parser->header_state) {
+ case h_connection_keep_alive:
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
+ break;
+ case h_connection_close:
+ parser->flags |= F_CONNECTION_CLOSE;
+ break;
+ case h_transfer_encoding_chunked:
+ parser->flags |= F_CHUNKED;
+ break;
+ case h_connection_upgrade:
+ parser->flags |= F_CONNECTION_UPGRADE;
+ break;
+ default:
+ break;
+ }
+
+ UPDATE_STATE(s_header_field_start);
+ REEXECUTE();
+ }
+
+ case s_header_value_discard_ws_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+ UPDATE_STATE(s_header_value_discard_lws);
+ break;
+ }
+
+ case s_header_value_discard_lws:
+ {
+ if (ch == ' ' || ch == '\t') {
+ UPDATE_STATE(s_header_value_discard_ws);
+ break;
+ } else {
+ switch (parser->header_state) {
+ case h_connection_keep_alive:
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
+ break;
+ case h_connection_close:
+ parser->flags |= F_CONNECTION_CLOSE;
+ break;
+ case h_connection_upgrade:
+ parser->flags |= F_CONNECTION_UPGRADE;
+ break;
+ case h_transfer_encoding_chunked:
+ parser->flags |= F_CHUNKED;
+ break;
+ default:
+ break;
+ }
+ MARK(header_value);
+ UPDATE_STATE(s_header_field_start);
+ CALLBACK_DATA_NOADVANCE(header_value);
+ REEXECUTE();
+ }
+ }
+
+ case s_headers_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+
+ if (parser->flags & F_TRAILING) {
+ /* End of a chunked request */
+ UPDATE_STATE(s_message_done);
+ CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
+ REEXECUTE();
+ }
+
+ UPDATE_STATE(s_headers_done);
+
+ parser->upgrade =
+ ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) ==
+ (F_UPGRADE | F_CONNECTION_UPGRADE) ||
+ parser->method == HTTP_CONNECT);
+
+ if (settings->on_headers_complete) {
+ switch (settings->on_headers_complete(parser)) {
+ case 0:
+ break;
+
+ case 1:
+ parser->flags |= F_SKIPBODY;
+ break;
+
+ default:
+ SET_ERRNO(HPE_CB_headers_complete);
+ RETURN(p - data); /* Error */
+ }
+ }
+
+ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+ RETURN(p - data);
+ }
+
+ REEXECUTE();
+ }
+
+ case s_headers_done:
+ {
+ int hasBody;
+ STRICT_CHECK(ch != LF);
+
+ parser->nread = 0;
+
+ hasBody = parser->flags & F_CHUNKED ||
+ (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
+ if (parser->upgrade && (parser->method == HTTP_CONNECT ||
+ (parser->flags & F_SKIPBODY) || !hasBody)) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ RETURN((p - data) + 1);
+ }
+
+ if (parser->flags & F_SKIPBODY) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ } else if (parser->flags & F_CHUNKED) {
+ UPDATE_STATE(s_chunk_size_start);
+ } else {
+ if (parser->content_length == 0) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ } else if (parser->content_length != ULLONG_MAX) {
+ UPDATE_STATE(s_body_identity);
+ } else {
+ if (!http_message_needs_eof(parser)) {
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ } else {
+ UPDATE_STATE(s_body_identity_eof);
+ }
+ }
+ }
+
+ break;
+ }
+
+ case s_body_identity:
+ {
+ uint64_t to_read = MIN(parser->content_length,
+ (uint64_t) ((data + len) - p));
+
+ assert(parser->content_length != 0
+ && parser->content_length != ULLONG_MAX);
+ MARK(body);
+ parser->content_length -= to_read;
+ p += to_read - 1;
+
+ if (parser->content_length == 0) {
+ UPDATE_STATE(s_message_done);
+ CALLBACK_DATA_(body, p - body_mark + 1, p - data);
+ REEXECUTE();
+ }
+
+ break;
+ }
+ case s_body_identity_eof:
+ MARK(body);
+ p = data + len - 1;
+
+ break;
+
+ case s_message_done:
+ UPDATE_STATE(NEW_MESSAGE());
+ CALLBACK_NOTIFY(message_complete);
+ if (parser->upgrade) {
+ RETURN((p - data) + 1);
+ }
+ break;
+
+ case s_chunk_size_start:
+ {
+ assert(parser->nread == 1);
+ assert(parser->flags & F_CHUNKED);
+
+ unhex_val = unhex[(unsigned char)ch];
+ if (UNLIKELY(unhex_val == -1)) {
+ SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+ goto error;
+ }
+
+ parser->content_length = unhex_val;
+ UPDATE_STATE(s_chunk_size);
+ break;
+ }
+
+ case s_chunk_size:
+ {
+ uint64_t t;
+
+ assert(parser->flags & F_CHUNKED);
+
+ if (ch == CR) {
+ UPDATE_STATE(s_chunk_size_almost_done);
+ break;
+ }
+
+ unhex_val = unhex[(unsigned char)ch];
+
+ if (unhex_val == -1) {
+ if (ch == ';' || ch == ' ') {
+ UPDATE_STATE(s_chunk_parameters);
+ break;
+ }
+
+ SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+ goto error;
+ }
+
+ t = parser->content_length;
+ t *= 16;
+ t += unhex_val;
+
+ if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+ goto error;
+ }
+
+ parser->content_length = t;
+ break;
+ }
+
+ case s_chunk_parameters:
+ {
+ assert(parser->flags & F_CHUNKED);
+ if (ch == CR) {
+ UPDATE_STATE(s_chunk_size_almost_done);
+ break;
+ }
+ break;
+ }
+
+ case s_chunk_size_almost_done:
+ {
+ assert(parser->flags & F_CHUNKED);
+ STRICT_CHECK(ch != LF);
+
+ parser->nread = 0;
+
+ if (parser->content_length == 0) {
+ parser->flags |= F_TRAILING;
+ UPDATE_STATE(s_header_field_start);
+ } else {
+ UPDATE_STATE(s_chunk_data);
+ }
+ CALLBACK_NOTIFY(chunk_header);
+ break;
+ }
+
+ case s_chunk_data:
+ {
+ uint64_t to_read = MIN(parser->content_length,
+ (uint64_t) ((data + len) - p));
+
+ assert(parser->flags & F_CHUNKED);
+ assert(parser->content_length != 0
+ && parser->content_length != ULLONG_MAX);
+
+ MARK(body);
+ parser->content_length -= to_read;
+ p += to_read - 1;
+
+ if (parser->content_length == 0) {
+ UPDATE_STATE(s_chunk_data_almost_done);
+ }
+
+ break;
+ }
+
+ case s_chunk_data_almost_done:
+ assert(parser->flags & F_CHUNKED);
+ assert(parser->content_length == 0);
+ STRICT_CHECK(ch != CR);
+ UPDATE_STATE(s_chunk_data_done);
+ CALLBACK_DATA(body);
+ break;
+
+ case s_chunk_data_done:
+ assert(parser->flags & F_CHUNKED);
+ STRICT_CHECK(ch != LF);
+ parser->nread = 0;
+ UPDATE_STATE(s_chunk_size_start);
+ CALLBACK_NOTIFY(chunk_complete);
+ break;
+
+ default:
+ assert(0 && "unhandled state");
+ SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
+ goto error;
+ }
+ }
+
+ assert(((header_field_mark ? 1 : 0) +
+ (header_value_mark ? 1 : 0) +
+ (url_mark ? 1 : 0) +
+ (body_mark ? 1 : 0) +
+ (status_mark ? 1 : 0)) <= 1);
+
+ CALLBACK_DATA_NOADVANCE(header_field);
+ CALLBACK_DATA_NOADVANCE(header_value);
+ CALLBACK_DATA_NOADVANCE(url);
+ CALLBACK_DATA_NOADVANCE(body);
+ CALLBACK_DATA_NOADVANCE(status);
+
+ RETURN(len);
+
+error:
+ if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
+ SET_ERRNO(HPE_UNKNOWN);
+ }
+
+ RETURN(p - data);
+}
+
+int http_message_needs_eof (const http_parser *parser)
+{
+ if (parser->type == HTTP_REQUEST) {
+ return 0;
+ }
+
+ if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
+ parser->status_code == 204 || /* No Content */
+ parser->status_code == 304 || /* Not Modified */
+ parser->flags & F_SKIPBODY) { /* response to a HEAD request */
+ return 0;
+ }
+
+ if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int http_should_keep_alive (const http_parser *parser)
+{
+ if (parser->http_major > 0 && parser->http_minor > 0) {
+ if (parser->flags & F_CONNECTION_CLOSE) {
+ return 0;
+ }
+ } else {
+ if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
+ return 0;
+ }
+ }
+
+ return !http_message_needs_eof(parser);
+}
+
+
+ const char *
+http_method_str (enum http_method m)
+{
+ return ELEM_AT(method_strings, m, "<unknown>");
+}
+
+
+ void
+http_parser_init (http_parser *parser, enum http_parser_type t)
+{
+ void *data = parser->data; /* preserve application data */
+ memset(parser, 0, sizeof(*parser));
+ parser->data = data;
+ parser->type = t;
+ parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
+ parser->http_errno = HPE_OK;
+}
+
+ void
+http_parser_settings_init(http_parser_settings *settings)
+{
+ memset(settings, 0, sizeof(*settings));
+}
+
+const char *
+http_errno_name(enum http_errno err) {
+ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+ return http_strerror_tab[err].name;
+}
+
+const char *
+http_errno_description(enum http_errno err) {
+ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+ return http_strerror_tab[err].description;
+}
+
+static enum http_host_state
+http_parse_host_char(enum http_host_state s, const char ch) {
+ switch(s) {
+ case s_http_userinfo:
+ case s_http_userinfo_start:
+ if (ch == '@') {
+ return s_http_host_start;
+ }
+
+ if (IS_USERINFO_CHAR(ch)) {
+ return s_http_userinfo;
+ }
+ break;
+
+ case s_http_host_start:
+ if (ch == '[') {
+ return s_http_host_v6_start;
+ }
+
+ if (IS_HOST_CHAR(ch)) {
+ return s_http_host;
+ }
+
+ break;
+
+ case s_http_host:
+ if (IS_HOST_CHAR(ch)) {
+ return s_http_host;
+ }
+
+ /* FALLTHROUGH */
+ case s_http_host_v6_end:
+ if (ch == ':') {
+ return s_http_host_port_start;
+ }
+
+ break;
+
+ case s_http_host_v6:
+ if (ch == ']') {
+ return s_http_host_v6_end;
+ }
+
+ /* FALLTHROUGH */
+ case s_http_host_v6_start:
+ if (IS_HEX(ch) || ch == ':' || ch == '.') {
+ return s_http_host_v6;
+ }
+
+ if (s == s_http_host_v6 && ch == '%') {
+ return s_http_host_v6_zone_start;
+ }
+ break;
+
+ case s_http_host_v6_zone:
+ if (ch == ']') {
+ return s_http_host_v6_end;
+ }
+
+ /* FALLTHROUGH */
+ case s_http_host_v6_zone_start:
+ if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
+ ch == '~') {
+ return s_http_host_v6_zone;
+ }
+ break;
+
+ case s_http_host_port:
+ case s_http_host_port_start:
+ if (IS_NUM(ch)) {
+ return s_http_host_port;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ return s_http_host_dead;
+}
+
+static int
+http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
+ enum http_host_state s;
+ size_t buflen = 0;
+ const char *p;
+
+ assert(u->field_set & (1 << UF_HOST));
+
+ buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
+
+ u->field_data[UF_HOST].len = 0;
+
+ s = found_at ? s_http_userinfo_start : s_http_host_start;
+
+ for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
+ enum http_host_state new_s = http_parse_host_char(s, *p);
+
+ if (new_s == s_http_host_dead) {
+ return 1;
+ }
+
+ switch(new_s) {
+ case s_http_host:
+ if (s != s_http_host) {
+ u->field_data[UF_HOST].off = p - buf;
+ }
+ u->field_data[UF_HOST].len++;
+ break;
+
+ case s_http_host_v6:
+ if (s != s_http_host_v6) {
+ u->field_data[UF_HOST].off = p - buf;
+ }
+ u->field_data[UF_HOST].len++;
+ break;
+
+ case s_http_host_v6_zone_start:
+ case s_http_host_v6_zone:
+ u->field_data[UF_HOST].len++;
+ break;
+
+ case s_http_host_port:
+ if (s != s_http_host_port) {
+ u->field_data[UF_PORT].off = p - buf;
+ u->field_data[UF_PORT].len = 0;
+ u->field_set |= (1 << UF_PORT);
+ }
+ u->field_data[UF_PORT].len++;
+ break;
+
+ case s_http_userinfo:
+ if (s != s_http_userinfo) {
+ u->field_data[UF_USERINFO].off = p - buf ;
+ u->field_data[UF_USERINFO].len = 0;
+ u->field_set |= (1 << UF_USERINFO);
+ }
+ u->field_data[UF_USERINFO].len++;
+ break;
+
+ default:
+ break;
+ }
+ s = new_s;
+ }
+
+ switch (s) {
+ case s_http_host_start:
+ case s_http_host_v6_start:
+ case s_http_host_v6:
+ case s_http_host_v6_zone_start:
+ case s_http_host_v6_zone:
+ case s_http_host_port_start:
+ case s_http_userinfo:
+ case s_http_userinfo_start:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
+ struct http_parser_url *u)
+{
+ enum state s;
+ const char *p;
+ enum http_parser_url_fields uf, old_uf;
+ int found_at = 0;
+
+ u->port = u->field_set = 0;
+ s = is_connect ? s_req_server_start : s_req_spaces_before_url;
+ old_uf = UF_MAX;
+
+ for (p = buf; p < buf + buflen; p++) {
+ s = parse_url_char(s, *p);
+
+ /* Figure out the next field that we're operating on */
+ switch (s) {
+ case s_dead:
+ return 1;
+ case s_req_schema_slash:
+ case s_req_schema_slash_slash:
+ case s_req_server_start:
+ case s_req_query_string_start:
+ case s_req_fragment_start:
+ continue;
+
+ case s_req_schema:
+ uf = UF_SCHEMA;
+ break;
+
+ case s_req_server_with_at:
+ found_at = 1;
+
+ case s_req_server:
+ uf = UF_HOST;
+ break;
+
+ case s_req_path:
+ uf = UF_PATH;
+ break;
+
+ case s_req_query_string:
+ uf = UF_QUERY;
+ break;
+
+ case s_req_fragment:
+ uf = UF_FRAGMENT;
+ break;
+
+ default:
+ assert(!"Unexpected state");
+ return 1;
+ }
+
+ if (uf == old_uf) {
+ u->field_data[uf].len++;
+ continue;
+ }
+
+ u->field_data[uf].off = p - buf;
+ u->field_data[uf].len = 1;
+
+ u->field_set |= (1 << uf);
+ old_uf = uf;
+ }
+
+ if ((u->field_set & (1 << UF_SCHEMA)) &&
+ (u->field_set & (1 << UF_HOST)) == 0) {
+ return 1;
+ }
+
+ if (u->field_set & (1 << UF_HOST)) {
+ if (http_parse_host(buf, u, found_at) != 0) {
+ return 1;
+ }
+ }
+
+ if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
+ return 1;
+ }
+
+ if (u->field_set & (1 << UF_PORT)) {
+ unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
+
+ if (v > 0xffff) {
+ return 1;
+ }
+
+ u->port = (uint16_t) v;
+ }
+
+ return 0;
+}
+
+void
+http_parser_pause(http_parser *parser, int paused) {
+ if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
+ HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
+ SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
+ } else {
+ assert(0 && "Attempting to pause parser in error state");
+ }
+}
+
+int
+http_body_is_final(const struct http_parser *parser) {
+ return parser->state == s_message_done;
+}
+
+unsigned long
+http_parser_version(void) {
+ return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
+ HTTP_PARSER_VERSION_MINOR * 0x00100 |
+ HTTP_PARSER_VERSION_PATCH * 0x00001;
+}
diff --git a/src/lynq/lib/liblynq-protcl/http/src/lynq_msgq.c b/src/lynq/lib/liblynq-protcl/http/src/lynq_msgq.c
new file mode 100644
index 0000000..5005c18
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/http/src/lynq_msgq.c
@@ -0,0 +1,33 @@
+#include <sys/msg.h>
+#include <sys/ipc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "http/lynq_msgq.h"
+
+
+int lynq_msgq_init(char *pathname, int create)
+{
+ key_t key = ftok(pathname, 66);
+ int queueId = msgget(key, IPC_CREAT | create);
+ if(queueId == -1)
+ {
+ //LYDBGLOG("[%s %d] create msg error \n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_MSG);
+ return ERR_MSG;
+ }
+
+ return queueId ;
+}
+
+int lynq_msgq_send(int queueId, struct mymesg *ckxmsg)
+{
+ if(msgsnd(queueId, ckxmsg, 512, 0) < 0)
+ {
+ //LYDBGLOG("[%s %d] send msg error \n", __FUNCTION__, __LINE__);
+ LYVERBLOG("+[http]: error num = %d\n", ERR_MSG);
+ return ERR_MSG;
+ }
+
+ return 0;
+}
diff --git a/src/lynq/lib/liblynq-protcl/include/ftp/lynq_ftp.h b/src/lynq/lib/liblynq-protcl/include/ftp/lynq_ftp.h
new file mode 100644
index 0000000..12e3f09
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/include/ftp/lynq_ftp.h
@@ -0,0 +1,171 @@
+#include<stdio.h>
+#include<sys/socket.h>
+#include<stdlib.h>
+#include<string.h>
+#include<strings.h>
+#include<unistd.h>
+#include<netinet/in.h>
+#include<netdb.h>
+#include<errno.h>
+#include<sys/types.h>
+#include<sys/stat.h>
+#include<fcntl.h>
+#include "liblog/liblog.h"
+#include "liblog/lynq_deflog.h"
+
+
+#define SERV_PORT 21
+#define MAXSIZE 1024
+//#define MAXBUF 1024
+#define FTP_FILE_TYPE_LEN 4
+#define FTP_MAX_ASCII_LEN 1024
+#define FTPSHMPATH "/"
+#define FTPSHMID 'K'
+
+
+int error;
+char errorbuf[10];
+
+#if 1
+/*log error info */
+
+#define FTP_NET_ERROR 31 //network
+#define FTP_DNS_ERROR 32 //DNS
+#define FTP_CONNECT_ERROR 33 //connect
+#define FTP_TIMEROUT 34 //time out
+#define FTP_SERVER_ERROR 35 //server
+#define FTP_OPERATION_NOT_ALLOW 36 //operation not allow
+#define FTP_REPLAY_ERROR 37 //replay
+#define FTP_USER_ERROR 38 //user
+#define FTP_PASSWORD_ERROR 39 //pwd
+#define FTP_TYPE_ERROR 40 //type
+#define FTP_REST_ERROR 41 //rest
+#define FTP_PASSIVE_ERROR 42 //passive
+#define FTP_ACTIVE_ERROR 43 //active
+#define FTP_OPERATE_ERROR 44 //operate
+#define FTP_UPLOAD_ERROR 45 //upload
+#define FTP_DOWNLOAD_ERROR 46 //download
+#define FTP_FILE_ACTION_ERROR 47 //action error
+#define FTP_MANUAL_QUIT 48 //manual quit
+#define FTP_ERROR_FLAG 49
+#define FTP_SOCK_ERROR 50 //socket error
+#define FTP_RCV_ERROR 51 //rcv error
+#define FTP_SEND_ERROR 52 //send error
+#define FTP_CLOSE_ERROR 53 //close error
+#define FTP_READ_ERROR 54 //read error
+#define FTP_WRITE_ERROR 55 //write error
+#define FTP_LS_ERROR 55 //ls error
+
+#endif
+
+#if 1
+/***********ftp return vauil******************/
+
+#define FTP_100_INIT_WAIT_LAST_CMD 100
+#define FTP_125_TRANSFER_START 125
+#define FTP_150_OPEN_DATA_CONNECT 150
+
+#define FTP_200_COMMAND_SUCCESSFUL 200
+#define FTP_213_FILE_STATUS 213
+#define FTP_220_SERVER_READY_FOR_NEW_USER 220
+#define FTP_221_CLOSE_CONTROL_CONNECT 221
+#define FTP_226_TRANSFER_COMPLATE 226
+#define FTP_227_ENTRY_PASV_MODE 227
+#define FTP_230_USER_LOGGED_IN 230
+#define FTP_250_REQUEST_FILE_ACTION_OK 250
+#define FTP_257_PATH_NAME 257
+
+
+#define FTP_331_NAMEOK_PASS_REQUIRE 331
+#define FTP_350_FILE_OPER_OK_WAIT_NEXT 350
+
+#define FTP_421_CONTROL_LINK_SHUTDOWN 421
+#define FTP_425_CANNOT_OPEN_DATA_CONNECT 425
+
+
+#define FTP_500_COMMAND_ERROR 500
+#define FTP_501_PARAMETER_ERROR 501
+#define FTP_502_COMMAND_NOT_IMP 502
+#define FTP_503_BAD_SEQUENCE_OF_CMD 503
+
+#define FTP_530_CANNOT_LOG_IN 530
+#define FTP_532_NEED_ACCOUNT 532
+#define FTP_534_CANNOT_CONN_CAUSE_SSL 534
+#define FTP_550_FILE_CANT_FIND 550
+
+
+#endif
+
+typedef struct ftp_socket_info
+{
+ int id;
+ int index;
+ char protocol[10];
+ int session;
+ char action[10];
+
+ int control_sockfd;
+ int portnum;//port num 1~65535
+ char is_pasv_mode[225];//0:initiative 1:pasv
+ char file_type[FTP_FILE_TYPE_LEN+1];//type "A" or "I"
+ char put_opt[FTP_FILE_TYPE_LEN+1];// "APPE", "STOU", "STOR"
+ int rest; //xu chuan wei zhi;
+ char sevname[FTP_MAX_ASCII_LEN + 1];//addr :192.168.1.89;
+ char username[FTP_MAX_ASCII_LEN + 1];//user
+ char pw[FTP_MAX_ASCII_LEN + 1];//password
+ char getfilename[FTP_MAX_ASCII_LEN + 1];//get file name;
+ char getfilename_path[FTP_MAX_ASCII_LEN + 1];//get file path;
+ char putfilename[FTP_MAX_ASCII_LEN + 1];//put file name;
+ char putfilename_path[FTP_MAX_ASCII_LEN + 1];//put file path;
+ //char conmd[255];
+ char dir[1024];
+ char del_mkr_filename[1024];
+ char respond[1024];
+ int flag;
+ int flag1;
+ int modify_thread;
+ int add_thread;
+}lynq_ftp_socker_info;
+
+
+int control_sockfd;
+int login_yes;
+int f;
+char putpathname[225];
+char hoster[255];
+struct sockaddr_in servaddr;
+char rbuf[1024],rbuf1[1024],wbuf[1024],wbuf1[1024];
+int ftpshm_id;
+lynq_ftp_socker_info *FTP;
+
+int uartfd;
+int usbfd;
+//char BUF[1024];
+
+
+
+int lynq_ftp_put(int sck,char *pUploadFileName_s);
+extern int lynq_ftp_login(lynq_ftp_socker_info *FTP);
+extern void zeromery(char *a,int len);
+extern char *itoa(int value, char *string, int radix);
+extern void lynq_ftp_pwd(int control_sockfd);
+extern int strtosrv(char *str);
+extern void lynq_ftp_get(int sck, char *pDownloadFileName, int session);
+extern void lynq_ftp_rest(int control_sockfd);
+extern int cliopen(char *hoster, int port);
+extern int lynq_ftp_download(lynq_ftp_socker_info* FTP);
+extern int lynq_ftp_up(lynq_ftp_socker_info* FTP);
+int lynq_ftp_ls(lynq_ftp_socker_info* FTP);
+void lynq_ftp_cd(lynq_ftp_socker_info* FTP);
+void lynq_ftp_creat_mkd(lynq_ftp_socker_info* FTP);
+void lynq_ftp_delete_mkd(lynq_ftp_socker_info* FTP);
+void ftp_list(int sockfd, int session);
+void lynq_ftp_quit(lynq_ftp_socker_info* FTP);
+void lynq_ftp_deletefile_mkd(lynq_ftp_socker_info* FTP);
+
+
+extern void init(lynq_ftp_socker_info* FTP);
+extern int lynq_ftpshm_create( void );
+extern lynq_ftp_socker_info *ftpshm_act(int shmid);
+extern void lynq_ftpshm_deact(lynq_ftp_socker_info *shm);
+extern void lynq_ftpshm_del(int shmid);
diff --git a/src/lynq/lib/liblynq-protcl/include/http/lynq_http.h b/src/lynq/lib/liblynq-protcl/include/http/lynq_http.h
new file mode 100644
index 0000000..455abc2
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/include/http/lynq_http.h
@@ -0,0 +1,185 @@
+#ifndef _LYNQ_HTTP_H_
+#define _LYNQ_HTTP_H_
+
+#define HTTP_API
+
+
+#include "lynq_http_parser.h"
+#include "lynq_msgq.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <time.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <strings.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#ifdef _cplusplus
+extern "C" {
+#endif
+
+#define HTTP_INVALID_SOCKET -1
+#define HTTP_EINTR EINTR
+#define HTTP_EINPROGRESS EINPROGRESS
+#define HTTP_EWOULDBLOCK EWOULDBLOCK
+#define HTTP_EALREADY EALREADY
+
+#define free_member(member) if((member)) { free(member); (member) = NULL; }
+#define close_socket(fd) if(fd != HTTP_INVALID_SOCKET) { socket_close(fd); fd = HTTP_INVALID_SOCKET; }
+#define close_file(pf) if(pf != NULL) { fclose(pf); pf = NULL; }
+
+#define RECV_BUF_SIZE 4 * 1024
+
+#define socket_close close
+
+
+enum parser_statue_e { PARSERD_NONE = 0, PARSERD_FIELD, PARSERD_VALUE, PARSERD_BODY };
+
+enum proto_type_e { PROTO_HTTP = 0, PROTO_HTTPS };
+ typedef enum http_request_method_e
+ {
+ M_GET = 0,
+ M_POST,
+ M_HEAD
+ } http_request_method_e;
+
+ typedef enum http_connent_method_e
+ {
+ M_CLOSE = 0,
+ M_KEEP,
+ } http_connent_method_e;
+
+ enum http_error_e
+ {
+ ERR_OK = 0,
+
+ ERR_INVALID_PARAM,
+ ERR_OUT_MEMORY,
+ ERR_OPEN_FILE,
+ ERR_PARSE_REP,
+ ERR_URL_INVALID,
+ ERR_URL_INVALID_PROTO,
+ ERR_URL_INVALID_HOST,
+ ERR_URL_INVALID_IP,
+ ERR_URL_RESOLVED_HOST,
+ ERR_SOCKET_CREATE = 10,
+ ERR_SOCKET_SET_OPT,
+ ERR_SOCKET_NOBLOCKING,
+ ERR_SOCKET_CONNECT,
+ ERR_SOCKET_CONNECT_TIMEOUT,
+ ERR_SOCKET_SELECT,
+ ERR_SOCKET_WRITE,
+ ERR_SOCKET_READ,
+ ERR_SOCKET_TIMEOUT,
+ ERR_SOCKET_CLOSED,
+ ERR_SOCKET_GET_OPT = 20,
+ ERR_SSL_CREATE_CTX,
+ ERR_SSL_CREATE_SSL,
+ ERR_SSL_SET_FD,
+ ERR_SSL_CONNECT,
+ ERR_SSL_WRITE,
+ ERR_SSL_READ,
+ ERR_NOCERT,
+ ERR_MSG
+ };
+
+ struct lynq_http_client_t;
+ typedef struct lynq_http_client_t lynq_http_client_t;
+ typedef int (*data_recv_cb_t)( lynq_http_client_t* http, const char* data, int size, int total, void* user);
+
+ typedef int socket_t;
+
+
+ struct lynq_http_client_t
+ {
+ int index;
+
+ char protocol[10];
+ int session;
+
+ char action[10];
+ char *data;
+ char *section;
+ int request_method;
+ int connent_method;
+ int sockfd;
+ int modify_thread;
+ int add_thread;
+
+ FILE* pf;
+ char* filename;
+ char* body;
+ char* redirect_url;
+ char* header_field;
+ char* header_value;
+
+ char* post_data;
+ char* url;
+ int post_data_len;
+ struct http_parser_url u;
+ char* user_header;
+ int user_header_len;
+
+ http_parser_settings parser_setting;
+ struct http_parser parser;
+
+
+ char* user;
+ data_recv_cb_t recv_cb;
+
+ unsigned long body_len;
+ unsigned long content_length;
+
+ enum http_request_method_e method;
+ enum http_connent_method_e conn_method;
+ enum proto_type_e proto_type;
+
+ unsigned short field_size;
+ unsigned short value_size;
+ unsigned short cur_field_size;
+ unsigned short cur_value_size;
+ SSL_CTX *ctx;
+ SSL *ssl;
+
+ socket_t fd;
+ int timeout;
+
+ short status_code;
+ char parser_statue;
+ char error_code;
+ unsigned cancel : 1;
+ unsigned exit : 1;
+ unsigned download : 1;
+ unsigned redirect : 1;
+};
+
+
+int lynq_http_init(void);
+lynq_http_client_t* lynq_http_new();
+void lynq_http_destroy(lynq_http_client_t* http);
+int lynq_http_get_error_code(lynq_http_client_t* http);
+const char* lynq_http_sync_request(lynq_http_client_t* http, const char* url, http_request_method_e m, http_connent_method_e c_m);
+const char* lynq_http_sync_post_request(lynq_http_client_t* http, char* url, char* post_data, http_request_method_e m, http_connent_method_e c_m);
+int lynq_http_sync_download_file(lynq_http_client_t* http, char* url, char* filepath, http_request_method_e m, http_connent_method_e c_m);
+int lynq_http_set_data_recv_cb(lynq_http_client_t* http, data_recv_cb_t cb, void* user);
+int lynq_http_exit(lynq_http_client_t* http);
+int lynq_http_data_send(char *data);
+void *lynq_http_write_head_data(lynq_http_client_t* http);
+#ifdef _cplusplus
+}
+#endif
+#endif
+
diff --git a/src/lynq/lib/liblynq-protcl/include/http/lynq_http_parser.h b/src/lynq/lib/liblynq-protcl/include/http/lynq_http_parser.h
new file mode 100644
index 0000000..99d9f20
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/include/http/lynq_http_parser.h
@@ -0,0 +1,220 @@
+#ifndef _LYNQ_HTTP_PARSER_H_
+#define _LYNQ_HTTP_PARSER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HTTP_PARSER_VERSION_MAJOR 2
+#define HTTP_PARSER_VERSION_MINOR 5
+#define HTTP_PARSER_VERSION_PATCH 0
+#include <stddef.h>
+#include <stdint.h>
+#include "liblog/liblog.h"
+#include "liblog/lynq_deflog.h"
+
+
+
+#ifndef HTTP_PARSER_STRICT
+# define HTTP_PARSER_STRICT 1
+#endif
+
+#ifndef HTTP_MAX_HEADER_SIZE
+# define HTTP_MAX_HEADER_SIZE (80*1024)
+#endif
+
+ typedef struct http_parser http_parser;
+ typedef struct http_parser_settings http_parser_settings;
+
+ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
+ typedef int (*http_cb) (http_parser*);
+
+
+ /* Request Methods */
+#define HTTP_METHOD_MAP(XX) \
+ XX(0, DELETE, DELETE) \
+ XX(1, GET, GET) \
+ XX(2, HEAD, HEAD) \
+ XX(3, POST, POST) \
+ XX(4, PUT, PUT) \
+ /* pathological */ \
+ XX(5, CONNECT, CONNECT) \
+ XX(6, OPTIONS, OPTIONS) \
+ XX(7, TRACE, TRACE) \
+ /* WebDAV */ \
+ XX(8, COPY, COPY) \
+ XX(9, LOCK, LOCK) \
+ XX(10, MKCOL, MKCOL) \
+ XX(11, MOVE, MOVE) \
+ XX(12, PROPFIND, PROPFIND) \
+ XX(13, PROPPATCH, PROPPATCH) \
+ XX(14, SEARCH, SEARCH) \
+ XX(15, UNLOCK, UNLOCK) \
+ XX(16, BIND, BIND) \
+ XX(17, REBIND, REBIND) \
+ XX(18, UNBIND, UNBIND) \
+ XX(19, ACL, ACL) \
+ /* subversion */ \
+ XX(20, REPORT, REPORT) \
+ XX(21, MKACTIVITY, MKACTIVITY) \
+ XX(22, CHECKOUT, CHECKOUT) \
+ XX(23, MERGE, MERGE) \
+ /* upnp */ \
+ XX(24, MSEARCH, M-SEARCH) \
+ XX(25, NOTIFY, NOTIFY) \
+ XX(26, SUBSCRIBE, SUBSCRIBE) \
+ XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
+ /* RFC-5789 */ \
+ XX(28, PATCH, PATCH) \
+ XX(29, PURGE, PURGE) \
+ /* CalDAV */ \
+ XX(30, MKCALENDAR, MKCALENDAR) \
+
+ enum http_method
+ {
+#define XX(num, name, string) HTTP_##name = num,
+ HTTP_METHOD_MAP(XX)
+#undef XX
+ };
+
+
+ enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
+ enum flags
+ { F_CHUNKED = 1 << 0
+ , F_CONNECTION_KEEP_ALIVE = 1 << 1
+ , F_CONNECTION_CLOSE = 1 << 2
+ , F_CONNECTION_UPGRADE = 1 << 3
+ , F_TRAILING = 1 << 4
+ , F_UPGRADE = 1 << 5
+ , F_SKIPBODY = 1 << 6
+ };
+
+#define HTTP_ERRNO_MAP(XX) \
+ /* No error */ \
+ XX(OK, "success") \
+ \
+ /* Callback-related errors */ \
+ XX(CB_message_begin, "the on_message_begin callback failed") \
+ XX(CB_url, "the on_url callback failed") \
+ XX(CB_header_field, "the on_header_field callback failed") \
+ XX(CB_header_value, "the on_header_value callback failed") \
+ XX(CB_headers_complete, "the on_headers_complete callback failed") \
+ XX(CB_body, "the on_body callback failed") \
+ XX(CB_message_complete, "the on_message_complete callback failed") \
+ XX(CB_status, "the on_status callback failed") \
+ XX(CB_chunk_header, "the on_chunk_header callback failed") \
+ XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
+ \
+ /* Parsing-related errors */ \
+ XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
+ XX(HEADER_OVERFLOW, \
+ "too many header bytes seen; overflow detected") \
+ XX(CLOSED_CONNECTION, \
+ "data received after completed connection: close message") \
+ XX(INVALID_VERSION, "invalid HTTP version") \
+ XX(INVALID_STATUS, "invalid HTTP status code") \
+ XX(INVALID_METHOD, "invalid HTTP method") \
+ XX(INVALID_URL, "invalid URL") \
+ XX(INVALID_HOST, "invalid host") \
+ XX(INVALID_PORT, "invalid port") \
+ XX(INVALID_PATH, "invalid path") \
+ XX(INVALID_QUERY_STRING, "invalid query string") \
+ XX(INVALID_FRAGMENT, "invalid fragment") \
+ XX(LF_EXPECTED, "LF character expected") \
+ XX(INVALID_HEADER_TOKEN, "invalid character in header") \
+ XX(INVALID_CONTENT_LENGTH, \
+ "invalid character in content-length header") \
+ XX(INVALID_CHUNK_SIZE, \
+ "invalid character in chunk size header") \
+ XX(INVALID_CONSTANT, "invalid constant string") \
+ XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
+ XX(STRICT, "strict mode assertion failed") \
+ XX(PAUSED, "parser is paused") \
+ XX(UNKNOWN, "an unknown error occurred")
+
+#define HTTP_ERRNO_GEN(n, s) HPE_##n,
+ enum http_errno {
+ HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
+ };
+#undef HTTP_ERRNO_GEN
+
+#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
+
+ struct http_parser {
+ unsigned int type : 2; /* enum http_parser_type */
+ unsigned int flags : 7; /* F_* values from 'flags' enum; semi-public */
+ unsigned int state : 7; /* enum state from http_parser.c */
+ unsigned int header_state : 8; /* enum header_state from http_parser.c */
+ unsigned int index : 8; /* index into current matcher */
+
+ uint32_t nread; /* # bytes read in various scenarios */
+ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
+
+ unsigned short http_major;
+ unsigned short http_minor;
+ unsigned int status_code : 16;
+ unsigned int method : 8;
+ unsigned int http_errno : 7;
+ unsigned int upgrade : 1;
+ void *data;
+ };
+
+
+ struct http_parser_settings {
+ http_cb on_message_begin;
+ http_data_cb on_url;
+ http_data_cb on_status;
+ http_data_cb on_header_field;
+ http_data_cb on_header_value;
+ http_cb on_headers_complete;
+ http_data_cb on_body;
+ http_cb on_message_complete;
+ http_cb on_chunk_header;
+ http_cb on_chunk_complete;
+ };
+
+
+ enum http_parser_url_fields
+ {
+ UF_SCHEMA = 0,
+ UF_HOST = 1,
+ UF_PORT = 2,
+ UF_PATH = 3,
+ UF_QUERY = 4,
+ UF_FRAGMENT = 5,
+ UF_USERINFO = 6,
+ UF_MAX = 7,
+ };
+
+ struct http_parser_url {
+ uint16_t field_set; /* Bitmask of (1 << UF_*) values */
+ uint16_t port; /* Converted UF_PORT string */
+
+ struct {
+ uint16_t off; /* Offset into buffer in which field starts */
+ uint16_t len; /* Length of run in buffer */
+ } field_data[UF_MAX];
+ };
+
+ unsigned long http_parser_version(void);
+ void http_parser_init(http_parser *parser, enum http_parser_type type);
+ void http_parser_settings_init(http_parser_settings *settings);
+ size_t http_parser_execute(http_parser *parser,
+ const http_parser_settings *settings,
+ const char *data,
+ size_t len);
+
+ int http_should_keep_alive(const http_parser *parser);
+ const char *http_method_str(enum http_method m);
+ const char *http_errno_name(enum http_errno err);
+ const char *http_errno_description(enum http_errno err);
+ int http_parser_parse_url(const char *buf, size_t buflen,
+ int is_connect,
+ struct http_parser_url *u);
+ void http_parser_pause(http_parser *parser, int paused);
+ int http_body_is_final(const http_parser *parser);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/lynq/lib/liblynq-protcl/include/http/lynq_msgq.h b/src/lynq/lib/liblynq-protcl/include/http/lynq_msgq.h
new file mode 100644
index 0000000..784e077
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/include/http/lynq_msgq.h
@@ -0,0 +1,19 @@
+#ifndef _LYNQ_MSGQ_H_
+#define _LYNQ_MSGQ_H_
+
+#include <sys/msg.h>
+#include <sys/ipc.h>
+#include "liblog/liblog.h"
+#include "liblog/lynq_deflog.h"
+#include "http/lynq_http.h"
+
+struct mymesg{
+ long int mtype;
+ char mtext[512];
+};
+
+int lynq_msgq_init(char *pathname, int create);
+int lynq_msgq_send(int queueId, struct mymesg *ckxmsg);
+
+#endif
+
diff --git a/src/lynq/lib/liblynq-protcl/include/lynq_mqtt/lynq_mqtt.h b/src/lynq/lib/liblynq-protcl/include/lynq_mqtt/lynq_mqtt.h
new file mode 100644
index 0000000..0422faa
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/include/lynq_mqtt/lynq_mqtt.h
@@ -0,0 +1,70 @@
+#ifndef __LYNQ_MQTT_H__
+#define __LYNQ_MQTT_H__
+#include <mosquitto.h>
+
+
+struct mqtt_set_will{
+ int will_flag;
+ char *will_topic;
+ int will_payloadlen;
+ char *will_payload;
+ int will_qos;
+ bool retain;
+};
+
+struct mqtt_set_parament
+{
+ char *protocol;
+ int session;
+ char *action;
+ int modify_thread;
+ int add_thread;
+
+ char *usrname; //服务端用户名
+ char *pwd; //服务端密码
+ char *ip_addr;
+ int port;
+ int keep_time;
+
+ int subscribe_qos;
+ int publish_qos;
+
+ char *subscribe_topic;
+ char *unsubscribe_topic; //lt add @2021.7.13 for unsubscribe topic
+
+ char *publish_topic;
+ char *publish_data;
+
+ char *client_id;
+ bool clean_session;
+
+ struct mqtt_set_will set_will;
+
+};
+
+
+#define NO_ERROR 0
+#define CREATE_LIENT_ERROR 1
+#define USER_PWD_ERROR 2
+#define CONNECT_FAIL 3
+#define CREATE_LOOP_FAIL 4
+#define MQTT_DISCONNECT_FAIL 5
+#define MQTT_CONNECT_FAIL 6
+
+
+int lynq_mqtt_connect_init(struct mqtt_set_parament mqtt_message);
+void lynq_mosquitto_set_connect_callback(void (*connect_callback)(struct mosquitto *mosq, void *userdata, int result));
+void lynq_mosquitto_set_message_callback(void (*message_callback)(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message));
+void lynq_mosquitto_set_subscribe_callback(void (*subscribe_callback)(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos));
+void lynq_mosquitto_set_disconnect_callback( void (*disconnect_callback)( struct mosquitto *mosq,void *obj, int rc));
+void lynq_mosquitto_set_publish_callback(void (*on_publish)(struct mosquitto *mosq, void *obj, int mid));
+
+void lynq_mosquitto_publish_message(char *pub_topic,int pub_buf_len,char *pub_buf,int qos); //发布
+void lynq_mosquitto_subscribe_message(char *sub_topic,int sub_qos); // 订阅
+void lynq_mosquitto_disconnect(void); //断开
+
+int lynq_mqtt_login(struct mqtt_set_parament mqtt_message);
+void lynq_mosquitto_subscribe_message(char *sub_topic,int sub_qos);
+void lynq_mosquitto_publish_message(char *pub_topic,int pub_buf_len,char *pub_buf,int qos);
+void lynq_mosquitto_unsubscribe_message(char *unsub_topic);
+#endif //__LYNQ_MQTT_H__
diff --git a/src/lynq/lib/liblynq-protcl/lynq_mqtt/lynq_mqtt.c b/src/lynq/lib/liblynq-protcl/lynq_mqtt/lynq_mqtt.c
new file mode 100644
index 0000000..a7380ae
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/lynq_mqtt/lynq_mqtt.c
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "lynq_mqtt/lynq_mqtt.h"
+#include "liblog/lynq_deflog.h"
+
+#define HOST "58.246.1.50" // IP
+#define PORT 63743
+
+#define KEEP_ALIVE 60
+
+
+static int mqtt_session = 0;
+
+
+void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
+{
+ char *str_payload = NULL;
+ if(message->payloadlen){
+ LYVERBLOG("+[mqtt][message%d]: topic:%s---data:%s\n",mqtt_session,message->topic, (char *)message->payload);//lt mod @2021.7.13 for mqtt_session
+ str_payload = malloc(message->payloadlen);
+ memset(str_payload,0,message->payloadlen);
+ memcpy(str_payload,message->payload,message->payloadlen);
+printf("0x:");//lt add @2021.7.13 for debug
+for(int i = 0; i < (message->payloadlen); i++)
+{
+printf(" %02x",str_payload[i]);
+}
+printf("\n");
+ free(str_payload);
+ str_payload = NULL;
+ }else{
+ LYVERBLOG("+[mqtt][message%d]: %s (null)\n",mqtt_session,message->topic); //lt mod @2021.7.13 for mqtt_session
+ }
+}
+
+void my_connect_callback(struct mosquitto *mosq, void *userdata, int result)
+{
+ int i;
+ if(!result){
+ LYVERBLOG("+[mqtt][connect][session%d]: ok!!\n", mqtt_session);
+ }else{
+ LYVERBLOG("+[mqtt][connect][session%d]: error num = %d\n", mqtt_session,MQTT_CONNECT_FAIL);
+ }
+}
+
+void my_disconnect_callback(struct mosquitto *mosq, void *userdata, int result)
+{
+ int i;
+ if(!result){
+ LYVERBLOG("+[mqtt][disconnect][session%d]: ok!!\n", mqtt_session);
+ }else{
+ LYVERBLOG("+[mqtt][disconnect][session%d]: error num = %d\n", mqtt_session,MQTT_DISCONNECT_FAIL);
+ }
+}
+
+void my_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos)
+{
+ LYVERBLOG("+[mqtt][subscribe][session%d]: ok!!\n", mqtt_session);
+}
+
+void my_unsubscribe_callback(struct mosquitto *mosq, void *obj, int mid)//lt add @2021.7.13 for unsubscribe callback function
+{
+ LYVERBLOG("+[mqtt][unsubscribe][session%d]: ok!!\n", mqtt_session);
+}
+
+void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
+{
+ LYVERBLOG("+[mqtt][publish][session%d]: ok!!\n", mqtt_session);
+}
+
+struct mosquitto *mosq = NULL;
+
+void lynq_mosquitto_set_message_callback(void (*message_callback)(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message))
+{
+ mosquitto_message_callback_set(mosq, message_callback);
+}
+
+
+void lynq_mosquitto_set_connect_callback(void (*connect_callback)(struct mosquitto *mosq, void *userdata, int result))
+{
+ mosquitto_connect_callback_set(mosq, connect_callback);
+}
+void lynq_mosquitto_set_subscribe_callback(void (*subscribe_callback)(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos))
+{
+ mosquitto_subscribe_callback_set(mosq, subscribe_callback); //lt mod @2021.7.13 for deleate my_subscribe_callback add subscribe_callback
+}
+
+void lynq_mosquitto_set_unsubscribe_callback(void (*on_unsubscribe)(struct mosquitto *mosq, void *obj, int mid)) //lt add @2021.7.13 for set unsubscribe callback function
+{
+ mosquitto_unsubscribe_callback_set(mosq,on_unsubscribe);
+}
+
+void lynq_mosquitto_set_publish_callback(void (*on_publish)(struct mosquitto *mosq, void *obj, int mid))
+{
+ mosquitto_publish_callback_set(mosq,on_publish);
+}
+
+void lynq_mosquitto_set_disconnect_callback( void (*disconnect_callback)( struct mosquitto *mosq,void *obj, int rc))
+{
+ mosquitto_disconnect_callback_set(mosq,disconnect_callback);
+}
+int lynq_mqtt_connect_init(struct mqtt_set_parament mqtt_message)
+{
+
+ int ret;
+ //libmosquitto ¿â³õʼ»¯
+ mosquitto_lib_init();
+
+ if(mqtt_message.client_id != NULL)
+ {
+ mosq = mosquitto_new(mqtt_message.client_id,mqtt_message.clean_session,NULL);//´´½¨mosquitto¿Í»§¶Ë
+ }else{
+ mosq = mosquitto_new(NULL,true,NULL);//´´½¨mosquitto¿Í»§¶Ë
+ }
+
+ if(!mosq){
+ LYVERBLOG("+[mqtt][init][session%d]: error num = %d\n", mqtt_message.session,CREATE_LIENT_ERROR);
+ mosquitto_lib_cleanup();
+ return CREATE_LIENT_ERROR;
+ }
+
+
+ lynq_mosquitto_set_connect_callback(my_connect_callback);
+ lynq_mosquitto_set_message_callback(my_message_callback);
+ lynq_mosquitto_set_subscribe_callback(my_subscribe_callback);
+ lynq_mosquitto_set_unsubscribe_callback(my_unsubscribe_callback); //lt add @2021.7.13 for set unsubscribe callback
+ lynq_mosquitto_set_disconnect_callback(my_disconnect_callback);
+ lynq_mosquitto_set_publish_callback(my_publish_callback);
+
+ // ÉèÖÃÁ¬½ÓµÄÓû§ÃûÓëÃÜÂë:£¬
+ // ²ÎÊý£º¾ä±ú¡¢Óû§Ãû¡¢ÃÜÂë
+ ret = mosquitto_username_pw_set(mosq, mqtt_message.usrname, mqtt_message.pwd);
+ if(ret){
+// LYVERBLOG("+[mqtt][init]: set username and password error!\n");
+ LYVERBLOG("+[mqtt][init][session%d]: error num = %d\n", mqtt_message.session,USER_PWD_ERROR);
+ mosquitto_destroy(mosq);
+ mosquitto_lib_cleanup();
+ return USER_PWD_ERROR;
+ }
+
+ if(mqtt_message.set_will.will_flag == 1)
+ {
+ mosquitto_will_set( mosq,mqtt_message.set_will.will_topic,mqtt_message.set_will.will_payloadlen,mqtt_message.set_will.will_payload,mqtt_message.set_will.will_qos,mqtt_message.set_will.retain);
+ }
+ //Á¬½Ó·þÎñÆ÷
+ if(mosquitto_connect(mosq, mqtt_message.ip_addr, mqtt_message.port, mqtt_message.keep_time)){
+// LYVERBLOG("+[mqtt][init]: unable to connect!\n");
+ LYVERBLOG("+[mqtt][init][session%d]: error num = %d\n", mqtt_message.session,CONNECT_FAIL);
+ return CONNECT_FAIL;
+ }
+ //¿ªÆôÒ»¸öỊ̈߳¬ÔÚÏß³ÌÀﲻͣµÄµ÷Óà mosquitto_loop() À´´¦ÀíÍøÂçÐÅÏ¢
+ int loop = mosquitto_loop_start(mosq);
+ if(loop != MOSQ_ERR_SUCCESS)
+ {
+// LYVERBLOG("+[mqtt][init]: mosquitto loop error\n");
+ LYVERBLOG("+[mqtt][init][session%d]: error num = %d\n", mqtt_message.session,CREATE_LOOP_FAIL);
+ return CREATE_LOOP_FAIL;
+ }
+ return NO_ERROR;
+}
+
+void lynq_mosquitto_publish_message(char *pub_topic,int pub_buf_len,char *pub_buf,int qos)
+{
+ mosquitto_publish(mosq,NULL,pub_topic,pub_buf_len,pub_buf,qos,0);
+}
+
+void lynq_mosquitto_subscribe_message(char *sub_topic,int sub_qos)
+{
+ mosquitto_subscribe(mosq, NULL, sub_topic, sub_qos);
+}
+
+void lynq_mosquitto_unsubscribe_message(char *unsub_topic) //lt add @2021.7.13 for unsubscribe function
+{
+ mosquitto_unsubscribe(mosq,NULL,unsub_topic);
+}
+
+void lynq_mosquitto_disconnect(void)
+{
+ mosquitto_disconnect(mosq);
+}
+
+#if 1
+struct mqtt_set_parament mqtt_set_data;
+void factory_mqtt_test(void)
+{
+ char buff[10] = {"123456789"};
+ buff[10] = '\0';
+
+ mqtt_set_data.usrname = "admin";
+ mqtt_set_data.pwd = "password";
+ mqtt_set_data.ip_addr = HOST;
+ mqtt_set_data.port = PORT;
+ mqtt_set_data.keep_time = KEEP_ALIVE;
+
+
+ lynq_mqtt_connect_init(mqtt_set_data);
+
+ lynq_mosquitto_set_connect_callback(my_connect_callback);
+ lynq_mosquitto_set_message_callback(my_message_callback);
+ lynq_mosquitto_set_subscribe_callback(my_subscribe_callback);
+ lynq_mosquitto_set_disconnect_callback(my_disconnect_callback);
+ lynq_mosquitto_set_publish_callback(my_publish_callback);
+
+ lynq_mosquitto_subscribe_message("/S2C/DATA ",2);
+
+ for(int i = 1000; i > 1; i--)
+ {
+ if((i % 10) == 0)
+ {
+ /*·¢²¼ÏûÏ¢*/
+ lynq_mosquitto_publish_message("/S2C/DATA ",10,buff,0);
+ }
+ sleep(1);
+ memset(buff,0,10);
+ }
+}
+#endif
+
+
+int lynq_mqtt_login(struct mqtt_set_parament mqtt_message)
+{
+ mqtt_session = mqtt_message.session;
+ lynq_mqtt_connect_init(mqtt_message);
+}
+
diff --git a/src/lynq/lib/liblynq-protcl/makefile b/src/lynq/lib/liblynq-protcl/makefile
new file mode 100644
index 0000000..e7018b4
--- /dev/null
+++ b/src/lynq/lib/liblynq-protcl/makefile
@@ -0,0 +1,94 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+ -std=gnu++14 \
+ -g -Os \
+ -flto \
+ -DRIL_SHLIB \
+ -DATCI_PARSE \
+ -DKEEP_ALIVE \
+ -DECALL_SUPPORT \
+ -fpermissive \
+
+$(warning ################# C2K support: $(RAT_CONFIG_C2K_SUPPORT))
+ifeq ($(strip $(RAT_CONFIG_C2K_SUPPORT)), yes)
+ LOCAL_CFLAGS += -DC2K_SUPPORT
+
+endif
+
+ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), dsds)
+ LOCAL_CFLAGS += -DANDROID_SIM_COUNT_2 \
+ -DANDROID_MULTI_SIM \
+ -DMODE_DSDS
+endif
+
+ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), dsss)
+ LOCAL_CFLAGS += -DMODE_DSSS
+endif
+
+$(warning ################# TARGET_PLATFORM: $(TARGET_PLATFORM))
+ifeq ($(strip $(TARGET_PLATFORM)), mt2731)
+#$(warning #################add for debug $(ROOT), $(includedir))
+$(warning ################# TARGET_PLATFORM_MT2731)
+ LOCAL_CFLAGS += -DTARGET_PLATFORM_MT2731 \
+ -DMD_93_SUPPORT
+else ifeq ($(strip $(TARGET_PLATFORM)), mt2635)
+$(warning ################# TARGET_PLATFORM_MT2635)
+ LOCAL_CFLAGS += -DTARGET_PLATFORM_MT2635 \
+ -DMD_90_SUPPORT
+endif
+
+$(warning ################# RITA ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH = .
+
+LOCAL_C_INCLUDES = \
+ -I. \
+ -I$(ROOT)$(includedir)/openssl \
+ -I$(ROOT)$(includedir)/liblog \
+ -I$(LOCAL_PATH)/include \
+
+
+LOCAL_LIBS := \
+ -L. \
+ -ldl \
+ -lpthread \
+ -llynq-log \
+ -lssl \
+ -lcrypto \
+ -lmosquitto \
+
+SOURCES = $(wildcard *.c wildcard *.h ftp/*.c http/src/*.c lynq_mqtt/*.c)
+
+EXECUTABLE = liblynq-protcl.so
+
+OBJECTS=$(SOURCES:.c=.o)
+
+
+.PHONY: build clean install pack_rootfs
+
+all: build
+$(EXECUTABLE): $(OBJECTS)
+ $(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.c
+ $(CC) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build: $(EXECUTABLE)
+ $(warning ########## build $(EXECUTABLE) ##########)
+
+install:
+ mkdir -p $(ROOT)$(base_libdir)/
+ install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+ mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+
+pack_rootfs:
+ mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+ cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+ $(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+ mkdir -p $(PACK_TO)$(base_libdir)/
+ cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+ $(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+ $(RM) $(OBJECTS) $(EXECUTABLE)