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