Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIXED] Connection fails if URL is missing port #531

Merged
merged 1 commit into from
Mar 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/natsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@
#define WAIT_FOR_WRITE (1)
#define WAIT_FOR_CONNECT (2)

#define DEFAULT_PORT_STRING "4222"

#define DEFAULT_DRAIN_TIMEOUT 30000 // 30 seconds

#define MAX_FRAMES (50)
Expand Down
215 changes: 90 additions & 125 deletions src/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,61 +46,21 @@ _parsePort(int *port, const char *sport)
return s;
}

static natsStatus
_parseHostAndPort(natsUrl *url, char *host, bool uInfo)
{
natsStatus s = NATS_OK;
char *sport = NULL;

sport = strrchr(host, ':');
if (sport != NULL)
{
const char *startPort = (const char*) (sport+1);
char *endPort = strchr(startPort, '/');

if (endPort != NULL)
*endPort = '\0';

s = _parsePort(&(url->port), startPort);
if (s != NATS_OK)
return NATS_UPDATE_ERR_STACK(s);

*sport = '\0';
}

if (uInfo)
{
url->host = NATS_STRDUP(host + 1);
*host = '\0';

if (url->host == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
}
else
{
if (*host == '\0')
url->host = NATS_STRDUP("localhost");
else
url->host = NATS_STRDUP(host);
if (url->host == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
}

return NATS_UPDATE_ERR_STACK(s);
}

natsStatus
natsUrl_Create(natsUrl **newUrl, const char *urlStr)
{
natsStatus s = NATS_OK;
bool uInfo = false;
char *copy = NULL;
char *ptr = NULL;
char *host = NULL;
char *pwd = NULL;
const char *scheme= NULL;
const char *user = NULL;
const char *pwd = NULL;
const char *host = NULL;
const char *port = NULL;
const char *path = NULL;
natsUrl *url = NULL;

if ((urlStr == NULL) || (strlen(urlStr) == 0))
if (nats_IsStringEmpty(urlStr))
return nats_setDefaultError(NATS_INVALID_ARG);

url = (natsUrl*) NATS_CALLOC(1, sizeof(natsUrl));
Expand All @@ -109,107 +69,112 @@ natsUrl_Create(natsUrl **newUrl, const char *urlStr)

s = nats_Trim(&copy, urlStr);

// Add scheme if missing.
if ((s == NATS_OK) && (strstr(copy, "://") == NULL))
// Scheme
if (s == NATS_OK)
{
char *str = NULL;

if (nats_asprintf(&str, "nats://%s", copy) == -1)
s = nats_setDefaultError(NATS_NO_MEMORY);
ptr = strstr(copy, "://");
if (ptr == NULL)
{
scheme = "nats";
ptr = copy;
}
else
{
NATS_FREE(copy);
copy = str;
*ptr = '\0';
scheme = (const char*) copy;
ptr += 3;
}
}
// Add default host/port if missing.
// User info
if (s == NATS_OK)
{
char *start = NULL;
char *sep = strrchr(ptr, '@');

// Now that we know that there is a scheme, move past it.
start = strstr(copy, "://");
start += 3;

// If we are at then end, will add "localhost:4222".
if (*start != '\0')
if (sep != NULL)
{
// First, search for end of IPv6 address (if applicable)
ptr = strrchr(start, ']');
if (ptr == NULL)
ptr = start;
host = (const char*) (sep+1);
*sep = '\0';

// From that point, search for the last ':' character
ptr = strrchr(ptr, ':');
}
if ((*start == '\0') || (ptr == NULL) || (*(ptr+1) == '\0'))
{
char *str = NULL;
int res = 0;

if (*start == '\0')
res = nats_asprintf(&str, "%slocalhost:%s", copy, DEFAULT_PORT_STRING);
else if (ptr != NULL)
res = nats_asprintf(&str, "%s%s", copy, DEFAULT_PORT_STRING);
else
res = nats_asprintf(&str, "%s:%s", copy, DEFAULT_PORT_STRING);

if (res == -1)
s = nats_setDefaultError(NATS_NO_MEMORY);
else
if (ptr != sep)
{
NATS_FREE(copy);
copy = str;
sep = strchr(ptr, ':');
if (sep != NULL)
{
*sep = '\0';
if (sep != ptr)
user = (const char*) ptr;
if (sep+1 != host)
pwd = (const char*) (sep+1);
}
else
{
user = (const char*) ptr;
}
}
}
else
{
host = (const char*) ptr;
}
}

// Keep a copy of the full URL.
// Host
if (s == NATS_OK)
{
url->fullUrl = NATS_STRDUP(copy);
if (url->fullUrl == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
}

// At this point, we are guaranteed to have '://' in the string
if ((s == NATS_OK)
&& ((ptr = strstr(copy, "://")) != NULL)
&& (*(ptr += 3) != '\0'))
{
// If '@' is present, everything after is the host
// everything before is username/password combo.

host = strrchr(ptr, '@');
if (host != NULL)
uInfo = true;
else
host = ptr;

if ((host != NULL) && (host[1] != '\0'))
// Search for end of IPv6 address (if applicable)
ptr = strrchr(host, ']');
if (ptr == NULL)
ptr = (char*) host;

// From that point, search for the last ':' character
ptr = strrchr(ptr, ':');
if (ptr != NULL)
{
s = _parseHostAndPort(url, host, uInfo);
*ptr = '\0';
port = (const char*) (ptr+1);
}

if ((s == NATS_OK) && uInfo)
if (nats_IsStringEmpty(host))
host = "localhost";
}
// Port
if (s == NATS_OK)
{
if (port != NULL)
{
pwd = strchr(ptr, ':');
if ((pwd != NULL) && (pwd[1] != '\0'))
{
url->password = NATS_STRDUP(pwd + 1);
*pwd = '\0';

if (url->password == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
}
char *sep = strchr(port, '/');

if ((s == NATS_OK) && (strlen(ptr) > 0))
if (sep != NULL)
{
url->username = NATS_STRDUP(ptr);
if (url->username == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
*sep = '\0';
path = (const char*) (sep+1);
}
}
if (nats_IsStringEmpty(port))
url->port = 4222;
else
s = _parsePort(&url->port, port);
}
// Assemble everything
if (s == NATS_OK)
{
const char *userval = (nats_IsStringEmpty(user) ? "" : user);
const char *usep = (nats_IsStringEmpty(pwd) ? "" : ":");
const char *pwdval = (nats_IsStringEmpty(pwd) ? "" : pwd);
const char *hsep = (nats_IsStringEmpty(user) ? "" : "@");
const char *pathsep = (nats_IsStringEmpty(path) ? "" : "/");
const char *pathval = (nats_IsStringEmpty(path) ? "" : path);

DUP_STRING(s, url->host, host);

if (user != NULL)
IF_OK_DUP_STRING(s, url->username, user);
if (pwd != NULL)
IF_OK_DUP_STRING(s, url->password, pwd);

if ((s == NATS_OK) && nats_asprintf(&url->fullUrl, "%s://%s%s%s%s%s:%d%s%s",
scheme, userval, usep, pwdval, hsep, host, url->port, pathsep, pathval) < 0)
{
s = nats_setDefaultError(NATS_NO_MEMORY);
}
}

NATS_FREE(copy);
Expand Down
Loading