~rcr/rirc

fd8384dfb3683e5614b91bb391c710be89c14feb — Richard Robbins 1 year, 2 months ago 5e441c6
add --ipv4, --ipv6 flags
7 files changed, 54 insertions(+), 18 deletions(-)

M CHANGELOG
M README.md
M src/io.c
M src/io.h
M src/rirc.c
M src/state.c
M test/io.mock.c
M CHANGELOG => CHANGELOG +3 -1
@@ 4,6 4,8 @@ Summary of notable changes and features
## Unreleased (dev)
### Features
 - add command :disconnect
 - add cli option `--ipv4`
 - add cli option `--ipv6`
 - add SSL support
    - add mbedtls git submodule
    - add CA_CERT_PATH define to config.h


@@ 12,7 14,7 @@ Summary of notable changes and features
    - add command /cap-ls
    - add command /cap-list
 - changed standard versions
    - c99 -> c11
    - c99          -> c11
    - POSIX.1-2001 -> POSIX.1-2008
### Fixes


M README.md => README.md +5 -1
@@ 72,7 72,7 @@ Help:
  -h, --help      Print this message and exit
  -v, --version   Print rirc version and exit

Options:
Server options:
  -s, --server=SERVER       Connect to SERVER
  -p, --port=PORT           Connect to SERVER using PORT
  -w, --pass=PASS           Connect to SERVER using PASS


@@ 80,6 80,10 @@ Options:
  -r, --realname=REALNAME   Connect to SERVER using REALNAME
  -n, --nicks=NICKS         Comma separated list of nicks to use for SERVER
  -c, --chans=CHANNELS      Comma separated list of channels to join for SERVER

Connection options:
      --ipv4                Connect to only ipv4 addresses
      --ipv6                Connect to only ipv6 addresses
```

Commands:

M src/io.c => src/io.c +9 -1
@@ 127,6 127,7 @@ struct connection
	mbedtls_ssl_context tls_ctx;
	pthread_mutex_t mtx;
	pthread_t tid;
	uint8_t flags;
	unsigned ping;
	unsigned rx_sleep;
};


@@ 163,7 164,7 @@ static int io_net_connect(struct connection*);
static void io_net_close(int);

struct connection*
connection(const void *obj, const char *host, const char *port)
connection(const void *obj, const char *host, const char *port, uint8_t flags)
{
	struct connection *cx;



@@ 171,6 172,7 @@ connection(const void *obj, const char *host, const char *port)
		fatal("malloc: %s", strerror(errno));

	cx->obj = obj;
	cx->flags = flags;
	cx->host = strdup(host);
	cx->port = strdup(port);
	cx->st_cur = IO_ST_DXED;


@@ 826,6 828,12 @@ io_net_connect(struct connection *cx)
		.ai_socktype = SOCK_STREAM,
	};

	if (cx->flags & IO_IPV_4)
		hints.ai_family = AF_INET;

	if (cx->flags & IO_IPV_6)
		hints.ai_family = AF_INET6;

	errno = 0;

	if ((ret = getaddrinfo(cx->host, cx->port, &hints, &res)) != 0) {

M src/io.h => src/io.h +9 -4
@@ 73,8 73,9 @@
 * a call to io_stop
 */

#include <stddef.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>

struct connection;



@@ 107,11 108,15 @@ enum io_sig_t
	IO_SIG_SIZE
};

#define IO_IPV_4 (1 << 1)
#define IO_IPV_6 (1 << 2)

/* Returns a connection, or NULL if limit is reached */
struct connection* connection(
	const void*,  /* callback object */
	const char*,  /* host */
	const char*); /* port */
	const void*, /* callback object */
	const char*, /* host */
	const char*, /* port */
	uint8_t);    /* flags */

void connection_free(struct connection*);


M src/rirc.c => src/rirc.c +25 -9
@@ 92,6 92,8 @@ opt_arg_str(char c)
		case 'c': return "-c/--chans";
		case 'u': return "-u/--username";
		case 'r': return "-r/--realname";
		case '4': return "--ipv4";
		case '6': return "--ipv6";
		default:
			fatal("unknown option flag '%c'", c);
	}


@@ 136,6 138,8 @@ parse_args(int argc, char **argv)
		{"realname", required_argument, 0, 'r'},
		{"help",     no_argument,       0, 'h'},
		{"version",  no_argument,       0, 'v'},
		{"ipv4",     no_argument,       0, '4'},
		{"ipv6",     no_argument,       0, '6'},
		{0, 0, 0, 0}
	};



@@ 147,6 151,7 @@ parse_args(int argc, char **argv)
		const char *chans;
		const char *username;
		const char *realname;
		uint8_t flags;
		struct server *s;
	} cli_servers[MAX_CLI_SERVERS];



@@ 170,44 175,55 @@ parse_args(int argc, char **argv)
				cli_servers[n_servers - 1].chans = NULL;
				cli_servers[n_servers - 1].username = NULL;
				cli_servers[n_servers - 1].realname = NULL;
				cli_servers[n_servers - 1].flags = 0;
				break;

			#define CHECK_SERVER_OPTARG(OPT_C) \
				if (*optarg == '-') \
			#define CHECK_SERVER_OPTARG(OPT_C, REQ) \
				if ((REQ) && *optarg == '-') \
					arg_error("option '%s' requires an argument", opt_arg_str((OPT_C))); \
				if (n_servers == 0) \
					arg_error("option '%s' requires a server argument first", opt_arg_str((OPT_C)));

			case 'p': /* Connect using port */
				CHECK_SERVER_OPTARG(opt_c);
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].port = optarg;
				break;

			case 'w': /* Connect using port */
				CHECK_SERVER_OPTARG(opt_c);
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].pass = optarg;
				break;

			case 'n': /* Comma separated list of nicks to use */
				CHECK_SERVER_OPTARG(opt_c);
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].nicks = optarg;
				break;

			case 'c': /* Comma separated list of channels to join */
				CHECK_SERVER_OPTARG(opt_c);
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].chans = optarg;
				break;

			case 'u': /* Connect using username */
				CHECK_SERVER_OPTARG(opt_c);
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].username = optarg;
				break;

			case 'r': /* Connect using realname */
				CHECK_SERVER_OPTARG(opt_c);
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].realname = optarg;
				break;

			case '4':
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].flags |= IO_IPV_4;
				break;

			case '6':
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].flags |= IO_IPV_6;
				break;

			#undef CHECK_SERVER_OPTARG

			case 'h':


@@ 254,7 270,7 @@ parse_args(int argc, char **argv)
			(cli_servers[i].realname ? cli_servers[i].realname : default_realname)
		);

		s->connection = connection(s, cli_servers[i].host, cli_servers[i].port);
		s->connection = connection(s, cli_servers[i].host, cli_servers[i].port, cli_servers[i].flags);

		if (server_list_add(state_server_list(), s))
			arg_error("duplicate server: %s:%s", cli_servers[i].host, cli_servers[i].port);

M src/state.c => src/state.c +1 -1
@@ 828,7 828,7 @@ command(struct channel *c, char *buf)
				newlinef(s->channel, 0, "-!!-", "already connected to %s:%s", host, port);
			} else {
				s = server(host, port, pass, user, real);
				s->connection = connection(s, host, port);
				s->connection = connection(s, host, port, 0);
				server_list_add(state_server_list(), s);
				channel_set_current(s->channel);
				io_cx(s->connection);

M test/io.mock.c => test/io.mock.c +2 -1
@@ 35,11 35,12 @@ io_sendf(struct connection *c, const char *fmt, ...)
}

struct connection*
connection(const void *o, const char *h, const char *p)
connection(const void *o, const char *h, const char *p, uint8_t f)
{
	UNUSED(o);
	UNUSED(h);
	UNUSED(p);
	UNUSED(f);
	return NULL;
}