tests/server: round of tidy-ups (part 2)

General tidy-ups, to identify and reduce duplications and potential
issues, while also making the server modules compile as a single binary.

- ensure unique symbols and no shadowing across server sources, by
  renaming variables.
- move globals common to multiple servers into shared `util` module.
- drop constants with a single use.
- undef macro before re-using them across server sources.
- move common functions into shared `util` module.
- drop redundant static declarations.
- disable IPv6 code when built without IPv6.
- start syncing the 3 almost identical copies of `sockdaemon` function.
- drop unused `timeval.h` header.
- drop `poll()` from `wait_ms()`, for macOS, following an earlier core
  update.
  Follow-up to c72cefea0f #15096

Follow-up to 9213e4e497 #16525
Cherry-picked from #15000
Closes #16609
This commit is contained in:
Viktor Szakats 2024-09-22 17:48:17 +02:00
parent 07f99b72d5
commit bc55b435af
No known key found for this signature in database
GPG Key ID: B5ABD165E2AEF201
9 changed files with 369 additions and 430 deletions

View File

@ -63,12 +63,6 @@
/* include memdebug.h last */
#include "memdebug.h"
#define DEFAULT_PORT 1883 /* MQTT default port */
#ifndef DEFAULT_CONFIG
#define DEFAULT_CONFIG "mqttd.config"
#endif
#define MQTT_MSG_CONNECT 0x10
#define MQTT_MSG_CONNACK 0x20
#define MQTT_MSG_PUBLISH 0x30
@ -77,7 +71,7 @@
#define MQTT_MSG_SUBACK 0x90
#define MQTT_MSG_DISCONNECT 0xe0
struct configurable {
struct mqttd_configurable {
unsigned char version; /* initial version byte in the request must match
this */
bool publish_before_suback;
@ -90,39 +84,23 @@ struct configurable {
#define REQUEST_DUMP "server.input"
#define CONFIG_VERSION 5
static struct configurable config;
static struct mqttd_configurable m_config;
static const char *configfile = DEFAULT_CONFIG;
static const char *logdir = "log";
static char loglockfile[256];
#ifdef USE_IPV6
static bool use_ipv6 = FALSE;
#endif
static const char *ipv_inuse = "IPv4";
static unsigned short port = DEFAULT_PORT;
static void resetdefaults(void)
static void mqttd_resetdefaults(void)
{
logmsg("Reset to defaults");
config.version = CONFIG_VERSION;
config.publish_before_suback = FALSE;
config.short_publish = FALSE;
config.excessive_remaining = FALSE;
config.error_connack = 0;
config.testnum = 0;
m_config.version = CONFIG_VERSION;
m_config.publish_before_suback = FALSE;
m_config.short_publish = FALSE;
m_config.excessive_remaining = FALSE;
m_config.error_connack = 0;
m_config.testnum = 0;
}
static unsigned char byteval(char *value)
{
unsigned long num = strtoul(value, NULL, 10);
return num & 0xff;
}
static void getconfig(void)
static void mqttd_getconfig(void)
{
FILE *fp = fopen(configfile, FOPEN_READTEXT);
resetdefaults();
mqttd_resetdefaults();
if(fp) {
char buffer[512];
logmsg("parse config file");
@ -131,28 +109,28 @@ static void getconfig(void)
char value[32];
if(2 == sscanf(buffer, "%31s %31s", key, value)) {
if(!strcmp(key, "version")) {
config.version = byteval(value);
logmsg("version [%d] set", config.version);
m_config.version = byteval(value);
logmsg("version [%d] set", m_config.version);
}
else if(!strcmp(key, "PUBLISH-before-SUBACK")) {
logmsg("PUBLISH-before-SUBACK set");
config.publish_before_suback = TRUE;
m_config.publish_before_suback = TRUE;
}
else if(!strcmp(key, "short-PUBLISH")) {
logmsg("short-PUBLISH set");
config.short_publish = TRUE;
m_config.short_publish = TRUE;
}
else if(!strcmp(key, "error-CONNACK")) {
config.error_connack = byteval(value);
logmsg("error-CONNACK = %d", config.error_connack);
m_config.error_connack = byteval(value);
logmsg("error-CONNACK = %d", m_config.error_connack);
}
else if(!strcmp(key, "Testnum")) {
config.testnum = atoi(value);
logmsg("testnum = %d", config.testnum);
m_config.testnum = atoi(value);
logmsg("testnum = %d", m_config.testnum);
}
else if(!strcmp(key, "excessive-remaining")) {
logmsg("excessive-remaining set");
config.excessive_remaining = TRUE;
m_config.excessive_remaining = TRUE;
}
}
}
@ -163,25 +141,6 @@ static void getconfig(void)
}
}
static void loghex(unsigned char *buffer, ssize_t len)
{
char data[12000];
ssize_t i;
unsigned char *ptr = buffer;
char *optr = data;
ssize_t width = 0;
int left = sizeof(data);
for(i = 0; i < len && (left >= 0); i++) {
msnprintf(optr, left, "%02x", ptr[i]);
width += 2;
optr += 2;
left -= 2;
}
if(width)
logmsg("'%s'", data);
}
typedef enum {
FROM_CLIENT,
FROM_SERVER
@ -218,7 +177,7 @@ static int connack(FILE *dump, curl_socket_t fd)
};
ssize_t rc;
packet[3] = config.error_connack;
packet[3] = m_config.error_connack;
rc = swrite(fd, (char *)packet, sizeof(packet));
if(rc > 0) {
@ -343,7 +302,7 @@ static size_t encode_length(size_t packetlen,
}
static size_t decode_length(unsigned char *buf,
static size_t decode_length(unsigned char *buffer,
size_t buflen, size_t *lenbytes)
{
size_t len = 0;
@ -352,7 +311,7 @@ static size_t decode_length(unsigned char *buf,
unsigned char encoded = 0x80;
for(i = 0; (i < buflen) && (encoded & 0x80); i++) {
encoded = buf[i];
encoded = buffer[i];
len += (encoded & 0x7f) * mult;
mult *= 0x80;
}
@ -379,7 +338,7 @@ static int publish(FILE *dump,
unsigned char rembuffer[4];
size_t encodedlen;
if(config.excessive_remaining) {
if(m_config.excessive_remaining) {
/* manually set illegal remaining length */
rembuffer[0] = 0xff;
rembuffer[1] = 0xff;
@ -410,7 +369,7 @@ static int publish(FILE *dump,
memcpy(&packet[payloadindex], payload, payloadlen);
sendamount = packetlen;
if(config.short_publish)
if(m_config.short_publish)
sendamount -= 2;
rc = swrite(fd, (char *)packet, sendamount);
@ -493,9 +452,9 @@ static curl_socket_t mqttit(curl_socket_t fd)
if(!dump)
goto end;
getconfig();
mqttd_getconfig();
testno = config.testnum;
testno = m_config.testnum;
if(testno)
logmsg("Found test number %ld", testno);
@ -627,7 +586,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
stream = test2fopen(testno, logdir);
error = getpart(&data, &datalen, "reply", "data", stream);
if(!error) {
if(!config.publish_before_suback) {
if(!m_config.publish_before_suback) {
if(suback(dump, fd, packet_id)) {
logmsg("failed sending SUBACK");
free(data);
@ -640,7 +599,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
goto end;
}
free(data);
if(config.publish_before_suback) {
if(m_config.publish_before_suback) {
if(suback(dump, fd, packet_id)) {
logmsg("failed sending SUBACK");
goto end;
@ -698,7 +657,7 @@ end:
if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must
accept()
*/
static bool incoming(curl_socket_t listenfd)
static bool mqttd_incoming(curl_socket_t listenfd)
{
fd_set fds_read;
fd_set fds_write;
@ -776,8 +735,9 @@ static bool incoming(curl_socket_t listenfd)
return TRUE;
}
static curl_socket_t sockdaemon(curl_socket_t sock,
unsigned short *listenport)
static curl_socket_t mqttd_sockdaemon(curl_socket_t sock,
unsigned short *listenport,
bool bind_only)
{
/* passive daemon style */
srvr_sockaddr_union_t listener;
@ -802,7 +762,9 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
rc = wait_ms(delay);
if(rc) {
/* should not happen */
logmsg("wait_ms() failed with error (%d)", rc);
error = errno;
logmsg("wait_ms() failed with error (%d) %s",
error, strerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@ -896,6 +858,12 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
}
}
/* bindonly option forces no listening */
if(bind_only) {
logmsg("instructed to bind port without listening");
return sock;
}
/* start accepting connections */
rc = listen(sock, 5);
if(0 != rc) {
@ -916,13 +884,15 @@ int main(int argc, char *argv[])
curl_socket_t msgsock = CURL_SOCKET_BAD;
int wrotepidfile = 0;
int wroteportfile = 0;
const char *pidname = ".mqttd.pid";
const char *portname = ".mqttd.port";
bool juggle_again;
int error;
int arg = 1;
pidname = ".mqttd.pid";
portname = ".mqttd.port";
serverlogfile = "log/mqttd.log";
configfile = "mqttd.config";
server_port = 1883; /* MQTT default port */
while(argc > arg) {
if(!strcmp("--version", argv[arg])) {
@ -986,7 +956,7 @@ int main(int argc, char *argv[])
argv[arg]);
return 0;
}
port = util_ultous(ulnum);
server_port = util_ultous(ulnum);
arg++;
}
}
@ -1036,7 +1006,7 @@ int main(int argc, char *argv[])
{
/* passive daemon style */
sock = sockdaemon(sock, &port);
sock = mqttd_sockdaemon(sock, &server_port, FALSE);
if(CURL_SOCKET_BAD == sock) {
goto mqttd_cleanup;
}
@ -1044,20 +1014,20 @@ int main(int argc, char *argv[])
}
logmsg("Running %s version", ipv_inuse);
logmsg("Listening on port %hu", port);
logmsg("Listening on port %hu", server_port);
wrotepidfile = write_pidfile(pidname);
if(!wrotepidfile) {
goto mqttd_cleanup;
}
wroteportfile = write_portfile(portname, port);
wroteportfile = write_portfile(portname, server_port);
if(!wroteportfile) {
goto mqttd_cleanup;
}
do {
juggle_again = incoming(sock);
juggle_again = mqttd_incoming(sock);
} while(juggle_again);
mqttd_cleanup:

View File

@ -50,9 +50,6 @@
/* include memdebug.h last */
#include "memdebug.h"
static bool use_ipv6 = FALSE;
static const char *ipv_inuse = "IPv4";
int main(int argc, char *argv[])
{
int arg = 1;
@ -71,14 +68,21 @@ int main(int argc, char *argv[])
return 0;
}
else if(!strcmp("--ipv6", argv[arg])) {
#if defined(CURLRES_IPV6)
ipv_inuse = "IPv6";
use_ipv6 = TRUE;
arg++;
#else
puts("IPv6 support has been disabled in this program");
return 1;
#endif
}
else if(!strcmp("--ipv4", argv[arg])) {
/* for completeness, we support this option as well */
ipv_inuse = "IPv4";
#if defined(CURLRES_IPV6)
use_ipv6 = FALSE;
#endif
arg++;
}
else {
@ -127,13 +131,8 @@ int main(int argc, char *argv[])
freeaddrinfo(ai);
}
#else
if(use_ipv6) {
puts("IPv6 support has been disabled in this program");
return 1;
}
else {
/* gethostbyname() resolve */
struct hostent *he;
{
struct hostent *he; /* gethostbyname() resolve */
#ifdef __AMIGA__
he = gethostbyname((unsigned char *)host);

View File

@ -56,19 +56,15 @@
/* include memdebug.h last */
#include "memdebug.h"
#ifdef USE_IPV6
static bool use_ipv6 = FALSE;
#endif
static const char *ipv_inuse = "IPv4";
static int serverlogslocked = 0;
#undef REQBUFSIZ
#define REQBUFSIZ 150000
static long prevtestno = -1; /* previous test number we served */
static long prevpartno = -1; /* previous part number we served */
static bool prevbounce = FALSE; /* instructs the server to override the
requested part number to prevpartno + 1 when
prevtestno and current test are the same */
static long rtspd_prevtestno = -1; /* previous test number we served */
static long rtspd_prevpartno = -1; /* previous part number we served */
static bool rtspd_prevbounce = FALSE; /* instructs the server to override the
requested part number to
prevpartno + 1 when prevtestno and
current test are the same */
#define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
#define RCMD_IDLE 1 /* told to sit idle */
@ -85,7 +81,7 @@ typedef enum {
#define SET_RTP_PKT_LEN(p,l) (((p)[2] = (char)(((l) >> 8) & 0xFF)), \
((p)[3] = (char)((l) & 0xFF)))
struct httprequest {
struct rtspd_httprequest {
char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */
size_t checkindex; /* where to start checking of the request */
size_t offset; /* size of the incoming request */
@ -112,14 +108,6 @@ struct httprequest {
size_t rtp_buffersize;
};
static int ProcessRequest(struct httprequest *req);
static void storerequest(char *reqbuf, size_t totalsize);
#define DEFAULT_PORT 8999
static const char *logdir = "log";
static char loglockfile[256];
#define RTSPDVERSION "curl test suite RTSP server/0.1"
#define REQUEST_DUMP "server.input"
@ -145,7 +133,7 @@ static char loglockfile[256];
/* sent as reply to a QUIT */
static const char *docquit =
static const char *docquit_rtsp =
"HTTP/1.1 200 Goodbye" END_OF_HEADERS;
/* sent as reply to a CONNECT */
@ -179,7 +167,7 @@ static const char *doc404_RTSP = "RTSP/1.0 404 Not Found\r\n"
#define RTP_DATA_SIZE 12
static const char *RTP_DATA = "$_1234\n\0Rsdf";
static int ProcessRequest(struct httprequest *req)
static int rtspd_ProcessRequest(struct rtspd_httprequest *req)
{
char *line = &req->reqbuf[req->checkindex];
bool chunked = FALSE;
@ -189,7 +177,7 @@ static int ProcessRequest(struct httprequest *req)
int prot_major, prot_minor;
char *end = strstr(line, END_OF_HEADERS);
logmsg("ProcessRequest() called with testno %ld and line [%s]",
logmsg("rtspd_ProcessRequest() called with testno %ld and line [%s]",
req->testno, line);
/* try to figure out the request characteristics as soon as possible, but
@ -418,10 +406,10 @@ static int ProcessRequest(struct httprequest *req)
if(!end) {
/* we don't have a complete request yet! */
logmsg("ProcessRequest returned without a complete request");
logmsg("rtspd_ProcessRequest returned without a complete request");
return 0; /* not complete yet */
}
logmsg("ProcessRequest found a complete request");
logmsg("rtspd_ProcessRequest found a complete request");
if(req->pipe)
/* we do have a full set, advance the checkindex to after the end of the
@ -573,7 +561,7 @@ static int ProcessRequest(struct httprequest *req)
}
/* store the entire request in a file */
static void storerequest(char *reqbuf, size_t totalsize)
static void rtspd_storerequest(char *reqbuf, size_t totalsize)
{
int res;
int error = 0;
@ -627,7 +615,7 @@ storerequest_cleanup:
}
/* return 0 on success, non-zero on failure */
static int get_request(curl_socket_t sock, struct httprequest *req)
static int rtspd_get_request(curl_socket_t sock, struct rtspd_httprequest *req)
{
int error;
int fail = 0;
@ -695,7 +683,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
if(fail) {
/* dump the request received so far to the external file */
reqbuf[req->offset] = '\0';
storerequest(reqbuf, req->offset);
rtspd_storerequest(reqbuf, req->offset);
return 1;
}
@ -704,7 +692,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
req->offset += (size_t)got;
reqbuf[req->offset] = '\0';
done_processing = ProcessRequest(req);
done_processing = rtspd_ProcessRequest(req);
if(got_exit_signal)
return 1;
if(done_processing && req->pipe) {
@ -730,7 +718,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
reqbuf[req->offset] = '\0';
/* dump the request to an external file */
storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
rtspd_storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
if(got_exit_signal)
return 1;
@ -738,7 +726,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
}
/* returns -1 on failure */
static int send_doc(curl_socket_t sock, struct httprequest *req)
static int rtspd_send_doc(curl_socket_t sock, struct rtspd_httprequest *req)
{
ssize_t written;
size_t count;
@ -791,7 +779,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
switch(req->testno) {
case DOCNUMBER_QUIT:
logmsg("Replying to QUIT");
buffer = docquit;
buffer = docquit_rtsp;
break;
case DOCNUMBER_WERULEZ:
/* we got a "friends?" question, reply back that we sure are */
@ -890,11 +878,11 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
logmsg("connection close instruction \"swsclose\" found in response");
}
if(strstr(buffer, "swsbounce")) {
prevbounce = TRUE;
rtspd_prevbounce = TRUE;
logmsg("enable \"swsbounce\" in the next request");
}
else
prevbounce = FALSE;
rtspd_prevbounce = FALSE;
dump = fopen(responsedump, "ab");
if(!dump) {
@ -1016,8 +1004,8 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
free(cmd);
req->open = persistent;
prevtestno = req->testno;
prevpartno = req->partno;
rtspd_prevtestno = req->testno;
rtspd_prevpartno = req->partno;
return 0;
}
@ -1031,17 +1019,17 @@ int main(int argc, char *argv[])
int wrotepidfile = 0;
int wroteportfile = 0;
int flag;
unsigned short port = DEFAULT_PORT;
const char *pidname = ".rtsp.pid";
const char *portname = NULL; /* none by default */
struct httprequest req;
unsigned short port = 8999;
struct rtspd_httprequest req;
int rc;
int error;
int arg = 1;
memset(&req, 0, sizeof(req));
pidname = ".rtsp.pid";
serverlogfile = "log/rtspd.log";
serverlogslocked = 0;
while(argc > arg) {
if(!strcmp("--version", argv[arg])) {
@ -1284,9 +1272,9 @@ int main(int argc, char *argv[])
}
#endif
/* initialization of httprequest struct is done in get_request(), but due
to pipelining treatment the pipelining struct field must be initialized
previously to FALSE every time a new connection arrives. */
/* initialization of httprequest struct is done in rtspd_get_request(),
but due to pipelining treatment the pipelining struct field must be
initialized previously to FALSE every time a new connection arrives. */
req.pipelining = FALSE;
@ -1294,24 +1282,24 @@ int main(int argc, char *argv[])
if(got_exit_signal)
break;
if(get_request(msgsock, &req))
if(rtspd_get_request(msgsock, &req))
/* non-zero means error, break out of loop */
break;
if(prevbounce) {
if(rtspd_prevbounce) {
/* bounce treatment requested */
if(req.testno == prevtestno) {
req.partno = prevpartno + 1;
if(req.testno == rtspd_prevtestno) {
req.partno = rtspd_prevpartno + 1;
logmsg("BOUNCE part number to %ld", req.partno);
}
else {
prevbounce = FALSE;
prevtestno = -1;
prevpartno = -1;
rtspd_prevbounce = FALSE;
rtspd_prevtestno = -1;
rtspd_prevpartno = -1;
}
}
send_doc(msgsock, &req);
rtspd_send_doc(msgsock, &req);
if(got_exit_signal)
break;

View File

@ -114,20 +114,14 @@
/* include memdebug.h last */
#include "memdebug.h"
#define DEFAULT_PORT 8999
/* buffer is this excessively large only to be able to support things like
test 1003 which tests exceedingly large server response lines */
#define BUFFER_SIZE 17010
static bool verbose = FALSE;
static bool bind_only = FALSE;
#ifdef USE_IPV6
static bool use_ipv6 = FALSE;
#endif
static const char *ipv_inuse = "IPv4";
static unsigned short port = DEFAULT_PORT;
static unsigned short connectport = 0; /* if non-zero, we activate this mode */
static bool s_bind_only = FALSE;
static unsigned short server_connectport = 0; /* if non-zero,
we activate this mode */
enum sockmode {
PASSIVE_LISTEN, /* as a server waiting for connections */
@ -1126,7 +1120,8 @@ static bool juggle(curl_socket_t *sockfdp,
else if(!memcmp("PORT", buffer, 4)) {
/* Question asking us what PORT number we are listening to.
Replies to PORT with "IPv[num]/[port]" */
msnprintf((char *)buffer, sizeof(buffer), "%s/%hu\n", ipv_inuse, port);
msnprintf((char *)buffer, sizeof(buffer), "%s/%hu\n",
ipv_inuse, server_port);
buffer_len = (ssize_t)strlen((char *)buffer);
msnprintf(data, sizeof(data), "PORT\n%04zx\n", buffer_len);
if(!write_stdout(data, 10))
@ -1231,8 +1226,9 @@ static bool juggle(curl_socket_t *sockfdp,
#endif
}
static curl_socket_t sockdaemon(curl_socket_t sock,
unsigned short *listenport)
static curl_socket_t sockfilt_sockdaemon(curl_socket_t sock,
unsigned short *listenport,
bool bind_only)
{
/* passive daemon style */
srvr_sockaddr_union_t listener;
@ -1380,8 +1376,6 @@ int main(int argc, char *argv[])
curl_socket_t msgsock = CURL_SOCKET_BAD;
int wrotepidfile = 0;
int wroteportfile = 0;
const char *pidname = ".sockfilt.pid";
const char *portname = NULL; /* none by default */
bool juggle_again;
int rc;
int error;
@ -1389,7 +1383,9 @@ int main(int argc, char *argv[])
enum sockmode mode = PASSIVE_LISTEN; /* default */
const char *addr = NULL;
pidname = ".sockfilt.pid";
serverlogfile = "log/sockfilt.log";
server_port = 8999;
while(argc > arg) {
if(!strcmp("--version", argv[arg])) {
@ -1437,7 +1433,7 @@ int main(int argc, char *argv[])
arg++;
}
else if(!strcmp("--bindonly", argv[arg])) {
bind_only = TRUE;
s_bind_only = TRUE;
arg++;
}
else if(!strcmp("--port", argv[arg])) {
@ -1445,7 +1441,7 @@ int main(int argc, char *argv[])
if(argc > arg) {
char *endptr;
unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
port = util_ultous(ulnum);
server_port = util_ultous(ulnum);
arg++;
}
}
@ -1462,7 +1458,7 @@ int main(int argc, char *argv[])
argv[arg]);
return 0;
}
connectport = util_ultous(ulnum);
server_connectport = util_ultous(ulnum);
arg++;
}
}
@ -1518,7 +1514,7 @@ int main(int argc, char *argv[])
goto sockfilt_cleanup;
}
if(connectport) {
if(server_connectport) {
/* Active mode, we should connect to the given port number */
mode = ACTIVE;
#ifdef USE_IPV6
@ -1526,7 +1522,7 @@ int main(int argc, char *argv[])
#endif
memset(&me.sa4, 0, sizeof(me.sa4));
me.sa4.sin_family = AF_INET;
me.sa4.sin_port = htons(connectport);
me.sa4.sin_port = htons(server_connectport);
me.sa4.sin_addr.s_addr = INADDR_ANY;
if(!addr)
addr = "127.0.0.1";
@ -1538,7 +1534,7 @@ int main(int argc, char *argv[])
else {
memset(&me.sa6, 0, sizeof(me.sa6));
me.sa6.sin6_family = AF_INET6;
me.sa6.sin6_port = htons(connectport);
me.sa6.sin6_port = htons(server_connectport);
if(!addr)
addr = "::1";
Curl_inet_pton(AF_INET6, addr, &me.sa6.sin6_addr);
@ -1549,7 +1545,7 @@ int main(int argc, char *argv[])
if(rc) {
error = SOCKERRNO;
logmsg("Error connecting to port %hu (%d) %s",
connectport, error, sstrerror(error));
server_connectport, error, sstrerror(error));
write_stdout("FAIL\n", 5);
goto sockfilt_cleanup;
}
@ -1558,7 +1554,7 @@ int main(int argc, char *argv[])
}
else {
/* passive daemon style */
sock = sockdaemon(sock, &port);
sock = sockfilt_sockdaemon(sock, &server_port, s_bind_only);
if(CURL_SOCKET_BAD == sock) {
write_stdout("FAIL\n", 5);
goto sockfilt_cleanup;
@ -1568,12 +1564,12 @@ int main(int argc, char *argv[])
logmsg("Running %s version", ipv_inuse);
if(connectport)
logmsg("Connected to port %hu", connectport);
else if(bind_only)
logmsg("Bound without listening on port %hu", port);
if(server_connectport)
logmsg("Connected to port %hu", server_connectport);
else if(s_bind_only)
logmsg("Bound without listening on port %hu", server_port);
else
logmsg("Listening on port %hu", port);
logmsg("Listening on port %hu", server_port);
wrotepidfile = write_pidfile(pidname);
if(!wrotepidfile) {
@ -1581,7 +1577,7 @@ int main(int argc, char *argv[])
goto sockfilt_cleanup;
}
if(portname) {
wroteportfile = write_portfile(portname, port);
wroteportfile = write_portfile(portname, server_port);
if(!wroteportfile) {
write_stdout("FAIL\n", 5);
goto sockfilt_cleanup;

View File

@ -85,20 +85,10 @@
/* include memdebug.h last */
#include "memdebug.h"
#define DEFAULT_PORT 8905
#ifndef DEFAULT_REQFILE
#define DEFAULT_REQFILE "log/socksd-request.log"
#endif
#ifndef DEFAULT_CONFIG
#define DEFAULT_CONFIG "socksd.config"
#endif
static const char *backendaddr = "127.0.0.1";
static unsigned short backendport = 0; /* default is use client's */
struct configurable {
struct socksd_configurable {
unsigned char version; /* initial version byte in the request must match
this */
unsigned char nmethods_min; /* minimum number of nmethods to expect */
@ -123,34 +113,24 @@ struct configurable {
#define CONFIG_ADDR backendaddr
#define CONFIG_CONNECTREP 0
static struct configurable config;
static struct socksd_configurable s_config;
static const char *reqlogfile = DEFAULT_REQFILE;
static const char *configfile = DEFAULT_CONFIG;
static const char *reqlogfile = "log/socksd-request.log";
static const char *socket_type = "IPv4";
static unsigned short port = DEFAULT_PORT;
static void resetdefaults(void)
static void socksd_resetdefaults(void)
{
logmsg("Reset to defaults");
config.version = CONFIG_VERSION;
config.nmethods_min = CONFIG_NMETHODS_MIN;
config.nmethods_max = CONFIG_NMETHODS_MAX;
config.responseversion = CONFIG_RESPONSEVERSION;
config.responsemethod = CONFIG_RESPONSEMETHOD;
config.reqcmd = CONFIG_REQCMD;
config.connectrep = CONFIG_CONNECTREP;
config.port = CONFIG_PORT;
strcpy(config.addr, CONFIG_ADDR);
strcpy(config.user, "user");
strcpy(config.password, "password");
}
static unsigned char byteval(char *value)
{
unsigned long num = strtoul(value, NULL, 10);
return num & 0xff;
s_config.version = CONFIG_VERSION;
s_config.nmethods_min = CONFIG_NMETHODS_MIN;
s_config.nmethods_max = CONFIG_NMETHODS_MAX;
s_config.responseversion = CONFIG_RESPONSEVERSION;
s_config.responsemethod = CONFIG_RESPONSEMETHOD;
s_config.reqcmd = CONFIG_REQCMD;
s_config.connectrep = CONFIG_CONNECTREP;
s_config.port = CONFIG_PORT;
strcpy(s_config.addr, CONFIG_ADDR);
strcpy(s_config.user, "user");
strcpy(s_config.password, "password");
}
static unsigned short shortval(char *value)
@ -159,12 +139,10 @@ static unsigned short shortval(char *value)
return num & 0xffff;
}
static int socket_domain = AF_INET;
static void getconfig(void)
static void socksd_getconfig(void)
{
FILE *fp = fopen(configfile, FOPEN_READTEXT);
resetdefaults();
socksd_resetdefaults();
if(fp) {
char buffer[512];
logmsg("parse config file");
@ -173,32 +151,32 @@ static void getconfig(void)
char value[260];
if(2 == sscanf(buffer, "%31s %259s", key, value)) {
if(!strcmp(key, "version")) {
config.version = byteval(value);
logmsg("version [%d] set", config.version);
s_config.version = byteval(value);
logmsg("version [%d] set", s_config.version);
}
else if(!strcmp(key, "nmethods_min")) {
config.nmethods_min = byteval(value);
logmsg("nmethods_min [%d] set", config.nmethods_min);
s_config.nmethods_min = byteval(value);
logmsg("nmethods_min [%d] set", s_config.nmethods_min);
}
else if(!strcmp(key, "nmethods_max")) {
config.nmethods_max = byteval(value);
logmsg("nmethods_max [%d] set", config.nmethods_max);
s_config.nmethods_max = byteval(value);
logmsg("nmethods_max [%d] set", s_config.nmethods_max);
}
else if(!strcmp(key, "backend")) {
strcpy(config.addr, value);
logmsg("backend [%s] set", config.addr);
strcpy(s_config.addr, value);
logmsg("backend [%s] set", s_config.addr);
}
else if(!strcmp(key, "backendport")) {
config.port = shortval(value);
logmsg("backendport [%d] set", config.port);
s_config.port = shortval(value);
logmsg("backendport [%d] set", s_config.port);
}
else if(!strcmp(key, "user")) {
strcpy(config.user, value);
logmsg("user [%s] set", config.user);
strcpy(s_config.user, value);
logmsg("user [%s] set", s_config.user);
}
else if(!strcmp(key, "password")) {
strcpy(config.password, value);
logmsg("password [%s] set", config.password);
strcpy(s_config.password, value);
logmsg("password [%s] set", s_config.password);
}
/* Methods:
o X'00' NO AUTHENTICATION REQUIRED
@ -206,12 +184,12 @@ static void getconfig(void)
o X'02' USERNAME/PASSWORD
*/
else if(!strcmp(key, "method")) {
config.responsemethod = byteval(value);
logmsg("method [%d] set", config.responsemethod);
s_config.responsemethod = byteval(value);
logmsg("method [%d] set", s_config.responsemethod);
}
else if(!strcmp(key, "response")) {
config.connectrep = byteval(value);
logmsg("response [%d] set", config.connectrep);
s_config.connectrep = byteval(value);
logmsg("response [%d] set", s_config.connectrep);
}
}
}
@ -219,25 +197,6 @@ static void getconfig(void)
}
}
static void loghex(unsigned char *buffer, ssize_t len)
{
char data[1200];
ssize_t i;
unsigned char *ptr = buffer;
char *optr = data;
ssize_t width = 0;
int left = sizeof(data);
for(i = 0; i < len && (left >= 0); i++) {
msnprintf(optr, left, "%02x", ptr[i]);
width += 2;
optr += 2;
left -= 2;
}
if(width)
logmsg("'%s'", data);
}
/* RFC 1928, SOCKS5 byte index */
#define SOCKS5_VERSION 0
#define SOCKS5_NMETHODS 1 /* number of methods that is listed */
@ -303,13 +262,13 @@ static curl_socket_t socks4(curl_socket_t fd,
logmsg("SOCKS4 connect message too short: %zd", rc);
return CURL_SOCKET_BAD;
}
if(!config.port)
if(!s_config.port)
s4port = (unsigned short)((buffer[SOCKS4_DSTPORT] << 8) |
(buffer[SOCKS4_DSTPORT + 1]));
else
s4port = config.port;
s4port = s_config.port;
connfd = socksconnect(s4port, config.addr);
connfd = socksconnect(s4port, s_config.addr);
if(connfd == CURL_SOCKET_BAD) {
/* failed */
cd = 91;
@ -353,7 +312,7 @@ static curl_socket_t sockit(curl_socket_t fd)
curl_socket_t connfd = CURL_SOCKET_BAD;
unsigned short s5port;
getconfig();
socksd_getconfig();
rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
if(rc <= 0) {
@ -372,14 +331,14 @@ static curl_socket_t sockit(curl_socket_t fd)
return CURL_SOCKET_BAD;
}
if(buffer[SOCKS5_VERSION] != config.version) {
logmsg("VERSION byte not %d", config.version);
if(buffer[SOCKS5_VERSION] != s_config.version) {
logmsg("VERSION byte not %d", s_config.version);
return CURL_SOCKET_BAD;
}
if((buffer[SOCKS5_NMETHODS] < config.nmethods_min) ||
(buffer[SOCKS5_NMETHODS] > config.nmethods_max)) {
if((buffer[SOCKS5_NMETHODS] < s_config.nmethods_min) ||
(buffer[SOCKS5_NMETHODS] > s_config.nmethods_max)) {
logmsg("NMETHODS byte not within %d - %d ",
config.nmethods_min, config.nmethods_max);
s_config.nmethods_min, s_config.nmethods_max);
return CURL_SOCKET_BAD;
}
/* after NMETHODS follows that many bytes listing the methods the client
@ -391,8 +350,8 @@ static curl_socket_t sockit(curl_socket_t fd)
logmsg("Incoming request deemed fine!");
/* respond with two bytes: VERSION + METHOD */
response[0] = config.responseversion;
response[1] = config.responsemethod;
response[0] = s_config.responseversion;
response[1] = s_config.responsemethod;
rc = (send)(fd, (char *)response, 2, 0);
if(rc != 2) {
logmsg("Sending response failed!");
@ -411,7 +370,7 @@ static curl_socket_t sockit(curl_socket_t fd)
logmsg("READ %zd bytes", rc);
loghex(buffer, rc);
if(config.responsemethod == 2) {
if(s_config.responsemethod == 2) {
/* RFC 1929 authentication
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
@ -440,10 +399,10 @@ static curl_socket_t sockit(curl_socket_t fd)
logmsg("Too short packet for ulen %d plen %d: %zd", ulen, plen, rc);
return CURL_SOCKET_BAD;
}
if((ulen != strlen(config.user)) ||
(plen != strlen(config.password)) ||
memcmp(&buffer[SOCKS5_UNAME], config.user, ulen) ||
memcmp(&buffer[SOCKS5_UNAME + ulen + 1], config.password, plen)) {
if((ulen != strlen(s_config.user)) ||
(plen != strlen(s_config.password)) ||
memcmp(&buffer[SOCKS5_UNAME], s_config.user, ulen) ||
memcmp(&buffer[SOCKS5_UNAME + ulen + 1], s_config.password, plen)) {
/* no match! */
logmsg("mismatched credentials!");
login = FALSE;
@ -475,18 +434,18 @@ static curl_socket_t sockit(curl_socket_t fd)
return CURL_SOCKET_BAD;
}
if(buffer[SOCKS5_VERSION] != config.version) {
logmsg("Request VERSION byte not %d", config.version);
if(buffer[SOCKS5_VERSION] != s_config.version) {
logmsg("Request VERSION byte not %d", s_config.version);
return CURL_SOCKET_BAD;
}
/* 1 == CONNECT */
if(buffer[SOCKS5_REQCMD] != config.reqcmd) {
logmsg("Request COMMAND byte not %d", config.reqcmd);
if(buffer[SOCKS5_REQCMD] != s_config.reqcmd) {
logmsg("Request COMMAND byte not %d", s_config.reqcmd);
return CURL_SOCKET_BAD;
}
/* reserved, should be zero */
if(buffer[SOCKS5_RESERVED]) {
logmsg("Request COMMAND byte not %d", config.reqcmd);
logmsg("Request COMMAND byte not %d", s_config.reqcmd);
return CURL_SOCKET_BAD;
}
/* ATYP:
@ -550,26 +509,26 @@ static curl_socket_t sockit(curl_socket_t fd)
}
}
if(!config.port) {
if(!s_config.port) {
unsigned char *portp = &buffer[SOCKS5_DSTADDR + len];
s5port = (unsigned short)((portp[0] << 8) | (portp[1]));
}
else
s5port = config.port;
s5port = s_config.port;
if(!config.connectrep)
connfd = socksconnect(s5port, config.addr);
if(!s_config.connectrep)
connfd = socksconnect(s5port, s_config.addr);
if(connfd == CURL_SOCKET_BAD) {
/* failed */
rep = 1;
}
else {
rep = config.connectrep;
rep = s_config.connectrep;
}
/* */
response[SOCKS5_VERSION] = config.responseversion;
response[SOCKS5_VERSION] = s_config.responseversion;
/*
o REP Reply field:
@ -663,7 +622,7 @@ static int tunnel(struct perclient *cp, fd_set *fds)
if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must
accept()
*/
static bool incoming(curl_socket_t listenfd)
static bool socksd_incoming(curl_socket_t listenfd)
{
fd_set fds_read;
fd_set fds_write;
@ -799,12 +758,10 @@ static bool incoming(curl_socket_t listenfd)
return TRUE;
}
static curl_socket_t sockdaemon(curl_socket_t sock,
unsigned short *listenport
#ifdef USE_UNIX_SOCKETS
, const char *unix_socket
#endif
)
static curl_socket_t socksd_sockdaemon(curl_socket_t sock,
unsigned short *listenport,
const char *unix_socket,
bool bind_only)
{
/* passive daemon style */
srvr_sockaddr_union_t listener;
@ -816,6 +773,10 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
int attempt = 0;
int error = 0;
#ifndef USE_UNIX_SOCKETS
(void)unix_socket;
#endif
do {
attempt++;
flag = 1;
@ -938,6 +899,12 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
}
}
/* bindonly option forces no listening */
if(bind_only) {
logmsg("instructed to bind port without listening");
return sock;
}
/* start accepting connections */
rc = listen(sock, 5);
if(0 != rc) {
@ -958,18 +925,19 @@ int main(int argc, char *argv[])
curl_socket_t msgsock = CURL_SOCKET_BAD;
int wrotepidfile = 0;
int wroteportfile = 0;
const char *pidname = ".socksd.pid";
const char *portname = NULL; /* none by default */
bool juggle_again;
int error;
int arg = 1;
#ifdef USE_UNIX_SOCKETS
const char *unix_socket = NULL;
#ifdef USE_UNIX_SOCKETS
bool unlink_socket = false;
#endif
pidname = ".socksd.pid";
serverlogfile = "log/socksd.log";
configfile = "socksd.config";
server_port = 8905;
while(argc > arg) {
if(!strcmp("--version", argv[arg])) {
@ -1054,7 +1022,7 @@ int main(int argc, char *argv[])
if(argc > arg) {
char *endptr;
unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
port = util_ultous(ulnum);
server_port = util_ultous(ulnum);
arg++;
}
}
@ -1099,11 +1067,7 @@ int main(int argc, char *argv[])
{
/* passive daemon style */
sock = sockdaemon(sock, &port
#ifdef USE_UNIX_SOCKETS
, unix_socket
#endif
);
sock = socksd_sockdaemon(sock, &server_port, unix_socket, FALSE);
if(CURL_SOCKET_BAD == sock) {
goto socks5_cleanup;
}
@ -1120,7 +1084,7 @@ int main(int argc, char *argv[])
logmsg("Listening on Unix socket %s", unix_socket);
else
#endif
logmsg("Listening on port %hu", port);
logmsg("Listening on port %hu", server_port);
wrotepidfile = write_pidfile(pidname);
if(!wrotepidfile) {
@ -1128,14 +1092,14 @@ int main(int argc, char *argv[])
}
if(portname) {
wroteportfile = write_portfile(portname, port);
wroteportfile = write_portfile(portname, server_port);
if(!wroteportfile) {
goto socks5_cleanup;
}
}
do {
juggle_again = incoming(sock);
juggle_again = socksd_incoming(sock);
} while(juggle_again);
socks5_cleanup:

View File

@ -58,26 +58,26 @@
/* include memdebug.h last */
#include "memdebug.h"
static int socket_domain = AF_INET;
static bool use_gopher = FALSE;
static int serverlogslocked = 0;
static bool is_proxy = FALSE;
#undef REQBUFSIZ
#define REQBUFSIZ (2*1024*1024)
#define MAX_SLEEP_TIME_MS 250
static long prevtestno = -1; /* previous test number we served */
static long prevpartno = -1; /* previous part number we served */
static bool prevbounce = FALSE; /* instructs the server to override the
requested part number to prevpartno + 1 when
prevtestno and current test are the same */
static long sws_prevtestno = -1; /* previous test number we served */
static long sws_prevpartno = -1; /* previous part number we served */
static bool sws_prevbounce = FALSE; /* instructs the server to override the
requested part number to
prevpartno + 1 when prevtestno and
current test are the same */
#define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
#define RCMD_IDLE 1 /* told to sit idle */
#define RCMD_STREAM 2 /* told to stream */
struct httprequest {
struct sws_httprequest {
char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */
bool connect_request; /* if a CONNECT */
unsigned short connect_port; /* the port number CONNECT used */
@ -101,7 +101,7 @@ struct httprequest {
- skip bytes. */
int rcmd; /* doing a special command, see defines above */
int prot_version; /* HTTP version * 10 */
int callcount; /* times ProcessRequest() gets called */
int callcount; /* times sws_ProcessRequest() gets called */
bool skipall; /* skip all incoming data */
bool noexpect; /* refuse Expect: (don't read the body) */
bool connmon; /* monitor the state of the connection, log disconnects */
@ -117,14 +117,6 @@ struct httprequest {
static curl_socket_t all_sockets[MAX_SOCKETS];
static size_t num_sockets = 0;
static int ProcessRequest(struct httprequest *req);
static void storerequest(const char *reqbuf, size_t totalsize);
#define DEFAULT_PORT 8999
static const char *logdir = "log";
static char loglockfile[256];
#define SWSVERSION "curl test suite HTTP server/0.1"
#define REQUEST_DUMP "server.input"
@ -136,8 +128,7 @@ static char loglockfile[256];
#define RESPONSE_PROXY_DUMP "proxy.response"
/* file in which additional instructions may be found */
#define DEFAULT_CMDFILE "log/server.cmd"
static const char *cmdfile = DEFAULT_CMDFILE;
static const char *cmdfile = "log/server.cmd";
/* very-big-path support */
#define MAXDOCNAMELEN 140000
@ -174,7 +165,7 @@ static const char *cmdfile = DEFAULT_CMDFILE;
static const char *end_of_headers = END_OF_HEADERS;
/* sent as reply to a QUIT */
static const char *docquit =
static const char *docquit_sws =
"HTTP/1.1 200 Goodbye" END_OF_HEADERS;
/* send back this on 404 file not found */
@ -212,7 +203,7 @@ static bool socket_domain_is_ip(void)
#endif
/* parse the file on disk that might have a test number for us */
static int parse_cmdfile(struct httprequest *req)
static int parse_cmdfile(struct sws_httprequest *req)
{
FILE *f = fopen(cmdfile, FOPEN_READTEXT);
if(f) {
@ -230,7 +221,7 @@ static int parse_cmdfile(struct httprequest *req)
}
/* based on the testno, parse the correct server commands */
static int parse_servercmd(struct httprequest *req)
static int sws_parse_servercmd(struct sws_httprequest *req)
{
FILE *stream;
int error;
@ -334,7 +325,7 @@ static int parse_servercmd(struct httprequest *req)
return 0; /* OK! */
}
static int ProcessRequest(struct httprequest *req)
static int sws_ProcessRequest(struct sws_httprequest *req)
{
char *line = &req->reqbuf[req->checkindex];
bool chunked = FALSE;
@ -515,7 +506,7 @@ static int ProcessRequest(struct httprequest *req)
req->testno = DOCNUMBER_404;
}
else
parse_servercmd(req);
sws_parse_servercmd(req);
}
else if((req->offset >= 3)) {
unsigned char *l = (unsigned char *)line;
@ -544,7 +535,7 @@ static int ProcessRequest(struct httprequest *req)
}
/* find and parse <servercmd> for this test */
parse_servercmd(req);
sws_parse_servercmd(req);
if(use_gopher) {
/* when using gopher we cannot check the request until the entire
@ -757,7 +748,7 @@ static int ProcessRequest(struct httprequest *req)
}
/* store the entire request in a file */
static void storerequest(const char *reqbuf, size_t totalsize)
static void sws_storerequest(const char *reqbuf, size_t totalsize)
{
int res;
int error = 0;
@ -811,7 +802,7 @@ storerequest_cleanup:
dumpfile, errno, strerror(errno));
}
static void init_httprequest(struct httprequest *req)
static void init_httprequest(struct sws_httprequest *req)
{
req->checkindex = 0;
req->offset = 0;
@ -838,11 +829,11 @@ static void init_httprequest(struct httprequest *req)
req->upgrade_request = 0;
}
static int send_doc(curl_socket_t sock, struct httprequest *req);
static int sws_send_doc(curl_socket_t sock, struct sws_httprequest *req);
/* returns 1 if the connection should be serviced again immediately, 0 if there
is no data waiting, or < 0 if it should be closed */
static int get_request(curl_socket_t sock, struct httprequest *req)
static int sws_get_request(curl_socket_t sock, struct sws_httprequest *req)
{
int fail = 0;
char *reqbuf = req->reqbuf;
@ -852,11 +843,11 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
if(req->upgrade_request) {
/* upgraded connection, work it differently until end of connection */
logmsg("Upgraded connection, this is no longer HTTP/1");
send_doc(sock, req);
sws_send_doc(sock, req);
/* dump the request received so far to the external file */
reqbuf[req->offset] = '\0';
storerequest(reqbuf, req->offset);
sws_storerequest(reqbuf, req->offset);
req->offset = 0;
/* read websocket traffic */
@ -906,7 +897,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
logmsg("log the websocket traffic");
/* dump the incoming websocket traffic to the external file */
reqbuf[req->offset] = '\0';
storerequest(reqbuf, req->offset);
sws_storerequest(reqbuf, req->offset);
req->offset = 0;
}
init_httprequest(req);
@ -945,7 +936,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
if(fail) {
/* dump the request received so far to the external file */
reqbuf[req->offset] = '\0';
storerequest(reqbuf, req->offset);
sws_storerequest(reqbuf, req->offset);
return -1;
}
@ -954,7 +945,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
req->offset += (size_t)got;
reqbuf[req->offset] = '\0';
req->done_processing = ProcessRequest(req);
req->done_processing = sws_ProcessRequest(req);
if(got_exit_signal)
return -1;
}
@ -976,7 +967,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
/* at the end of a request dump it to an external file */
if(fail || req->done_processing)
storerequest(reqbuf, req->offset);
sws_storerequest(reqbuf, req->offset);
if(got_exit_signal)
return -1;
@ -984,7 +975,7 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
}
/* returns -1 on failure */
static int send_doc(curl_socket_t sock, struct httprequest *req)
static int sws_send_doc(curl_socket_t sock, struct sws_httprequest *req)
{
ssize_t written;
size_t count;
@ -1036,7 +1027,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
switch(req->testno) {
case DOCNUMBER_QUIT:
logmsg("Replying to QUIT");
buffer = docquit;
buffer = docquit_sws;
break;
case DOCNUMBER_WERULEZ:
/* we got a "friends?" question, reply back that we sure are */
@ -1130,11 +1121,11 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
logmsg("connection close instruction \"swsclose\" found in response");
}
if(strstr(buffer, "swsbounce")) {
prevbounce = TRUE;
sws_prevbounce = TRUE;
logmsg("enable \"swsbounce\" in the next request");
}
else
prevbounce = FALSE;
sws_prevbounce = FALSE;
dump = fopen(responsedump, "ab");
if(!dump) {
@ -1204,8 +1195,8 @@ retry:
logmsg("Sending response failed. Only (%zu bytes) of (%zu bytes) "
"were sent",
responsesize-count, responsesize);
prevtestno = req->testno;
prevpartno = req->partno;
sws_prevtestno = req->testno;
sws_prevpartno = req->partno;
free(ptr);
free(cmd);
return -1;
@ -1252,8 +1243,8 @@ retry:
free(cmd);
req->open = use_gopher ? FALSE : persistent;
prevtestno = req->testno;
prevpartno = req->partno;
sws_prevtestno = req->testno;
sws_prevpartno = req->partno;
return 0;
}
@ -1586,7 +1577,7 @@ static void http_connect(curl_socket_t *infdp,
/* a new connection on listener socket (most likely from client) */
curl_socket_t datafd = accept(rootfd, NULL, NULL);
if(datafd != CURL_SOCKET_BAD) {
static struct httprequest *req2;
static struct sws_httprequest *req2;
int err = 0;
if(!req2) {
req2 = malloc(sizeof(*req2));
@ -1606,7 +1597,7 @@ static void http_connect(curl_socket_t *infdp,
#endif
init_httprequest(req2);
while(!req2->done_processing) {
err = get_request(datafd, req2);
err = sws_get_request(datafd, req2);
if(err < 0) {
/* this socket must be closed, done or not */
break;
@ -1615,7 +1606,7 @@ static void http_connect(curl_socket_t *infdp,
/* skip this and close the socket if err < 0 */
if(err >= 0) {
err = send_doc(datafd, req2);
err = sws_send_doc(datafd, req2);
if(!err && req2->connect_request) {
/* sleep to prevent triggering libcurl known bug #39. */
for(loop = 2; (loop > 0) && !got_exit_signal; loop--)
@ -1849,7 +1840,7 @@ http_connect_cleanup:
*infdp = CURL_SOCKET_BAD;
}
static void http_upgrade(struct httprequest *req)
static void http_upgrade(struct sws_httprequest *req)
{
(void)req;
logmsg("Upgraded to ... %u", req->upgrade_request);
@ -1938,7 +1929,8 @@ static curl_socket_t accept_connection(curl_socket_t sock)
/* returns 1 if the connection should be serviced again immediately, 0 if there
is no data waiting, or < 0 if it should be closed */
static int service_connection(curl_socket_t msgsock, struct httprequest *req,
static int service_connection(curl_socket_t msgsock,
struct sws_httprequest *req,
curl_socket_t listensock,
const char *connecthost,
int keepalive_secs)
@ -1947,27 +1939,27 @@ static int service_connection(curl_socket_t msgsock, struct httprequest *req,
return -1;
while(!req->done_processing) {
int rc = get_request(msgsock, req);
int rc = sws_get_request(msgsock, req);
if(rc <= 0) {
/* Nothing further to read now, possibly because the socket was closed */
return rc;
}
}
if(prevbounce) {
if(sws_prevbounce) {
/* bounce treatment requested */
if(req->testno == prevtestno) {
req->partno = prevpartno + 1;
if(req->testno == sws_prevtestno) {
req->partno = sws_prevpartno + 1;
logmsg("BOUNCE part number to %ld", req->partno);
}
else {
prevbounce = FALSE;
prevtestno = -1;
prevpartno = -1;
sws_prevbounce = FALSE;
sws_prevtestno = -1;
sws_prevpartno = -1;
}
}
send_doc(msgsock, req);
sws_send_doc(msgsock, req);
if(got_exit_signal)
return -1;
@ -2019,19 +2011,16 @@ int main(int argc, char *argv[])
int wrotepidfile = 0;
int wroteportfile = 0;
int flag;
unsigned short port = DEFAULT_PORT;
unsigned short port = 8999;
#ifdef USE_UNIX_SOCKETS
const char *unix_socket = NULL;
bool unlink_socket = false;
#endif
const char *pidname = ".http.pid";
const char *portname = ".http.port";
struct httprequest *req = NULL;
struct sws_httprequest *req = NULL;
int rc = 0;
int error;
int arg = 1;
const char *connecthost = "127.0.0.1";
const char *socket_type = "IPv4";
char port_str[11];
const char *location_str = port_str;
int keepalive_secs = 5;
@ -2040,7 +2029,10 @@ int main(int argc, char *argv[])
/* a default CONNECT port is basically pointless but still ... */
size_t socket_idx;
pidname = ".http.pid";
portname = ".http.port";
serverlogfile = "log/sws.log";
serverlogslocked = 0;
while(argc > arg) {
if(!strcmp("--version", argv[arg])) {
@ -2337,8 +2329,8 @@ int main(int argc, char *argv[])
if(!wroteportfile)
goto sws_cleanup;
/* initialization of httprequest struct is done before get_request(), but
the pipelining struct field must be initialized previously to FALSE
/* initialization of httprequest struct is done before sws_get_request(),
but the pipelining struct field must be initialized previously to FALSE
every time a new connection arrives. */
init_httprequest(req);
@ -2440,7 +2432,7 @@ int main(int argc, char *argv[])
if(req->connmon) {
const char *keepopen = "[DISCONNECT]\n";
storerequest(keepopen, strlen(keepopen));
sws_storerequest(keepopen, strlen(keepopen));
}
if(!req->open)

View File

@ -152,8 +152,6 @@ struct bf {
#define REQUEST_DUMP "server.input"
#define DEFAULT_PORT 8999 /* UDP */
/*****************************************************************************
* GLOBAL VARIABLES *
*****************************************************************************/
@ -185,7 +183,7 @@ static int current; /* index of buffer in use */
static int newline = 0; /* fillbuf: in middle of newline expansion */
static int prevchar = -1; /* putbuf: previous char (cr check) */
static tftphdr_storage_t buf;
static tftphdr_storage_t trsbuf;
static tftphdr_storage_t ackbuf;
static srvr_sockaddr_union_t from;
@ -196,18 +194,8 @@ static curl_socket_t peer = CURL_SOCKET_BAD;
static unsigned int timeout;
static unsigned int maxtimeout = 5 * TIMEOUT;
#ifdef USE_IPV6
static bool use_ipv6 = FALSE;
#endif
static const char *ipv_inuse = "IPv4";
static const char *logdir = "log";
static char loglockfile[256];
static const char *pidname = ".tftpd.pid";
static const char *portname = NULL; /* none by default */
static int serverlogslocked = 0;
static int wrotepidfile = 0;
static int wroteportfile = 0;
static int tftpd_wrotepidfile = 0;
static int tftpd_wroteportfile = 0;
#ifdef HAVE_SIGSETJMP
static sigjmp_buf timeoutbuf;
@ -282,12 +270,12 @@ static void timer(int signum)
timeout += rexmtval;
if(timeout >= maxtimeout) {
if(wrotepidfile) {
wrotepidfile = 0;
if(tftpd_wrotepidfile) {
tftpd_wrotepidfile = 0;
unlink(pidname);
}
if(wroteportfile) {
wroteportfile = 0;
if(tftpd_wroteportfile) {
tftpd_wroteportfile = 0;
unlink(portname);
}
if(serverlogslocked) {
@ -549,7 +537,7 @@ int main(int argc, char **argv)
struct tftphdr *tp;
ssize_t n = 0;
int arg = 1;
unsigned short port = DEFAULT_PORT;
unsigned short port = 8999; /* UDP */
curl_socket_t sock = CURL_SOCKET_BAD;
int flag;
int rc;
@ -559,7 +547,9 @@ int main(int argc, char **argv)
memset(&test, 0, sizeof(test));
pidname = ".tftpd.pid";
serverlogfile = "log/tftpd.log";
serverlogslocked = 0;
while(argc > arg) {
if(!strcmp("--version", argv[arg])) {
@ -743,15 +733,15 @@ int main(int argc, char **argv)
}
}
wrotepidfile = write_pidfile(pidname);
if(!wrotepidfile) {
tftpd_wrotepidfile = write_pidfile(pidname);
if(!tftpd_wrotepidfile) {
result = 1;
goto tftpd_cleanup;
}
if(portname) {
wroteportfile = write_portfile(portname, port);
if(!wroteportfile) {
tftpd_wroteportfile = write_portfile(portname, port);
if(!tftpd_wroteportfile) {
result = 1;
goto tftpd_cleanup;
}
@ -769,7 +759,7 @@ int main(int argc, char **argv)
else
fromlen = sizeof(from.sa6);
#endif
n = (ssize_t)recvfrom(sock, &buf.storage[0], sizeof(buf.storage), 0,
n = (ssize_t)recvfrom(sock, &trsbuf.storage[0], sizeof(trsbuf.storage), 0,
&from.sa, &fromlen);
if(got_exit_signal)
break;
@ -817,7 +807,7 @@ int main(int argc, char **argv)
maxtimeout = 5*TIMEOUT;
tp = &buf.hdr;
tp = &trsbuf.hdr;
tp->th_opcode = ntohs(tp->th_opcode);
if(tp->th_opcode == opcode_RRQ || tp->th_opcode == opcode_WRQ) {
memset(&test, 0, sizeof(test));
@ -854,9 +844,9 @@ tftpd_cleanup:
if(got_exit_signal)
logmsg("signalled to die");
if(wrotepidfile)
if(tftpd_wrotepidfile)
unlink(pidname);
if(wroteportfile)
if(tftpd_wroteportfile)
unlink(portname);
if(serverlogslocked) {
@ -916,7 +906,7 @@ static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
filename = cp;
do {
bool endofit = true;
while(cp < &buf.storage[size]) {
while(cp < &trsbuf.storage[size]) {
if(*cp == '\0') {
endofit = false;
break;
@ -929,7 +919,7 @@ static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
/* before increasing pointer, make sure it is still within the legal
space */
if((cp + 1) < &buf.storage[size]) {
if((cp + 1) < &trsbuf.storage[size]) {
++cp;
if(first) {
/* store the mode since we need it later */
@ -1003,7 +993,7 @@ static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
}
/* Based on the testno, parse the correct server commands. */
static int parse_servercmd(struct testcase *req)
static int tftpd_parse_servercmd(struct testcase *req)
{
FILE *stream;
int error;
@ -1117,7 +1107,7 @@ static int validate_access(struct testcase *test,
test->testno = testno;
(void)parse_servercmd(test);
(void)tftpd_parse_servercmd(test);
stream = test2fopen(testno, logdir);
@ -1324,7 +1314,7 @@ send_ack:
alarm(rexmtval);
#endif
/* normally times out and quits */
n = sread(peer, &buf.storage[0], sizeof(buf.storage));
n = sread(peer, &trsbuf.storage[0], sizeof(trsbuf.storage));
#ifdef HAVE_ALARM
alarm(0);
#endif
@ -1354,7 +1344,7 @@ static void nak(int error)
int length;
struct errmsg *pe;
tp = &buf.hdr;
tp = &trsbuf.hdr;
tp->th_opcode = htons(opcode_ERROR);
tp->th_code = htons((unsigned short)error);
for(pe = errmsgs; pe->e_code >= 0; pe++)
@ -1370,6 +1360,6 @@ static void nak(int error)
* report from glibc with FORTIFY_SOURCE */
memcpy(tp->th_msg, pe->e_msg, length + 1);
length += 5;
if(swrite(peer, &buf.storage[0], length) != length)
if(swrite(peer, &trsbuf.storage[0], length) != length)
logmsg("nak: fail\n");
}

View File

@ -36,11 +36,6 @@
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#elif defined(HAVE_SYS_POLL_H)
#include <sys/poll.h>
#endif
#ifdef MSDOS
#include <dos.h> /* delay() */
@ -53,10 +48,23 @@
#include "curlx.h" /* from the private lib dir */
#include "getpart.h"
#include "util.h"
#include "timeval.h"
#include "timediff.h"
const char *serverlogfile = NULL; /* needs init from main() */
/* need init from main() */
const char *pidname = NULL;
const char *portname = NULL; /* none by default */
const char *serverlogfile = NULL;
int serverlogslocked;
const char *configfile = NULL;
const char *logdir = "log";
char loglockfile[256];
#ifdef USE_IPV6
bool use_ipv6 = FALSE;
#endif
const char *ipv_inuse = "IPv4";
unsigned short server_port = 0;
const char *socket_type = "IPv4";
int socket_domain = AF_INET;
static struct timeval tvnow(void);
@ -137,6 +145,31 @@ void logmsg(const char *msg, ...)
}
}
void loghex(unsigned char *buffer, ssize_t len)
{
char data[12000];
ssize_t i;
unsigned char *ptr = buffer;
char *optr = data;
ssize_t width = 0;
int left = sizeof(data);
for(i = 0; i < len && (left >= 0); i++) {
msnprintf(optr, left, "%02x", ptr[i]);
width += 2;
optr += 2;
left -= 2;
}
if(width)
logmsg("'%s'", data);
}
unsigned char byteval(char *value)
{
unsigned long num = strtoul(value, NULL, 10);
return num & 0xff;
}
#ifdef _WIN32
/* use instead of perror() on generic Windows */
static void win32_perror(const char *msg)
@ -239,13 +272,6 @@ static long timediff(struct timeval newer, struct timeval older)
*/
int wait_ms(int timeout_ms)
{
#if !defined(MSDOS) && !defined(USE_WINSOCK)
#ifndef HAVE_POLL
struct timeval pending_tv;
#endif
struct timeval initial_tv;
int pending_ms;
#endif
int r = 0;
if(!timeout_ms)
@ -259,26 +285,27 @@ int wait_ms(int timeout_ms)
#elif defined(USE_WINSOCK)
Sleep((DWORD)timeout_ms);
#else
pending_ms = timeout_ms;
initial_tv = tvnow();
do {
int error;
#ifdef HAVE_POLL
r = poll(NULL, 0, pending_ms);
#else
pending_tv.tv_sec = pending_ms / 1000;
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
r = select(0, NULL, NULL, NULL, &pending_tv);
#endif /* HAVE_POLL */
if(r != -1)
break;
error = errno;
if(error && (error != EINTR))
break;
pending_ms = timeout_ms - (int)timediff(tvnow(), initial_tv);
if(pending_ms <= 0)
break;
} while(r == -1);
/* avoid using poll() for this since it behaves incorrectly with no sockets
on Apple operating systems */
{
struct timeval pending_tv;
struct timeval initial_tv = tvnow();
int pending_ms = timeout_ms;
do {
int error;
pending_tv.tv_sec = pending_ms / 1000;
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
r = select(0, NULL, NULL, NULL, &pending_tv);
if(r != -1)
break;
error = errno;
if(error && (error != EINTR))
break;
pending_ms = timeout_ms - (int)timediff(tvnow(), initial_tv);
if(pending_ms <= 0)
break;
} while(r == -1);
}
#endif /* USE_WINSOCK */
if(r)
r = -1;

View File

@ -51,14 +51,27 @@ enum {
char *data_to_hex(char *data, size_t len);
void logmsg(const char *msg, ...) CURL_PRINTF(1, 2);
void loghex(unsigned char *buffer, ssize_t len);
unsigned char byteval(char *value);
#define SERVERLOGS_LOCKDIR "lock" /* within logdir */
/* global variable, where to find the 'data' dir */
extern const char *path;
/* global variable, log file name */
extern const char *serverlogfile;
/* global variables */
extern const char *path; /* where to find the 'data' dir */
extern const char *pidname;
extern const char *portname;
extern const char *serverlogfile; /* log file name */
extern int serverlogslocked;
extern const char *configfile;
extern const char *logdir;
extern char loglockfile[256];
#ifdef USE_IPV6
extern bool use_ipv6;
#endif
extern const char *ipv_inuse;
extern unsigned short server_port;
extern const char *socket_type;
extern int socket_domain;
#ifdef _WIN32
int win32_init(void);