ref: 2e99eaaea1aa6776eda10f5ec8bd90adcfe8424a
dir: /sip.c/
#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); }