shithub: catphone

Download patch

ref: 2e99eaaea1aa6776eda10f5ec8bd90adcfe8424a
author: rodri <rgl@antares-labs.eu>
date: Sun Jul 23 18:52:31 EDT 2023

layed out initial structures. began work on registration procedure.

--- /dev/null
+++ b/alloc.c
@@ -1,0 +1,44 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+void *
+emalloc(ulong n)
+{
+	void *p;
+
+	p = malloc(n);
+	if(p == nil)
+		sysfatal("malloc: %r");
+	setmalloctag(p, getcallerpc(&n));
+	return p;
+}
+
+void *
+erealloc(void *p, ulong n)
+{
+	void *np;
+
+	np = realloc(p, n);
+	if(np == nil){
+		if(n == 0)
+			return nil;
+		sysfatal("realloc: %r");
+	}
+	if(p == nil)
+		setmalloctag(np, getcallerpc(&p));
+	else
+		setrealloctag(np, getcallerpc(&p));
+	return np;
+}
+
+Image *
+eallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong col)
+{
+	Image *i;
+
+	i = allocimage(d, r, chan, repl, col);
+	if(i == nil)
+		sysfatal("allocimage: %r");
+	return i;
+}
--- /dev/null
+++ b/dat.h
@@ -1,0 +1,117 @@
+typedef enum {
+	REGISTER,
+	INVITE,
+	ACK,
+	BYE,
+	CANCEL,
+	OPTIONS,
+	NOTIFY,
+	SUBSCRIBE,
+	INFO,
+	MESSAGE,
+	UPDATE,
+	REFER
+} SipMethod;
+
+/* rfc3261 § 21 - Response Codes */
+typedef enum {
+	/* 1xx Provisional */
+	Trying		= 100,
+	Ringing		= 180,
+	CallForwarded	= 181,
+	Queued		= 182,
+	SessionProgress	= 183,
+
+	/* 2xx Successful */
+	OK		= 200,
+
+	/* 3xx Redirection */
+	MultiChoice		= 300,
+	MovedPerm		= 301,
+	MovedTemp		= 302,
+	UseProxy		= 305,
+	AltService		= 380,
+
+	/* 4xx Request Failure */
+	BadRequest		= 400,
+	Unauthorized		= 401,
+	PaymentRequired		= 402,
+	Forbidden		= 403,
+	NotFound		= 404,
+	MethodNotAllowed	= 405,
+	RequestNotAcceptable	= 406,
+	ProxyAuthRequired	= 407,
+	RequestTimeout		= 408,
+	Gone			= 410,
+	EntityTooLarge		= 413,
+	URITooLong		= 414,
+	UnsupportedMedia	= 415,
+	UnsupportedURIScheme	= 416,
+	BadExtension		= 420,
+	ExtensionRequired	= 421,
+	IntervalTooBrief	= 423,
+	TempUnavailable		= 480,
+	CallDoesNotExist	= 481,
+	LoopDetected		= 482,
+	TooManyHops		= 483,
+	AddressIncomplete	= 484,
+	Ambiguous		= 485,
+	BusyHere		= 486,
+	RequestTerminated	= 487,
+	NotAcceptableHere	= 488,
+	RequestPending		= 491,
+	Undecipherable		= 493,
+
+	/* 5xx Server Failure */
+	InternalError		= 500,
+	NotImplemented		= 501,
+	BadGateway		= 502,
+	ServiceUnavailable	= 503,
+	ServerTimeout		= 504,
+	VersionNotSupported	= 505,
+	MessageTooLarge		= 513,
+
+	/* 6xx Global Failures */
+	BusyEverywhere		= 600,
+	Decline			= 603,
+	DoesNotExistAnywhere	= 604,
+	NotAcceptable		= 606,
+	
+} SipStatus;
+
+typedef struct Hdr Hdr;
+typedef struct Hdrtab Hdrtab;
+typedef struct Sipmsg Sipmsg;
+typedef struct Sip Sip;
+
+struct Hdr
+{
+	char *name;
+	char *value;
+	Hdr *next;
+};
+
+struct Hdrtab
+{
+	Hdr *headers[13];
+};
+
+struct Sipmsg
+{
+	Hdrtab;
+	char *version;
+	SipMethod method;
+};
+
+/* SIP UAC (see rfc3261 § 8.1, 12.1.2) */
+struct Sip
+{
+	int version;
+
+	NetConnInfo *nci;
+	int fd;
+
+	int (*reg)(Sip*, char*, char*);
+};
+
+extern int debug;
--- /dev/null
+++ b/fns.h
@@ -1,0 +1,10 @@
+void *emalloc(ulong);
+void *erealloc(void*, ulong);
+Image *eallocimage(Display*, Rectangle, ulong, int, ulong);
+
+void addheader(Hdrtab*, char*, char*);
+Hdr *getheader(Hdrtab*, char*);
+void delheader(Hdrtab*, char*);
+
+Sip *mksip(int);
+void rmsip(Sip*);
--- /dev/null
+++ b/main.c
@@ -1,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include "dat.h"
+#include "fns.h"
+
+int debug;
+
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-d] addr username password\n", argv0);
+	exits("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+	Sip *sip;
+	char *addr;
+	int fd;
+
+	ARGBEGIN{
+	default: usage();
+	case 'd':
+		debug++;
+		break;
+	}ARGEND;
+	if(argc != 3)
+		usage();
+
+	addr = netmkaddr(argv[0], "udp", "sip");
+	if(debug)
+		fprint(2, "connecting to %s\n", addr);
+
+	fd = dial(addr, nil, nil, nil);
+	if(fd < 0)
+		sysfatal("couldn't establish the connection");
+
+	if(debug)
+		fprint(2, "connection established\n");
+
+	sip = mksip(fd);
+	if(sip == nil)
+		sysfatal("mksip: %r");
+	sip->reg(sip, argv[1], argv[2]);
+	rmsip(sip);
+
+	threadexitsall(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,25 @@
+</$objtype/mkfile
+
+MAN=/sys/man/1
+BIN=/$objtype/bin
+TARG=\
+	catphone
+
+OFILES=\
+	main.$O\
+	alloc.$O\
+	sip.$O\
+
+HFILES=\
+	dat.h\
+	fns.h\
+
+</sys/src/cmd/mkone
+
+install:V: man
+
+uninstall:V:
+	for(i in $TARG){
+		rm -f $BIN/$i
+		rm -f $MAN/$i
+	}
--- /dev/null
+++ b/sip.c
@@ -1,0 +1,211 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include "dat.h"
+#include "fns.h"
+
+static char sipversion[] = "SIP/2.0";
+static char *methodstrtab[] = {
+ [REGISTER]	"REGISTER",
+ [INVITE]	"INVITE",
+ [ACK]		"ACK",
+ [BYE]		"BYE",
+ [CANCEL]	"CANCEL",
+ [OPTIONS]	"OPTIONS",
+ [NOTIFY]	"NOTIFY",
+ [SUBSCRIBE]	"SUBSCRIBE",
+ [INFO]		"INFO",
+ [MESSAGE]	"MESSAGE",
+ [UPDATE]	"UPDATE",
+ [REFER]	"REFER",
+};
+
+static char registerhdr0[] = "REGISTER sip:%s %s\r\n"
+	"Via: %s/UDP %s:%s;branch=z9hG4bK703d971c0c737b8e;rport\r\n"
+	"Contact: <sip:%s-0x82a66a010@%s:%s>;expires=3849\r\n"
+	"Max-Forwards: 70\r\n"
+	"To: <sip:%s@%s>\r\n"
+	"From: <sip:%s@%s>;tag=4a5a693256d38cbc\r\n"
+	"Call-ID: 2cee372fc4be4e45\r\n"
+	"CSeq: 16021 REGISTER\r\n"
+	"User-Agent: catphone (plan9front)\r\n"
+	"Allow: INVITE,ACK,BYE,CANCEL,OPTIONS,NOTIFY,SUBSCRIBE,INFO,MESSAGE,UPDATE,REFER\r\n"
+	"Content-Length: 0\r\n"
+	"\r\n";
+static char registerhdr[] = "REGISTER sip:10.0.0.104 SIP/2.0\r\n"
+	"Via: SIP/2.0/UDP 10.0.1.9:54022;branch=z9hG4bKdf800c31b9a88ffb;rport\r\n"
+	"Contact: <sip:sam-0x82a66a010@10.0.1.9:54022>;expires=3849\r\n"
+	"Max-Forwards: 70\r\n"
+	"Authorization: Digest username=\"sam\", realm=\"asterisk\", nonce=\"0d39ab10\", uri=\"sip:10.0.0.104\", response=\"a12e05b52604b5226763ce577d5c240b\", algorithm=MD5\r\n"
+	"To: <sip:sam@10.0.0.104>\r\n"
+	"From: <sip:sam@10.0.0.104>;tag=4a5a693256d38cbc\r\n"
+	"Call-ID: 2cee372fc4be4e45\r\n"
+	"CSeq: 16022 REGISTER\r\n"
+	"User-Agent: catphone (plan9front)\r\n"
+	"Allow: INVITE,ACK,BYE,CANCEL,OPTIONS,NOTIFY,SUBSCRIBE,INFO,MESSAGE,UPDATE,REFER\r\n"
+	"Content-Length: 0\r\n"
+	"\r\n";
+
+static char *
+getmethodstr(SipMethod m)
+{
+	return methodstrtab[m];
+}
+
+static uint
+hash(char *s)
+{
+	uint h;
+
+	h = 0x811c9dc5;
+	while(*s != 0)
+		h = (h^(uchar)*s++) * 0x1000193;
+	return h % 13;
+}
+
+void
+addheader(Hdrtab *ht, char *name, char *value)
+{
+	Hdr *h, *newh;
+	uint key;
+
+	key = hash(name);
+	newh = emalloc(sizeof(Hdr));
+	newh->name = strdup(name);
+	newh->value = strdup(value);
+	newh->next = nil;
+
+	h = ht->headers[key];
+	if(h == nil){
+		ht->headers[key] = newh;
+		return;
+	}
+	while(h->next != nil)
+		h = h->next;
+	h->next = newh;
+}
+
+Hdr *
+getheader(Hdrtab *ht, char *name)
+{
+	Hdr *h;
+	uint key;
+
+	key = hash(name);
+	for(h = ht->headers[key]; h != nil; h = h->next)
+		if(cistrcmp(h->name, name) == 0)
+			return h;
+	return nil;
+}
+
+void
+delheader(Hdrtab *ht, char *name)
+{
+	Hdr **h, *nh;
+	uint key;
+
+	key = hash(name);
+	h = &ht->headers[key];
+	while(*h != nil){
+		nh = (*h)->next;
+		if(cistrcmp((*h)->name, name) == 0){
+			free((*h)->name);
+			free((*h)->value);
+			free(*h);
+		}
+		*h = nh;
+	}
+}
+
+void
+delheaders(Hdrtab *ht)
+{
+	Hdr *h, *nh;
+	int i;
+
+	for(i = 0; i < nelem(ht->headers); i++)
+		for(h = ht->headers[i]; h != nil; h = nh){
+			nh = h->next;
+			free(h->name);
+			free(h->value);
+			free(h);
+		}
+}
+
+/* rfc3261 § 10 - Registrations */
+static int
+sip_register(Sip *s, char *user, char *pass)
+{
+	Biobuf *bin, *bout;
+	char *line, *p, *kv[2];
+	int n;
+
+	if((bin = Bfdopen(s->fd, OREAD)) == nil)
+		sysfatal("Bfdopen: %r");
+	if((bout = Bfdopen(s->fd, OWRITE)) == nil)
+		sysfatal("Bfdopen: %r");
+
+	/* present yourself */
+	Bprint(bout, registerhdr0, s->nci->rsys, sipversion,
+		sipversion, s->nci->lsys, s->nci->lserv,
+		user, s->nci->lsys, s->nci->lserv,
+		user, s->nci->rsys,
+		user, s->nci->rsys);
+	Bflush(bout);
+
+	/* wait for the challenge */
+	while((line = Brdline(bin, '\n')) != nil){
+		if(strncmp(line, "\r\n", 2) == 0)
+			break;
+
+		p = strchr(line, '\r');
+		*p++ = 0, *p = 0;
+		if(debug)
+			fprint(2, "%s\n", line);
+
+		if(strstr(line, ":") == nil)
+			continue;
+
+		gettokens(line, kv, nelem(kv), ": ");
+		if(debug)
+			fprint(2, "got key=%s value=%s\n", kv[0], kv[1]);
+	}
+
+	/* respond to the challenge */
+
+	/* get the OK */
+
+	Bterm(bin);
+	Bterm(bout);
+
+	return 0;
+}
+
+Sip *
+mksip(int fd)
+{
+	Sip *s;
+
+	s = emalloc(sizeof(Sip));
+	memset(s, 0, sizeof *s);
+	s->version = 2;
+	s->nci = getnetconninfo(nil, fd);
+	if(s->nci == nil){
+		werrstr("couldn't getnetconninfo");
+		free(s);
+		return nil;
+	}
+	s->fd = fd;
+	s->reg = sip_register;
+
+	return s;
+}
+
+void
+rmsip(Sip *s)
+{
+	close(s->fd);
+	freenetconninfo(s->nci);
+	free(s);
+}