• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Unionman Technology Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "server_process.h"
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <winsock2.h>
24 #include <ws2tcpip.h>
25 
26 #include "openssl/err.h"
27 #include "openssl/ssl.h"
28 
29 #define SERVER_PEM "config/serverKey.pem"
30 #define SERVER_CER "config/serverCert.cer"
31 #define SRVER_PROFILE "config/serverInfo.json"
32 #define PORT_NUMBER 5022
33 
34 static int s_sockfd = -1;
35 static SSL_CTX* s_ctx = NULL;
36 static SSL* ssl = NULL;
37 
38 
39 #define LOG_PRINT(fmt, ...) printf("[ServerProcess][%s:%d] " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
40 #define DO_CHECK(cond, log, ...)                                                                                       \
41     if (!(cond)) {                                                                                                     \
42         LOG_PRINT(log);                                                                                                \
43         __VA_ARGS__;                                                                                                   \
44     }
45 
46 
47 char* respondContent = NULL;
48 
readServerProfileFromLocal(void)49 int readServerProfileFromLocal(void)
50 {
51     // write file
52     const char* file_name = SRVER_PROFILE;
53     FILE* serverProfileFile = fopen(file_name, "rb");
54 
55     if (serverProfileFile == NULL) {
56         printf("serverInfo.json is not exist.");
57         return -1;
58     }
59 
60     (void)fseek(serverProfileFile, 0, SEEK_END);
61     long fileSize = ftell(serverProfileFile);
62     (void)fseek(serverProfileFile, 0, SEEK_SET);
63 
64     if (fileSize < 0) {
65         return -1;
66     }
67     respondContent = (char*)malloc(fileSize + 1);
68     size_t len = fread(respondContent, 1, fileSize, serverProfileFile);
69     if (len < 0) {
70         return -1;
71     }
72     respondContent[len] = 0;
73 
74     (void)fclose(serverProfileFile);
75 
76     return 0;
77 }
78 
79 /* 创建socket环境 */
Init(void)80 int Init(void)
81 {
82     struct sockaddr_in serverAddr = { 0 };
83     int sockfd;
84     {
85         WSADATA data;
86         WSAStartup(MAKEWORD(2L, 2L), &data);
87     }
88     sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
89     DO_CHECK(sockfd != -1, "Failed to create socket");
90 
91     serverAddr.sin_family = AF_INET;
92     serverAddr.sin_addr.s_addr = INADDR_ANY;
93     serverAddr.sin_port = htons(PORT_NUMBER); /* 端口号 */
94 
95     DO_CHECK(bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == 0, "Failed to bind socket");
96     DO_CHECK(listen(sockfd, SOMAXCONN) == 0, "Failed to listen on socket");
97     LOG_PRINT("Server is listening on port 5022 ");
98     s_sockfd = sockfd;
99     return 0;
100 }
101 
102 
103 /* 服务打开的接口 */
Open(void)104 int Open(void)
105 {
106     const SSL_METHOD* method;
107     SSL_CTX* ctx;
108 
109     SSL_library_init();
110     SSL_load_error_strings();
111     method = TLS_server_method(); /* 使用TLS v1.2作为方法 */
112     ctx = SSL_CTX_new(method);
113     if (!ctx) {
114         ERR_print_errors_fp(stderr);
115         return -1;
116     }
117     if (SSL_CTX_use_certificate_file(ctx, SERVER_CER, SSL_FILETYPE_PEM) <= 0) {
118         ERR_print_errors_fp(stderr);
119         return -1;
120     }
121     if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_PEM, SSL_FILETYPE_PEM) <= 0) {
122         ERR_print_errors_fp(stderr);
123         return -1;
124     }
125 
126     s_ctx = ctx;
127     return 0;
128 }
129 
130 
131 /* 每隔100ms调用一次 */
MainLoop(void)132 int MainLoop(void)
133 {
134     /* 接受连接 */
135     int accfd = accept(s_sockfd, NULL, NULL);
136 
137     DO_CHECK(readServerProfileFromLocal() == 0, "Failed to read ServerProfile");
138 
139     /* 创建 SSL 上下文 */
140     SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
141 
142     /* 载入数字证书和私钥 */
143     SSL_CTX_use_certificate_file(ctx, SERVER_CER, SSL_FILETYPE_PEM);
144     SSL_CTX_use_PrivateKey_file(ctx, SERVER_PEM, SSL_FILETYPE_PEM);
145 
146     /* 创建 SSL 对象 */
147     SSL* ssl = SSL_new(ctx);
148     SSL_set_fd(ssl, accfd);
149 
150     /* 建立 SSL 连接 */
151     if (SSL_accept(ssl) == -1) {
152         perror("SSL_accept");
153         close(accfd);
154         return 0;
155     }
156 
157     /* 发送数据 */
158     SSL_write(ssl, respondContent, strlen(respondContent));
159 
160     /* 接收数据 */
161     char buf[1024];
162     int len = SSL_read(ssl, buf, sizeof(buf));
163     buf[len] = '\0';
164     printf("Received: %s\n", buf);
165 
166     /* 关闭连接套接字 */
167     usleep(100000L);
168     close(accfd);
169     return 0;
170 }
171 
172 /* 关闭服务并释放资源 */
Close(void)173 int Close(void)
174 {
175     /* 关闭 SSL 连接 */
176     SSL_shutdown(ssl);
177     SSL_free(ssl);
178     SSL_CTX_free(s_ctx);
179     WSACleanup();
180     close(s_sockfd);
181     s_sockfd = NULL;
182     return 0;
183 }
184