diff options
-rw-r--r-- | alloc.c | 44 | ||||
-rw-r--r-- | dat.h | 117 | ||||
-rw-r--r-- | fns.h | 10 | ||||
-rw-r--r-- | main.c | 52 | ||||
-rw-r--r-- | mkfile | 25 | ||||
-rw-r--r-- | readme.md | 0 | ||||
-rw-r--r-- | sip.c | 211 |
7 files changed, 459 insertions, 0 deletions
@@ -0,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; +} @@ -0,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; @@ -0,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*); @@ -0,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); +} @@ -0,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 + } diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/readme.md @@ -0,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); +} |