#define _XOPEN_SOURCE
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#define min(a,b) (a)<(b)?(a):(b)
#define local_path "xxx"
#define account "xxx"
#define password "xxx"
char cookie[1024] = {0};
int cookieLen = 0;
int readline_sock_ssl(SSL *ssl,char* RecvData,int RecvLen)
{
char tmp;
int len = 0;
int ret;
while(len < RecvLen && (ret = SSL_read(ssl,&tmp,1)) == 1)
{
if(tmp == '\r'||tmp == '\n')
break;
memcpy(RecvData + len,&tmp,1);
len += 1;
}
if(ret < 0)
{
return ret;
}
else if(ret == 0)
{
return -1;
}
else if(len >= RecvLen)
{
return -1;
}
else if(tmp == '\r')
{
ret = SSL_read(ssl,&tmp,1);
if(ret != 1)
{
return -1;
}
else
{
return len;
}
}
else if(tmp == '\n')
{
return len;
}
}
int readbytes_sock_ssl(SSL *ssl,char* RecvData,int RecvLen)
{
int len = 0,ret = 0;
while(len < RecvLen && (ret = SSL_read(ssl,RecvData + len,RecvLen - len)) > 0)
{
len += ret;
}
if(ret < 0)
return ret;
return len;
}
int readline_sock(int sockfd,char* RecvData,int RecvLen)
{
char tmp;
int len = 0;
int ret;
while(len < RecvLen && (ret = recv(sockfd,&tmp,1,0)) == 1)
{
if(tmp == '\r' || tmp == '\n')
break;
memcpy(RecvData + len,&tmp,1);
len += 1;
}
if(ret < 0)
{
return ret;
}
else if(ret == 0)
{
return -1;
}
else if(len >= RecvLen)
{
return -1;
}
else if(tmp == '\r')
{
ret = recv(sockfd,&tmp,1,0);
if(ret != 1)
{
return -1;
}
else
{
return len;
}
}
else if(tmp == '\n')
{
return len;
}
}
int readbytes_sock(int sockfd,char* RecvData,int RecvLen)
{
int len = 0,ret = 0;
while(len < RecvLen && (ret = recv(sockfd,RecvData + len,RecvLen - len,0)) > 0)
{
len += ret;
}
if(ret < 0)
return ret;
return len;
}
int connect_host_ssl(SSL* ssl,char *sInData, int iInLen, char *sOutData, int iOutSize,char *response_code,int saveCookie)
{
char tmp[4096];
int retu,len,recv_len = 0;
char *index;
char name[100],value[300];
int flag = 0;
char content_length[20] = {0};
len = SSL_write(ssl, sInData, iInLen);
if (len < 0)
{
retu = -1;
goto finish;
}
memset(tmp,0,sizeof(tmp));
retu = 0;
retu = readline_sock_ssl(ssl,tmp,sizeof(tmp));
if(retu < 0)
goto finish;
index = strchr(tmp,' ');
if(index == NULL)
{
retu = -1;
goto finish;
}
strncpy(response_code,index + 1,3);
do
{
memset(tmp,0,sizeof(tmp));
retu = readline_sock_ssl(ssl,tmp,sizeof(tmp));
if(retu <= 0)break;
memset(name,0,sizeof(name));
memset(value,0,sizeof(value));
index = strchr(tmp,':');
if(index == NULL)
{
retu = -1;
break;
}
strncpy(name,tmp,index - tmp);
if(*(index+1) == ' ')
index += 2;
else
index += 1;
strcpy(value,index);
printf("name:[%s] value[%s]\n",name,value);
if(strcasecmp(name,"Set-Cookie") == 0)
{
if(saveCookie)
{
if(strstr(value,"deleted") != NULL)
continue;
index = strchr(value,';');
strncpy(cookie + cookieLen,value,index - value);
cookieLen += (index - value);
strcpy(cookie + cookieLen,"; ");
cookieLen += 2;
}
else
continue;
}
else if(strcasecmp(name,"Transfer-Encoding") == 0)
{
flag = 1;
}
else if(strcasecmp(name,"Content-Length") == 0)
{
flag = 2;
strncpy(content_length,value,min(sizeof(content_length),strlen(value)));
}
else
{
setenv(name,value,1);
}
}while(1);
if(saveCookie && cookieLen > 2&& strcmp(&cookie[cookieLen - 2],"; ") == 0)
{
cookieLen -= 2;
cookie[cookieLen] = 0x00;
}
printf("cookie[%s]\n",cookie);
if(retu < 0)
{
goto finish;
}
recv_len = 0;
//index = NULL;
//index = getenv("Transfer-Encoding");
//if(index != NULL && strcasecmp(index,"chunked") == 0)
if(flag == 1)
{
while(1)
{
memset(tmp,0,sizeof(tmp));
retu = readline_sock_ssl(ssl,tmp,sizeof(tmp));
if(retu <= 0)
{
retu = -1;
goto finish;
}
len = 0;
sscanf(tmp,"%x",&len);
if(len == 0)
{
//finish read
break;
}
printf("read bytes[%d]\n",len);
memset(tmp,0,sizeof(tmp));
if(len >=sizeof(tmp))
{
retu = -1;
goto finish;
}
retu = readbytes_sock_ssl(ssl,tmp,len);
if(retu < 0)
goto finish;
printf("have read [%d]\n",retu);
if(retu != len)
{
retu = -1;
goto finish;
}
else
{
if(recv_len + len >= iOutSize)
{
retu = -1;
goto finish;
}
memcpy(sOutData + recv_len,tmp,len);
recv_len += len;
}
memset(tmp,0,sizeof(tmp));
retu = readline_sock_ssl(ssl,tmp,sizeof(tmp));
if(retu < 0)
goto finish;
if(retu == 0)
continue;
else
{
retu = -1;
goto finish;
}
}
if(len == 0) retu = recv_len;
goto finish;
}
//index = NULL;
//index = getenv("Content-Length");
//if(index != NULL)
if(flag == 2)
{
index = content_length;
len = 0;
len = atol(index);
printf("read bytes[%d]\n",len);
if(len >= iOutSize)
{
retu = -1;
goto finish;
}
else
{
retu = readbytes_sock_ssl(ssl,sOutData,len);
if(retu < 0)
goto finish;
printf("have read[%d]\n",retu);
if(retu != len)
{
retu = -1;
goto finish;
}
goto finish;
}
}
finish:
//unsetenv("Transfer-Encoding");
//unsetenv("Content-Length");
if(errno == ETIMEDOUT || errno == 11)//ETIMEDOUT //Resource temporarily unavailable
retu = -19;
/*
if(ssl)
{
SSL_shutdown(ssl);
SSL_free(ssl);
}
if(sockfd)
close(sockfd);
if(ctx)
SSL_CTX_free(ctx);
*/
return retu;
}
int connect_host(int sockfd,char *sInData, int iInLen, char *sOutData, int iOutSize,char *response_code,int saveCookie)
{
char tmp[4096];
int retu,len,recv_len = 0;
char *index;
char name[100],value[300];
int flag;
char content_length[20] = {0};
len = send(sockfd, sInData, iInLen,0);
if (len < 0)
{
//close(sockfd);
//return -1;
retu = -1;
goto finish;
}
memset(tmp,0,sizeof(tmp));
recv_len = 0;
len = 0;
retu = 0;
retu = readline_sock(sockfd,tmp,sizeof(tmp));
if(retu < 0)
goto finish;
index = strchr(tmp,' ');
if(index == NULL)
{
retu = -1;
goto finish;
}
strncpy(response_code,index + 1,3);
do
{
memset(tmp,0,sizeof(tmp));
retu = readline_sock(sockfd,tmp,sizeof(tmp));
if(retu <= 0)break;
memset(name,0,sizeof(name));
memset(value,0,sizeof(value));
index = strchr(tmp,':');
if(index == NULL) break;
strncpy(name,tmp,index - tmp);
if(*(index+1) == ' ')
index += 2;
else
index += 1;
strcpy(value,index);
printf("name:[%s] value[%s]\n",name,value);
if(strcasecmp(name,"Set-Cookie") == 0)
{
if(saveCookie)
{
if(strstr(value,"deleted") != NULL)
continue;
index = strchr(value,';');
strncpy(cookie + cookieLen,value,index - value);
cookieLen += (index - value);
strcpy(cookie + cookieLen,"; ");
cookieLen += 2;
}
else
continue;
}
else if(strcasecmp(name,"Transfer-Encoding") == 0)
{
flag = 1;
}
else if(strcasecmp(name,"Content-Length") == 0)
{
flag = 2;
strncpy(content_length,value,min(sizeof(content_length),strlen(value)));
}
else
{
setenv(name,value,1);
}
}while(1);
if(saveCookie && cookieLen > 2&& strcmp(&cookie[cookieLen - 2],"; ") == 0)
{
cookieLen -= 2;
cookie[cookieLen] = 0x00;
}
printf("cookie[%s]\n",cookie);
if(retu < 0)
{
goto finish;
}
recv_len = 0;
//index = NULL;
//index = getenv("Transfer-Encoding");
//if(index != NULL && strcasecmp(index,"chunked") == 0)
if(flag == 1)
{
len = 0;
while(1)
{
memset(tmp,0,sizeof(tmp));
retu = readline_sock(sockfd,tmp,sizeof(tmp));
if(retu <= 0)
{
retu = -1;
goto finish;
}
len = 0;
sscanf(tmp,"%x",&len);
printf("read bytes[%d]\n",len);
if(len == 0)
{
//printf("finish\n");
break;
}
memset(tmp,0,sizeof(tmp));
if(len >=sizeof(tmp))
{
retu = -1;
goto finish;
}
retu = readbytes_sock(sockfd,tmp,len);
if(retu < 0)
goto finish;
printf("have read[%d]\n",retu);
if(retu != len)
{
retu = -1;
goto finish;
}
else
{
if(recv_len + len >= iOutSize)
{
retu = -1;
goto finish;
}
memcpy(sOutData + recv_len,tmp,len);
recv_len += len;
}
memset(tmp,0,sizeof(tmp));
retu = readline_sock(sockfd,tmp,sizeof(tmp));
if(retu < 0)
goto finish;
if(retu == 0)
continue;
else
{
retu = -1;
goto finish;
}
}
if(len == 0) retu = recv_len;
goto finish;
}
//index = NULL;
//index = getenv("Content-Length");
//if(index != NULL)
if(flag == 2)
{
index = content_length;
len = 0;
len = atoi(index);
printf("read bytes[%d]\n",len);
if(len >= iOutSize)
{
retu = -1;
goto finish;
}
else
{
retu = readbytes_sock(sockfd,sOutData,len);
if(retu < 0)
goto finish;
printf("have read[%d]\n",len);
if(retu < len)
{
retu = -1;
goto finish;
}
goto finish;
}
}
finish:
//unsetenv("Transfer-Encoding");
//unsetenv("Content-Length");
if(errno == ETIMEDOUT || errno == 11)//ETIMEDOUT //Resource temporarily unavailable
retu = -19;
if(sockfd)
close(sockfd);
return retu;
}
static void active_nonblock(int sock)
{
int ret;
int flags = fcntl(sock,F_GETFL);
if(flags == -1)
return;
flags|=O_NONBLOCK;
ret = fcntl(sock,F_SETFL,flags);
if(ret == -1)
return ;
}
static void deactive_nonblock(int sock)
{
int ret;
int flags = fcntl(sock,F_GETFL);
if(flags == -1)
return ;
flags &= (~O_NONBLOCK);
ret = fcntl(sock,F_SETFL,flags);
if(ret == -1)
return;
}
int startup(char* host,int port,unsigned int wait_second)
{
struct hostent* phost = NULL;
struct sockaddr_in sin;
char **ptr;
int sockfd;
int ret;
phost = gethostbyname(host);
if(phost == NULL)
return -1;
for(ptr = phost->h_addr_list;*ptr != NULL;ptr++)
{
printf("%s\n",inet_ntoa(*(struct in_addr*)ptr));
sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
memcpy(&sin.sin_addr,*ptr,phost->h_length);
if(wait_second > 0)
active_nonblock(sockfd);
ret = connect(sockfd,(struct sockaddr*)&sin,sizeof(sin));
if(ret < 0&&errno == EINPROGRESS)//in nonblock state,ret =-1 no mean connect fail
{
fd_set rfds;
struct timeval timeout;
FD_ZERO(&rfds);
FD_SET(sockfd,&rfds);
timeout.tv_sec = wait_second;
timeout.tv_usec = 0;
do
{
ret = select(sockfd+1,NULL,&rfds,NULL,&timeout);
printf("select [%d] errno[%d] [%s]\n",ret,errno,strerror(errno));
}while(ret < 0&&errno == EINTR);
if(ret == 0)
{
errno = ETIMEDOUT;
ret = -1;
}
else //if(ret < 0)
{
int err;
int socklen = sizeof(err);
int socketerr = getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&err,&socklen);
if(socketerr == -1)
{
ret = -1;
}
if(err == 0)
ret = 0;
else
{
errno = err;
ret = -1;
}
}
}
if(wait_second > 0)
deactive_nonblock(sockfd);
printf("select finish [%d] errno[%d] [%s]\n",ret,errno,strerror(errno));
if(ret == 0)
{
errno = 0;
break;
}
}
printf("finish %d %s\n",errno,strerror(errno));
if(ret < 0)
return -1;
else
return sockfd;
}
SSL* startup_ssl(char* host,int port,unsigned int wait_second)
{
int sockfd;
const SSL_METHOD *meth;
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
/* SSL 库初始化,参看 ssl-server.c 代码 */
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
meth = TLSv1_client_method();
//meth = SSLv3_client_method();
//申请SSL会话的环境
ctx = SSL_CTX_new(meth);
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
return NULL;
}
sockfd = startup(host,port,wait_second);
printf("sockfd %d %d %s\n",sockfd,errno,strerror(errno));
if(sockfd < 0)
{
SSL_CTX_free(ctx);
ctx = NULL;
return NULL;
}
else
{
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
/* 建立 SSL 连接 */
if (SSL_connect(ssl) == -1){
ERR_print_errors_fp(stderr);
SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
ctx = NULL;
ssl = NULL;
return NULL;
}
else
{
SSL_CTX_free(ctx);
ctx = NULL;
return ssl;
}
}
}
int pack_GET_model(char *source,char *outdata,char* host,char * requestFunction,char *cookie,int ifClose)
{
int len = 0;
if(source != NULL && source[0] != 0x00)
len = sprintf(outdata, "GET %s?%s HTTP/1.1\r\n",requestFunction,source);
else
len = sprintf(outdata, "GET %s HTTP/1.1\r\n",requestFunction);
strcpy(outdata+len, "Host: ");
len+= 6;
strcpy(outdata+len,host);
len+=strlen(host);
strcpy(outdata+len,"\r\n");
len+=2;
strcpy(outdata+len, "Accept: text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8\r\n");
len+= 78;
if(ifClose)
{
strcpy(outdata+len, "Connection: close\r\n");
len+= 19;
}
else
{
strcpy(outdata+len, "Connection: keep-alive\r\n");
len += 24;
}
if(cookie != NULL && cookie[0] != 0x00)
{
len += sprintf(outdata+len, "Cookie: %s\r\n",cookie);
}
strcpy(outdata+len, "Accept-Language: zh-Hans-CN, zh-Hans; q=0.8, en-US; q=0.5, en; q=0.3\r\n");
len+= 70;
strcpy(outdata+len, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134\r\n");
len+= 143;
strcpy(outdata+len, "\r\n");
len+=2;
return len;
}
int pack_POST_model(char *source,char *outdata,char* host,char * requestFunction,char *cookie,char* Content_Type,int ifClose)
{
int len = 0,source_len = strlen(source);
len = sprintf(outdata, "POST %s HTTP/1.1\r\n",requestFunction);
len += sprintf(outdata+len, "Host: %s\r\n",host);
len += sprintf(outdata+len, "Content-Length: %d\r\n",source_len);
//strcpy(outdata+len, "Accept: text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8\r\n");
//len+= 78;
if(ifClose)
{
strcpy(outdata+len, "Connection: close\r\n");
len+= 19;
}
else
{
strcpy(outdata+len, "Connection: keep-alive\r\n");
len += 24;
}
strcpy(outdata+len, "Accept-Language: zh-Hans-CN, zh-Hans; q=0.8, en-US; q=0.5, en; q=0.3\r\n");
len+= 70;
strcpy(outdata+len, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134\r\n");
len+= 143;
len += sprintf(outdata+len, "Content-Type: %s\r\n",Content_Type);
if(cookie != NULL && cookie[0] != 0x00)
{
len += sprintf(outdata+len, "Cookie: %s\r\n",cookie);
}
strcpy(outdata+len, "\r\n");
len+=2;
strcpy(outdata+len, source);
len+=source_len;
strcpy(outdata+len, "\r\n");
len+=2;
return len;
}
int analysize_url(char *url,char *host,int* port,char* path,char* data)
{
char * index = NULL,*index2 = NULL;
if(memcmp(url,"https",5) == 0)
{
*port = 443;
}
else
{
*port = 80;
}
index = strstr(url,"//");
if(index == NULL) return -1;
index += 2;
index2 = strchr(index,'/');
if(index2 == NULL)
{
strcpy(host,index);
strcpy(path,"/");
data = NULL;
return 0;
}
strncpy(host,index,index2-index);
index = index2;
index2 = strchr(index,'?');
if(index2 == NULL)
{
strcpy(path,index);
data = NULL;
return 0 ;
}
strncpy(path,index,index2-index);
strcpy(data,index2+1);
return 0;
}
int makeDirs(char *path)
{
char path_tmp[100] = {0};
char *index = NULL,*index2 = NULL;
char * index_tmp = NULL;
int ret = 0;
struct stat s;
if(path[0] != '/')
return -1;
index = path;
path_tmp[0] = path[0];
index_tmp = path_tmp;
while(*index != 0x00)
{
index2 = strchr(index+1,'/');
if(index2 == NULL)
{
strcpy(index_tmp,index);
index_tmp += strlen(index_tmp);
index += strlen(index);
}
else
{
strncpy(index_tmp,index,index2-index);
index_tmp += (index2-index);
index = index2;
}
ret = stat(path_tmp,&s);
if(ret == 0)//file exist
{
if((s.st_mode & S_IFDIR) == S_IFDIR)//file exist and is dir
{
continue;
}
else
{
fprintf(stderr,"%s exist,and not file\n",path_tmp);
return -1;
}
}
ret = mkdir(path_tmp,0755);
if(ret < 0)
{
fprintf(stderr,"%d %s\n",errno,strerror(errno));
return ret;
}
}
return 0;
}
int main()
{
char host[50] = "rrys.tv";
int port=80;
char path[1024];
char data[1024];
int sockfd = 0;
int ret;
char sendData[2048],recvData[4096];
int sendLen,recvLen;
char response_code[4];
char * index;
char tmp[1024];
printf("***01\n");
{
time_t t;
struct tm ltime;
t = time(NULL);
localtime_r(&t,<ime);
char tmp[1024] = {0};
sprintf(tmp,"%s/log",local_path);
printf("%s\n",tmp);
makeDirs(tmp);
sprintf(tmp,"%s/log/YYet_ddd.log",local_path,ltime.tm_year+1900,ltime.tm_mon+1,ltime.tm_mday);
printf("%s\n",tmp);
int fd = open(tmp,O_WRONLY|O_CREAT|O_TRUNC,0664);
printf("open fd[%d]\n",fd);
dup2(fd,STDOUT_FILENO);
dup2(fd,STDERR_FILENO);
}
printf("startup\n");
sockfd = startup(host,port,30);
if(sockfd < 0) return ;
printf("sockfd[%d]\n",sockfd);
memset(sendData,0,sizeof(sendData));
memset(recvData,0,sizeof(recvData));
sendLen = recvLen = 0;
memset(response_code,0,sizeof(response_code));
//去rrys.tv获取人人影视的域名
sendLen = pack_GET_model(NULL,sendData,host,"/",NULL,1);
printf("sendData[%s]\n",sendData);
recvLen = connect_host(sockfd,sendData,sendLen,recvData,sizeof(recvData),response_code,0);
printf("response_code[%s]recvLen[%d]\n",response_code,recvLen);
printf("recvData[%s]\n",recvData);
index = getenv("Location");
if(index == NULL) return;
printf("Location[%s]\n",index);
memset(tmp,0,sizeof(tmp));
strcpy(tmp,index);
close(sockfd);
memset(host,0,sizeof(host));
memset(path,0,sizeof(path));
memset(data,0,sizeof(data));
analysize_url(tmp,host,&port,path,data);
printf("host[%s]port[%d]path[%s]data[%s]\n",host,port,path,data);
//获取域名结束
//登陆账号
memset(sendData,0,sizeof(sendData));
memset(recvData,0,sizeof(recvData));
sendLen = recvLen = 0;
memset(response_code,0,sizeof(response_code));
memset(cookie,0,sizeof(cookie));
cookieLen = 0;
sprintf(data,"account=%s&password=%s&remember=0&url_back=",account,password);
//sprintf(path,"/User/Login/ajaxLogin");
sockfd = startup(host,port,30);
sendLen = pack_POST_model(data,sendData,host,"/User/Login/ajaxLogin",NULL,"application/x-www-form-urlencoded",1);
printf("sendData[%s]\n",sendData);
recvLen = connect_host(sockfd,sendData,sendLen,recvData,sizeof(recvData),response_code,1);
printf("response_code[%s]recvLen[%d]\n",response_code,recvLen);
printf("recvData[%s]\n",recvData);
close(sockfd);
//登陆账号结束
//查询登陆状态
memset(sendData,0,sizeof(sendData));
memset(recvData,0,sizeof(recvData));
sendLen = recvLen = 0;
memset(response_code,0,sizeof(response_code));
sockfd = startup(host,port,30);
sendLen = pack_GET_model(NULL,sendData,host,"/user/login/getCurUserTopInfo",cookie,1);
printf("sendData[%s]\n",sendData);
recvLen = connect_host(sockfd,sendData,sendLen,recvData,sizeof(recvData),response_code,0);
printf("response_code[%s]recvLen[%d]\n",response_code,recvLen);
printf("recvData[%s]\n",recvData);
close(sockfd);
//查询结束
}
local_path,account,password这些自己填吧。
我对返回的http response code没有进行过多的判断。
主要流程:
1、GET http://rrys.tv,获取人人影视的域名,在返回的http头中,如Location: http://www.zmz2019.com/rrys
2、POST http://www.zmz2019.com/rrys/User/Login/ajaxLogin,正文内容是“account=%s&password=%s&remember=0&url_back=”,content-type必须是“Content-Type: application/x-www-form-urlencoded”
3、保留上一步的返回的cookie
如上图所示,有些cookie中带有deleted,跳过不保存就好。
4、GET http://www.zmz2019.com/rrys/user/login/getCurUserTopInfo,需要用到上一步的cookie,如下图
5、返回的信息中,cont_login表示的是登陆天数