M port/devbit.c => port/devbit.c +1 -1
@@ 487,7 487,7 @@ bitread(Chan *c, void *va, long n, ulong offset)
ws = 1<<(3-gscreen.ldepth); /* pixels per byte */
l = (gscreen.r.max.x+ws-1)/ws - gscreen.r.min.x/ws;
t = offset-5*12;
- miny = t/l;
+ miny = t/l; /* unsigned computation */
maxy = (t+n)/l;
if(miny >= gscreen.r.max.y)
return 0;
M port/devip.c => port/devip.c +33 -19
@@ 226,6 226,30 @@ ipclonecon(Chan *c)
base = ipconv[c->dev];
etab = &base[conf.ip];
for(new = base; new < etab; new++) {
+ new = ipincoming(c->dev);
+ if(new == 0)
+ error(Enodev);
+
+ c->qid.path = CHDIR|STREAMQID(new-base, ipchanqid);
+ devwalk(c, "ctl", 0, 0, streamgen);
+
+ streamopen(c, &ipinfo);
+ pushq(c->stream, new->stproto);
+ new->ref--;
+ return new;
+ }
+
+ error(Enodev);
+}
+
+Ipconv *
+ipincoming(int dev)
+{
+ Ipconv *base, *new, *etab;
+
+ base = ipconv[dev];
+ etab = &base[conf.ip];
+ for(new = base; new < etab; new++) {
if(new->ref == 0 && canqlock(new)) {
if(new->ref ||
(new->stproto == &tcpinfo && new->tcpctl.state != CLOSED) ||
@@ 234,18 258,11 @@ ipclonecon(Chan *c)
continue;
}
new->ref++;
- c->qid.path = CHDIR|STREAMQID(new-base, ipchanqid);
- devwalk(c, "ctl", 0, 0, streamgen);
qunlock(new);
-
- streamopen(c, &ipinfo);
- pushq(c->stream, new->stproto);
- new->ref--;
return new;
}
}
-
- error(Enodev);
+ return 0;
}
void
@@ 642,7 659,7 @@ tcpstopen(Queue *q, Stream *s)
}
int
-tcp_havecon(Ipconv *s)
+iphavecon(Ipconv *s)
{
return s->curlog;
}
@@ 655,28 672,25 @@ iplisten(Chan *c, Ipconv *s, Ipconv *base)
qlock(&s->listenq);
for(;;) {
- sleep(&s->listenr, tcp_havecon, s);
-
- /* Search for the new connection, clone the control channel and
- * return an open channel to the listener
- */
- for(new = base, etab = &base[conf.ip]; new < etab; new++) {
- if(new->psrc == s->psrc && new->pdst != 0 &&
- new->dst && (new->tcpctl.flags & CLONE) == 0) {
- new->ref++;
+ sleep(&s->listenr, iphavecon, s);
+ new = base;
+ for(etab = &base[conf.ip]; new < etab; new++) {
+ if(new->newcon) {
/* Remove the listen channel reference */
streamclose(c);
s->curlog--;
+
/* Attach the control channel to the new connection */
+ new->newcon = 0;
c->qid.path = CHDIR|STREAMQID(new-base, ipchanqid);
devwalk(c, "ctl", 0, 0, streamgen);
streamopen(c, &ipinfo);
pushq(c->stream, new->stproto);
new->ref--;
-
qunlock(&s->listenq);
+
return;
}
}
M port/ipdat.h => port/ipdat.h +3 -5
@@ 263,22 263,19 @@ struct Ipconv
int ref;
Qinfo *stproto; /* Stream protocol for this device */
Ipaddr dst; /* Destination from connect */
-
Port psrc; /* Source port */
Port pdst; /* Destination port */
- uchar ptype; /* Source port type */
Ipifc *ipinterface; /* Ip protocol interface */
Queue *readq; /* Pointer to upstream read q */
-
QLock listenq; /* List of people waiting incoming cons */
Rendez listenr; /* Some where to sleep while waiting */
- Ipconv *listen;
char err; /* Async protocol error */
int backlog; /* Maximum number of waiting connections */
int curlog; /* Number of waiting connections */
- int contype;
+ int newcon; /* Flags that this is the start of a connection */
+
union {
Tcpctl tcpctl; /* Tcp control block */
Ilcb ilctl; /* Il control block */
@@ 476,6 473,7 @@ int seq_gt(int, int);
void appendb(Block **, Block *);
Ipconv *ip_conn(Ipconv *, Port, Port, Ipaddr dest, char proto);
void ipmkdir(Qinfo *, Dirtab *, Ipconv *);
+Ipconv *ipincoming(Ipconv*);
int inb_window(Tcpctl *, int);
Block *htontcp(Tcp *, Block *, Tcphdr *);
void start_timer(Timer *);
M port/stil.c => port/stil.c +21 -7
@@ 12,10 12,9 @@
#include "ipdat.h"
#define DPRINT if(pip)print
-int ilcksum = 1;
-
-static int initseq = 25000;
-char *ilstate[] = { "Closed", "Syncer", "Syncee", "Established", "Listening", "Closing" };
+int ilcksum = 1;
+static int initseq = 25000;
+char *ilstate[] = { "Closed", "Syncer", "Syncee", "Established", "Listening", "Closing" };
void ilrcvmsg(Ipconv*, Block*);
void ilackproc(void*);
@@ 186,7 185,7 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
{
Ilhdr *ih;
int plen;
- Ipconv *s, *etab;
+ Ipconv *s, *etab, *new;
short sp, dp;
ih = (Ilhdr *)bp;
@@ 210,13 209,29 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
}
}
+
for(s = ipc; s < etab; s++) {
if(s->ilctl.state == Illistening && s->psrc == 0) {
/* Do the listener stuff */
- ilprocess(s, ih, bp);
+ new = ipincoming(ipc);
+ if(new == 0)
+ goto reset;
+ if(ih->type != Ilsync)
+ goto reset;
+
+ new->newcon = 1;
+ new->ipinterface = s->ipinterface;
+ s->ipinterface->ref++;
+ new->psrc = sp;
+ new->pdst = dp;
+ new->dst = nhgetl(ih->src);
+ ilprocess(new, ih, bp);
+
+ wakeup(&s->listenr);
return;
}
}
+reset:
ilsendctl(0, ih, Ilreset, 0);
drop:
freeb(bp);
@@ 333,5 348,4 @@ ilstart(Ipconv *ipc, int type, int window)
ilsendctl(ipc, 0, Ilsync, 1);
break;
}
-
}
M port/stip.c => port/stip.c +0 -1
@@ 555,7 555,6 @@ ip_csum(uchar *addr)
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
-
return (sum^0xffff);
}
M port/tcpinput.c => port/tcpinput.c +5 -18
@@ 34,7 34,7 @@ tcpinit(void)
void
tcp_input(Ipconv *ipc, Block *bp)
{
- Ipconv *s, *new, *etab;
+ Ipconv *s, *new;
Tcpctl *tcb;
Tcphdr *h;
Tcp seg;
@@ 108,21 108,8 @@ tcp_input(Ipconv *ipc, Block *bp)
goto clear;
}
- /* Find a conversation to clone onto */
- etab = &ipc[conf.ip];
- for(new = ipc; new < etab; new++) {
- if(new->ref == 0 && canqlock(new)) {
- if(new->ref || new->tcpctl.state != CLOSED) {
- qunlock(new);
- continue;
- }
- new->ref++;
- qunlock(new);
- break;
- }
- }
-
- if(new == etab)
+ new = ipincoming(ipc);
+ if(new == 0)
goto clear;
s->curlog++;
@@ 137,11 124,11 @@ tcp_input(Ipconv *ipc, Block *bp)
new->tcpctl.acktimer.arg = new;
new->tcpctl.acktimer.state = TIMER_STOP;
+ new->newcon = 1;
new->ipinterface = s->ipinterface;
s->ipinterface->ref++;
-
- /* Wake the sleeping dodo */
wakeup(&s->listenr);
+
s = new;
}