diff --git a/index.php b/index.php new file mode 100644 index 0000000..b863a57 --- /dev/null +++ b/index.php @@ -0,0 +1,102 @@ +", "practice"); + + if (mysqli_connect_errno()) { + //printf("Connect failed: %s\n", mysqli_connect_error()); + exit(); + } + + //printf("#connect successfully

\n"); + + if(isset($_GET["inst"])) + { + $serial = "\"".$_GET["inst"]."\""; + if( !(isset($_GET["code"]))) + { + //echo "not API
"; + $query = "SELECT OpCode FROM status WHERE SerialNo = $serial"; + //echo "#query
=>
$query

"; + + if ($result = mysqli_query($link, $query)) + { + if ($row = mysqli_fetch_row($result)) + { + $service_code = "\"$row[0]\""; + echo "service_code:$row[0]"; + + //echo "

insert service_code to log
"; + $query = "INSERT INTO log(Time,SerialNo,OpCode) VALUES (\"$time\", $serial, $service_code)"; + //echo "#query
=>
$query

"; + mysqli_query($link, $query); + //printf("Insert New Record sucessfully
"); + } + else + { + //echo "

insert wrong service_code to log
"; + $query = "INSERT INTO log(Time,SerialNo,OpCode,msg) VALUES (\"$time\", $serial, \"\",\"wrong serial\")"; + mysqli_query($link, $query); + + //printf("Insert New wrong record sucessfully

"); + } + mysqli_free_result($result); + mysqli_free_result($row); + } + } + else + { + //echo "is API
"; + $service_code = "\"".$_GET["code"]."\""; + + if($service_code == "\"666\"") + { + //echo "
insert API's service code to log
"; + $query = "INSERT INTO log(Time,SerialNo,OpCode) VALUES (\"$time\", $serial, $service_code)"; + mysqli_query($link, $query); + //printf("Insert into log sucessfully

"); + + //printf("update status to 666
"); + $query="UPDATE status SET OpCode = $service_code WHERE SerialNo = $serial"; + mysqli_query($link, $query); + //printf("update successfully.
Affected rows (UPDATE): %d
", mysqli_affected_rows($link)); + } + else if($service_code == "\"400\"") + { + if(isset($_GET["msg"])) + { + $msg="\"".$_GET["msg"]."\""; + $query = "INSERT INTO log(Time,SerialNo,OpCode,msg) VALUES (\"$time\", $serial, $service_code,$msg)"; + mysqli_query($link, $query); + //printf("Insert 400 sucessfully

"); + + //printf("update status to 000
"); + $query="UPDATE status SET OpCode = \"000\" WHERE SerialNo = $serial"; + mysqli_query($link, $query); + //printf("update successfully.
Affected rows (UPDATE): %d
", mysqli_affected_rows($link)); + } + } + else if($service_code == "\"777\"") + { + //echo "
insert API's service code to log
"; + $query = "INSERT INTO log(Time,SerialNo,OpCode) VALUES (\"$time\", $serial, $service_code)"; + mysqli_query($link, $query); + //printf("Insert into log sucessfully

"); + + //printf("update status to 000
"); + $query="UPDATE status SET OpCode = \"000\" WHERE SerialNo = $serial"; + mysqli_query($link, $query); + //printf("update successfully.
Affected rows (UPDATE): %d
", mysqli_affected_rows($link)); + } + + } + } + else + { + //printf("no serial"); + } + +mysqli_close($link); +?> \ No newline at end of file diff --git a/serviceApi.c b/serviceApi.c new file mode 100644 index 0000000..806724d --- /dev/null +++ b/serviceApi.c @@ -0,0 +1,515 @@ +#include +#include //memcmp 要 include 的 header +#include +#include //getpid() +#include +#include +#include +#include //sockaddr_in +#include //socket() + +#define PORT 80 // Client 所要連線的 port +#define MAXDATASIZE 500 //最大可收的 bytes 大小 + +char ip[50]; +char port[50]; +char user[50]; +char password[50]; +char folder[50]; +char command[500]; +char serial[50]; +int checkT = 0, checkR = 0; //0為complete; -1回傳開檔失敗; -2回傳 傳檔/收檔失敗 的錯誤 Message +int errorCountR = 0, errorCountT = 0; + +void readConfig() //用來存取 ip, port, password 等等變數的 function +{ + FILE *fp; + fp = fopen("service.cfg", "r"); //開檔,讀取service.cfg的檔案 + if(fp == NULL) + printf("open failure\n"); + else + { + while(1) + { + fgets(command, 500, fp); //從fp中一次讀取一行指令(500字元)到common中 + + if(feof(fp)) //如讀到底則 Break + { + break; + } + else + { + char check[500]; + sscanf(command, "%s %*s", check); //從command中讀取前面的字元存到 check 中,後面的字元省略 + + if(memcmp(check, "IP", 2) == 0) //如 (check == "IP") 則從 command 中讀取後面的字元存到 ip 變數中,前面的字元省略 + { + sscanf(command, "%*s %s", ip); + } + else if(memcmp(check, "PORT", 4) == 0) + { + sscanf(command, "%*s %s", port); + } + else if(memcmp(check, "PASSWORD", 8) == 0) + { + sscanf(command, "%*s %s", password); + } + else if(memcmp(check, "USER", 4) == 0) + { + sscanf(command, "%*s %s", user); + } + else if(memcmp(check, "FOLDER", 6) == 0) + { + sscanf(command, "%*s %s", folder); + } + } + } + fclose(fp); + } +} + +/*void readSerialNo() //用來讀取序號用的 function +{ + FILE *fp2; + fp2 = fopen("/proc/cpuinfo", "r"); + + if(fp2 == NULL) + { + printf("open failure\n"); + } + else + { + while(1) + { + fgets(command, 500, fp2); + if(feof(fp2)) + { + break; + } + else + { + char check[500]; + sscanf(command, "%s %*[]", check); + if(memcmp(check, "Serial", 6) == 0) + { + sscanf(command, "%*[^:] %*s %s", serial); //從command中,前面到:為止都省略掉,再省略一個空格,讀取最後一個字元存到serial + //printf("%s\n", serial); + sprintf(serial, "%s", serial); //把serial存成指定格式(%s) + //printf("%d\n", strlen(serial)); //測試serial有幾個字元 + } + } + } + fclose(fp2); //記得關檔 + } +}*/ + +void FileRevOk() //查看是否成功下載檔案,如成功跳出"file recv successfully" +{ //如失敗跳出 "file not recv" + char buf[500]; + FILE *pp; + + printf("Befor receive, 以上正常\n"); + + if((pp = popen(command, "r")) == NULL) + { + printf("popen() error!\n"); + checkR = -1; + return; //回傳 not found + } + else + { + while(fgets(buf, sizeof(buf), pp)) + { + //printf("%s", buf); + if(memcmp(buf, "file recv ok", 12) == 0) + { + printf("file recv successfully\n"); + pclose(pp); + checkR = 0; + return; + } + } + + pclose(pp); + printf("file not recv\n"); + checkR = -2; + return; + } +} + +void FileTransferOk() +{ + char buf[500]; + FILE *pp; + + puts("Befor transfer, 以上正常\n"); + + if((pp = popen(command, "r")) == NULL) + { + printf("popen() error!\n"); + checkT = -1; + return; + } + else + { + while(fgets(buf, sizeof(buf), pp)) + { + if(memcmp(buf, "Transfer OK.", 12) == 0) + { + printf("file transfer successfully\n"); + pclose(pp); + checkT = 0; + return; + } + } + + pclose(pp); + printf("file not transfer\n"); + checkT = -2; + return; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// // +// tcpConnect // +// // +//////////////////////////////////////////////////////////////////////////////// + +int tcpConnect(int return_code, char msg[50]) +{ + int sockfd; //socket的描述 + int i; + int numbytes; + int service_code; + char buf[MAXDATASIZE]; + struct hostent *host; + struct sockaddr_in info; + struct timeval tv; + + sprintf(buf, "GET /index.php?inst=%s&&code=%d&&msg=%s HTTP/1.1\r\n", serial, return_code, msg); + i = strlen(buf); + + if(return_code == 400) + { + //printf("Failure, Error message : %s\n", message); + sprintf(&buf[i], "Host: %s\r\nConnection: Failure\r\n\r\n\r\n\0\0\0\0\0\0\0", ip); + } + else if(return_code == 777) + { + //printf("complete\n"); + sprintf(&buf[i], "Host: %s\r\nConnection: Complete\r\n\r\n\r\n\0\0\0\0\0\0\0", ip); + } + else if(return_code == 666) + { + //printf("under processing\n"); + sprintf(&buf[i], "Host: %s\r\nConnection: Keep-Alive\r\n\r\n\r\n\0\0\0\0\0\0\0", ip); + } + else + { + puts("your return_code is wrong.\n"); + } + + sockfd = socket(AF_INET, SOCK_STREAM, 0); //socket的描述浮 + if(sockfd == -1) + { + perror("socket"); + exit(1); + } + + + bzero(&info, sizeof(info)); //初始化,將struct涵蓋的bits設為0 + info.sin_family = AF_INET; //使用IPv4協定的地址 + info.sin_addr.s_addr = inet_addr(ip); //IP address, inet_addr()可將字串IP變成 binary's IP + //info.sin_addr.s_addr = inet_addr("10.0.0.49");//先指向自己的 IP 練習, 可以把防火牆打開測試connected的timeout + info.sin_port = htons(PORT); //埠號,Host TO Network Short integer的縮寫,它將本機端的字節序(endian)轉換成了網路端的字節序 + //printf("test %x\n", info.sin_addr.s_addr); + + //socket的連線 + //沒有timeout版本的connect + if((connect(sockfd, (struct sockaddr *)&info, sizeof(info))) == -1) + { + perror("connect"); + exit(1); + } + printf("connect successfully\n"); + //沒有timeout版本的connect + + + //有timeout 版本的connect + /*int res = connect(sockfd, (struct sockaddr *)&info, sizeof(info)); + if(res < 0) + { + if(errno == EINPROGRESS) //connect 還在進行中 + { + perror("EINPROGRESS in connect"); + + fd_set myset; + do + { + tv.tv_sec = 10; + tv.tv_usec = 0; + FD_ZERO(&myset); + FD_SET(sockfd, &myset); + res = select(sockfd+1, NULL, &myset, NULL, &tv); + if(res < 0 && errno != EINTR) + { + perror("connect error"); + exit(1); + } + else if(res >0) + { + socklen_t len; + int valopt; + + len = sizeof(int); + if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &len) < 0) //getsockopt can determine if the socket is connected (=0, connected) + { + perror("Error in getsockopt()"); + exit(1); + } + + if(valopt) + { + perror("Error in delay"); + exit(1); + } + break; + } + else + { + perror("Timeout"); + exit(1); + } + }while(1); + } + else + { + perror("connect error"); + exit(1); + } + }//有timeout版的connect + */ + + //傳送資料(send a message on a socket),如正確 send 會回傳實際送出的 Byte 數 + if((send(sockfd, buf, sizeof(buf), 0)) == -1) + { + perror("send"); + exit(1); + } + //printf("send:\n%s\n", buf); + printf("After the send function \n\n"); + + + //接收資料,如正確 recv 會回傳實際讀到並寫入到 buffer 的 Byte 數 + numbytes = recv(sockfd, buf, sizeof(buf), 0); + //printf("numbytes = %d\n", numbytes); + if(numbytes == -1) + { + perror("recv"); + exit(1); + } + + close(sockfd); + + buf[numbytes] = '\0'; + printf("Received in pid = %d, text = %s \n", getpid(), buf); + + return 0; +} + +int updateFirmware() +{ + int sockfd; //socket的描述 + int i; + int numbytes; + int service_code; + char buf[12] = {1,2,0,0,0,6,1,6,0,0x70,1,0x81}; + struct hostent *host; + struct sockaddr_in info; + + i = strlen(buf); + + sockfd = socket(AF_INET, SOCK_STREAM, 0); //socket的描述浮 + if(sockfd == -1) + { + perror("socket"); + exit(1); + } + + bzero(&info, sizeof(info)); //初始化,將struct涵蓋的bits設為0 + info.sin_family = AF_INET; //使用IPv4協定的地址 + //info.sin_addr.s_addr = inet_addr(ip); //IP address, inet_addr()可將字串IP變成 binary's IP + info.sin_addr.s_addr = inet_addr("127.0.0.1");//先指向自己的 IP 練習, 可以把防火牆打開測試connected的timeout + info.sin_port = htons(502); //埠號,Host TO Network Short integer的縮寫,它將本機端的字節序(endian)轉換成了網路端的字節序 + + //socket的連線 + //沒有timeout版本的connect + if((connect(sockfd, (struct sockaddr *)&info, sizeof(info))) == -1) + { + perror("connect"); + exit(1); + } + + //傳送資料(send a message on a socket),如正確 send 會回傳實際送出的 Byte 數 + if((send(sockfd, buf, sizeof(buf), 0)) == -1) + { + perror("send"); + exit(1); + } + printf("After the send function \n\n"); + + //接收資料,如正確 recv 會回傳實際讀到並寫入到 buffer 的 Byte 數 + numbytes = recv(sockfd, buf, sizeof(buf), 0); + if(numbytes == -1) + { + perror("recv"); + exit(1); + } + + close(sockfd); + + buf[numbytes] = '\0'; + + return 0; + +} +///////////////////// main /////////////////////////////////////////// + +int main(int argc, char *argv[]) +{ + int return_code; + int version; + int date; + + return_code = atoi(argv[4]); + version = atoi(argv[6]); + date = atoi(argv[8]); + sprintf(serial, "%s", argv[9]); + + readConfig(); //呼叫存取ip,password等等變數的function + if(return_code == 0) //如return_code為0,則輸出0且結束 + printf("0\n"); //do nothing + else if(return_code == 400) + puts("工作失敗\n"); + else if(return_code == 666) + puts("上一個程式還在執行中\n"); + else if(return_code == 777) + puts("已完成\n"); + else if(return_code == 10|| return_code == 110 || return_code == 20 || return_code == 120 || + return_code == 1 || return_code == 101 || return_code == 200 || return_code == 300) + { + tcpConnect(666, ""); //呼叫tcp function會回處理中(參數666) + errorCountPlus: //如errorCountR or errorCountT <3會用goto回到這裡再執行一次 + switch(return_code) + { + case 10: //如return_code為 010 則上傳 vAlert8.cfg + sprintf(command, "./ftpUpload.exe %s %s %s %s %s vAlert8.cfg STOR", ip, port, user, password, folder); + //printf("test command %s\n", command); //sprintf 為,把這些格式的值寫到command中 + system(command); //叫 system 去執行command(自己設的變數) + FileTransferOk(); + break; + case 110: //如return_code為 110 則下載 vAlert8.cfg + sprintf(command, "./ftpClient.exe %s %s %s %s vAlert8.cfg reset\n", ip, port, user, password); + //printf("%s\n", command); + system(command); + FileRevOk(); + break; + case 20: //如return_code為 020 則上傳 vAlert8Common.cfg + sprintf(command, "./ftpUpload.exe %s %s %s %s %s vAlert8Common.cfg STOR", ip, port, user, password, folder); + //printf("%s\n", command); + system(command); + FileTransferOk(); + break; + case 120: //如return_code為 120 則下載 vAlert8Common.cfg + sprintf(command, "./ftpClient.exe %s %s %s %s vAlert8Common.cfg reset", ip, port, user, password); + //printf("%s\n",command); + system(command); + FileRevOk(); + break; + case 1: //如return_code為 001 則上傳清單上的檔案,需先下載再上傳檔案清單 + sprintf(command, "./ftpClient.exe %s %s %s %s uploadFileList_%s reset", ip, port, user, password, serial); + system(command); //先下載檔案 + FileRevOk(); + + FILE *fp3; + fp3 = fopen("uploadFileList.txt","r"); + if(fp3 == NULL) + { + printf("open failure\n"); + } + else //再上傳檔案清單 + { + char temp[500]; + fgets(temp, 500, fp3); + sprintf(command,"./ftpUpload.exe %s %s %s %s %s/%s uploadFileList_%s STOR", ip, port, user, password, folder, temp, serial); + //printf("%s\n", command); + system(command); + FileTransferOk(); + } + fclose(fp3); + break; + case 101: //如return_code為 101 則單純下載檔案清單 + sprintf(command, "./ftpClients.exe %s %s %s %s uploadFileList_%s reset", ip, port, user, password, serial); + //printf("%s\n", command); + system(command); + FileRevOk(); + break; + case 200: + puts("更新韌體\n"); + updateFirmware(); + break; + case 300: //如return_code為 300 則先下載 run_serial.sh,並執行排程 + sprintf(command, "./ftpClient.exe %s %s %s %s run_%s.sh reset", ip, port, user, password, serial); + //printf("%s\n", command); + system(command); + FileRevOk(); + + sprintf(command, "sudo chmod +x run_%s.sh", serial);//改成可執行檔 + //printf("first %s\n", command); + system(command); + + sprintf(command, "sudo ./run_%s.sh", serial); //執行排程 + //printf("second %s\n", command); + system(command); + break; + }//end switch + }//end else if + else + { + puts("wrong code\n"); + } + if(checkR == 0 && checkT == 0) //FileRevOk && FileTransferOk 的結果都收到OK回傳777 + { + tcpConnect(777, ""); + } + else //Received 沒收到三次會回傳400 + { + if(checkR != 0 && errorCountR < 3) + { + errorCountR++; + printf("Received fail %d time\n", errorCountR); + checkR = 0; + goto errorCountPlus; + } + else if(checkR == -1) + tcpConnect(400, "popen()_error"); + else if(checkR == -2) + tcpConnect(400, "file_not_recv"); + + + if(checkT != 0 && errorCountT < 3) //Transfer 沒收到三次會回傳400 + { + errorCountT++; + printf("Transfer fail %d time\n", errorCountT); + checkT = 0; + goto errorCountPlus; + } + else if(checkT == -1) + tcpConnect(400, "popen()_error"); + else if(checkT == -2) + tcpConnect(400, "file_not_transfer"); + } + + return 0; +} \ No newline at end of file