Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <ip.h>
4
#include <thread.h>
5
#include "netbios.h"
6
 
7
static struct {
8
	int thread;
9
	QLock;
10
	int fd;
11
} udp = { -1 };
12
 
13
typedef struct Listen Listen;
14
 
15
struct Listen {
16
	NbName to;
17
	int (*deliver)(void *magic, NbDgram *s);
18
	void *magic;
19
	Listen *next;
20
};
21
 
22
static struct {
23
	Lock;
24
	ushort id;
25
} id;
26
 
27
struct {
28
	QLock;
29
	NbnsTransaction *head;
30
} transactionlist;
31
 
32
static void
33
udplistener(void *)
34
{	
35
	for (;;) {
36
		uchar msg[Udphdrsize + 576];
37
		int len = read(udp.fd, msg, sizeof(msg));
38
		if (len < 0)
39
			break;
40
		if (len >= nbudphdrsize) {
41
			NbnsMessage *s;
42
//			Udphdr *uh;
43
			uchar *p;
44
 
45
//			uh = (Udphdr*)msg;
46
			p = msg + nbudphdrsize;
47
			len -= nbudphdrsize;
48
			s = nbnsconvM2S(p, len);
49
			if (s) {
50
//print("%I:%d -> %I:%d\n", uh->raddr, nhgets(uh->rport), uh->laddr, nhgets(uh->lport));
51
//nbnsdumpmessage(s);
52
				if (s->response) {
53
					NbnsTransaction *t;
54
					qlock(&transactionlist);
55
					for (t = transactionlist.head; t; t = t->next)
56
						if (t->id == s->id)
57
							break;
58
					if (t)
59
						sendp(t->c, s);
60
					else
61
						nbnsmessagefree(&s);
62
					qunlock(&transactionlist);
63
				}
64
				else
65
					nbnsmessagefree(&s);
66
			}
67
		}
68
	}
69
}
70
 
71
static char *
72
startlistener(void)
73
{
74
	qlock(&udp);
75
	if (udp.thread < 0) {
76
		char *e;
77
		e = nbudpannounce(NbnsPort, &udp.fd);
78
		if (e) {
79
			qunlock(&udp);
80
			return e;
81
		}
82
		udp.thread = proccreate(udplistener, nil, 16384);
83
	}
84
	qunlock(&udp);
85
	return nil;
86
}
87
 
88
ushort
89
nbnsnextid(void)
90
{
91
	ushort rv;
92
	lock(&id);
93
	rv = id.id++;
94
	unlock(&id);
95
	return rv;
96
}
97
 
98
NbnsTransaction *
99
nbnstransactionnew(NbnsMessage *s, uchar *ipaddr)
100
{
101
	NbnsTransaction *t;
102
	uchar msg[Udphdrsize + 576];
103
	Udphdr *u;
104
	int len;
105
 
106
	startlistener();
107
	len = nbnsconvS2M(s, msg + nbudphdrsize, sizeof(msg) - nbudphdrsize);
108
	if (len == 0)
109
		return 0;
110
	t = mallocz(sizeof(*t), 1);
111
	if (t == nil)
112
		return nil;
113
	t->id = s->id;	
114
	t->c = chancreate(sizeof(NbnsMessage *), 3);
115
	if (t->c == nil) {
116
		free(t);
117
		return nil;
118
	}
119
	qlock(&transactionlist);
120
	t->next = transactionlist.head;
121
	transactionlist.head = t;
122
	qunlock(&transactionlist);
123
	u = (Udphdr *)msg;
124
	ipmove(u->laddr, nbglobals.myipaddr);
125
	hnputs(u->lport, NbnsPort);
126
	if (s->broadcast || ipaddr == nil)
127
		ipmove(u->raddr, nbglobals.bcastaddr);
128
	else
129
		ipmove(u->raddr, ipaddr);
130
	hnputs(u->rport, NbnsPort);
131
	write(udp.fd, msg, len + nbudphdrsize);
132
	return t;
133
}
134
 
135
void
136
nbnstransactionfree(NbnsTransaction **tp)
137
{
138
	NbnsTransaction **tp2;
139
	NbnsMessage *s;
140
	NbnsTransaction *t;
141
 
142
	t = *tp;
143
	if (t) {
144
		qlock(&transactionlist);
145
		while ((s = nbrecvp(t->c)) != nil)
146
			nbnsmessagefree(&s);
147
		for (tp2 = &transactionlist.head; *tp2 && *tp2 != t; tp2 = &(*tp2)->next)
148
			;
149
		if (*tp2) {
150
			*tp2 = t->next;
151
			free(t);
152
		}
153
		qunlock(&transactionlist);
154
		*tp = nil;
155
	}
156
}