Add configuration file loading and parsing
[src/drm-lease-manager.git] / drm-lease-manager / main.c
1 /* Copyright 2020-2021 IGEL Co., Ltd.
2  *
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 "lease-config.h"
17 #include "lease-manager.h"
18 #include "lease-server.h"
19 #include "log.h"
20
21 #include <assert.h>
22 #include <getopt.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25
26 static void usage(const char *progname)
27 {
28         printf("Usage: %s [OPTIONS] [<DRM device>]\n\n"
29                "Options:\n"
30                "-h, --help \tPrint this help\n"
31                "-c, --config \t path to configuration file (default "
32                "/etc/drm-lease-manager.toml)\n"
33                "-v, --verbose \tEnable verbose debug messages\n"
34                "-t, --lease-transfer \tAllow lease transfter to new clients\n"
35                "-k, --keep-on-crash \tDon't close lease on client crash\n",
36                progname);
37 }
38
39 const char *opts = "vtkhc:";
40 const struct option options[] = {
41     {"help", no_argument, NULL, 'h'},
42     {"verbose", no_argument, NULL, 'v'},
43     {"lease-transfer", no_argument, NULL, 't'},
44     {"keep-on-crash", no_argument, NULL, 'k'},
45     {"config", required_argument, NULL, 'c'},
46     {NULL, 0, NULL, 0},
47 };
48
49 int main(int argc, char **argv)
50 {
51         char *device = "/dev/dri/card0";
52         char *config_file = "/etc/drm-lease-manager.toml";
53
54         bool debug_log = false;
55         bool can_transfer_leases = false;
56         bool keep_on_crash = false;
57
58         int c;
59         while ((c = getopt_long(argc, argv, opts, options, NULL)) != -1) {
60                 int ret = EXIT_FAILURE;
61                 switch (c) {
62                 case 'v':
63                         debug_log = true;
64                         break;
65                 case 't':
66                         can_transfer_leases = true;
67                         break;
68                 case 'k':
69                         keep_on_crash = true;
70                         break;
71                 case 'c':
72                         config_file = optarg;
73                         break;
74                 case 'h':
75                         ret = EXIT_SUCCESS;
76                         /* fall through */
77                 default:
78                         usage(argv[0]);
79                         return ret;
80                 }
81         }
82
83         if (optind < argc)
84                 device = argv[optind];
85
86         dlm_log_enable_debug(debug_log);
87
88         struct lease_config *lease_configs = NULL;
89         int num_configs = parse_config(config_file, &lease_configs);
90
91         struct lm *lm =
92             lm_create_with_config(device, num_configs, lease_configs);
93
94         if (!lm) {
95                 ERROR_LOG("DRM Lease initialization failed\n");
96                 return EXIT_FAILURE;
97         }
98
99         struct lease_handle **lease_handles = NULL;
100         int count_ids = lm_get_lease_handles(lm, &lease_handles);
101         assert(count_ids > 0);
102
103         struct ls *ls = ls_create(lease_handles, count_ids);
104         if (!ls) {
105                 lm_destroy(lm);
106                 ERROR_LOG("Client socket initialization failed\n");
107                 return EXIT_FAILURE;
108         }
109
110         struct ls_req req;
111         while (ls_get_request(ls, &req)) {
112                 switch (req.type) {
113                 case LS_REQ_GET_LEASE: {
114                         int fd = lm_lease_grant(lm, req.lease_handle);
115
116                         if (fd < 0 && can_transfer_leases)
117                                 fd = lm_lease_transfer(lm, req.lease_handle);
118
119                         if (fd < 0) {
120                                 ERROR_LOG(
121                                     "Can't fulfill lease request: lease=%s\n",
122                                     req.lease_handle->name);
123                                 ls_disconnect_client(ls, req.client);
124                                 break;
125                         }
126
127                         struct ls_client *active_client =
128                             req.lease_handle->user_data;
129                         if (active_client)
130                                 ls_disconnect_client(ls, active_client);
131
132                         req.lease_handle->user_data = req.client;
133
134                         if (!ls_send_fd(ls, req.client, fd)) {
135                                 ERROR_LOG(
136                                     "Client communication error: lease=%s\n",
137                                     req.lease_handle->name);
138                                 ls_disconnect_client(ls, req.client);
139                                 lm_lease_revoke(lm, req.lease_handle);
140                         }
141                         break;
142                 }
143                 case LS_REQ_RELEASE_LEASE:
144                 case LS_REQ_CLIENT_DISCONNECT:
145                         ls_disconnect_client(ls, req.client);
146                         req.lease_handle->user_data = NULL;
147                         lm_lease_revoke(lm, req.lease_handle);
148
149                         if (!keep_on_crash || req.type == LS_REQ_RELEASE_LEASE)
150                                 lm_lease_close(req.lease_handle);
151
152                         break;
153                 default:
154                         ERROR_LOG("Internal error: Invalid lease request\n");
155                         goto done;
156                 }
157         }
158 done:
159         ls_destroy(ls);
160         lm_destroy(lm);
161         release_config(num_configs, lease_configs);
162         return EXIT_FAILURE;
163 }