use libnotify for notifications
[irssi-notify.git] / listen.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <netdb.h>
10 #include <arpa/inet.h>
11 #include <sys/wait.h>
12 #include <signal.h>
13 #include <libnotify/notify.h>
14
15 #define PORT "3490" // the port users will be connecting to
16
17 #define BACKLOG 10 // how many pending connections queue will hold
18
19 void sigchld_handler(int s)
20 {
21 while(waitpid(-1, NULL, WNOHANG) > 0);
22 }
23
24 // get sockaddr, IPv4
25 void *get_in_addr(struct sockaddr *sa)
26 {
27 if (sa->sa_family == AF_INET) {
28 return &(((struct sockaddr_in*)sa)->sin_addr);
29 }
30 }
31
32 int main(void)
33 {
34 int sockfd, activefd; // listen on sockfd, new connection on activefd
35 struct addrinfo hints, *servinfo, *p;
36 struct sockaddr_storage their_addr; // connector's address information
37 socklen_t sin_size;
38 struct sigaction sa;
39 int yes=1;
40 char source[INET6_ADDRSTRLEN];
41 // char CLIENT_IP[15] = "107.21.205.69\0";
42 int rv;
43
44 memset(&hints, 0, sizeof hints); // make sure the struct is empty
45 hints.ai_family = AF_INET; // IPv4
46 hints.ai_socktype = SOCK_STREAM;
47 hints.ai_flags = AI_PASSIVE; // use my IP
48
49 if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
50 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
51 return 1;
52 }
53
54 // servinfo now points to a linked list of 1 or more struct addrinfos
55
56 // loop through all the results and bind to the first we can
57 for(p = servinfo; p != NULL; p = p->ai_next) {
58 if ((sockfd = socket(p->ai_family, p->ai_socktype,
59 p->ai_protocol)) == -1) {
60 perror("irssi-notify: socket");
61 continue;
62 }
63
64 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
65 sizeof(int)) == -1) {
66 perror("setsockopt");
67 exit(1);
68 }
69
70 if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
71 close(sockfd);
72 perror("irssi-notify: bind");
73 continue;
74 }
75
76 break;
77 }
78
79 if (p == NULL) {
80 fprintf(stderr, "irssi-notify: failed to bind\n");
81 return 2;
82 }
83
84 freeaddrinfo(servinfo); // all done with this structure
85
86 if (listen(sockfd, BACKLOG) == -1) {
87 perror("listen");
88 exit(1);
89 }
90
91 sa.sa_handler = sigchld_handler; // reap all dead processes
92 sigemptyset(&sa.sa_mask);
93 sa.sa_flags = SA_RESTART;
94 if (sigaction(SIGCHLD, &sa, NULL) == -1) {
95 perror("sigaction");
96 exit(1);
97 }
98
99 printf("irssi-notify: waiting for connections...\n");
100
101 while(1) { // main accept() loop
102 sin_size = sizeof their_addr;
103 activefd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
104 if (activefd == -1) {
105 perror("accept");
106 continue;
107 }
108
109 inet_ntop(their_addr.ss_family,
110 get_in_addr((struct sockaddr *)&their_addr),
111 source, sizeof source);
112
113 if (strcmp(source, "50.16.219.8") != 0 &&
114 strcmp(source, "127.0.0.1") != 0){
115 close(activefd);
116 continue;
117 }
118
119 if (!fork()) { // this is the child process
120 close(sockfd); // child doesn't need the listener
121 char buf[4096];
122 if (recv(activefd, buf, 99, 0) == -1) {
123 perror("recv");
124 exit(1);
125 }
126 buf[4096] = '\0';
127 printf("irssi-notify: recieved '%s'\n", buf);
128 notify_init("irssi-notify");
129 NotifyNotification * notification =
130 notify_notification_new("", buf, "irssi-notify");
131 notify_notification_show(notification, NULL);
132 close(activefd);
133 exit(0);
134 }
135 close(activefd);
136 }
137
138 return 0;
139 }