initial commit
[quakecontrol.git] / common.c
1 #include "common.h"
2
3 #include <unistd.h>
4 #include <strings.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9
10 extern char *rcon_host, *rcon_port, *rcon_pass, *map;
11
12 void senderr(char *errmsg, bool myfault) {
13   if (myfault) {
14     puts("Status: 500 CGI error");
15   } else {
16     puts("Status: 400 CGI error");
17   }
18   puts("Content-Type: text/plain;charset=utf8");
19   puts("X-Frame-Options: DENY");
20   puts("");
21   puts("An error occured while processing your request:");
22   puts(errmsg);
23   exit(0);
24 }
25
26 struct inifile *get_config(void) {
27   static struct inifile *res = NULL;
28   if (!res) res = slurp_inifile(CONFIG_PATH);
29   if (!res) {
30     // error!
31     senderr("can't fetch config", true);
32   }
33   return res;
34 }
35
36 char *getcval(char *key) {
37   char *r = inifile_lookup(get_config(), key);
38   if (!r) {
39     // error!
40     senderr("config value missing", true);
41   }
42   return r;
43 }
44
45 void rcon_send(char *data) {
46   // get config
47   char *host = getcval("rcon_host");
48   char *port = getcval("rcon_port");
49   char *pass = getcval("rcon_pass");
50   
51   // construct packet
52   size_t pass_len = strlen(pass);
53   size_t data_len = strlen(data);
54   size_t packet_len = 4+4+1+pass_len+1+data_len +1;
55   char buf[packet_len];
56   char *p = buf;
57   memcpy(p, "\xff\xff\xff\xffrcon ", 9); p += 9;
58   memcpy(p, pass, pass_len); p += pass_len;
59   *(p++) = ' ';
60   memcpy(p, data, data_len); p += data_len;
61   *(p++) = '\0';
62   
63   // connect
64   int fd = socket(AF_INET, SOCK_DGRAM, 0);
65   if (fd == -1) senderr("can't create UDP socket", true);
66   struct sockaddr_in addr;
67   bzero(&addr, sizeof(addr));
68   addr.sin_family = AF_INET;
69   addr.sin_port = htons(atoi(port));
70   if (!inet_aton(host, &addr.sin_addr)) senderr("bad ipv4 addr in config", true);
71   if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)))
72     senderr("can't connect UDP socket", true);
73   
74   // send
75   if (write(fd, buf, packet_len) != packet_len)
76     senderr("incomplete packet sent or write error", true);
77   
78   close(fd);
79 }