1 /*
2 * qstat
3 * by Steve Jankowski
4 *
5 * qserver functions
6 * Copyright 2004 Ludwig Nussel
7 *
8 * Licensed under the Artistic License, see LICENSE.txt for license terms
9 */
10
11 #include "qstat.h"
12 #include "qserver.h"
13 #include "debug.h"
14
15 #ifndef _WIN32
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #endif
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/types.h>
24
25 // TODO: get rid of this and use send_packet instead, remove n_requests hack from a2s
26 query_status_t
qserver_send_initial(struct qserver * server,const char * data,size_t len)27 qserver_send_initial(struct qserver *server, const char *data, size_t len)
28 {
29 int status = INPROGRESS;
30
31 if (data) {
32 int ret;
33 debug(2, "[%s] send", server->type->type_prefix);
34 if (4 <= get_debug_level()) {
35 output_packet(server, data, len, 1);
36 }
37
38 if (server->flags & FLAG_BROADCAST) {
39 ret = send_broadcast(server, data, len);
40 } else {
41 ret = send(server->fd, data, len, 0);
42 }
43
44 if (ret == SOCKET_ERROR) {
45 send_error(server, ret);
46 status = SYS_ERROR;
47 }
48 }
49
50 if ((server->retry1 == n_retries) || server->flags & FLAG_BROADCAST) {
51 gettimeofday(&server->packet_time1, NULL);
52 } else {
53 server->n_retries++;
54 }
55
56 server->retry1--;
57 server->n_packets++;
58
59 return (status);
60 }
61
62
63 query_status_t
qserver_send(struct qserver * server,const char * data,size_t len)64 qserver_send(struct qserver *server, const char *data, size_t len)
65 {
66 int status = INPROGRESS;
67
68 if (data) {
69 int ret;
70 if (server->flags & FLAG_BROADCAST) {
71 ret = send_broadcast(server, data, len);
72 } else {
73 ret = send(server->fd, data, len, 0);
74 }
75
76 if (ret == SOCKET_ERROR) {
77 send_error(server, ret);
78 status = SYS_ERROR;
79 }
80 }
81
82 server->retry1 = n_retries - 1;
83 gettimeofday(&server->packet_time1, NULL);
84 server->n_requests++;
85 server->n_packets++;
86
87 return (status);
88 }
89
90
91 int
send_broadcast(struct qserver * server,const char * pkt,size_t pktlen)92 send_broadcast(struct qserver *server, const char *pkt, size_t pktlen)
93 {
94 struct sockaddr_in addr;
95
96 addr.sin_family = AF_INET;
97 if (no_port_offset || server->flags & TF_NO_PORT_OFFSET) {
98 addr.sin_port = htons(server->port);
99 } else {
100 addr.sin_port = htons((unsigned short)(server->port + server->type->port_offset));
101 }
102 addr.sin_addr.s_addr = server->ipaddr;
103 memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero));
104
105 return (sendto(server->fd, (const char *)pkt, pktlen, 0, (struct sockaddr *)&addr, sizeof(addr)));
106 }
107
108
109 int
register_send(struct qserver * server)110 register_send(struct qserver *server)
111 {
112 if ((server->retry1 == n_retries) || server->flags & FLAG_BROADCAST) {
113 server->n_requests++;
114 } else {
115 server->n_retries++;
116 }
117
118 // New request so reset the sent time. This ensures
119 // that we record an accurate ping time even on retry
120 gettimeofday(&server->packet_time1, NULL);
121 server->retry1--;
122 server->n_packets++;
123
124 return (INPROGRESS);
125 }
126
127
128 query_status_t
send_packet(struct qserver * server,const char * data,size_t len)129 send_packet(struct qserver *server, const char *data, size_t len)
130 {
131 debug(2, "[%s] send", server->type->type_prefix);
132 if (4 <= get_debug_level()) {
133 output_packet(server, data, len, 1);
134 }
135
136 if (data) {
137 int ret;
138 if (server->flags & FLAG_BROADCAST) {
139 ret = send_broadcast(server, data, len);
140 } else {
141 ret = send(server->fd, data, len, 0);
142 }
143
144 if (ret == SOCKET_ERROR) {
145 return (send_error(server, ret));
146 }
147 }
148
149 register_send(server);
150
151 return (INPROGRESS);
152 }
153
154
155 query_status_t
send_error(struct qserver * server,int rc)156 send_error(struct qserver *server, int rc)
157 {
158 unsigned int ipaddr = ntohl(server->ipaddr);
159 const char *errstr = strerror(errno);
160
161 fprintf(stderr, "Error on %d.%d.%d.%d: %s, skipping ...\n",
162 (ipaddr >> 24) & 0xff,
163 (ipaddr >> 16) & 0xff,
164 (ipaddr >> 8) & 0xff,
165 ipaddr & 0xff,
166 errstr
167 );
168 return (SYS_ERROR);
169 }
170