1 #include "uwsgi.h"
2 
3 extern struct uwsgi_server uwsgi;
4 
5 
6 
uwsgi_systemd_notify(char * message)7 void uwsgi_systemd_notify(char *message) {
8 
9 	struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
10 	struct iovec *iovec = msghdr->msg_iov;
11 
12 	iovec[0].iov_base = "STATUS=";
13 	iovec[0].iov_len = 7;
14 
15 	iovec[1].iov_base = message;
16 	iovec[1].iov_len = strlen(message);
17 
18 	iovec[2].iov_base = "\n";
19 	iovec[2].iov_len = 1;
20 
21 	msghdr->msg_iovlen = 3;
22 
23 	if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
24 		uwsgi_error("sendmsg()");
25 	}
26 }
27 
uwsgi_systemd_notify_ready(void)28 void uwsgi_systemd_notify_ready(void) {
29 
30 	struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
31 	struct iovec *iovec = msghdr->msg_iov;
32 
33 	iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
34 	iovec[0].iov_len = 30;
35 
36 	msghdr->msg_iovlen = 1;
37 
38 	if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
39 		uwsgi_error("sendmsg()");
40 	}
41 }
42 
43 
uwsgi_systemd_init(char * systemd_socket)44 void uwsgi_systemd_init(char *systemd_socket) {
45 
46 	struct sockaddr_un *sd_sun;
47 	struct msghdr *msghdr;
48 
49 	uwsgi.notification_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
50 	if (uwsgi.notification_fd < 0) {
51 		uwsgi_error("socket()");
52 		return;
53 	}
54 
55 	size_t len = strlen(systemd_socket);
56 	sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
57 	memset(sd_sun, 0, sizeof(struct sockaddr_un));
58 	sd_sun->sun_family = AF_UNIX;
59 	strncpy(sd_sun->sun_path, systemd_socket, UMIN(len, sizeof(sd_sun->sun_path)));
60 	if (sd_sun->sun_path[0] == '@')
61 		sd_sun->sun_path[0] = 0;
62 
63 	msghdr = uwsgi_malloc(sizeof(struct msghdr));
64 	memset(msghdr, 0, sizeof(struct msghdr));
65 
66 	msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec) * 3);
67 	memset(msghdr->msg_iov, 0, sizeof(struct iovec) * 3);
68 
69 	msghdr->msg_name = sd_sun;
70 	msghdr->msg_namelen = sizeof(struct sockaddr_un) - (sizeof(sd_sun->sun_path) - len);
71 
72 	uwsgi.notification_object = msghdr;
73 
74 	uwsgi.notify = uwsgi_systemd_notify;
75 	uwsgi.notify_ready = uwsgi_systemd_notify_ready;
76 
77 }
78 
uwsgi_notify_socket_manage(int fd)79 int uwsgi_notify_socket_manage(int fd) {
80 	char buf[8192];
81         ssize_t rlen = read(fd, buf, 8192);
82         if (rlen < 0) {
83                 if (uwsgi_is_again()) return 0;
84                 uwsgi_error("uwsgi_notify_socket_manage()/read()");
85                 exit(1);
86         }
87 
88 	if (rlen > 0) {
89 		uwsgi_log_verbose("[notify-socket] %.*s\n", rlen, buf);
90         }
91 
92         return 0;
93 }
94 
uwsgi_notify_msg(char * dst,char * msg,size_t len)95 int uwsgi_notify_msg(char *dst, char *msg, size_t len) {
96 	static int notify_fd = -1;
97 	if (notify_fd < 0) {
98 		notify_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
99 		if (notify_fd < 0) {
100 			uwsgi_error("uwsgi_notify_msg()/socket()");
101 			return -1;
102 		}
103 	}
104 	struct sockaddr_un un_addr;
105 	memset(&un_addr, 0, sizeof(struct sockaddr_un));
106         un_addr.sun_family = AF_UNIX;
107         // use 102 as the magic number
108         strncat(un_addr.sun_path, dst, 102);
109         if (sendto(notify_fd, msg, len, 0, (struct sockaddr *) &un_addr, sizeof(un_addr)) < 0) {
110 		return -1;
111 	}
112 	return 0;
113 }
114